wmbutton: initTooltip has no argument
[dockapps.git] / wmtz / wmtz / wmtz.c
blobecffb774435314e06e28d1050e413181c0907433
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 "../wmgeneral/wmgeneral.h"
41 #include "../wmgeneral/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
55 http://www.geocities.com/jl1n/wmtz/wmtz.html\""
59 * Typedefs
61 typedef struct
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 */
71 * Global variables
73 timezone_t zone[6];
74 double longitude = 0.0;
75 double latitude = 0.0;
76 static struct tm *clk;
77 char *pname;
78 char *uconfig_file;
79 char *config_file;
80 char *defedit;
81 char *month[12];
82 char *week_day[7];
83 char wmtz_mask_bits[64*64];
84 int wmtz_mask_width = 64;
85 int wmtz_mask_height = 64;
86 int mono = 0;
87 extern char *tzname[2];
88 static char originalTZ[64];
91 * Function declarations
93 void usage(void);
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);
105 int handleJD(void);
106 void errH(int printErrno, int exitCode, const char *msg, ...);
107 void handleTheMenu(int but_stat);
108 double jdn(time_t curtime);
111 /*****************************************************************************\
112 |* main *|
113 \*****************************************************************************/
114 int main(int argc, char *argv[]) {
116 int i;
117 char *envbuf;
119 /* Store away the executable name for error messages */
120 if ( (pname = strrchr( argv[0], '/' )) == NULL )
121 pname = argv[0];
122 else
123 pname++;
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);
131 else
133 // Set originalTZ to TZ erase TZ env.
134 (void) sprintf(originalTZ, "TZ");
137 /* Parse Command Line */
138 for (i=1; i<argc; i++) {
139 char *arg = argv[i];
141 if (*arg=='-') {
142 switch (arg[1]) {
143 case 'd' :
144 if (strcmp(arg+1, "display")) {
145 usage();
146 exit(1);
148 break;
149 case 'g' :
150 if (strcmp(arg+1, "geometry")) {
151 usage();
152 exit(1);
154 break;
155 case 'j' :
156 if (strcmp(arg+1, "jd")) {
157 usage();
158 exit(1);
160 handleJD();
161 exit(0);
162 break;
163 case 'm' :
164 mono = 1;
165 break;
166 case 'v' :
167 printversion();
168 exit(0);
169 break;
170 case 'c' :
171 if (argc > (i+1))
173 uconfig_file = strdup(argv[i+1]);
174 if (uconfig_file == NULL)
175 errH(1, 1, "strdup");
176 i++;
178 break;
179 case 'e' :
180 if (argc > (i+1))
182 defedit = strdup(argv[i+1]);
183 if (defedit == NULL)
184 errH(1, 1, "strdup");
185 i++;
187 break;
188 default:
189 usage();
190 exit(0);
191 break;
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);
211 return 0;
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;
222 double jd = 0;
223 float swatch_beats;
224 time_t curtime;
225 time_t prevtime;
226 char *home;
227 char buf[64];
228 char blitstr[STRSIZE];
229 XEvent Event;
231 if (mono)
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);
240 else
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",
262 uconfig_file);
263 config_file = strdup(uconfig_file);
264 free(uconfig_file);
265 Read_Config_File(config_file);
267 else
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 */
279 free(config_file);
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);
292 RedrawWindow();
293 prevtime = time(0) - 1;
295 while (1)
297 waitpid(0, NULL, WNOHANG);
299 /* If wmtz have been mouse-clicked, show menu */
300 if ( clicked )
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)
310 prevtime = curtime;
312 /* Update the display */
313 for (j=1; j<6; j++)
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);
362 jd = jdn(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);
372 jd = jdn(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);
384 for (k=0; k<3; k++)
385 if (buf[k] == 0)
386 buf[k] = ' ';
388 buf[3] = ':';
389 buf[4] = 0;
390 hour = clk->tm_hour;
392 /* Print Label */
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 )
400 putenv(zone[j].tz);
401 tzset();
402 clk = localtime(&curtime);
404 strncpy(buf, tzname[0], 3);
406 for (k=0; k<3; k++)
407 if (buf[k] == 0)
408 buf[k] = ' ';
410 buf[3] = ':';
411 buf[4] = 0;
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 */
418 putenv(originalTZ);
421 /* Display time in specified time zone without TZ env. var. */
422 else
424 clk = gmtime(&curtime);
425 strncpy(buf, zone[j].label, 3);
427 for (k=0; k<3; k++)
428 if (buf[k] == 0)
429 buf[k] = ' ';
431 buf[3] = ':';
432 buf[4] = 0;
434 hour = clk->tm_hour - zone[j].diff;
435 if (hour > 23 )
436 hour -= 24;
437 else if (hour < 0 )
438 hour += 24;
440 /* Print Label */
441 snprintf(blitstr, STRSIZE, "%s%02i.%02i",buf,hour,clk->tm_min);
442 BlitString(blitstr, 5, (11*(j-1)) + 5);
446 RedrawWindow();
448 /* X Events */
449 while (XPending(display))
451 XNextEvent(display, &Event);
452 switch (Event.type)
454 case Expose:
455 RedrawWindow();
456 break;
457 case DestroyNotify:
458 XCloseDisplay(display);
459 exit(0);
460 break;
461 case ButtonPress:
462 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
463 but_stat = i;
464 break;
465 case ButtonRelease:
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);
472 clicked = 0;
474 else /* Show the menu instead of time */
476 clicked = 1;
479 but_stat = -1;
480 break;
481 default:
485 usleep(10000);
490 /*****************************************************************************\
491 |* handleTheMenu *|
492 \*****************************************************************************/
493 void handleTheMenu(int but_stat)
495 char *editor;
496 char *ed;
498 switch( but_stat )
500 case 0:
501 execCommand(ABOUT);
502 break;
503 case 1:
504 break;
505 case 2:
506 /* Figure out what editor to use */
507 if ( defedit == NULL )
509 ed = getenv("XEDITOR");
510 if ( ed == NULL )
511 ed = "xedit";
513 else
515 ed = defedit;
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);
523 free(editor);
524 break;
525 case 3:
526 Read_Config_File(config_file);
527 break;
528 case 4:
529 exit(0);
530 break;
531 default:
533 return;
537 /*****************************************************************************\
538 |* ReadConfigSetting *|
539 \*****************************************************************************/
540 int ReadConfigString(FILE *fp, char *setting, char *value)
542 char str[1024];
543 char buf[1024];
544 int i;
545 int len;
546 int slen;
547 char *p=NULL;
549 if (!fp)
551 return 0;
554 snprintf(str,1024, "%s=", setting);
555 slen = strlen(str);
557 fseek(fp, 0, SEEK_SET);
559 while ( !feof(fp) )
562 if (!fgets(buf, 512, fp))
563 break;
565 len = strlen(buf);
567 /* strip linefeed */
568 for (i=0; i!=len; i++)
569 if (buf[i] == '\n')
570 buf[i] = 0;
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++)
578 if ( buf[i] == '=' )
580 p=buf+i+1;
581 strcpy(value, p);
582 return 1;
586 return 0;
590 /*****************************************************************************\
591 |* ReadConfigInt *|
592 \*****************************************************************************/
593 int ReadConfigInt(FILE *fp, char *setting, int *value)
595 char buf[1024];
597 if (ReadConfigString(fp, setting, (char *) &buf))
599 *value = atoi(buf);
600 return 1;
603 return 0;
607 /*****************************************************************************\
608 |* ReadConfigDouble *|
609 \*****************************************************************************/
610 int ReadConfigDouble(FILE *fp, char *setting, double *value)
612 char buf[1024];
614 if (ReadConfigString(fp, setting, (char *) &buf))
616 *value = atof(buf);
617 return 1;
620 return 0;
624 /*****************************************************************************\
625 |* Read_Config_File *|
626 \*****************************************************************************/
627 int Read_Config_File( char *filename )
629 FILE *fp;
630 char temp[253];
632 fp = fopen(filename, "r");
633 if (fp)
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); */
665 fclose(fp);
666 return 1;
668 else
670 errH(1, 0, "Unable to open %s", filename);
671 return 0;
676 /*****************************************************************************\
677 |* BlitString - Blits a string at given coordinates. *|
678 \*****************************************************************************/
679 void BlitString(char *name, int x, int y)
681 int i;
682 int c;
683 int k;
685 k = x;
686 for (i=0; name[i]; i++)
689 c = toupper(name[i]);
690 if (c >= 'A' && c <= 'Z')
691 { /* its a letter */
692 c -= 'A';
693 copyXPMArea(c * CHAR_WIDTH, 74, CHAR_WIDTH, 8, k, y);
694 k += CHAR_WIDTH;
696 else if ( c >= '0' && c <= ':')
698 c -= '0';
699 copyXPMArea(c * CHAR_WIDTH, 64, CHAR_WIDTH, 8, k, y);
700 k += CHAR_WIDTH;
702 else if (c == ';') /* used as a slim ':' */
704 copyXPMArea(60, 64, CHAR_WIDTH, 8, k, y);
705 k += 4;
707 else if (c=='.')
709 copyXPMArea(115, 64, 4, 8, k, y);
710 k += 4;
712 else if (c=='@')
714 copyXPMArea(108, 64, CHAR_WIDTH, 8, k, y);
715 k += CHAR_WIDTH;
717 else /* print a ' ' */
719 copyXPMArea(120, 64, CHAR_WIDTH, 8, k, y);
720 k += CHAR_WIDTH;
726 /*****************************************************************************\
727 |* usage *|
728 \*****************************************************************************/
729 void usage(void)
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 /*****************************************************************************\
747 |* printversion *|
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);
762 if (*val < 0)
763 *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;
783 t2 = t*t;
784 t3 = t2*t;
786 /* Expression from "Astronomical Algorithms" by J. Meeus */
787 ts = 280.46061837 + 360.98564736629 * ( jde - 2451545.0 )
788 + 0.000387933 * t2 - t3/38710000.0;
790 range( &ts, 360.0 );
791 ts /= 15.0;
793 /* If local time add one hour for every 15 degree in longitude */
794 if ( mode == LMST )
796 ts += longitude/15.0;
799 range( &ts, 24.0 );
800 result[0] = (int)ts;
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 )
811 int a, b, c, d;
812 double jd;
814 day = day + hour/24.0 + minute/1440.0 + second/86400.0;
816 if ( month < 3 )
818 year -= 1;
819 month += 12;
822 /* If the date is a Julian calendar date, set julian to TRUE */
823 if ( julian )
825 b = 0;
827 else /* If Gregorian calendar date, julian should be FALSE */
829 a = year/100;
830 b = 2 - a + a/4;
832 c = 365.25 * (year + 4716);
833 d = 30.6001 * (month + 1);
834 jd = c + d + day + b - 1524.5;
836 return( jd );
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;
847 if ( jd < 0 )
848 return 0;
850 jd += 0.5;
851 ij = floor(jd);
852 frac = jd - ij;
854 if ( ij < 2299161 )
856 a = ij;
858 else
860 alfa = floor((ij - 1867216.25)/36524.25);
861 beta = floor(alfa/4);
862 a = ij + 1 + alfa - beta;
865 b = a + 1524;
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;
873 if (e < 14)
874 *month = e - 1;
875 else if (e == 14 || e == 15)
876 *month = e - 13;
877 else
878 return 0;
880 if (*month > 2)
881 *year = c - 4716;
882 else if (*month == 1 || *month == 2)
883 *year = c - 4715;
884 else
885 return 0;
887 return 1;
891 /*****************************************************************************\
892 |* handleJD *|
893 \*****************************************************************************/
894 int handleJD( void )
896 int conv, y, m, d, h, min, sec;
897 double day, jd;
899 printf(" 1 : Date to JD.\n 2 : JD to date.\n");
900 printf("Choose conversion (1 or 2): ");
901 scanf("%d", &conv);
903 if (conv == 1 )
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 ) );
909 else if (conv == 2)
911 printf("Enter Julian Day Number: ");
912 scanf("%lf", &jd );
913 if ( !calendarDate( jd, &y, &m, &day ) )
915 printf("Conversion error! Negative JD not allowed.\n");
916 return 0;
919 printf("\nGregorian date: %d-%2.2d-%2.4f\n", y, m, day);
921 else
923 printf("Invalid choice! Try again, please...\n");
924 handleJD();
926 return 1;
929 /*****************************************************************************\
930 |* errH *|
931 \*****************************************************************************/
932 void errH(int printErrno, int exitCode, const char *msg, ...)
934 int error = errno;
935 va_list arg;
936 char buf[2048];
938 /* Put the name of the program first */
939 buf[0] = 0;
940 strcat(buf, pname);
941 strcat(buf, ": ");
943 va_start(arg, msg);
944 vsprintf(buf+strlen(buf), msg, arg);
945 if (printErrno)
946 sprintf(buf+strlen(buf), ": %s", strerror(error));
947 strcat(buf, "\n");
948 fflush(stdout);
949 fputs(buf, stderr);
950 fflush(NULL);
951 va_end(arg);
953 if ( exitCode )
954 exit(exitCode);
956 return;