3 * wmWeather-1.31 (C) 1999 Mike Henderson (mghenderson@lanl.gov)
5 * - Shows Local Weather conditions
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, or (at your option)
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 (see the file COPYING); if not, write to the
22 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301 USA
30 * - Add a GTK popup window to display data in a nicer way. Currently just use
33 * - Add "current conditions" graphic (as background?). I.e. one of those little
34 * cartoons that show clouds or sun with rain or snow, etc. on it...
36 * - Scrolling line to display "sundry" parameters.
38 * - Or maybe auto-switch between panels at some user-defined rate?
43 * Version 1.31 - released May 4, 1999.
44 * fixed some conversion bugs in wind speed..
46 * Version 1.30 - released April 13, 1999.
47 * Fixed a bug whereby the App would crash when trying to gain input
48 * focus under non-WindowMaker WMs (focus is now grabbed by
49 * `PointerRoot' not `iconwin').
51 * Added StationID and `time-of-last-update' labels. To do this I needed
52 * to shrink the fonts down and scrunch them together a bit more.
54 * Added new command line option to change their color;
57 * Added code to properly decode wind speed when in MPS.
59 * Fixed bug in beaufort wind speed calcs.
61 * Version 1.29 - released March 17, 1999.
62 * Reorganized wmgeneral.c and renamed it xutils.c (wmgeneral.h
63 * -> xutils.h as well ). Also moved it into the same directory as wmWeather.
64 * Now, the openXwindow is split into 2 parts. You first need to call
65 * initXwindow(argc, argv). This allows us to check the display depth
66 * before we commit to a particular pixmap (this will be useful in my
67 * other DockApps to dynamically set appropriate pixmaps based on depth).
68 * Got rid of alot of the other routines that I never use.
70 * Added 4 more command line option to set the colors of the text:
72 * -bc <color> for setting the BackGround color.
73 * -lc <color> for setting the Label color.
74 * -dc <color> for setting the Data color.
75 * -wgc <color> for setting the Wind Gust color.
77 * Also cleaned up the pixmap to minimize the number of colors used.
79 * Changed metric toggle to work with a key press (any key).
81 * Added double click support. Now double clicking does the following:
83 * Double Mouse Left: pops up the fully decoded METAR file
86 * Double Mouse Middle: Currently undefined.
88 * Double Mouse Right: Forces a new update (i.e. download.)
91 * Version 1.28 - released March 9, 1999.
92 * Changed -celsius (-c) option to -metric (-m). Naming makes more
95 * Added -W option to display WindChill instead of DewPoint.
96 * Since Windchill is not always available, we only show it if its
97 * available. If its not, we paste up DewPoint as default.
99 * Also added -mps option to display wind speed in units of
100 * meters/second (when in -metric mode).
102 * Version 1.27 - released March 8, 1999.
103 * fixed bug in speed calculation when wind is gusting.
105 * Version 1.26 - released February 24, 1999.
106 * Added -delay option.
108 * Version 1.25 - released February 16, 1999.
109 * Added Wind speeds on the 'Beaufort scale'
110 * Thanks to Paul Martin <pm@zetnet.net> for this addition.
112 * Version 1.24 - released February 12, 1999.
113 * Added --passive-ftp option to wget.
115 * Version 1.23 - released February 2, 1999.
116 * Few more bug fixes...
117 * Added support for different Pressure units...
120 * Version 1.22 - released February 1, 1999.
121 * Fixed minor bug in direction abbreviations. Added a bit more to man
124 * Version 1.21 - released January 29, 1999.
125 * Fixed a problem in the perl script. Made the file paths absolute.
127 * Version 1.2 - released January 29, 1999.
128 * Added Wind speed line. Ended up decoding the Raw METAR line.
129 * Fixed a few bugs...
130 * Changed location of files from /tmp to ~/.wmWeatherReports
131 * Changed units of pressure and wind speed to mmHg and km/h
132 * when Metric is set. (Really should change the flag to -metric).
134 * Version 1.1 - released January 25, 1999.
136 * Added command line switch to display Temp's in deg. C
139 * Version 1.0 - released January 19, 1999.
160 #include "wmWeather_master.xpm"
161 #include "wmWeather_mask.xbm"
166 * Delay between refreshes (in microseconds)
169 #define WMWEATHER_VERSION "1.31"
170 #define DEFAULT_UPDATEDELAY 900L
175 void ParseCMDLine(int argc
, char *argv
[]);
176 void ButtonPressEvent(XButtonEvent
*);
177 void KeyPressEvent(XKeyEvent
*);
178 char *StringToUpper(char *);
183 int ShowWindChill
= 0;
184 int WindChillAvail
= 1;
188 int ForceDownload
= 1;
189 int PressureUnits
= 0;
190 int MetersPerSecond
= 0;
191 double PressureConv
= 1.0;
193 int GotFirstClick1
, GotDoubleClick1
;
194 int GotFirstClick2
, GotDoubleClick2
;
195 int GotFirstClick3
, GotDoubleClick3
;
200 * In a more readable form the Compass directions are:
201 * static char *CompassDirection[] = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
202 * "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}
203 * We convert to digits in the sequence `NWSE' so we dont have to put all these
204 * combinations into the pixmap.
206 static char *CompassDirection
[] = { "0", "003", "03", "303", "3", "323", "23", "223",
207 "2", "221", "21", "121", "1", "101", "01", "001"};
211 char LabelColor
[30] = "#79bdbf";
212 char WindGustColor
[30] = "#ff0000";
213 char DataColor
[30] = "#ffbf50";
214 char BackColor
[30] = "#181818";
215 char StationTimeColor
[30] = "#c5a6ff";
222 int main(int argc
, char *argv
[]) {
226 int n
, s
, m
, dt1
, dt2
, dt3
, yd
;
229 int Year
, Month
, Day
;
230 int Hours
, Mins
, Secs
;
231 int UpdateLTHour
= 0.0, UpdateLTMin
= 0.0, UpdateUTHour
, UpdateUTMin
;
232 long CurrentLocalTime
;
233 double UpdateUT
, UpdateLT
, UT
, LT
, DT
, hour24();
236 double jd(), CurrentJD
;
237 char command
[1024], Line
[512], FileName
[10];
238 int Tens
, q
, digit
, chr
;
239 double Pressure
, Temperature
, sgn
, Humidity
, DewPoint
, WindChill
, val
;
240 double Direction
, Speed
;
254 * Parse any command line arguments.
256 ParseCMDLine(argc
, argv
);
261 * Do the window opening in 2 stages. After the initXwindow() call,
262 * we know what the Depth of the Display is. We can then pick an appropriate
263 * XPM to use. I.e. may want to use one that has fewer colors to make the App work
264 * better on a low-color 8-bit display.
266 initXwindow(argc
, argv
);
267 openXwindow(argc
, argv
, wmWeather_master
, wmWeather_mask_bits
, wmWeather_mask_width
,
268 wmWeather_mask_height
, BackColor
, LabelColor
, WindGustColor
, DataColor
, StationTimeColor
);
290 * Keep track of # of seconds
314 * Double Click Delays
315 * Keep track of click events. If Delay too long, set GotFirstClick's to False.
317 if (DblClkDelay
> 15) {
320 GotFirstClick1
= 0; GotDoubleClick1
= 0;
321 GotFirstClick2
= 0; GotDoubleClick2
= 0;
322 GotFirstClick3
= 0; GotDoubleClick3
= 0;
342 * Process any pending X events.
344 while(XPending(display
)){
345 XNextEvent(display
, &event
);
351 ButtonPressEvent(&event
.xbutton
);
354 KeyPressEvent(&event
.xkey
);
359 XSetInputFocus(display
, PointerRoot
, RevertToParent
, CurrentTime
);
362 XSetInputFocus(display
, PointerRoot
, RevertToParent
, CurrentTime
);
376 * Check the Current Conditions file every (approx.) several seconds.
377 * Can significantly reduce this frequency later. But its
378 * easier to debug this way...
379 * Do this before trying to download again! The file may be there and it
382 if ((dt2
> 5)||(ForceUpdate
)){
387 * Compute Current Julian Date
389 CurrentLocalTime
= time(CurrentTime
);
390 tTime
= gmtime(&CurrentLocalTime
);
391 Year
= tTime
->tm_year
+1900;
392 Month
= tTime
->tm_mon
+1;
393 Day
= tTime
->tm_mday
;
394 Hours
= tTime
->tm_hour
;
395 Mins
= tTime
->tm_min
;
396 Secs
= tTime
->tm_sec
;
397 UT
= (double)Hours
+ (double)Mins
/60.0 + (double)Secs
/3600.0;
398 CurrentJD
= jd(Year
, Month
, Day
, UT
);
400 CurrentLocalTime
= time(CurrentTime
);
401 tTime
= localtime(&CurrentLocalTime
);
402 Year
= tTime
->tm_year
+1900;
403 Month
= tTime
->tm_mon
+1;
404 Day
= tTime
->tm_mday
;
405 Hours
= tTime
->tm_hour
;
406 Mins
= tTime
->tm_min
;
407 Secs
= tTime
->tm_sec
;
408 LT
= (double)Hours
+ (double)Mins
/60.0 + (double)Secs
/3600.0;
411 if (DT
> 24.0) DT
-= 24.0;
412 if (DT
< 0.00) DT
+= 24.0;
417 * Read in weather data
419 sprintf(FileName
, "%s/.wmWeatherReports/%s.dat", getenv("HOME"), StationID
);
420 if ((fp
= fopen(FileName
, "r")) != NULL
){
422 fgets(Line
, 512, fp
);
423 fgets(Line
, 512, fp
);
424 fgets(Line
, 512, fp
);
425 fscanf(fp
, "%d:%d", &UpdateUTHour
, &UpdateUTMin
);
426 if (UpdateUTHour
!= 99){
427 UpdateUT
= UpdateUTHour
+ UpdateUTMin
/60.0;
428 UpdateLT
= UpdateUT
- DT
;
429 if (UpdateLT
< 0.0) UpdateLT
+= 24.0;
430 if (UpdateLT
> 24.0) UpdateLT
-= 24.0;
431 UpdateLTHour
= (int)UpdateLT
;
432 UpdateLTMin
= (int)((UpdateLT
- (double)UpdateLTHour
)*60.0 + 0.5);
433 if (UpdateLTMin
>= 60){
435 if (UpdateLTHour
>= 24) UpdateLTHour
= 0;
443 fscanf(fp
, "%lf", &Temperature
);
444 if (Metric
) Temperature
= (Temperature
-32.0)*5.0/9.0;
445 fscanf(fp
, "%lf", &DewPoint
);
446 if (Metric
) DewPoint
= (DewPoint
-32.0)*5.0/9.0;
448 fscanf(fp
, "%lf", &WindChill
);
450 * If WindChill is not available, revert to DewPoint
452 WindChillAvail
= (WindChill
< -900.0) ? 0 : 1;
453 if (Metric
) WindChill
= (WindChill
-32.0)*5.0/9.0;
455 fscanf(fp
, "%lf", &Pressure
); Pressure
+= 0.005;
456 Pressure
*= PressureConv
;
457 fscanf(fp
, "%lf", &Humidity
);
458 fscanf(fp
, "%lf", &Direction
);
459 fscanf(fp
, "%lf", &Speed
);
461 if (MetersPerSecond
) Speed
*= 0.4473;
462 else if (!Beaufort
) Speed
*= 1.609;
468 Temperature
= -9999.0;
491 if ( (dt3
> 5) || ForceUpdate
){
501 copyXPMArea(5, 69, 54, 54, 5, 5);
505 * Paste up Station ID and time of last update.
509 chr
= (int)StationID
[0] - 65; copyXPMArea(chr
*5+2, 128, 5, 6, 7+q
, 6); q
+= 5;
510 chr
= (int)StationID
[1] - 65; copyXPMArea(chr
*5+2, 128, 5, 6, 7+q
, 6); q
+= 5;
511 chr
= (int)StationID
[2] - 65; copyXPMArea(chr
*5+2, 128, 5, 6, 7+q
, 6); q
+= 5;
512 chr
= (int)StationID
[3] - 65; copyXPMArea(chr
*5+2, 128, 5, 6, 7+q
, 6); q
+= 5;
514 if (UpdateLTHour
!= 99){
516 Tens
= (int)(UpdateLTHour
);
517 copyXPMArea(Tens
/10*5+2, 135, 5, 6, 36+q
, 6); q
+= 5;
518 copyXPMArea(Tens
%10*5+2, 135, 5, 6, 36+q
, 6); q
+= 5;
519 copyXPMArea(53, 135, 1, 6, 36+q
, 6); q
+= 2;
520 Tens
= (int)(UpdateLTMin
);
521 copyXPMArea(Tens
/10*5+2, 135, 5, 6, 36+q
, 6); q
+= 5;
522 copyXPMArea(Tens
%10*5+2, 135, 5, 6, 36+q
, 6); q
+= 5;
534 * Paste up Temperature.
536 if ((Temperature
> -999.0)&&(Temperature
< 1000.0)){
537 sgn
= (Temperature
< 0.0) ? -1.0 : 1.0;
539 Temperature
= (double)((int)(Temperature
+ 0.5));
541 if (Temperature
>= 100.0){
542 if (sgn
< 0.0) { copyXPMArea(0*5+66, 35, 5, 6, 25, 15); q
+= 5; }
543 digit
= (int)(Temperature
/100.0);
544 copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 15); q
+= 5;
545 Tens
= (int)(Temperature
-digit
*100.0);
546 copyXPMArea(Tens
/10*5+66, 57, 5, 6, 25+q
, 15); q
+= 5;
547 copyXPMArea(Tens
%10*5+66, 57, 5, 6, 25+q
, 15); q
+= 5;
549 if (sgn
< 0.0) { copyXPMArea(0*5+66, 35, 5, 6, 25, 15); q
+= 5; }
550 Tens
= (int)(Temperature
);
551 if (Tens
>= 10) { copyXPMArea(Tens
/10*5+66, 57, 5, 6, 25+q
, 15); q
+= 5; }
552 copyXPMArea(Tens
%10*5+66, 57, 5, 6, 25+q
, 15); q
+= 5;
555 copyXPMArea(72, 34, 3, 3, 25+q
, 14); q
+= 4;
556 copyXPMArea(81, 35, 4, 6, 25+q
, 15);
558 copyXPMArea(72, 34, 8, 7, 25+q
, 14);
569 * Paste up DewPoint or WindChill Temperature.
571 if (ShowWindChill
&& WindChillAvail
){
573 copyXPMArea(66, 87, 17, 8, 5, 24);
576 copyXPMArea(5, 87, 17, 8, 5, 24);
579 if ((val
> -999.0)&&(val
< 1000.0)){
580 sgn
= (val
< 0.0) ? -1.0 : 1.0;
582 val
= (double)((int)(val
+ 0.5));
585 if (sgn
< 0.0) { copyXPMArea(0*5+66, 57, 5, 6, 25, 24); q
+= 5; }
586 digit
= (int)(val
/100.0);
587 copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 24); q
+= 5;
588 Tens
= (int)(val
-digit
*100.0);
589 copyXPMArea(Tens
/10*5+66, 57, 5, 6, 25+q
, 24); q
+= 5;
590 copyXPMArea(Tens
%10*5+66, 57, 5, 6, 25+q
, 24); q
+= 5;
592 if (sgn
< 0.0) { copyXPMArea(0*5+66, 35, 5, 6, 25, 24); q
+= 5; }
594 if (Tens
>= 10) { copyXPMArea(Tens
/10*5+66, 57, 5, 6, 25+q
, 24); q
+= 5; }
595 copyXPMArea(Tens
%10*5+66, 57, 5, 6, 25+q
, 24); q
+= 5;
598 copyXPMArea(72, 34, 3, 3, 25+q
, 23); q
+= 4;
599 copyXPMArea(81, 35, 4, 6, 25+q
, 24);
601 copyXPMArea(72, 34, 8, 7, 25+q
, 23);
617 if ((Pressure
> 0.0)&&(Pressure
<= 10000.0)){
620 digit
= (int)(val
/1000.0);
621 if (digit
> 0) { copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5; }
622 val
-= (double)digit
*1000;
624 digit
= (int)(val
/100.0);
625 if ((digit
> 0)||(Pressure
> 999.0)) { copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5; }
626 val
-= (double)digit
*100;
628 digit
= (int)(val
/10.0);
629 if ((digit
> 0)||(Pressure
> 99.0)) { copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5; }
630 val
-= (double)digit
*10;
633 copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5;
634 val
-= (double)digit
;
637 if ((PressureUnits
!= 2)||(!Metric
)){
639 copyXPMArea(10*5+66+1, 57, 4, 6, 25+q
, 33); q
+= 4;
641 val
*= 10; digit
= (int)val
;
642 copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5;
643 val
-= (double)digit
;
646 val
*= 10; digit
= (int)val
;
647 copyXPMArea(digit
*5+66, 57, 5, 6, 25+q
, 33); q
+= 5;
648 /* val -= (double)digit; */
665 if ((Humidity
> -999.0)&&(Humidity
<= 100.0)){
666 if (Humidity
== 100.0){
667 copyXPMArea(1*5+66, 57, 5, 6, 25+q
, 42); q
+= 5;
668 copyXPMArea(0*5+66, 57, 5, 6, 25+q
, 42); q
+= 5;
669 copyXPMArea(0*5+66, 57, 5, 6, 25+q
, 42); q
+= 5;
671 Tens
= (int)(Humidity
);
672 if (Tens
>= 10) { copyXPMArea(Tens
/10*5+66, 57, 5, 6, 25+q
, 42); q
+= 5; }
673 copyXPMArea(Tens
%10*5+66, 57, 5, 6, 25+q
, 42); q
+= 5;
675 copyXPMArea(121, 57, 5, 6, 25+q
, 42);
687 * Paste up Wind Info.
689 if ((Direction
== 0.0)&&(Speed
== 0.0)){
692 * Just write out `Calm' if both values are 0
694 copyXPMArea(66, 4, 23, 7, 25, 51);
699 * If the Direction < 0 this means that there was a "Wind direction
700 * Variability Group" found in the METAR code. I.e. Direction is variable.
701 * I think value should be the average. In any case flag it by making it a
704 * Likewise, if Speed < 0, this means that a "Gusty" modifier was found
705 * in the RAW METAR code, and the value is only the average of the low
706 * and high values given. Again, flag it in a different color...
709 if ((Direction
>= -360.0)&&(Direction
<= 360.0)){
710 sgn
= (Direction
< 0.0) ? -1.0 : 1.0;
711 yd
= (sgn
< 0.0) ? 50 : 43;
714 i
= (int)(Direction
/360.0*16.0 + 0.5);
716 strcpy(dir
, CompassDirection
[i
]);
718 for (j
=0; j
<len
; ++j
){
719 digit
= (int)dir
[j
] - 48;
720 copyXPMArea(digit
*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5;
723 } else if (Direction
> 0.0){
726 * In this case, the wind direction is variable with speed < 6 Knots.
727 * A numerical direction is not given in these cases. Just write out 'VRB'.
730 copyXPMArea(4*5+66, 43, 5, 6, 25+q
, 51); q
+= 5;
731 copyXPMArea(5*5+66, 43, 5, 6, 25+q
, 51); q
+= 5;
732 copyXPMArea(6*5+66, 43, 5, 6, 25+q
, 51); q
+= 9;
735 if (Metric
&& Beaufort
) {
739 sgn
= (Speed
< 0.0) ? -1.0 : 1.0;
740 spd
= (int)(sgn
* (int)Speed
);
741 if (spd
> 1) { beau
= 1; }
742 if (spd
> 3) { beau
= 2; }
743 if (spd
> 4) { beau
= 3; }
744 if (spd
> 10) { beau
= 4; }
745 if (spd
> 16) { beau
= 5; }
746 if (spd
> 21) { beau
= 6; }
747 if (spd
> 27) { beau
= 7; }
748 if (spd
> 33) { beau
= 8; }
749 if (spd
> 40) { beau
= 9; }
750 if (spd
> 47) { beau
= 10; }
751 if (spd
> 55) { beau
= 11; }
752 if (spd
> 63) { beau
= 12; }
753 if (spd
> 71) { beau
= 13; }
754 Speed
= sgn
* (double) beau
;
755 q
++; copyXPMArea(76, 35, 4, 6, 25+q
, 51); q
+= 6;
759 if ((Speed
> -999.0)&&(Speed
< 1000.0)){
760 sgn
= (Speed
< 0.0) ? -1.0 : 1.0;
761 yd
= (sgn
< 0.0) ? 64 : 57;
764 digit
= (int)(Speed
/100.0);
765 copyXPMArea(digit
*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5;
766 Tens
= (int)(Speed
-digit
*100.0);
767 copyXPMArea(Tens
/10*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5;
768 copyXPMArea(Tens
%10*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5;
771 if (Tens
>= 10) { copyXPMArea(Tens
/10*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5; }
772 copyXPMArea(Tens
%10*5+66, yd
, 5, 6, 25+q
, 51); q
+= 5;
786 * Make changes visible
797 * Reset "force update" flag
805 * Check every 5 min if the values are not up to date...
808 * We still need to add a flashing LED to warn about
809 * times that are out of date. Also need to determine if it is uptodate...
812 if (((!UpToDate
)&&(dt1
> UpdateDelay
)) || ForceDownload
){
817 * Execute Perl script to grab the Latest METAR Report
819 sprintf(command
, "GrabWeather %s &", StationID
);
832 * Wait for next update
848 void ParseCMDLine(int argc
, char *argv
[]) {
857 UpdateDelay
= DEFAULT_UPDATEDELAY
;
858 for (i
= 1; i
< argc
; i
++) {
860 if (!strcmp(argv
[i
], "-display")){
864 } else if (!strcmp(argv
[i
], "-bc")){
866 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
867 fprintf(stderr
, "wmWeather: No color found\n");
871 strcpy(BackColor
, argv
[++i
]);
873 } else if (!strcmp(argv
[i
], "-tc")){
875 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
876 fprintf(stderr
, "wmWeather: No color found\n");
880 strcpy(StationTimeColor
, argv
[++i
]);
882 } else if (!strcmp(argv
[i
], "-lc")){
884 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
885 fprintf(stderr
, "wmWeather: No color found\n");
889 strcpy(LabelColor
, argv
[++i
]);
891 } else if (!strcmp(argv
[i
], "-wgc")){
893 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
894 fprintf(stderr
, "wmWeather: No color found\n");
898 strcpy(WindGustColor
, argv
[++i
]);
900 } else if (!strcmp(argv
[i
], "-dc")){
902 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
903 fprintf(stderr
, "wmWeather: No color found\n");
907 strcpy(DataColor
, argv
[++i
]);
909 } else if (!strcmp(argv
[i
], "-beaufort")){
913 } else if (!strcmp(argv
[i
], "-mps")){
917 } else if (!strcmp(argv
[i
], "-W")){
921 } else if ((!strcmp(argv
[i
], "-metric"))||(!strcmp(argv
[i
], "-m"))){
925 } else if (!strcmp(argv
[i
], "-kPa")){
928 PressureConv
= 3.38639;
930 } else if (!strcmp(argv
[i
], "-hPa")){
933 PressureConv
= 33.8639;
935 } else if (!strcmp(argv
[i
], "-mmHg")){
940 } else if ((!strcmp(argv
[i
], "-station"))||(!strcmp(argv
[i
], "-s"))){
942 if ((i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
943 fprintf(stderr
, "wmWeather: No METAR station ID found\n");
947 strcpy(StationID
, StringToUpper(argv
[++i
]));
949 } else if (!strcmp(argv
[i
], "-delay")) {
951 if( (i
+1 >= argc
)||(argv
[i
+1][0] == '-')) {
953 fprintf(stderr
,"You must give a time with the -delay option.\n");
957 } else if(sscanf(argv
[i
+1], "%ld", &UpdateDelay
) != 1) {
959 fprintf(stderr
,"Dont understand the delay time you have entered (%s).\n", argv
[i
+1]);
965 * Convert Time to seconds
978 if (StationID
[0] == '\0') {
979 fprintf(stderr
, "\nwmWeather: You must specify a METAR station code\n\n");
984 if ((Metric
)&&(PressureUnits
== 0)){
993 if (Beaufort
&& MetersPerSecond
){
994 fprintf(stderr
, "\nwmWeather: You cant use both -beaufort and -mps together.\n\n");
1004 printf("\nwmWeather version: %s\n", WMWEATHER_VERSION
);
1005 printf("\nusage: wmWeather -s <StationID> [-display <Display>] [-h] [-metric] [-kPa] [-hPa] [-mmHg]\n");
1006 printf(" [-beaufort] [-mps] [-W] [-delay <Time in Minutes>] [-bc <color>]\n");
1007 printf(" [-lc <color>] [-dc <color>] [-wgc <color>] [-tc <color>]\n\n");
1008 printf("\t-display <Display>\t\tUse alternate X display.\n\n");
1009 printf("\t-h\t\t\t\tDisplay help screen.\n");
1010 printf("\n\t-station <METAR StationID>\n");
1011 printf("\t-s <METAR StationID>\tThe 4-character METAR Station ID.\n\n");
1012 printf("\t-W\t\t\t\tIf available, display WindChill instead\n");
1013 printf("\t\t\t\t\tof DewPoint Temperature.\n");
1014 printf("\t-metric\n");
1015 printf("\t-m\t\t\t\tDisplay variables in metric units.\n\n");
1016 printf("\t-kPa\t\t\t\tWhen toggled to metric display, show pressure\n");
1017 printf("\t\t\t\t\tin units of kPa.\n\n");
1018 printf("\t-hPa\t\t\t\tWhen toggled to metric display, show pressure\n");
1019 printf("\t\t\t\t\tin units of hPa.\n\n");
1020 printf("\t-mmHg\t\t\t\tWhen toggled to metric display, show pressure\n");
1021 printf("\t\t\t\t\tin units of mmHg. (This is the default for metric).\n\n");
1022 printf("\t-beaufort\t\t\tWhen toggled to metric display, show windspeed\n");
1023 printf("\t\t\t\t\ton the Beaufort scale. (default is km/h.)\n\n");
1024 printf("\t-mps\t\t\t\tWhen toggled to metric display, show windspeed\n");
1025 printf("\t\t\t\t\tin units of meters/second. (default is km/h.)\n\n");
1026 printf("\t-bc <color>\t\t\tBackground color. (#7e9e69 is a greenish LCD color).\n\n");
1027 printf("\t-lc <color>\t\t\tLabel color.\n\n");
1028 printf("\t-dc <color>\t\t\tData color.\n\n");
1029 printf("\t-wgc <color>\t\t\tGusty-wind/variable-direction color.\n\n");
1030 printf("\t-tc <color>\t\t\tStation ID and Time color.\n\n");
1031 printf("\t-delay <Time in Minutes>\tOverride time (in minutes) between updates (default\n");
1032 printf("\t\t\t\t\tis %ld minutes). (Times are approximate.)\n", DEFAULT_UPDATEDELAY
/60);
1033 printf("\n\nTo find out more about the METAR/TAF system and to find the \n");
1034 printf("METAR code for your location, look at:\n\n");
1035 printf(" http://www.nws.noaa.gov/oso/oso1/oso12/metar.htm \n\n");
1036 printf("for NOAA's ""National Weather Service METAR/TAF Information"" page.\n");
1037 printf("To locate your site ID go to NOAA's ""Meteorological Station Information\nLookup"" page at:\n\n");
1038 printf(" http://www.nws.noaa.gov/oso/siteloc.shtml\n\n");
1050 * Compute the Julian Day number for the given date.
1051 * Julian Date is the number of days since noon of Jan 1 4713 B.C.
1053 double jd(ny
, nm
, nd
, UT
)
1057 double A
, B
, C
, D
, JD
, day
;
1062 if ((nm
== 1) || (nm
== 2)){
1067 if (((double)ny
+nm
/12.0+day
/365.25)>=(1582.0+10.0/12.0+15.0/365.25)){
1068 A
= ((int)(ny
/ 100.0));
1069 B
= 2.0 - A
+ (int)(A
/4.0);
1075 C
= (int)((365.25*(double)ny
) - 0.75);
1078 C
= (int)(365.25*(double)ny
);
1081 D
= (int)(30.6001*(double)(nm
+1));
1084 JD
= B
+ C
+ D
+ day
+ 1720994.5;
1092 * This routine handles button presses.
1094 * - Left Mouse single click toggles Deg F/C for temperatures.
1095 * - Some other click event should display the full METAR report -- lots of
1096 * juicy stuff in there... Should bring up a separate window...
1100 void ButtonPressEvent(XButtonEvent
*xev
){
1105 * Process single clicks.
1108 if ((xev
->button
== Button1
) && (xev
->type
== ButtonPress
)){
1110 if (GotFirstClick1
) GotDoubleClick1
= 1;
1111 else GotFirstClick1
= 1;
1113 } else if ((xev
->button
== Button2
) && (xev
->type
== ButtonPress
)){
1115 if (GotFirstClick2
) GotDoubleClick2
= 1;
1116 else GotFirstClick2
= 1;
1118 } else if ((xev
->button
== Button3
) && (xev
->type
== ButtonPress
)){
1120 if (GotFirstClick3
) GotDoubleClick3
= 1;
1121 else GotFirstClick3
= 1;
1129 * We got a double click on Mouse Button1 (i.e. the left one)
1131 if (GotDoubleClick1
) {
1133 GotDoubleClick1
= 0;
1134 sprintf(Command
, "xmessage -center -file %s/.wmWeatherReports/%s.TXT &", getenv("HOME"), StationID
);
1140 * We got a double click on Mouse Button2 (i.e. the left one)
1142 if (GotDoubleClick2
) {
1144 GotDoubleClick2
= 0;
1149 * We got a double click on Mouse Button3 (i.e. the left one)
1151 if (GotDoubleClick3
) {
1153 GotDoubleClick3
= 0;
1167 * This routine handles key presses.
1170 void KeyPressEvent(XKeyEvent
*xev
){
1178 switch(PressureUnits
){
1179 case 0: PressureConv
= 25.4;
1182 case 1: PressureConv
= 3.38639;
1185 case 2: PressureConv
= 33.8639;
1188 case 3: PressureConv
= 25.4;
1192 } else if (!Metric
){
1207 char *StringToUpper(char *String
) {
1211 for (i
= 0; i
< strlen(String
); i
++)
1212 String
[i
] = toupper(String
[i
]);