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(void);
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(void);
237 static void control(unsigned int btn
, int x
, int y
, unsigned int state
);
238 static void draw_dockapp(void);
239 static void update(void);
240 static void switch_light(void);
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(void);
247 static void draw_datedigit(void);
248 static void draw_itimedigit(void);
249 static void draw_binarytime(void);
250 static void parse_arguments(int argc
, char **argv
);
251 static void print_help(char *prog
);
252 static void time_update(void);
253 static Bool
raise_alarm(void);
254 static Bool
filestat(const char *filename
, time_t *time
, int mode
);
255 static int my_system(char *cmd
, char *opt
);
256 void *xmalloc(size_t size
);
257 char *xstrdup(const char *string
);
258 static void alrm_add(Alarm
**list
, const char *value
);
259 static void free_alrm(Alarm
**list
);
260 static Bool
alarms_on(Alarm
*list
);
261 static void switch_alarms(Alarm
*list
);
262 static Bool
getbool(char *value
);
263 static Bool
load_cfgfile(void);
264 static char *get_calend_file(int type
);
265 static int cal_alrms_chg(void);
266 static void load_cal_file(int type
);
267 static void load_calalrms(void);
268 static void reload_alarms(void);
269 static void show_cal_file(int type
);
270 static void show_cal(void);
271 static char *robust_home(void);
275 int main(int argc
, char **argv
) {
279 sa
.sa_handler
= SIG_IGN
;
281 sa
.sa_flags
= SA_NOCLDWAIT
;
285 sigemptyset(&sa
.sa_mask
);
286 sigaction(SIGCHLD
, &sa
, NULL
);
288 /* Set default for style dir : */
289 SET_STRING(style_dir
, DATADIR
);
294 /* Load default configuration file */
296 char *Home
= robust_home();
297 config_file
= xmalloc(strlen(Home
) + strlen(DEFAULT_CFGFILE
) + 2);
298 sprintf(config_file
, "%s/%s", Home
, DEFAULT_CFGFILE
);
303 /* Parse CommandLine */
304 parse_arguments(argc
, argv
);
307 char *Home
= robust_home();
308 config_file
= xmalloc(strlen(Home
) + strlen(DEFAULT_CFGFILE
) + 2);
309 sprintf(config_file
, "%s/%s", Home
, DEFAULT_CFGFILE
);
313 style
= default_style
;
314 load_style(style_name
);
317 setlocale(LC_TIME
, "");
318 setlocale(LC_CTYPE
, "");
319 setlocale(LC_COLLATE
, "");
322 /* Initialize Application */
323 dockapp_open_window(display_name
, argv
[0], SIZE
, SIZE
, argc
, argv
);
324 dockapp_set_eventmask(ButtonPressMask
);
328 if (showcal
) show_cal();
332 if (dockapp_nextevent_or_timeout(&event
, update_interval
* 1000 - 10)) {
334 switch (event
.type
) {
336 control(event
.xbutton
.button
,
339 event
.xbutton
.state
);
353 static void rotate_style(void) {
355 struct dirent
*dir_ent
;
357 Bool is_next
= False
;
359 if (! style_dir
) return;
360 if ((dir
= opendir(style_dir
)) == NULL
) return;
361 while ((dir_ent
= readdir(dir
)) != NULL
) {
362 if (strstr(dir_ent
->d_name
, ".mwcs") != NULL
) {
363 if (is_next
|| (! style_name
)) {
364 next
= xstrdup(dir_ent
->d_name
);
368 if (style_name
&& (strstr(style_name
, dir_ent
->d_name
) != NULL
))
375 style_name
= xmalloc(strlen(next
)+strlen(style_dir
)+2);
376 sprintf(style_name
, "%s/%s", style_dir
, next
);
380 FREE(style
.letters_s
);
391 style
= default_style
;
397 static Bool
stringdiff(const char *s1
, const char *s2
) {
398 if (!s1
&& !s2
) return False
;
399 if (!s1
&& s2
) return True
;
400 if (s1
&& !s2
) return True
;
401 if (strcmp(s1
, s2
) == 0) return False
;
406 static char *set_filename(const char *file_name
, const char *ext
) {
407 int length
= style_dir
? strlen(style_dir
) + 1 : 0;
408 char *filename
= NULL
;
409 if (! file_name
) return NULL
;
410 if ((file_name
[0] == '.') || (file_name
[0] == '/') ||
411 (ext
&& (strstr(file_name
, ext
) != NULL
))) { /* local file */
413 filename
= xstrdup(file_name
);
414 e
= strrchr(filename
, '/');
415 if ((!style_dir
) && (e
!= NULL
)) {
417 int i
= 0, style_len
= strlen(filename
) - strlen(e
);
418 style_dir
= xmalloc(style_len
+ 2);
420 style_dir
[i
++] = p
[0];
426 length
+= strlen(file_name
);
427 length
+= ext
? strlen(ext
) + 1 : 1;
428 filename
= xmalloc(length
);
429 sprintf(filename
, "%s%s%s%s",
430 style_dir
? style_dir
: "",
431 style_dir
? "/" : "",
439 static Bool
set_style_value(StyleDef opt
, char *value
) {
441 char *string1
= NULL
;
442 char *string2
= NULL
;
446 *(int *)(opt
.var
) = atoi(value
);
449 *(Bool
*)(opt
.var
) = getbool(value
);
452 string1
= *(char **)(opt
.var
);
453 SET_STRING(string1
, value
);
454 *(char **)(opt
.var
) = string1
;
457 string1
= *(char **)(opt
.var
);
458 string2
= set_filename(value
, NULL
);
459 SET_STRING(string1
, string2
);
460 *(char **)(opt
.var
) = string1
;
463 default: res
= False
;
469 static void set_style_default(StyleDef opt
) {
470 char *string1
= NULL
;
471 char *string2
= NULL
;
475 *(int *)(opt
.var
) = *(int *)(opt
.defval
);
478 *(Bool
*)(opt
.var
) = *(Bool
*)(opt
.defval
);
481 string1
= *(char **)(opt
.var
);
482 string2
= *(char **)(opt
.defval
);
483 SET_STRING(string1
, string2
);
484 *(char **)(opt
.var
) = string1
;
487 string1
= *(char **)(opt
.var
);
488 string2
= set_filename(*(char **)(opt
.defval
), NULL
);
489 SET_STRING(string1
, string2
);
490 *(char **)(opt
.var
) = string1
;
497 static void load_stylepart(const char *filename
, StyleDef
*opts
) {
501 if ((!filename
) || (filename
[0] == '-')) {
502 for (i
= 0 ; opts
[i
].key
; i
++)
503 set_style_default(opts
[i
]);
506 if ((file
= fopen(filename
, "r")) == NULL
) return;
507 while (!feof(file
)) {
508 char line
[MAXSTRLEN
+ 1], *value
;
512 if (!fgets(line
, MAXSTRLEN
, file
))
519 if (line
[n
- 1] == '\n') line
[n
- 1] = 0;
520 if ((line
[0] == '#') || (line
[0] == 0)) continue;
521 value
= strchr(line
, '=') + 1;
522 while ((value
[0] == ' ') && (value
[0] != 0)) value
++;
523 if (value
[0] == 0) continue;
525 for (j
= 0 ; opts
[j
].key
; j
++) {
526 size_t length
= strlen(opts
[j
].key
);
527 if (strlen(line
) <= length
) continue;
528 if (strncmp(line
, opts
[j
].key
, length
) == 0) {
529 set_style_value(opts
[j
], value
);
535 fprintf(stderr
, "Error in %s at line %d :\n[%s].\n",
541 static void load_style(const char *stylename
) {
542 StyleDef parts_style_opts
[] = {
543 {"Parts", T_FILE
, &style
.parts
, &default_style
.parts
},
544 {"BDigitHeight", T_INT
, &style
.bdigith
, &default_style
.bdigith
},
545 {"BDigitWidth", T_INT
, &style
.bdigitw
, &default_style
.bdigitw
},
546 {"SDigitHeight", T_INT
, &style
.sdigith
, &default_style
.sdigith
},
547 {"SDigitWidth", T_INT
, &style
.sdigitw
, &default_style
.sdigitw
},
548 {"BDigitSep", T_INT
, &style
.bsep
, &default_style
.bsep
},
549 {"SDigitSep", T_INT
, &style
.ssep
, &default_style
.ssep
},
550 {NULL
, T_STRING
, NULL
, NULL
}
552 StyleDef letters_style_opts
[] = {
553 {"Letters", T_FILE
, &style
.letters
, &default_style
.letters
},
554 {"LetterHeight", T_INT
, &style
.letterh
, &default_style
.letterh
},
555 {"LetterWidth", T_INT
, &style
.letterw
, &default_style
.letterw
},
556 {"LetterSep", T_INT
, &style
.lsep
, &default_style
.lsep
},
557 {NULL
, T_STRING
, NULL
, NULL
}
559 StyleDef itime_style_opts
[] = {
560 {"IBacklightOn", T_FILE
, &style
.ibackl
, &default_style
.ibackl
},
561 {"IBacklightOff", T_FILE
, &style
.ibacku
, &default_style
.ibacku
},
562 {"Beats_PosX", T_INT
, &style
.bposx
, &default_style
.bposx
},
563 {"Beats_PosY", T_INT
, &style
.bposy
, &default_style
.bposy
},
564 {"Beats_Big", T_BOOL
, &style
.bbig
, &default_style
.bbig
},
565 {"10thOB_PosX", T_INT
, &style
.tposx
, &default_style
.tposx
},
566 {"10thOB_PosY", T_INT
, &style
.tposy
, &default_style
.tposy
},
567 {"10thOB_Big", T_BOOL
, &style
.tbig
, &default_style
.tbig
},
568 {"10thOB_Display", T_BOOL
, &style
.tdisp
, &default_style
.tdisp
},
569 {"Graph_PosX", T_INT
, &style
.gposx
, &default_style
.gposx
},
570 {"Graph_PosY", T_INT
, &style
.gposy
, &default_style
.gposy
},
571 {"Graph_Display", T_BOOL
, &style
.gdisp
, &default_style
.gdisp
},
572 {NULL
, T_STRING
, NULL
, NULL
}
574 StyleDef btime_style_opts
[] = {
575 {"BBacklightOn", T_FILE
, &style
.bbackl
, &default_style
.bbackl
},
576 {"BBacklightOff", T_FILE
, &style
.bbacku
, &default_style
.bbacku
},
577 {"Bin_HX", T_INT
, &style
.binhx
, &default_style
.binhx
},
578 {"Bin_HY", T_INT
, &style
.binhy
, &default_style
.binhy
},
579 {"Bin_MX", T_INT
, &style
.binmx
, &default_style
.binmx
},
580 {"Bin_MY", T_INT
, &style
.binmy
, &default_style
.binmy
},
581 {"Bin_SX", T_INT
, &style
.binsx
, &default_style
.binsx
},
582 {"Bin_SY", T_INT
, &style
.binsy
, &default_style
.binsy
},
583 {"Bin_ZX", T_INT
, &style
.binzx
, &default_style
.binzx
},
584 {"Bin_ZY", T_INT
, &style
.binzy
, &default_style
.binzy
},
585 {"Bin_WX", T_INT
, &style
.binwx
, &default_style
.binwx
},
586 {"Bin_WY", T_INT
, &style
.binwy
, &default_style
.binwy
},
587 {"Bin_DX", T_INT
, &style
.bindx
, &default_style
.bindx
},
588 {"Bin_DY", T_INT
, &style
.bindy
, &default_style
.bindy
},
589 {"Bin_OX", T_INT
, &style
.binox
, &default_style
.binox
},
590 {"Bin_OY", T_INT
, &style
.binoy
, &default_style
.binoy
},
591 {"Bin_IX", T_INT
, &style
.binix
, &default_style
.binix
},
592 {"Bin_IY", T_INT
, &style
.biniy
, &default_style
.biniy
},
593 {"Bin_d1X", T_INT
, &style
.bind1x
, &default_style
.bind1x
},
594 {"Bin_d1Y", T_INT
, &style
.bind1y
, &default_style
.bind1y
},
595 {"Bin_d2X", T_INT
, &style
.bind2x
, &default_style
.bind2x
},
596 {"Bin_d2Y", T_INT
, &style
.bind2y
, &default_style
.bind2y
},
597 {"Bin_d3X", T_INT
, &style
.bind3x
, &default_style
.bind3x
},
598 {"Bin_d3Y", T_INT
, &style
.bind3y
, &default_style
.bind3y
},
599 {"Bin_d4X", T_INT
, &style
.bind4x
, &default_style
.bind4x
},
600 {"Bin_d4Y", T_INT
, &style
.bind4y
, &default_style
.bind4y
},
601 {NULL
, T_STRING
, NULL
, NULL
}
603 StyleDef main_style_opts
[] = {
604 {"PartsStyle", T_FILE
, &style
.parts_s
, &default_style
.parts_s
},
605 {"LettersStyle", T_FILE
, &style
.letters_s
, &default_style
.letters_s
},
606 {"ITimeStyle", T_FILE
, &style
.itime_s
, &default_style
.itime_s
},
607 {"BTimeStyle", T_FILE
, &style
.btime_s
, &default_style
.btime_s
},
608 {"BacklightOn", T_FILE
, &style
.backl
, &default_style
.backl
},
609 {"BacklightOff", T_FILE
, &style
.backu
, &default_style
.backu
},
610 {"NbColors", T_INT
, &style
.ncolors
, &default_style
.ncolors
},
611 {"Hours_PosX", T_INT
, &style
.hposx
, &default_style
.hposx
},
612 {"Hours_PosY", T_INT
, &style
.hposy
, &default_style
.hposy
},
613 {"Hours_Big", T_BOOL
, &style
.hbig
, &default_style
.hbig
},
614 {"Minutes_PosX", T_INT
, &style
.mposx
, &default_style
.mposx
},
615 {"Minutes_PosY", T_INT
, &style
.mposy
, &default_style
.mposy
},
616 {"Minutes_Big", T_BOOL
, &style
.mbig
, &default_style
.mbig
},
617 {"Seconds_PosX", T_INT
, &style
.sposx
, &default_style
.sposx
},
618 {"Seconds_PosY", T_INT
, &style
.sposy
, &default_style
.sposy
},
619 {"Seconds_Big", T_BOOL
, &style
.sbig
, &default_style
.sbig
},
620 {"Seconds_Colon", T_BOOL
, &style
.csec
, &default_style
.csec
},
621 {"AM_PosX", T_INT
, &style
.aposx
, &default_style
.aposx
},
622 {"AM_PosY", T_INT
, &style
.aposy
, &default_style
.aposy
},
623 {"PM_PosX", T_INT
, &style
.pposx
, &default_style
.pposx
},
624 {"PM_PosY", T_INT
, &style
.pposy
, &default_style
.pposy
},
625 {"ALRM_PosX", T_INT
, &style
.lposx
, &default_style
.lposx
},
626 {"ALRM_PosY", T_INT
, &style
.lposy
, &default_style
.lposy
},
627 {"Weekday_PosX", T_INT
, &style
.wposx
, &default_style
.wposx
},
628 {"Weekday_PosY", T_INT
, &style
.wposy
, &default_style
.wposy
},
629 {"Day_PosX", T_INT
, &style
.dposx
, &default_style
.dposx
},
630 {"Day_PosY", T_INT
, &style
.dposy
, &default_style
.dposy
},
631 {"Month_PosX", T_INT
, &style
.oposx
, &default_style
.oposx
},
632 {"Month_PosY", T_INT
, &style
.oposy
, &default_style
.oposy
},
633 {NULL
, T_STRING
, NULL
, NULL
}
641 if (! stylename
) return;
643 partsfile
= xstrdup(style
.parts_s
);
644 lettersfile
= xstrdup(style
.letters_s
);
645 itimefile
= xstrdup(style
.itime_s
);
646 btimefile
= xstrdup(style
.btime_s
);
647 filename
= set_filename(stylename
, ".mwcs");
650 load_stylepart(filename
, main_style_opts
);
653 if (stringdiff(partsfile
, style
.parts_s
) == True
)
654 load_stylepart(style
.parts_s
, parts_style_opts
);
657 if (stringdiff(lettersfile
, style
.letters_s
) == True
)
658 load_stylepart(style
.letters_s
, letters_style_opts
);
661 if (stringdiff(itimefile
, style
.itime_s
) == True
)
662 load_stylepart(style
.itime_s
, itime_style_opts
);
665 if (stringdiff(btimefile
, style
.btime_s
) == True
)
666 load_stylepart(style
.btime_s
, btime_style_opts
);
676 static void init_pixmap(char **src_pix
, Pixmap
*dst_pix
, const char *text
,
677 XpmColorSymbol
*c
, int n
, int keep_mask
) {
678 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
679 if (!dockapp_xpm2pixmap(src_pix
, dst_pix
, &mask
, c
, n
)) {
680 fprintf(stderr
, "Error initializing %s image.\n", text
);
683 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
687 static void init_pixfile(char *src_name
, Pixmap
*dst_pix
, const char *text
,
688 XpmColorSymbol
*c
, int n
, int keep_mask
) {
689 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
690 if (!dockapp_file2pixmap(src_name
, dst_pix
, &mask
, c
, n
)) {
691 fprintf(stderr
, "Error initializing %s image.\n", text
);
694 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
698 static void graphics_init(void) {
699 XpmColorSymbol colors
[3] = { {"Back0", NULL
, 0}, {"Back1", NULL
, 0}, {"Back2", NULL
, 0} };
703 ncolor
= style
.ncolors
;
705 colors
[0].pixel
= dockapp_getcolor(light_color
);
706 colors
[1].pixel
= dockapp_blendedcolor(light_color
, -24, -24, -24, 1.0);
708 colors
[0].pixel
= dockapp_getcolor(light_color
);
709 colors
[1].pixel
= dockapp_dividecolor(light_color
, 3);
710 colors
[2].pixel
= dockapp_blendedcolor(light_color
, -50, -50, -50, 1.0);
714 /* change raw xpm data to pixmap */
716 if (dockapp_iswindowed)
717 backlit_pix[1] = backgrd_pix[1] = WINDOWED_BG;
721 init_pixfile(style
.parts
, &parts
, "parts",
722 colors
, ncolor
, False
);
724 init_pixmap(parts_xpm
, &parts
, "parts",
725 colors
, ncolor
, False
);
728 init_pixfile(style
.letters
, &letters
, "letters",
729 colors
, ncolor
, False
);
731 init_pixmap(letters_xpm
, &letters
, "letters",
732 colors
, ncolor
, False
);
735 init_pixfile(style
.ibackl
, &backdropI_on
, "backlit background 2",
736 colors
, ncolor
, False
);
738 init_pixmap(backlightI_on_xpm
, &backdropI_on
, "backlit background 2",
739 colors
, ncolor
, False
);
742 init_pixfile(style
.ibacku
, &backdropI_off
, "background 2",
743 colors
, ncolor
, False
);
745 init_pixmap(backlightI_off_xpm
, &backdropI_off
, "background 2",
746 colors
, ncolor
, False
);
749 init_pixfile(style
.bbackl
, &backdropB_on
, "backlit background 3",
750 colors
, ncolor
, False
);
752 init_pixmap(backlightB_on_xpm
, &backdropB_on
, "backlit background 3",
753 colors
, ncolor
, False
);
756 init_pixfile(style
.bbacku
, &backdropB_off
, "background 3",
757 colors
, ncolor
, False
);
759 init_pixmap(backlightB_off_xpm
, &backdropB_off
, "background 3",
760 colors
, ncolor
, False
);
763 init_pixfile(style
.backl
, &backdrop_on
, "backlit background",
764 colors
, ncolor
, False
);
766 init_pixmap(backlight0_on_xpm
, &backdrop_on
, "backlit background",
767 colors
, ncolor
, False
);
770 init_pixfile(style
.backu
, &backdrop_off
, "background",
771 colors
, ncolor
, True
);
773 init_pixmap(backlight0_off_xpm
, &backdrop_off
, "background",
774 colors
, ncolor
, True
);
777 if (!dockapp_iswindowed
) dockapp_setshape(mask
, 0, 0);
778 if (mask
) XFreePixmap(display
, mask
);
780 /* pixmap : draw area */
781 if (pixmap
) XFreePixmap(display
, pixmap
);
782 pixmap
= dockapp_XCreatePixmap(SIZE
, SIZE
);
784 /* Initialize pixmap */
785 draw_background(backlight
);
787 dockapp_set_background(pixmap
);
793 static void control(unsigned int btn
, int x
, int y
, unsigned int state
) {
796 if (time_mode
== CLOCK
) {
797 if ( (x
>= style
.aposx
) && (x
<= style
.aposx
+ 12) &&
798 (y
>= style
.aposy
) && (y
<= style
.aposy
+ 7) ) {
801 } else if ( (x
>= style
.pposx
) && (x
<= style
.pposx
+ 12) &&
802 (y
>= style
.pposy
) && (y
<= style
.pposy
+ 7) ) {
805 } else if ( (x
>= style
.lposx
) && (x
<= style
.lposx
+ 22) &&
806 (y
>= style
.lposy
) && (y
<= style
.lposy
+ 7) ) {
807 if (alarms
) switch_alarms(alarms
);
811 if (state
& ControlMask
) {
813 if (time_mode
== 3) time_mode
= CLOCK
;
821 if (state
& ControlMask
) {
822 my_system("wmclockmon-config -f", config_file
);
825 load_style(style_name
);
831 if (state
& ControlMask
) {
832 my_system("wmclockmon-cal", NULL
);
834 switch_authorized
= !switch_authorized
;
842 static void draw_dockapp(void) {
844 draw_background(backlight
);
847 if (time_mode
== INTERNET
) {
849 } else if (time_mode
== BINARY
) {
857 dockapp_copy2window(pixmap
);
861 /* called by timer */
862 static void update(void) {
863 static Light pre_backlight
;
864 static Bool in_alarm_mode
= False
;
866 /* check config_file modifications */
867 if (load_cfgfile()) graphics_init();
869 /* get current time */
874 if (!in_alarm_mode
) {
875 in_alarm_mode
= True
;
876 my_system(command
, NULL
);
877 if (message
) my_system(msgcmd
, message
);
878 pre_backlight
= backlight
;
880 if ( (switch_authorized
) ||
881 ( (switch_authorized
) && (backlight
!= pre_backlight
) ) ) {
887 in_alarm_mode
= False
;
888 if (backlight
!= pre_backlight
) {
898 /* called when mouse button pressed */
899 static void switch_light(void) {
901 case LIGHTOFF
: backlight
= LIGHTON
; break;
902 case LIGHTON
: backlight
= LIGHTOFF
; break;
910 static void draw_background(Light back
) {
911 if (back
== LIGHTON
) {
912 if (time_mode
== INTERNET
)
913 dockapp_copyarea(backdropI_on
, pixmap
, 0, 0, 58, 58, 0, 0);
914 else if (time_mode
== BINARY
)
915 dockapp_copyarea(backdropB_on
, pixmap
, 0, 0, 58, 58, 0, 0);
917 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, 58, 58, 0, 0);
919 if (time_mode
== INTERNET
)
920 dockapp_copyarea(backdropI_off
, pixmap
, 0, 0, 58, 58, 0, 0);
921 else if (time_mode
== BINARY
)
922 dockapp_copyarea(backdropB_off
, pixmap
, 0, 0, 58, 58, 0, 0);
924 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, 58, 58, 0, 0);
929 static void draw_bigdigit(int num
, int x
, int y
) {
930 int dy
= 0, w
= style
.bdigitw
, h
= style
.bdigith
;
931 int incr
= style
.bdigitw
+ style
.bsep
;
933 if (num
< 0) num
= 0;
934 if (backlight
== LIGHTON
) dy
= style
.bdigith
;
937 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
, dy
, w
, h
, x
+ incr
, y
);
938 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
, dy
, w
, h
, x
, y
);
942 static void draw_smalldigit(int num
, int x
, int y
) {
943 int dx
= 0, w
= style
.sdigitw
, h
= style
.sdigith
;
944 int incr
= style
.sdigitw
+ style
.bsep
;
945 int dy
= 2 * style
.bdigith
;
947 if (num
< 0) num
= 0;
948 if (backlight
== LIGHTON
) dx
= style
.sdigitw
* 10;
951 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
+ dx
, dy
, w
, h
, x
+ incr
, y
);
952 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
+ dx
, dy
, w
, h
, x
, y
);
956 static char equiv(char letter
) {
957 int i
, sign
, oldsign
= 0;
958 char letr
[2], upcase
, ret
= 0;
960 upcase
= toupper(letter
);
961 letr
[0] = upcase
; letr
[1] = 0;
962 if (! isupper(upcase
)) return letter
;
963 for (i
= 0 ; upcases
[i
] ; i
++) {
964 sign
= strcoll(letr
, upcases
[i
]);
965 if ((oldsign
> 0) && (sign
< 0)) ret
= upcases
[i
-1][0];
968 if (ret
== 0) ret
= upcase
;
973 static void draw_textdigit(const char *text
, int x
, int y
) {
974 int i
, dy
= style
.letterh
, incr
= style
.letterw
+ style
.lsep
;
975 int w
= style
.letterw
, h
= style
.letterh
;
977 if (backlight
== LIGHTON
) dy
= style
.letterh
* 2;
978 for (i
= 0 ; text
[i
] ; i
++) {
979 int pos
= equiv(text
[i
]) - 'A';
980 dockapp_copyarea(letters
, pixmap
, pos
* w
, dy
, w
, h
, x
+ i
* incr
, y
);
985 static void draw_timedigit(void) {
986 int hour
= timeinfos
->tm_hour
, dx
= 0, dy
= 0;
988 if (backlight
== LIGHTON
) {
989 dx
= style
.sdigitw
* 10; /* AM/PM/ALRM parts positions */
990 dy
= style
.bdigith
; /* colon seconds */
997 hour
= (hour
> 12) ? hour
- 12 : hour
;
1001 draw_bigdigit(hour
, style
.hposx
, style
.hposy
);
1003 draw_smalldigit(hour
, style
.hposx
, style
.hposy
);
1006 draw_bigdigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1008 draw_smalldigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1011 if (timeinfos
->tm_sec
% 2 == 1) {
1013 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
);
1014 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
+ 9);
1016 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
);
1017 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
+ 4);
1022 draw_bigdigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1024 draw_smalldigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1028 /* Some say pm is when h>12 or h==0 but others (and my watch) told me
1029 * that the good way to handle am/pm is what is below
1031 if (timeinfos
->tm_hour
>= 12) /* PM */
1032 dockapp_copyarea(parts
, pixmap
, 36 + dx
, 49, 12, 7, style
.pposx
, style
.pposy
);
1034 dockapp_copyarea(parts
, pixmap
, 23 + dx
, 49, 12, 7, style
.aposx
, style
.aposy
);
1036 if (alarms_on(alarms
))
1037 dockapp_copyarea(parts
, pixmap
, dx
, 49, 22, 7, style
.lposx
, style
.lposy
);
1041 static void draw_datedigit(void) {
1045 draw_textdigit(label
, style
.wposx
, style
.wposy
);
1047 strftime(text
, 4, "%a", timeinfos
);
1048 draw_textdigit(text
, style
.wposx
, style
.wposy
);
1049 draw_smalldigit(timeinfos
->tm_mday
, style
.dposx
, style
.dposy
);
1050 strftime(text
, 4, "%b", timeinfos
);
1051 draw_textdigit(text
, style
.oposx
, style
.oposy
);
1056 static void draw_itimedigit(void) {
1057 int dx
= 0, dy
= 0, v1
, v10
, v100
, v0
, v00
, nb
, pc
;
1058 int bw
= style
.bdigitw
, bh
= style
.bdigith
;
1059 int binc
= style
.bdigitw
+ 2;
1060 int tw
= style
.sdigitw
, th
= style
.bdigith
;
1063 if (backlight
== LIGHTON
) {
1070 v100
= swtime
/ 100.0;
1071 v10
= (swtime
- v100
* 100) / 10.0;
1072 v1
= (swtime
- v100
* 100.0 - v10
* 10.0);
1073 v0
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 10;
1074 v00
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 1000;
1075 pc
= v00
- v0
* 100;
1077 /* draw main beats digit */
1082 dockapp_copyarea(parts
, pixmap
, v1
* 10, dy
, bw
, bh
, style
.bposx
+ 2 * binc
, style
.bposy
);
1083 dockapp_copyarea(parts
, pixmap
, v10
* 10, dy
, bw
, bh
, style
.bposx
+ binc
, style
.bposy
);
1084 dockapp_copyarea(parts
, pixmap
, v100
* 10, dy
, bw
, bh
, style
.bposx
, style
.bposy
);
1086 /* draw 10th of beats */
1087 dockapp_copyarea(parts
, pixmap
, v0
* 5 + dx
, 40, 5, 9, 49, 28);
1090 for (nb
= 0 ; nb
< pc
/ 6.25 ; nb
++)
1091 dockapp_copyarea(parts
, pixmap
, xd
, 0, 2, 9, 6 + nb
* 3, 45);
1095 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
) {
1097 int dx
= u
* (sx
+ d2x
) + d1x
;
1101 int by
= 2 * style
.bdigith
+ style
.sdigith
+ 7 + d
;
1103 if (num
== 0) return;
1104 if (backlight
== LIGHTON
) bx
= 50;
1106 b
[3] = 0; b
[2] = 0; b
[1] = 0; b
[0] = 0;
1109 fprintf(stderr
, "Error : num is too big (%d)\n", num
);
1116 for (i
= 0 ; i
< 4 ; i
++) {
1119 int py
= y
+ (3 - i
) * dy
+ d2y
;
1120 dockapp_copyarea(parts
, pixmap
, bx
, by
, sx
, sy
, px
, py
);
1126 static void draw_binarytime(void) {
1127 int sx
= style
.binzx
;
1128 int sy
= style
.binzy
;
1129 int d1x
= style
.bind1x
;
1130 int d1y
= style
.bind1y
;
1131 int d2x
= style
.bind2x
;
1132 int d2y
= style
.bind2y
;
1134 draw_bits(timeinfos
->tm_hour
/ 10, style
.binhx
, style
.binhy
, 0, 0,
1135 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1136 draw_bits(timeinfos
->tm_hour
% 10, style
.binhx
, style
.binhy
, 1, 0,
1137 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1139 draw_bits(timeinfos
->tm_min
/ 10, style
.binmx
, style
.binmy
, 0, 0,
1140 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1141 draw_bits(timeinfos
->tm_min
% 10, style
.binmx
, style
.binmy
, 1, 0,
1142 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1144 draw_bits(timeinfos
->tm_sec
/ 10, style
.binsx
, style
.binsy
, 0, 0,
1145 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1146 draw_bits(timeinfos
->tm_sec
% 10, style
.binsx
, style
.binsy
, 1, 0,
1147 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1149 if (style
.binix
!= -1) {
1150 int wd
= timeinfos
->tm_wday
== 0 ? 7 : timeinfos
->tm_wday
;
1159 draw_bits(wd
, style
.binwx
, style
.binwy
, 0, 1,
1160 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1162 draw_bits(timeinfos
->tm_mday
/ 10, style
.bindx
, style
.bindy
, 0, 1,
1163 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1164 draw_bits(timeinfos
->tm_mday
% 10, style
.bindx
, style
.bindy
, 1, 1,
1165 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1167 draw_bits((timeinfos
->tm_mon
+ 1) / 10, style
.binox
, style
.binoy
, 0, 1,
1168 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1169 draw_bits((timeinfos
->tm_mon
+ 1) % 10, style
.binox
, style
.binoy
, 1, 1,
1170 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1175 static void parse_arguments(int argc
, char **argv
) {
1177 for (i
= 1; i
< argc
; i
++) {
1178 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h")) {
1179 print_help(argv
[0]), exit(0);
1180 } else if (!strcmp(argv
[i
], "--version") || !strcmp(argv
[i
], "-v")) {
1181 printf("%s version %s\n", PACKAGE
, VERSION
), exit(0);
1182 } else if (!strcmp(argv
[i
], "--display") || !strcmp(argv
[i
], "-d")) {
1183 display_name
= argv
[i
+ 1];
1185 } else if (!strcmp(argv
[i
], "--backlight") || !strcmp(argv
[i
], "-bl")) {
1186 backlight
= LIGHTON
;
1187 } else if (!strcmp(argv
[i
], "--light-color") || !strcmp(argv
[i
], "-lc")) {
1189 fprintf(stderr
, "%s: argument \"%s\" needs an option.\n", argv
[0], argv
[i
]), exit(1);
1190 SET_STRING(light_color
, argv
[i
+ 1]);
1192 } else if (!strcmp(argv
[i
], "--windowed") || !strcmp(argv
[i
], "-w")) {
1193 dockapp_iswindowed
= True
;
1194 } else if (!strcmp(argv
[i
], "--broken-wm") || !strcmp(argv
[i
], "-bw")) {
1195 dockapp_isbrokenwm
= True
;
1196 } else if (!strcmp(argv
[i
], "--no-blink") || !strcmp(argv
[i
], "-nb")) {
1197 switch_authorized
= False
;
1198 } else if (!strcmp(argv
[i
], "--h12") || !strcmp(argv
[i
], "-12")) {
1200 } else if (!strcmp(argv
[i
], "--time-mode") || !strcmp(argv
[i
], "-tm")) {
1202 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1203 argv
[0], argv
[i
]), exit(1);
1204 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
1205 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1206 argv
[0], argv
[i
]), exit(1);
1207 if ((integer
< 0) || (integer
> 2))
1208 fprintf(stderr
, "%s: argument %s must be in [0,2]\n",
1209 argv
[0], argv
[i
]), exit(1);
1210 time_mode
= integer
;
1212 } else if (!strcmp(argv
[i
], "--alarm-cmd") || !strcmp(argv
[i
], "-c")) {
1213 SET_STRING(command
, argv
[i
+ 1]);
1215 } else if (!strcmp(argv
[i
], "--message-cmd") || !strcmp(argv
[i
], "-mc")) {
1216 SET_STRING(msgcmd
, argv
[i
+ 1]);
1218 } else if (!strcmp(argv
[i
], "--alarm") || !strcmp(argv
[i
], "-a")) {
1219 alrm_add(&alarms
, argv
[i
+ 1]);
1221 } else if (!strcmp(argv
[i
], "--cfg-file") || !strcmp(argv
[i
], "-f")) {
1222 SET_STRING(config_file
, argv
[i
+ 1]);
1224 } else if (!strcmp(argv
[i
], "--no-locale") || !strcmp(argv
[i
], "-nl")) {
1226 } else if (!strcmp(argv
[i
], "--style") || !strcmp(argv
[i
], "-s")) {
1227 SET_STRING(style_name
, argv
[i
+ 1]);
1229 } else if (!strcmp(argv
[i
], "--style-dir") || !strcmp(argv
[i
], "-sd")) {
1230 SET_STRING(style_dir
, argv
[i
+ 1]);
1232 } else if (!strcmp(argv
[i
], "--label") || !strcmp(argv
[i
], "-l")) {
1233 SET_STRING(label
, argv
[i
+ 1]);
1235 } else if (!strcmp(argv
[i
], "--show-cal") || !strcmp(argv
[i
], "-sc")) {
1237 } else if (!strcmp(argv
[i
], "--cal-alrm") || !strcmp(argv
[i
], "-ca")) {
1241 fprintf(stderr
, "%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
1242 print_help(argv
[0]), exit(1);
1248 static void print_help(char *prog
)
1250 printf("Usage : %s [OPTIONS]\n"
1251 "%s - Window Maker digital clock dockapp\n"
1252 " -h, --help show this help text and exit\n"
1253 " -v, --version show program version and exit\n"
1254 " -d, --display <string> display to use\n"
1255 " -bl, --backlight turn on back-light\n"
1256 " -lc, --light-color <color> backlight/led colour\n"
1257 " -tm, --time-mode <mode> start with time mode (0: clock, 1: internet time, 2: binary clock)\n"
1258 " -w, --windowed run the application in windowed mode\n"
1259 " -bw, --broken-wm activate broken window manager fix\n"
1260 " -a, --alarm <HH:MM> set alarm time to HH:MM (24h clock mode)\n"
1261 " -c, --alarm-cmd <string> command to launch when alarm raises\n"
1262 " -mc, --message-cmd <string> command to launch when alarm raises and a message is associated\n"
1263 " -12, --h12 12 hours clock mode (default is 24)\n"
1264 " -s, --style <file> style to use for display\n"
1265 " -sd, --style-dir <dir> directory where styles are stored\n"
1266 " -nb, --no-blink disable blinking when alarm is raised\n"
1267 " -f, --cfgfile <filename> use 'filename' as configuration file\n"
1268 " -nl, --no-locale don't use current locale\n"
1269 " -l, --label <string> use a label instead of date\n"
1270 " -ca, --cal-alrm load calendar alarms for today\n"
1271 " -sc, --show-cal show calendar at startup/00:00\n",
1276 static void time_update(void) {
1280 timeinfos
= localtime(&tnow
);
1282 if (time_mode
== INTERNET
) {
1284 swtime
= timeinfos
->tm_hour
* 3600
1285 + timeinfos
->tm_min
* 60
1286 + timeinfos
->tm_sec
;
1288 localtmzone
= timeinfos
->tm_gmtoff
;
1290 localtmzone
= timezone
;
1292 swtime
+= localtmzone
+3600;
1293 if (timeinfos
->tm_isdst
) swtime
-= 3600;
1299 if (swtime
< 0) swtime
+= 1000;
1304 static Bool
raise_alarm(void) {
1305 if ((timeinfos
->tm_hour
== 0) &&
1306 (timeinfos
->tm_min
== 0) &&
1307 (timeinfos
->tm_sec
== 0)) {
1308 if (showcal
) show_cal();
1309 if (calalrms
) reload_alarms();
1312 Alarm
*alrm
= alarms
;
1313 char thistime
[MAXSTRLEN
+ 1];
1314 char thisdate
[MAXSTRLEN
+ 1];
1316 strftime(thistime
, MAXSTRLEN
, "%H:%M", timeinfos
);
1317 strftime(thisdate
, MAXSTRLEN
, "%u", timeinfos
);
1319 if (alrm
->on
&& (strcmp(thistime
, alrm
->alarm_time
) == 0)) {
1320 message
= alrm
->message
;
1321 if (alrm
->alarm_date
) {
1322 if (strcmp(thisdate
, alrm
->alarm_date
) == 0)
1337 static Bool
filestat(const char *filename
, time_t *time
, int mode
) {
1341 if (stat(filename
, &s
) == -1) {
1342 if (*time
== 0) return False
;
1346 case MTIME
: t
= s
.st_mtime
; break;
1347 case ATIME
: t
= s
.st_atime
; break;
1359 static int my_system(char *cmd
, char *opt
) {
1361 extern char **environ
;
1363 if (cmd
== NULL
) return 1;
1365 if (pid
== -1) return -1;
1370 char *thiscommand
= xmalloc(strlen(cmd
)
1371 + (opt
? strlen(opt
) + 4 : 1));
1372 sprintf(thiscommand
, "%s %s%s%s", cmd
,
1378 argv
[2] = thiscommand
;
1380 execve("/bin/sh", argv
, environ
);
1390 void *xmalloc(size_t size
) {
1391 void *ret
= malloc(size
);
1393 perror("malloc() ");
1400 char *xstrdup(const char *string
) {
1401 char *ret
= string
? strdup(string
) : NULL
;
1402 if (string
&& (ret
== NULL
)) {
1403 perror("strdup() ");
1410 static void put_alrm(Alarm
**list
, const char *entry
,
1411 char *time
, char *date
, char *ison
, char *mesg
, Bool cal
) {
1416 lst
= xmalloc(sizeof(Alarm
));
1419 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1420 while ( (lst
->next
) && ok
) {
1422 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1425 lst
->next
= xmalloc(sizeof(Alarm
));
1428 lst
->entry
= xstrdup(entry
);
1429 lst
->alarm_time
= time
? xstrdup(time
) : NULL
;
1430 lst
->alarm_date
= date
? xstrdup(date
) : NULL
;
1431 lst
->on
= ison
? getbool(ison
) : True
;
1432 lst
->message
= mesg
? xstrdup(mesg
) : NULL
;
1438 static void alrm_add(Alarm
**list
, const char *value
) {
1439 char *time
= NULL
, *date
= NULL
, *ison
= NULL
, *mesg
= NULL
, *at
;
1440 char *tokstr
= xstrdup(value
);
1441 char *toksav
= tokstr
;
1443 if (! value
) return;
1444 at
= strchr(value
, '@');
1445 if (at
) ison
= strtok(tokstr
, "@");
1446 time
= strtok(at
? NULL
: tokstr
, "-.");
1447 if (strchr(value
, '-')) date
= strtok(NULL
, ".");
1448 mesg
= strtok(NULL
, "\n\0");
1450 put_alrm(list
, value
, time
, date
, ison
, mesg
, False
);
1456 static void free_alrm(Alarm
**list
) {
1457 Alarm
*lst
= *list
, *next
;
1461 FREE(lst
->alarm_time
);
1462 FREE(lst
->alarm_date
);
1471 static Bool
alarms_on(Alarm
*list
) {
1475 if (alrm
->on
) return True
;
1482 static void switch_alarms(Alarm
*list
) {
1486 if (alarms_on(list
)) set_to
= False
;
1488 char *tokstr
= xstrdup(alrm
->entry
);
1489 char *toksav
= tokstr
;
1490 Bool is_on
= alrm
->cal
|| getbool(strtok(tokstr
, "@"));
1492 if ((is_on
&& set_to
) || (!set_to
)) {
1501 static Bool
getbool(char *value
) {
1503 for (i
= 0 ; value
[i
] ; i
++) value
[i
] = tolower(value
[i
]);
1504 if (strcmp(value
, "0") == 0) return False
;
1505 if (strcmp(value
, "1") == 0) return True
;
1506 if (strcmp(value
, "true") == 0) return True
;
1507 if (strcmp(value
, "false") == 0) return False
;
1508 if (strcmp(value
, "yes") == 0) return True
;
1509 if (strcmp(value
, "no") == 0) return False
;
1510 if (strcmp(value
, "on") == 0) return True
;
1511 if (strcmp(value
, "off") == 0) return False
;
1512 printf("Error in converting \"%s\" to boolean value.\n", value
);
1517 static Bool
load_cfgfile(void) {
1519 int i
= 0, ok
= True
;
1520 char line
[MAXSTRLEN
+ 1];
1523 if ((file
= fopen(config_file
, "r")) == NULL
) {
1524 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1525 printf("Unable to open configuration file \"%s\".\n", config_file
);
1528 if (ok
&& (! filestat(config_file
, &config_mtime
, MTIME
))) {
1533 if (alarms
) free_alrm(&alarms
);
1534 while (! feof(file
)) {
1537 if (!fgets(line
, MAXSTRLEN
, file
))
1544 if (line
[n
- 1] == '\n') line
[n
- 1] = 0;
1545 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1546 value
= strchr(line
, '=');
1547 if (! value
) continue;
1549 while ((value
[0] != 0) && (value
[0] == ' ')) value
++;
1550 if (value
[0] == 0) continue;
1552 if (strncmp(line
, "Backlight", 9) == 0) {
1553 backlight
= getbool(value
) ? LIGHTON
: LIGHTOFF
;
1554 } else if (strncmp(line
, "Color", 5) == 0) {
1555 SET_STRING(light_color
, value
);
1556 } else if (strncmp(line
, "Alarm", 5) == 0) {
1557 alrm_add(&alarms
, value
);
1558 } else if (strncmp(line
, "Command", 7) == 0) {
1559 SET_STRING(command
, value
);
1560 } else if (strncmp(line
, "MessageCmd", 10) == 0) {
1561 SET_STRING(msgcmd
, value
);
1562 } else if (strncmp(line
, "Blink", 5) == 0) {
1563 switch_authorized
= getbool(value
);
1564 } else if (strncmp(line
, "H12", 3) == 0) {
1565 h12
= getbool(value
);
1566 } else if (strncmp(line
, "Locale", 6) == 0) {
1567 use_locale
= getbool(value
);
1568 } else if (strncmp(line
, "StyleDir", 8) == 0) {
1569 SET_STRING(style_dir
, value
);
1570 } else if (strncmp(line
, "Style", 5) == 0) {
1571 SET_STRING(style_name
, value
);
1572 } else if (strncmp(line
, "TimeMode", 5) == 0) {
1573 time_mode
= atoi(value
);
1574 } else if (strncmp(line
, "ShowCal", 7) == 0) {
1575 showcal
= getbool(value
);
1576 } else if (strncmp(line
, "CalAlrms", 8) == 0) {
1577 calalrms
= getbool(value
);
1579 printf("Error in %s at line %d :\n[%s].\n", config_file
, i
, line
);
1582 if (calalrms
) load_calalrms();
1584 } else if (calalrms
&& cal_alrms_chg()) {
1591 static char *get_calend_file(int type
) {
1592 char *Home
= robust_home();
1593 char *filename
= xmalloc(
1595 strlen(DEFAULT_CONFIGDIR
) +
1600 sprintf(filename
, "%s/%s/%04d-%02d-%02d",
1603 timeinfos
->tm_year
+ 1900,
1604 timeinfos
->tm_mon
+ 1,
1605 timeinfos
->tm_mday
);
1608 sprintf(filename
, "%s/%s/XXXX-%02d-%02d",
1611 timeinfos
->tm_mon
+ 1,
1612 timeinfos
->tm_mday
);
1615 sprintf(filename
, "%s/%s/XXXX-XX-%02d",
1618 timeinfos
->tm_mday
);
1626 static int cal_alrms_chg(void) {
1627 static time_t cal_u_mtime
= 0;
1628 static time_t cal_y_mtime
= 0;
1629 static time_t cal_m_mtime
= 0;
1630 char *cal_u_fname
= NULL
;
1631 char *cal_y_fname
= NULL
;
1632 char *cal_m_fname
= NULL
;
1633 int chg_u
, chg_y
, chg_m
;
1635 if (! calalrms
) return False
;
1636 cal_u_fname
= get_calend_file(1);
1637 cal_y_fname
= get_calend_file(2);
1638 cal_m_fname
= get_calend_file(3);
1639 chg_u
= filestat(cal_u_fname
, &cal_u_mtime
, MTIME
);
1640 chg_y
= filestat(cal_y_fname
, &cal_y_mtime
, MTIME
);
1641 chg_m
= filestat(cal_m_fname
, &cal_m_mtime
, MTIME
);
1645 if (chg_u
|| chg_y
|| chg_m
) return True
;
1650 static void load_cal_file(int type
) {
1652 char *calend_file
= get_calend_file(type
);
1655 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1656 while (! feof(file
)) {
1657 char line
[MAXSTRLEN
+ 1];
1659 if (!fgets(line
, MAXSTRLEN
, file
))
1662 if ( (line
[0] != 0) && (strncmp(line
, "@ ", 2) == 0) ) {
1663 char time
[MAXSTRLEN
+ 1];
1664 sscanf(line
, "@ %s ", time
);
1665 put_alrm(&alarms
, line
, time
, NULL
, NULL
, line
+ 8, True
);
1674 static void load_calalrms(void) {
1676 for (i
= 1 ; i
< 4 ; i
++) load_cal_file(i
);
1680 static void reload_alarms(void) {
1682 char line
[MAXSTRLEN
+ 1];
1685 if (alarms
) free_alrm(&alarms
);
1686 if ((file
= fopen(config_file
, "r")) == NULL
) {
1687 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1688 printf("Unable to open configuration file \"%s\".\n", config_file
);
1690 while (! feof(file
)) {
1693 if (!fgets(line
, MAXSTRLEN
, file
))
1699 if (line
[n
- 1] == '\n') line
[n
- 1] = 0;
1700 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1701 value
= strchr (line
, '=') + 1;
1702 while ((value
[0] == ' ') && (value
[0] != 0)) value
++;
1703 if (value
[0] == 0) continue;
1705 if (strncmp(line
, "Alarm", 5) == 0) alrm_add(&alarms
, value
);
1708 if (calalrms
) load_calalrms();
1712 static void show_cal_file(int type
) {
1716 char *calend_file
= get_calend_file(type
);
1718 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1719 while (! feof(file
)) {
1720 char line
[MAXSTRLEN
+ 1];
1722 if (!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(void) {
1744 for (i
= 1 ; i
< 4 ; i
++) show_cal_file(i
);
1748 static char *robust_home(void) {
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 (getpwuid(getuid()))
1756 return getpwuid(getuid())->pw_dir
;