1 /*****************************************************************************/
4 /* Shows local time in different timezones + JD + Sidereal time + */
5 /* internet time + local date and time. */
7 /* Jan Lindblom <99jl@home.se> (http://www.geocities.com/~jl1n/) */
9 /* wmtz.c was derived from: */
13 /* Multi-function system monitor */
14 /* Dave Clark (clarkd@skynet.ca) (http://www.neotokyo.org/illusion) */
15 /* Martijn Pieterse (pieterse@xs4all.nl) (http://windowmaker.mezaway.org) */
16 /* and Antoine Nulle (warp@xs4all.nl) (http://windowmaker.mezaway.org) */
18 /* This software is licensed through the GNU General Public Licence. */
19 /* Read the COPYING file for details. */
21 /*****************************************************************************/
33 #include <sys/types.h>
38 #include <X11/extensions/shape.h>
40 #include "../wmgeneral/wmgeneral.h"
41 #include "../wmgeneral/misc.h"
43 #include "wmtz_mono.xpm"
49 #define WMTZ_VERSION "0.7"
54 #define ABOUT "xmessage -center -buttons \"Close\" \"WMTZ - Window Maker Time Zone dockapp v0.7
55 http://www.geocities.com/jl1n/wmtz/wmtz.html\""
63 char label
[10]; /* Time zone designation */
64 int diff
; /* Time zone diff. from UT in hours */
65 double epoch
; /* Epoch (for JD) */
66 char tz
[256]; /* TZ environment variable string */
67 } timezone_t
; /* ...numbers of days to subtract from JD */
74 double longitude
= 0.0;
75 double latitude
= 0.0;
76 static struct tm
*clk
;
83 char wmtz_mask_bits
[64*64];
84 int wmtz_mask_width
= 64;
85 int wmtz_mask_height
= 64;
87 extern char *tzname
[2];
88 static char originalTZ
[64];
91 * Function declarations
94 void printversion(void);
95 void BlitString(char *name
, int x
, int y
);
96 void wmtz_routine(int, char **);
97 int ReadConfigInt(FILE *fp
, char *setting
, int *value
);
98 int ReadConfigString(FILE *fp
, char *setting
, char *value
);
99 int Read_Config_File(char *filename
);
100 void range(double *val
, double ran
);
101 void siderealTime(double jde
, int *result
, int mode
);
102 double julianDay(int year
, int month
, double day
, double hour
,
103 double minute
, double second
, int julian
);
104 int calendarDate(double jd
, int *year
, int *month
, double *day
);
106 void errH(int printErrno
, int exitCode
, const char *msg
, ...);
107 void handleTheMenu(int but_stat
);
108 double jdn(time_t curtime
);
111 /*****************************************************************************\
113 \*****************************************************************************/
114 int main(int argc
, char *argv
[]) {
119 /* Store away the executable name for error messages */
120 if ( (pname
= strrchr( argv
[0], '/' )) == NULL
)
125 /* Store away the TZ environment variable, if set */
126 if ( (envbuf
= getenv("TZ")) != NULL
)
128 //Write TZ=envbuf into originalTZ
129 (void) sprintf(originalTZ
, "TZ=%s", envbuf
);
133 // Set originalTZ to TZ erase TZ env.
134 (void) sprintf(originalTZ
, "TZ");
137 /* Parse Command Line */
138 for (i
=1; i
<argc
; i
++) {
144 if (strcmp(arg
+1, "display")) {
150 if (strcmp(arg
+1, "geometry")) {
156 if (strcmp(arg
+1, "jd")) {
173 uconfig_file
= strdup(argv
[i
+1]);
174 if (uconfig_file
== NULL
)
175 errH(1, 1, "strdup");
182 defedit
= strdup(argv
[i
+1]);
184 errH(1, 1, "strdup");
196 month
[0] = "JAN"; month
[1] = "FEB"; month
[2] = "MAR";
197 month
[3] = "APR"; month
[4] = "MAY"; month
[5] = "JUN";
198 month
[6] = "JUL"; month
[7] = "AUG"; month
[8] = "SEP";
199 month
[9] = "OUT"; month
[10] = "NOV"; month
[11] = "DEC";
201 week_day
[0] = "SUNDAY ";
202 week_day
[1] = "MONDAY ";
203 week_day
[2] = "TUESDAY ";
204 week_day
[3] = "WEDNESDAY";
205 week_day
[4] = "THURSDAY ";
206 week_day
[5] = "FRIDAY ";
207 week_day
[6] = "SATURDAY ";
209 wmtz_routine(argc
, argv
);
215 /*****************************************************************************\
216 |* wmtz_routine - Creates the wmtz window. *|
217 \*****************************************************************************/
218 void wmtz_routine(int argc
, char **argv
)
220 int j
= 0,k
= 0, hour
= 0, i
= 0;
221 int sid
[2], clicked
= 0, but_stat
= -1;
228 char blitstr
[STRSIZE
];
233 fprintf(stderr
, "Starting monochrome version.\n");
234 createXBMfromXPM(wmtz_mask_bits
, wmtz_mono_xpm
,
235 wmtz_mask_width
, wmtz_mask_height
);
237 openXwindow(argc
, argv
, wmtz_mono_xpm
, wmtz_mask_bits
,
238 wmtz_mask_width
, wmtz_mask_height
);
242 createXBMfromXPM(wmtz_mask_bits
, wmtz_master_xpm
,
243 wmtz_mask_width
, wmtz_mask_height
);
245 openXwindow(argc
, argv
, wmtz_master_xpm
, wmtz_mask_bits
,
246 wmtz_mask_width
, wmtz_mask_height
);
249 memset(&zone
, 0, sizeof(zone
));
251 AddMouseRegion(0, 5, 6, 58, 16);
252 AddMouseRegion(1, 5, 16, 58, 26);
253 AddMouseRegion(2, 5, 26, 58, 36);
254 AddMouseRegion(3, 5, 36, 58, 46);
255 AddMouseRegion(4, 5, 46, 58, 56);
257 /* Read config file */
258 if (uconfig_file
!= NULL
)
260 /* user-specified config file */
261 fprintf(stderr
, "Using user-specified config file '%s'.\n",
263 config_file
= strdup(uconfig_file
);
265 Read_Config_File(config_file
);
269 home
= getenv("HOME");
270 config_file
= malloc( strlen(home
) + 9 );
271 if (config_file
== NULL
)
272 errH(1, 1, "malloc");
274 sprintf(config_file
, "%s/.wmtzrc", home
);
276 if (!Read_Config_File(config_file
))
278 /* Fall back to /etc/wmtzrc */
280 config_file
= malloc( 12 );
281 if (config_file
== NULL
)
282 errH(1, 1, "malloc");
284 sprintf(config_file
, "/etc/wmtzrc");
286 fprintf(stderr
, "Using /etc/wmtzrc as config file.\n");
288 Read_Config_File(config_file
);
293 prevtime
= time(0) - 1;
297 waitpid(0, NULL
, WNOHANG
);
299 /* If wmtz have been mouse-clicked, show menu */
302 BlitString("MENU: ", 5, (11*(0)) + 5);
303 BlitString(" WMTZ ", 5, (11*(1)) + 5);
304 BlitString(" CONFIG ", 5, (11*(2)) + 5);
305 BlitString(" RESTART ", 5, (11*(3)) + 5);
306 BlitString(" QUIT ", 5, (11*(4)) + 5);
308 else if ( (curtime
= time(0)) > prevtime
)
312 /* Update the display */
315 /* Display empty line */
316 if (strncmp( zone
[j
].label
, "xxx", 3) == 0 )
318 BlitString(" ", 5, (11*(j
-1)) + 5);
321 /* Display local day/mon/year */
322 else if (strncmp( zone
[j
].label
, "DATE", 4) == 0 )
324 clk
= localtime(&curtime
);
325 while(clk
->tm_year
>99) clk
->tm_year
-=100;
326 snprintf(blitstr
, STRSIZE
,"%s %02d.%02d",
327 month
[clk
->tm_mon
],clk
->tm_mday
,clk
->tm_year
);
328 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
331 /* Display local weekday */
332 else if (strncmp( zone
[j
].label
, "WDAY", 4) == 0 )
334 clk
= localtime(&curtime
);
335 snprintf(blitstr
, STRSIZE
,"%s",week_day
[clk
->tm_wday
]);
336 BlitString(blitstr
, 4, (11*(j
-1)) + 5);
339 /* Display more precise internet time */
340 else if (strncmp( zone
[j
].label
,"@", 1) == 0 )
342 /* Calculate Internet time */
343 swatch_beats
= (float)(((curtime
+3600)%86400)/86.4);
344 snprintf (blitstr
, STRSIZE
, "@:%7.3f", swatch_beats
);
345 BlitString (blitstr
, 5, (11*(j
-1)) + 5);
348 /* Display Julian Day Number */
349 else if (strncmp( zone
[j
].label
, "JDN", 3) == 0 )
351 clk
= gmtime(&curtime
);
352 /* Calculate Julin Day Number */
353 jd
= jdn(curtime
) - zone
[j
].epoch
;
354 snprintf(blitstr
, STRSIZE
, "%10f", jd
);
355 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
358 /* Display Local Mean Sidereal Time */
359 else if (strncmp( zone
[j
].label
, "LMST", 3) == 0 )
361 clk
= gmtime(&curtime
);
363 siderealTime( jd
, sid
, LMST
);
364 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i","LST:", sid
[0], sid
[1]);
365 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
368 /* Display Greenwich Mean Sidereal Time */
369 else if (strncmp( zone
[j
].label
, "GMST", 3) == 0 )
371 clk
= gmtime(&curtime
);
373 siderealTime( jd
, sid
, GMST
);
374 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i","GST:", sid
[0], sid
[1]);
375 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
378 /* Display local time */
379 else if (strncmp( zone
[j
].label
, "LOCAL", 5) == 0 )
381 clk
= localtime(&curtime
);
382 strncpy(buf
, tzname
[0], 3);
393 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i",buf
,hour
,clk
->tm_min
);
394 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
397 /* Display time in specified time zone */
398 else if (strncmp( zone
[j
].label
, "TZONE", 4) == 0 )
402 clk
= localtime(&curtime
);
404 strncpy(buf
, tzname
[0], 3);
413 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i", buf
,
414 clk
->tm_hour
, clk
->tm_min
);
415 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
417 /* Reset TZ environment variable to old value */
421 /* Display time in specified time zone without TZ env. var. */
424 clk
= gmtime(&curtime
);
425 strncpy(buf
, zone
[j
].label
, 3);
434 hour
= clk
->tm_hour
- zone
[j
].diff
;
441 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i",buf
,hour
,clk
->tm_min
);
442 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
449 while (XPending(display
))
451 XNextEvent(display
, &Event
);
458 XCloseDisplay(display
);
462 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
466 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
467 if (but_stat
== i
&& but_stat
>= 0)
469 if ( clicked
) /* The menu is up */
471 handleTheMenu(but_stat
);
474 else /* Show the menu instead of time */
490 /*****************************************************************************\
492 \*****************************************************************************/
493 void handleTheMenu(int but_stat
)
506 /* Figure out what editor to use */
507 if ( defedit
== NULL
)
509 ed
= getenv("XEDITOR");
517 editor
= malloc( strlen(ed
)+strlen(config_file
)+2 );
518 if ( editor
== NULL
)
519 errH(1, 1, "malloc");
520 sprintf(editor
, "%s %s", ed
, config_file
);
521 waitpid( execCommand(editor
), NULL
, 0 );
522 Read_Config_File(config_file
);
526 Read_Config_File(config_file
);
537 /*****************************************************************************\
538 |* ReadConfigSetting *|
539 \*****************************************************************************/
540 int ReadConfigString(FILE *fp
, char *setting
, char *value
)
554 snprintf(str
,1024, "%s=", setting
);
557 fseek(fp
, 0, SEEK_SET
);
562 if (!fgets(buf
, 512, fp
))
568 for (i
=0; i
!=len
; i
++)
572 /* printf("Scanning '%s'...\n", buf); */
573 if ( strncmp(buf
, str
, strlen(str
)) == 0)
575 /* found our setting */
577 for(i
=0; i
!=slen
; i
++)
590 /*****************************************************************************\
592 \*****************************************************************************/
593 int ReadConfigInt(FILE *fp
, char *setting
, int *value
)
597 if (ReadConfigString(fp
, setting
, (char *) &buf
))
607 /*****************************************************************************\
608 |* ReadConfigDouble *|
609 \*****************************************************************************/
610 int ReadConfigDouble(FILE *fp
, char *setting
, double *value
)
614 if (ReadConfigString(fp
, setting
, (char *) &buf
))
624 /*****************************************************************************\
625 |* Read_Config_File *|
626 \*****************************************************************************/
627 int Read_Config_File( char *filename
)
632 fp
= fopen(filename
, "r");
635 ReadConfigString(fp
, "time1", zone
[1].label
);
636 ReadConfigString(fp
, "time2", zone
[2].label
);
637 ReadConfigString(fp
, "time3", zone
[3].label
);
638 ReadConfigString(fp
, "time4", zone
[4].label
);
639 ReadConfigString(fp
, "time5", zone
[5].label
);
640 ReadConfigInt(fp
, "utdiff1", &zone
[1].diff
);
641 ReadConfigInt(fp
, "utdiff2", &zone
[2].diff
);
642 ReadConfigInt(fp
, "utdiff3", &zone
[3].diff
);
643 ReadConfigInt(fp
, "utdiff4", &zone
[4].diff
);
644 ReadConfigInt(fp
, "utdiff5", &zone
[5].diff
);
645 ReadConfigDouble(fp
, "utdiff1", &zone
[1].epoch
);
646 ReadConfigDouble(fp
, "utdiff2", &zone
[2].epoch
);
647 ReadConfigDouble(fp
, "utdiff3", &zone
[3].epoch
);
648 ReadConfigDouble(fp
, "utdiff4", &zone
[4].epoch
);
649 ReadConfigDouble(fp
, "utdiff5", &zone
[5].epoch
);
651 ReadConfigString(fp
, "utdiff1", temp
);
652 sprintf(zone
[1].tz
, "TZ=%s", temp
);
653 ReadConfigString(fp
, "utdiff2", temp
);
654 sprintf(zone
[2].tz
, "TZ=%s", temp
);
655 ReadConfigString(fp
, "utdiff3", temp
);
656 sprintf(zone
[3].tz
, "TZ=%s", temp
);
657 ReadConfigString(fp
, "utdiff4", temp
);
658 sprintf(zone
[4].tz
, "TZ=%s", temp
);
659 ReadConfigString(fp
, "utdiff5", temp
);
660 sprintf(zone
[5].tz
, "TZ=%s", temp
);
662 ReadConfigDouble(fp
, "longitude", &longitude
);
663 /* ReadConfigDouble(fp, "latitude", &latitude); */
670 errH(1, 0, "Unable to open %s", filename
);
676 /*****************************************************************************\
677 |* BlitString - Blits a string at given coordinates. *|
678 \*****************************************************************************/
679 void BlitString(char *name
, int x
, int y
)
686 for (i
=0; name
[i
]; i
++)
689 c
= toupper(name
[i
]);
690 if (c
>= 'A' && c
<= 'Z')
693 copyXPMArea(c
* CHAR_WIDTH
, 74, CHAR_WIDTH
, 8, k
, y
);
696 else if ( c
>= '0' && c
<= ':')
699 copyXPMArea(c
* CHAR_WIDTH
, 64, CHAR_WIDTH
, 8, k
, y
);
702 else if (c
== ';') /* used as a slim ':' */
704 copyXPMArea(60, 64, CHAR_WIDTH
, 8, k
, y
);
709 copyXPMArea(115, 64, 4, 8, k
, y
);
714 copyXPMArea(108, 64, CHAR_WIDTH
, 8, k
, y
);
717 else /* print a ' ' */
719 copyXPMArea(120, 64, CHAR_WIDTH
, 8, k
, y
);
726 /*****************************************************************************\
728 \*****************************************************************************/
731 fprintf(stderr
, "\nwmtz - shows local time around the world and more.\n");
732 fprintf(stderr
, "See ~/.wmtzrc or /etc/wmtzrc for configuration.\n\n");
733 fprintf(stderr
, "Usage:\n");
734 fprintf(stderr
, " -display <display name>\n");
735 fprintf(stderr
, " -e <editor> use specified editor\n");
736 fprintf(stderr
, " -geometry +XPOS+YPOS initial window position\n");
737 fprintf(stderr
, " -jd Julian<->Date conversion\n");
738 fprintf(stderr
, " -c <filename> use specified config file\n");
739 fprintf(stderr
, " -m start monochrome version\n");
740 fprintf(stderr
, " -h this help screen\n");
741 fprintf(stderr
, " -v print the version number\n");
742 fprintf(stderr
, "\n");
746 /*****************************************************************************\
748 \*****************************************************************************/
749 void printversion(void)
751 fprintf(stderr
, "wmtz v%s\n", WMTZ_VERSION
);
755 /*****************************************************************************\
756 |* range - Put val in 0<->ran interval. *|
757 \*****************************************************************************/
758 void range (double *val
, double ran
)
760 *val
-= ran
*floor(*val
/ran
);
767 /*****************************************************************************\
768 |* jdn - converts a time_t to Julian Day *|
769 \*****************************************************************************/
770 double jdn(time_t curtime
)
772 return (curtime
/86400.0 + 2440587.5);
775 /*****************************************************************************\
776 |* siderealTime - Gives sidereal time from JD. *|
777 \*****************************************************************************/
778 void siderealTime( double jde
, int *result
, int mode
)
780 double t
, t2
, t3
, ts
;
782 t
= (jde
- 2451545.0)/36525.0;
786 /* Expression from "Astronomical Algorithms" by J. Meeus */
787 ts
= 280.46061837 + 360.98564736629 * ( jde
- 2451545.0 )
788 + 0.000387933 * t2
- t3
/38710000.0;
793 /* If local time add one hour for every 15 degree in longitude */
796 ts
+= longitude
/15.0;
801 result
[1] = (int)(60 *(ts
- result
[0]));
805 /*****************************************************************************\
806 |* julianDay - Gives JD from date. *|
807 \*****************************************************************************/
808 double julianDay( int year
, int month
, double day
, double hour
,
809 double minute
, double second
, int julian
)
814 day
= day
+ hour
/24.0 + minute
/1440.0 + second
/86400.0;
822 /* If the date is a Julian calendar date, set julian to TRUE */
827 else /* If Gregorian calendar date, julian should be FALSE */
832 c
= 365.25 * (year
+ 4716);
833 d
= 30.6001 * (month
+ 1);
834 jd
= c
+ d
+ day
+ b
- 1524.5;
840 /*****************************************************************************\
841 |* calendarDate - Gives date from JD. Only Gregorian calendar dates. *|
842 \*****************************************************************************/
843 int calendarDate( double jd
, int *year
, int *month
, double *day
)
845 double a
, b
, frac
, ij
, alfa
, beta
, c
, d
, e
, f
;
860 alfa
= floor((ij
- 1867216.25)/36524.25);
861 beta
= floor(alfa
/4);
862 a
= ij
+ 1 + alfa
- beta
;
866 c
= floor((b
- 122.1)/365.25);
867 d
= floor(365.25 * c
);
868 e
= floor((b
- d
)/30.6001);
869 f
= floor(30.6001 * e
);
871 *day
= b
- d
- f
+ frac
;
875 else if (e
== 14 || e
== 15)
882 else if (*month
== 1 || *month
== 2)
891 /*****************************************************************************\
893 \*****************************************************************************/
896 int conv
, y
, m
, d
, h
, min
, sec
;
899 printf(" 1 : Date to JD.\n 2 : JD to date.\n");
900 printf("Choose conversion (1 or 2): ");
905 printf("Enter UT date with time (YYYY,MM,DD,hh:mm:ss): ");
906 scanf("%d,%d,%d,%d:%d:%d", &y
, &m
, &d
, &h
, &min
, &sec
);
907 printf("\nJulian Day: %f\n", julianDay( y
, m
, d
, h
, min
, sec
, 0 ) );
911 printf("Enter Julian Day Number: ");
913 if ( !calendarDate( jd
, &y
, &m
, &day
) )
915 printf("Conversion error! Negative JD not allowed.\n");
919 printf("\nGregorian date: %d-%2.2d-%2.4f\n", y
, m
, day
);
923 printf("Invalid choice! Try again, please...\n");
929 /*****************************************************************************\
931 \*****************************************************************************/
932 void errH(int printErrno
, int exitCode
, const char *msg
, ...)
938 /* Put the name of the program first */
944 vsprintf(buf
+strlen(buf
), msg
, arg
);
946 sprintf(buf
+strlen(buf
), ": %s", strerror(error
));