wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmtz / wmtz / wmtz.c
blobe368ebcd2485fb4f7c81be65657264a053a2de05
1 /*****************************************************************************/
2 /* */
3 /* wmtz.c */
4 /* Shows local time in different timezones + JD + Sidereal time + */
5 /* internet time + local date and time. */
6 /* */
7 /* Jan Lindblom <99jl@home.se> (http://www.geocities.com/~jl1n/) */
8 /* */
9 /* wmtz.c was derived from: */
10 /* */
11 /* wminet.c */
12 /* */
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) */
17 /* */
18 /* This software is licensed through the GNU General Public Licence. */
19 /* Read the COPYING file for details. */
20 /* */
21 /*****************************************************************************/
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <time.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <stdarg.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <math.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
36 #include <X11/Xlib.h>
37 #include <X11/xpm.h>
38 #include <X11/extensions/shape.h>
40 #include <libdockapp/wmgeneral.h>
41 #include <libdockapp/misc.h>
42 #include "wmtz.xpm"
43 #include "wmtz_mono.xpm"
47 * Defines
49 #define WMTZ_VERSION "0.7"
50 #define CHAR_WIDTH 6
51 #define STRSIZE 10
52 #define LMST 1
53 #define GMST 0
54 #define ABOUT "xmessage -center -buttons \"Close\" \"WMTZ - Window Maker Time Zone dockapp v0.7 http://www.geocities.com/jl1n/wmtz/wmtz.html\""
58 * Typedefs
60 typedef struct
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 */
70 * Global variables
72 timezone_t zone[6];
73 double longitude = 0.0;
74 double latitude = 0.0;
75 static struct tm *clk;
76 char *pname;
77 char *uconfig_file;
78 char *config_file;
79 char *defedit;
80 char *month[12];
81 char *week_day[7];
82 char wmtz_mask_bits[64*64];
83 int wmtz_mask_width = 64;
84 int wmtz_mask_height = 64;
85 int mono = 0;
86 extern char *tzname[2];
87 static char originalTZ[64];
90 * Function declarations
92 void usage(void);
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);
104 int handleJD(void);
105 void errH(int printErrno, int exitCode, const char *msg, ...);
106 void handleTheMenu(int but_stat);
107 double jdn(time_t curtime);
110 /*****************************************************************************\
111 |* main *|
112 \*****************************************************************************/
113 int main(int argc, char *argv[]) {
115 int i;
116 char *envbuf;
118 /* Store away the executable name for error messages */
119 if ( (pname = strrchr( argv[0], '/' )) == NULL )
120 pname = argv[0];
121 else
122 pname++;
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);
130 else
132 // Set originalTZ to TZ erase TZ env.
133 (void) sprintf(originalTZ, "TZ");
136 /* Parse Command Line */
137 for (i=1; i<argc; i++) {
138 char *arg = argv[i];
140 if (*arg=='-') {
141 switch (arg[1]) {
142 case 'd' :
143 if (strcmp(arg+1, "display")) {
144 usage();
145 exit(1);
147 break;
148 case 'g' :
149 if (strcmp(arg+1, "geometry")) {
150 usage();
151 exit(1);
153 break;
154 case 'j' :
155 if (strcmp(arg+1, "jd")) {
156 usage();
157 exit(1);
159 handleJD();
160 exit(0);
161 break;
162 case 'm' :
163 mono = 1;
164 break;
165 case 'v' :
166 printversion();
167 exit(0);
168 break;
169 case 'c' :
170 if (argc > (i+1))
172 uconfig_file = strdup(argv[i+1]);
173 if (uconfig_file == NULL)
174 errH(1, 1, "strdup");
175 i++;
177 break;
178 case 'e' :
179 if (argc > (i+1))
181 defedit = strdup(argv[i+1]);
182 if (defedit == NULL)
183 errH(1, 1, "strdup");
184 i++;
186 break;
187 default:
188 usage();
189 exit(0);
190 break;
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);
210 return 0;
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;
221 double jd = 0;
222 float swatch_beats;
223 time_t curtime;
224 time_t prevtime;
225 char *home;
226 char buf[64];
227 char blitstr[STRSIZE];
228 XEvent Event;
230 if (mono)
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);
239 else
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",
261 uconfig_file);
262 config_file = strdup(uconfig_file);
263 free(uconfig_file);
264 Read_Config_File(config_file);
266 else
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 */
278 free(config_file);
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);
291 RedrawWindow();
292 prevtime = time(0) - 1;
294 while (1)
296 waitpid(0, NULL, WNOHANG);
298 /* If wmtz have been mouse-clicked, show menu */
299 if ( clicked )
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)
309 prevtime = curtime;
311 /* Update the display */
312 for (j=1; j<6; j++)
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);
361 jd = jdn(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);
371 jd = jdn(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);
383 for (k=0; k<3; k++)
384 if (buf[k] == 0)
385 buf[k] = ' ';
387 buf[3] = ':';
388 buf[4] = 0;
389 hour = clk->tm_hour;
391 /* Print Label */
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 )
399 putenv(zone[j].tz);
400 tzset();
401 clk = localtime(&curtime);
403 strncpy(buf, tzname[0], 3);
405 for (k=0; k<3; k++)
406 if (buf[k] == 0)
407 buf[k] = ' ';
409 buf[3] = ':';
410 buf[4] = 0;
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 */
417 putenv(originalTZ);
420 /* Display time in specified time zone without TZ env. var. */
421 else
423 clk = gmtime(&curtime);
424 strncpy(buf, zone[j].label, 3);
426 for (k=0; k<3; k++)
427 if (buf[k] == 0)
428 buf[k] = ' ';
430 buf[3] = ':';
431 buf[4] = 0;
433 hour = clk->tm_hour - zone[j].diff;
434 if (hour > 23 )
435 hour -= 24;
436 else if (hour < 0 )
437 hour += 24;
439 /* Print Label */
440 snprintf(blitstr, STRSIZE, "%s%02i.%02i",buf,hour,clk->tm_min);
441 BlitString(blitstr, 5, (11*(j-1)) + 5);
445 RedrawWindow();
447 /* X Events */
448 while (XPending(display))
450 XNextEvent(display, &Event);
451 switch (Event.type)
453 case Expose:
454 RedrawWindow();
455 break;
456 case DestroyNotify:
457 XCloseDisplay(display);
458 exit(0);
459 break;
460 case ButtonPress:
461 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
462 but_stat = i;
463 break;
464 case ButtonRelease:
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);
471 clicked = 0;
473 else /* Show the menu instead of time */
475 clicked = 1;
478 but_stat = -1;
479 break;
483 usleep(10000);
488 /*****************************************************************************\
489 |* handleTheMenu *|
490 \*****************************************************************************/
491 void handleTheMenu(int but_stat)
493 char *editor;
494 char *ed;
496 switch( but_stat )
498 case 0:
499 execCommand(ABOUT);
500 break;
501 case 1:
502 break;
503 case 2:
504 /* Figure out what editor to use */
505 if ( defedit == NULL )
507 ed = getenv("XEDITOR");
508 if ( ed == NULL )
509 ed = "xedit";
511 else
513 ed = defedit;
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);
521 free(editor);
522 break;
523 case 3:
524 Read_Config_File(config_file);
525 break;
526 case 4:
527 exit(0);
528 break;
530 return;
534 /*****************************************************************************\
535 |* ReadConfigSetting *|
536 \*****************************************************************************/
537 int ReadConfigString(FILE *fp, char *setting, char *value)
539 char str[1024];
540 char buf[1024];
541 int i;
542 int len;
543 int slen;
544 char *p=NULL;
546 if (!fp)
548 return 0;
551 snprintf(str,1024, "%s=", setting);
552 slen = strlen(str);
554 fseek(fp, 0, SEEK_SET);
556 while ( !feof(fp) )
559 if (!fgets(buf, 512, fp))
560 break;
562 len = strlen(buf);
564 /* strip linefeed */
565 for (i=0; i!=len; i++)
566 if (buf[i] == '\n')
567 buf[i] = 0;
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++)
575 if ( buf[i] == '=' )
577 p=buf+i+1;
578 strcpy(value, p);
579 return 1;
583 return 0;
587 /*****************************************************************************\
588 |* ReadConfigInt *|
589 \*****************************************************************************/
590 int ReadConfigInt(FILE *fp, char *setting, int *value)
592 char buf[1024];
594 if (ReadConfigString(fp, setting, (char *) &buf))
596 *value = atoi(buf);
597 return 1;
600 return 0;
604 /*****************************************************************************\
605 |* ReadConfigDouble *|
606 \*****************************************************************************/
607 int ReadConfigDouble(FILE *fp, char *setting, double *value)
609 char buf[1024];
611 if (ReadConfigString(fp, setting, (char *) &buf))
613 *value = atof(buf);
614 return 1;
617 return 0;
621 /*****************************************************************************\
622 |* Read_Config_File *|
623 \*****************************************************************************/
624 int Read_Config_File( char *filename )
626 FILE *fp;
627 char temp[253];
629 fp = fopen(filename, "r");
630 if (fp)
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); */
662 fclose(fp);
663 return 1;
665 else
667 errH(1, 0, "Unable to open %s", filename);
668 return 0;
673 /*****************************************************************************\
674 |* BlitString - Blits a string at given coordinates. *|
675 \*****************************************************************************/
676 void BlitString(char *name, int x, int y)
678 int i;
679 int c;
680 int k;
682 k = x;
683 for (i=0; name[i]; i++)
686 c = toupper(name[i]);
687 if (c >= 'A' && c <= 'Z')
688 { /* its a letter */
689 c -= 'A';
690 copyXPMArea(c * CHAR_WIDTH, 74, CHAR_WIDTH, 8, k, y);
691 k += CHAR_WIDTH;
693 else if ( c >= '0' && c <= ':')
695 c -= '0';
696 copyXPMArea(c * CHAR_WIDTH, 64, CHAR_WIDTH, 8, k, y);
697 k += CHAR_WIDTH;
699 else if (c == ';') /* used as a slim ':' */
701 copyXPMArea(60, 64, CHAR_WIDTH, 8, k, y);
702 k += 4;
704 else if (c=='.')
706 copyXPMArea(115, 64, 4, 8, k, y);
707 k += 4;
709 else if (c=='@')
711 copyXPMArea(108, 64, CHAR_WIDTH, 8, k, y);
712 k += CHAR_WIDTH;
714 else /* print a ' ' */
716 copyXPMArea(120, 64, CHAR_WIDTH, 8, k, y);
717 k += CHAR_WIDTH;
723 /*****************************************************************************\
724 |* usage *|
725 \*****************************************************************************/
726 void usage(void)
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 /*****************************************************************************\
744 |* printversion *|
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);
759 if (*val < 0)
760 *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;
780 t2 = t*t;
781 t3 = t2*t;
783 /* Expression from "Astronomical Algorithms" by J. Meeus */
784 ts = 280.46061837 + 360.98564736629 * ( jde - 2451545.0 )
785 + 0.000387933 * t2 - t3/38710000.0;
787 range( &ts, 360.0 );
788 ts /= 15.0;
790 /* If local time add one hour for every 15 degree in longitude */
791 if ( mode == LMST )
793 ts += longitude/15.0;
796 range( &ts, 24.0 );
797 result[0] = (int)ts;
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 )
808 int a, b, c, d;
809 double jd;
811 day = day + hour/24.0 + minute/1440.0 + second/86400.0;
813 if ( month < 3 )
815 year -= 1;
816 month += 12;
819 /* If the date is a Julian calendar date, set julian to TRUE */
820 if ( julian )
822 b = 0;
824 else /* If Gregorian calendar date, julian should be FALSE */
826 a = year/100;
827 b = 2 - a + a/4;
829 c = 365.25 * (year + 4716);
830 d = 30.6001 * (month + 1);
831 jd = c + d + day + b - 1524.5;
833 return( jd );
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;
844 if ( jd < 0 )
845 return 0;
847 jd += 0.5;
848 ij = floor(jd);
849 frac = jd - ij;
851 if ( ij < 2299161 )
853 a = ij;
855 else
857 alfa = floor((ij - 1867216.25)/36524.25);
858 beta = floor(alfa/4);
859 a = ij + 1 + alfa - beta;
862 b = a + 1524;
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;
870 if (e < 14)
871 *month = e - 1;
872 else if (e == 14 || e == 15)
873 *month = e - 13;
874 else
875 return 0;
877 if (*month > 2)
878 *year = c - 4716;
879 else if (*month == 1 || *month == 2)
880 *year = c - 4715;
881 else
882 return 0;
884 return 1;
888 /*****************************************************************************\
889 |* handleJD *|
890 \*****************************************************************************/
891 int handleJD( void )
893 int conv, y, m, d, h, min, sec;
894 double day, jd;
896 printf(" 1 : Date to JD.\n 2 : JD to date.\n");
897 printf("Choose conversion (1 or 2): ");
898 scanf("%d", &conv);
900 if (conv == 1 )
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 ) );
906 else if (conv == 2)
908 printf("Enter Julian Day Number: ");
909 scanf("%lf", &jd );
910 if ( !calendarDate( jd, &y, &m, &day ) )
912 printf("Conversion error! Negative JD not allowed.\n");
913 return 0;
916 printf("\nGregorian date: %d-%2.2d-%2.4f\n", y, m, day);
918 else
920 printf("Invalid choice! Try again, please...\n");
921 handleJD();
923 return 1;
926 /*****************************************************************************\
927 |* errH *|
928 \*****************************************************************************/
929 void errH(int printErrno, int exitCode, const char *msg, ...)
931 int error = errno;
932 va_list arg;
933 char buf[2048];
935 /* Put the name of the program first */
936 buf[0] = 0;
937 strcat(buf, pname);
938 strcat(buf, ": ");
940 va_start(arg, msg);
941 vsprintf(buf+strlen(buf), msg, arg);
942 if (printErrno)
943 sprintf(buf+strlen(buf), ": %s", strerror(error));
944 strcat(buf, "\n");
945 fflush(stdout);
946 fputs(buf, stderr);
947 fflush(NULL);
948 va_end(arg);
950 if ( exitCode )
951 exit(exitCode);
953 return;