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 <libdockapp/wmgeneral.h>
41 #include <libdockapp/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 http://www.geocities.com/jl1n/wmtz/wmtz.html\""
62 char label
[10]; /* Time zone designation */
63 int diff
; /* Time zone diff. from UT in hours */
64 double epoch
; /* Epoch (for JD) */
65 char tz
[256]; /* TZ environment variable string */
66 } timezone_t
; /* ...numbers of days to subtract from JD */
73 double longitude
= 0.0;
74 double latitude
= 0.0;
75 static struct tm
*clk
;
82 char wmtz_mask_bits
[64*64];
83 int wmtz_mask_width
= 64;
84 int wmtz_mask_height
= 64;
86 extern char *tzname
[2];
87 static char originalTZ
[64];
90 * Function declarations
93 void printversion(void);
94 void BlitString(char *name
, int x
, int y
);
95 void wmtz_routine(int, char **);
96 int ReadConfigInt(FILE *fp
, char *setting
, int *value
);
97 int ReadConfigString(FILE *fp
, char *setting
, char *value
);
98 int Read_Config_File(char *filename
);
99 void range(double *val
, double ran
);
100 void siderealTime(double jde
, int *result
, int mode
);
101 double julianDay(int year
, int month
, double day
, double hour
,
102 double minute
, double second
, int julian
);
103 int calendarDate(double jd
, int *year
, int *month
, double *day
);
105 void errH(int printErrno
, int exitCode
, const char *msg
, ...);
106 void handleTheMenu(int but_stat
);
107 double jdn(time_t curtime
);
110 /*****************************************************************************\
112 \*****************************************************************************/
113 int main(int argc
, char *argv
[]) {
118 /* Store away the executable name for error messages */
119 if ( (pname
= strrchr( argv
[0], '/' )) == NULL
)
124 /* Store away the TZ environment variable, if set */
125 if ( (envbuf
= getenv("TZ")) != NULL
)
127 //Write TZ=envbuf into originalTZ
128 (void) sprintf(originalTZ
, "TZ=%s", envbuf
);
132 // Set originalTZ to TZ erase TZ env.
133 (void) sprintf(originalTZ
, "TZ");
136 /* Parse Command Line */
137 for (i
=1; i
<argc
; i
++) {
143 if (strcmp(arg
+1, "display")) {
149 if (strcmp(arg
+1, "geometry")) {
155 if (strcmp(arg
+1, "jd")) {
172 uconfig_file
= strdup(argv
[i
+1]);
173 if (uconfig_file
== NULL
)
174 errH(1, 1, "strdup");
181 defedit
= strdup(argv
[i
+1]);
183 errH(1, 1, "strdup");
195 month
[0] = "JAN"; month
[1] = "FEB"; month
[2] = "MAR";
196 month
[3] = "APR"; month
[4] = "MAY"; month
[5] = "JUN";
197 month
[6] = "JUL"; month
[7] = "AUG"; month
[8] = "SEP";
198 month
[9] = "OUT"; month
[10] = "NOV"; month
[11] = "DEC";
200 week_day
[0] = "SUNDAY ";
201 week_day
[1] = "MONDAY ";
202 week_day
[2] = "TUESDAY ";
203 week_day
[3] = "WEDNESDAY";
204 week_day
[4] = "THURSDAY ";
205 week_day
[5] = "FRIDAY ";
206 week_day
[6] = "SATURDAY ";
208 wmtz_routine(argc
, argv
);
214 /*****************************************************************************\
215 |* wmtz_routine - Creates the wmtz window. *|
216 \*****************************************************************************/
217 void wmtz_routine(int argc
, char **argv
)
219 int j
= 0,k
= 0, hour
= 0, i
= 0;
220 int sid
[2], clicked
= 0, but_stat
= -1;
227 char blitstr
[STRSIZE
];
232 fprintf(stderr
, "Starting monochrome version.\n");
233 createXBMfromXPM(wmtz_mask_bits
, wmtz_mono_xpm
,
234 wmtz_mask_width
, wmtz_mask_height
);
236 openXwindow(argc
, argv
, wmtz_mono_xpm
, wmtz_mask_bits
,
237 wmtz_mask_width
, wmtz_mask_height
);
241 createXBMfromXPM(wmtz_mask_bits
, wmtz_master_xpm
,
242 wmtz_mask_width
, wmtz_mask_height
);
244 openXwindow(argc
, argv
, wmtz_master_xpm
, wmtz_mask_bits
,
245 wmtz_mask_width
, wmtz_mask_height
);
248 memset(&zone
, 0, sizeof(zone
));
250 AddMouseRegion(0, 5, 6, 58, 16);
251 AddMouseRegion(1, 5, 16, 58, 26);
252 AddMouseRegion(2, 5, 26, 58, 36);
253 AddMouseRegion(3, 5, 36, 58, 46);
254 AddMouseRegion(4, 5, 46, 58, 56);
256 /* Read config file */
257 if (uconfig_file
!= NULL
)
259 /* user-specified config file */
260 fprintf(stderr
, "Using user-specified config file '%s'.\n",
262 config_file
= strdup(uconfig_file
);
264 Read_Config_File(config_file
);
268 home
= getenv("HOME");
269 config_file
= malloc( strlen(home
) + 9 );
270 if (config_file
== NULL
)
271 errH(1, 1, "malloc");
273 sprintf(config_file
, "%s/.wmtzrc", home
);
275 if (!Read_Config_File(config_file
))
277 /* Fall back to /etc/wmtzrc */
279 config_file
= malloc( 12 );
280 if (config_file
== NULL
)
281 errH(1, 1, "malloc");
283 sprintf(config_file
, "/etc/wmtzrc");
285 fprintf(stderr
, "Using /etc/wmtzrc as config file.\n");
287 Read_Config_File(config_file
);
292 prevtime
= time(0) - 1;
296 waitpid(0, NULL
, WNOHANG
);
298 /* If wmtz have been mouse-clicked, show menu */
301 BlitString("MENU: ", 5, (11*(0)) + 5);
302 BlitString(" WMTZ ", 5, (11*(1)) + 5);
303 BlitString(" CONFIG ", 5, (11*(2)) + 5);
304 BlitString(" RESTART ", 5, (11*(3)) + 5);
305 BlitString(" QUIT ", 5, (11*(4)) + 5);
307 else if ( (curtime
= time(0)) > prevtime
)
311 /* Update the display */
314 /* Display empty line */
315 if (strncmp( zone
[j
].label
, "xxx", 3) == 0 )
317 BlitString(" ", 5, (11*(j
-1)) + 5);
320 /* Display local day/mon/year */
321 else if (strncmp( zone
[j
].label
, "DATE", 4) == 0 )
323 clk
= localtime(&curtime
);
324 while(clk
->tm_year
>99) clk
->tm_year
-=100;
325 snprintf(blitstr
, STRSIZE
,"%s %02d.%02d",
326 month
[clk
->tm_mon
],clk
->tm_mday
,clk
->tm_year
);
327 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
330 /* Display local weekday */
331 else if (strncmp( zone
[j
].label
, "WDAY", 4) == 0 )
333 clk
= localtime(&curtime
);
334 snprintf(blitstr
, STRSIZE
,"%s",week_day
[clk
->tm_wday
]);
335 BlitString(blitstr
, 4, (11*(j
-1)) + 5);
338 /* Display more precise internet time */
339 else if (strncmp( zone
[j
].label
,"@", 1) == 0 )
341 /* Calculate Internet time */
342 swatch_beats
= (float)(((curtime
+3600)%86400)/86.4);
343 snprintf (blitstr
, STRSIZE
, "@:%7.3f", swatch_beats
);
344 BlitString (blitstr
, 5, (11*(j
-1)) + 5);
347 /* Display Julian Day Number */
348 else if (strncmp( zone
[j
].label
, "JDN", 3) == 0 )
350 clk
= gmtime(&curtime
);
351 /* Calculate Julin Day Number */
352 jd
= jdn(curtime
) - zone
[j
].epoch
;
353 snprintf(blitstr
, STRSIZE
, "%10f", jd
);
354 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
357 /* Display Local Mean Sidereal Time */
358 else if (strncmp( zone
[j
].label
, "LMST", 3) == 0 )
360 clk
= gmtime(&curtime
);
362 siderealTime( jd
, sid
, LMST
);
363 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i","LST:", sid
[0], sid
[1]);
364 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
367 /* Display Greenwich Mean Sidereal Time */
368 else if (strncmp( zone
[j
].label
, "GMST", 3) == 0 )
370 clk
= gmtime(&curtime
);
372 siderealTime( jd
, sid
, GMST
);
373 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i","GST:", sid
[0], sid
[1]);
374 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
377 /* Display local time */
378 else if (strncmp( zone
[j
].label
, "LOCAL", 5) == 0 )
380 clk
= localtime(&curtime
);
381 strncpy(buf
, tzname
[0], 3);
392 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i",buf
,hour
,clk
->tm_min
);
393 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
396 /* Display time in specified time zone */
397 else if (strncmp( zone
[j
].label
, "TZONE", 4) == 0 )
401 clk
= localtime(&curtime
);
403 strncpy(buf
, tzname
[0], 3);
412 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i", buf
,
413 clk
->tm_hour
, clk
->tm_min
);
414 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
416 /* Reset TZ environment variable to old value */
420 /* Display time in specified time zone without TZ env. var. */
423 clk
= gmtime(&curtime
);
424 strncpy(buf
, zone
[j
].label
, 3);
433 hour
= clk
->tm_hour
- zone
[j
].diff
;
440 snprintf(blitstr
, STRSIZE
, "%s%02i.%02i",buf
,hour
,clk
->tm_min
);
441 BlitString(blitstr
, 5, (11*(j
-1)) + 5);
448 while (XPending(display
))
450 XNextEvent(display
, &Event
);
457 XCloseDisplay(display
);
461 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
465 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
466 if (but_stat
== i
&& but_stat
>= 0)
468 if ( clicked
) /* The menu is up */
470 handleTheMenu(but_stat
);
473 else /* Show the menu instead of time */
488 /*****************************************************************************\
490 \*****************************************************************************/
491 void handleTheMenu(int but_stat
)
504 /* Figure out what editor to use */
505 if ( defedit
== NULL
)
507 ed
= getenv("XEDITOR");
515 editor
= malloc( strlen(ed
)+strlen(config_file
)+2 );
516 if ( editor
== NULL
)
517 errH(1, 1, "malloc");
518 sprintf(editor
, "%s %s", ed
, config_file
);
519 waitpid( execCommand(editor
), NULL
, 0 );
520 Read_Config_File(config_file
);
524 Read_Config_File(config_file
);
534 /*****************************************************************************\
535 |* ReadConfigSetting *|
536 \*****************************************************************************/
537 int ReadConfigString(FILE *fp
, char *setting
, char *value
)
551 snprintf(str
,1024, "%s=", setting
);
554 fseek(fp
, 0, SEEK_SET
);
559 if (!fgets(buf
, 512, fp
))
565 for (i
=0; i
!=len
; i
++)
569 /* printf("Scanning '%s'...\n", buf); */
570 if ( strncmp(buf
, str
, strlen(str
)) == 0)
572 /* found our setting */
574 for(i
=0; i
!=slen
; i
++)
587 /*****************************************************************************\
589 \*****************************************************************************/
590 int ReadConfigInt(FILE *fp
, char *setting
, int *value
)
594 if (ReadConfigString(fp
, setting
, (char *) &buf
))
604 /*****************************************************************************\
605 |* ReadConfigDouble *|
606 \*****************************************************************************/
607 int ReadConfigDouble(FILE *fp
, char *setting
, double *value
)
611 if (ReadConfigString(fp
, setting
, (char *) &buf
))
621 /*****************************************************************************\
622 |* Read_Config_File *|
623 \*****************************************************************************/
624 int Read_Config_File( char *filename
)
629 fp
= fopen(filename
, "r");
632 ReadConfigString(fp
, "time1", zone
[1].label
);
633 ReadConfigString(fp
, "time2", zone
[2].label
);
634 ReadConfigString(fp
, "time3", zone
[3].label
);
635 ReadConfigString(fp
, "time4", zone
[4].label
);
636 ReadConfigString(fp
, "time5", zone
[5].label
);
637 ReadConfigInt(fp
, "utdiff1", &zone
[1].diff
);
638 ReadConfigInt(fp
, "utdiff2", &zone
[2].diff
);
639 ReadConfigInt(fp
, "utdiff3", &zone
[3].diff
);
640 ReadConfigInt(fp
, "utdiff4", &zone
[4].diff
);
641 ReadConfigInt(fp
, "utdiff5", &zone
[5].diff
);
642 ReadConfigDouble(fp
, "utdiff1", &zone
[1].epoch
);
643 ReadConfigDouble(fp
, "utdiff2", &zone
[2].epoch
);
644 ReadConfigDouble(fp
, "utdiff3", &zone
[3].epoch
);
645 ReadConfigDouble(fp
, "utdiff4", &zone
[4].epoch
);
646 ReadConfigDouble(fp
, "utdiff5", &zone
[5].epoch
);
648 ReadConfigString(fp
, "utdiff1", temp
);
649 sprintf(zone
[1].tz
, "TZ=%s", temp
);
650 ReadConfigString(fp
, "utdiff2", temp
);
651 sprintf(zone
[2].tz
, "TZ=%s", temp
);
652 ReadConfigString(fp
, "utdiff3", temp
);
653 sprintf(zone
[3].tz
, "TZ=%s", temp
);
654 ReadConfigString(fp
, "utdiff4", temp
);
655 sprintf(zone
[4].tz
, "TZ=%s", temp
);
656 ReadConfigString(fp
, "utdiff5", temp
);
657 sprintf(zone
[5].tz
, "TZ=%s", temp
);
659 ReadConfigDouble(fp
, "longitude", &longitude
);
660 /* ReadConfigDouble(fp, "latitude", &latitude); */
667 errH(1, 0, "Unable to open %s", filename
);
673 /*****************************************************************************\
674 |* BlitString - Blits a string at given coordinates. *|
675 \*****************************************************************************/
676 void BlitString(char *name
, int x
, int y
)
683 for (i
=0; name
[i
]; i
++)
686 c
= toupper(name
[i
]);
687 if (c
>= 'A' && c
<= 'Z')
690 copyXPMArea(c
* CHAR_WIDTH
, 74, CHAR_WIDTH
, 8, k
, y
);
693 else if ( c
>= '0' && c
<= ':')
696 copyXPMArea(c
* CHAR_WIDTH
, 64, CHAR_WIDTH
, 8, k
, y
);
699 else if (c
== ';') /* used as a slim ':' */
701 copyXPMArea(60, 64, CHAR_WIDTH
, 8, k
, y
);
706 copyXPMArea(115, 64, 4, 8, k
, y
);
711 copyXPMArea(108, 64, CHAR_WIDTH
, 8, k
, y
);
714 else /* print a ' ' */
716 copyXPMArea(120, 64, CHAR_WIDTH
, 8, k
, y
);
723 /*****************************************************************************\
725 \*****************************************************************************/
728 fprintf(stderr
, "\nwmtz - shows local time around the world and more.\n");
729 fprintf(stderr
, "See ~/.wmtzrc or /etc/wmtzrc for configuration.\n\n");
730 fprintf(stderr
, "Usage:\n");
731 fprintf(stderr
, " -display <display name>\n");
732 fprintf(stderr
, " -e <editor> use specified editor\n");
733 fprintf(stderr
, " -geometry +XPOS+YPOS initial window position\n");
734 fprintf(stderr
, " -jd Julian<->Date conversion\n");
735 fprintf(stderr
, " -c <filename> use specified config file\n");
736 fprintf(stderr
, " -m start monochrome version\n");
737 fprintf(stderr
, " -h this help screen\n");
738 fprintf(stderr
, " -v print the version number\n");
739 fprintf(stderr
, "\n");
743 /*****************************************************************************\
745 \*****************************************************************************/
746 void printversion(void)
748 fprintf(stderr
, "wmtz v%s\n", WMTZ_VERSION
);
752 /*****************************************************************************\
753 |* range - Put val in 0<->ran interval. *|
754 \*****************************************************************************/
755 void range (double *val
, double ran
)
757 *val
-= ran
*floor(*val
/ran
);
764 /*****************************************************************************\
765 |* jdn - converts a time_t to Julian Day *|
766 \*****************************************************************************/
767 double jdn(time_t curtime
)
769 return (curtime
/86400.0 + 2440587.5);
772 /*****************************************************************************\
773 |* siderealTime - Gives sidereal time from JD. *|
774 \*****************************************************************************/
775 void siderealTime( double jde
, int *result
, int mode
)
777 double t
, t2
, t3
, ts
;
779 t
= (jde
- 2451545.0)/36525.0;
783 /* Expression from "Astronomical Algorithms" by J. Meeus */
784 ts
= 280.46061837 + 360.98564736629 * ( jde
- 2451545.0 )
785 + 0.000387933 * t2
- t3
/38710000.0;
790 /* If local time add one hour for every 15 degree in longitude */
793 ts
+= longitude
/15.0;
798 result
[1] = (int)(60 *(ts
- result
[0]));
802 /*****************************************************************************\
803 |* julianDay - Gives JD from date. *|
804 \*****************************************************************************/
805 double julianDay( int year
, int month
, double day
, double hour
,
806 double minute
, double second
, int julian
)
811 day
= day
+ hour
/24.0 + minute
/1440.0 + second
/86400.0;
819 /* If the date is a Julian calendar date, set julian to TRUE */
824 else /* If Gregorian calendar date, julian should be FALSE */
829 c
= 365.25 * (year
+ 4716);
830 d
= 30.6001 * (month
+ 1);
831 jd
= c
+ d
+ day
+ b
- 1524.5;
837 /*****************************************************************************\
838 |* calendarDate - Gives date from JD. Only Gregorian calendar dates. *|
839 \*****************************************************************************/
840 int calendarDate( double jd
, int *year
, int *month
, double *day
)
842 double a
, b
, frac
, ij
, alfa
, beta
, c
, d
, e
, f
;
857 alfa
= floor((ij
- 1867216.25)/36524.25);
858 beta
= floor(alfa
/4);
859 a
= ij
+ 1 + alfa
- beta
;
863 c
= floor((b
- 122.1)/365.25);
864 d
= floor(365.25 * c
);
865 e
= floor((b
- d
)/30.6001);
866 f
= floor(30.6001 * e
);
868 *day
= b
- d
- f
+ frac
;
872 else if (e
== 14 || e
== 15)
879 else if (*month
== 1 || *month
== 2)
888 /*****************************************************************************\
890 \*****************************************************************************/
893 int conv
, y
, m
, d
, h
, min
, sec
;
896 printf(" 1 : Date to JD.\n 2 : JD to date.\n");
897 printf("Choose conversion (1 or 2): ");
902 printf("Enter UT date with time (YYYY,MM,DD,hh:mm:ss): ");
903 scanf("%d,%d,%d,%d:%d:%d", &y
, &m
, &d
, &h
, &min
, &sec
);
904 printf("\nJulian Day: %f\n", julianDay( y
, m
, d
, h
, min
, sec
, 0 ) );
908 printf("Enter Julian Day Number: ");
910 if ( !calendarDate( jd
, &y
, &m
, &day
) )
912 printf("Conversion error! Negative JD not allowed.\n");
916 printf("\nGregorian date: %d-%2.2d-%2.4f\n", y
, m
, day
);
920 printf("Invalid choice! Try again, please...\n");
926 /*****************************************************************************\
928 \*****************************************************************************/
929 void errH(int printErrno
, int exitCode
, const char *msg
, ...)
935 /* Put the name of the program first */
941 vsprintf(buf
+strlen(buf
), msg
, arg
);
943 sprintf(buf
+strlen(buf
), ": %s", strerror(error
));