wmweather+: Remove from repository.
This dockapp is still maintained by its original upstream author, Brad Jorsch, and a newer version (2.15) is available at [1]. Therefore, it is not appropriate for the Window Maker dockapps repository. [1] https://sourceforge.net/projects/wmweatherplus/
This commit is contained in:
parent
89c9512c8d
commit
fdb596cd42
77 changed files with 0 additions and 9897 deletions
dockapps.db.in
wmweather+
COPYINGChangeLogHINTSMakefile.amREADMEanimation.canimation.havn.cavn.h
b0rken
bootstrapcharacters.xpmconfigure.acconvert.cconvert.hdie.cdie.hdiff.cdiff.hdock.cdock.hdownload.cdownload.heta.ceta.hexample.conffont.cfont.hforecast.cforecast.hgetLine.cgetLine.hm4
metar.cmetar.hmoon.cmoon.hmrf.cmrf.hradar.cradar.hsubst.csubst.hsunzenith.csunzenith.hwarnings.cwarnings.hwmgeneral
Makefile.ammouse_regions.cmouse_regions.hrcfile.crcfile.hwmgeneral-gtk.cwmgeneral-gtk.hwmgeneral-x11.cwmgeneral-x11.hwmgeneral.cxpm_trans.cxpm_trans.h
wmweather+.1.inwmweather+.cwmweather+.hwmweather_master.xpm
|
@ -434,15 +434,6 @@ url = https://web.archive.org/web/20091027110712/http://geocities.com/jl1n/wmtz/
|
|||
dockapps = 24
|
||||
category = Date/Time
|
||||
|
||||
[wmweather+]
|
||||
image = "wmweather+.png,wmweather+2.png,wmweather+4.png"
|
||||
description = "wmweather+ will download the National Weather Serivce METAR bulletins, ANV and MRF forecasts, and any weather map for display in a WindowMaker dockapp. Think wmweather with a smaller font, forecasts, a weather map, and a sky condition display.
|
||||
|
||||
Please see the sourceforge page for the latest version."
|
||||
url = https://sourceforge.net/projects/wmweatherplus/
|
||||
dockapps = 112
|
||||
category = General/Others
|
||||
|
||||
[wmWeather]
|
||||
image = wmWeather.gif
|
||||
description = "Shows local weather conditions."
|
||||
|
|
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -1,247 +0,0 @@
|
|||
wmweather+ (2.12) unstable; urgency=low
|
||||
|
||||
* Remove curl handle from the multihandle before closing the file
|
||||
descriptor and before doing the callbacks. Otherwise we might get another
|
||||
completion message, which will cause double-free errors and such.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Tue, 17 Aug 2010 15:27:37 -0400
|
||||
|
||||
wmweather+ (2.11) unstable; urgency=low
|
||||
|
||||
* Apply 01_wmweather+_patch_displaydelay.dpatch from Debian
|
||||
* Fix Debian bug #419644 in a different way: First, change snprintf and
|
||||
vsnprintf handling to be more like AC_FUNC_MALLOC handles malloc. Second,
|
||||
just always call FUNC_VSNPRINTF_LIBOBJ instead of being conditional on
|
||||
snprintf.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Fri, 18 Jan 2008 10:30:05 -0500
|
||||
|
||||
wmweather+ (2.10) unstable; urgency=low
|
||||
|
||||
* Remove libwww, add libcurl.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sun, 06 Jan 2008 22:42:07 -0500
|
||||
|
||||
wmweather+ (2.9) unstable; urgency=low
|
||||
|
||||
* Add support for the new FW/SC distinction in some of the forecast data.
|
||||
Also do it for METAR, even though the two are supposedly the same there.
|
||||
* Fix some nasty double-free bugs in download.c if terminate_handler were to
|
||||
be called before HTLoadAbsolute/HTPostAbsolute returned.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Mon, 17 May 2004 23:55:48 -0400
|
||||
|
||||
wmweather+ (2.8) unstable; urgency=low
|
||||
|
||||
* The downloader now tracks active downloads, and refuses to start a second
|
||||
download when one is already active for a particular target file. Also,
|
||||
downloads now time out after 10 minutes.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Mon, 29 Mar 2004 22:22:31 -0500
|
||||
|
||||
wmweather+ (2.7) unstable; urgency=low
|
||||
|
||||
* Oops, forgot to fix the manpage when the URIs changed in v2.5.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Fri, 21 Nov 2003 20:55:07 -0500
|
||||
|
||||
wmweather+ (2.6) unstable; urgency=low
|
||||
|
||||
* Use atexit() to clean up downloaded files.
|
||||
* Alter forecast parsers to be less picky. 'AVN' and 'MRF' are changing to
|
||||
'GFS' and 'GFSX' on Dec 16, and looking for just "MOS GUIDANCE" instead of
|
||||
"xxx MOS GUIDANCE" should work about as well.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Fri, 21 Nov 2003 20:55:07 -0500
|
||||
|
||||
wmweather+ (2.5) unstable; urgency=low
|
||||
|
||||
* Added the "-display-mode" option. This fixes part of Debian bug #200110.
|
||||
* Tack the PID on to downloaded files, so multiple instances of wmweather+
|
||||
won't stomp on each other. This fixes the rest of Debian bug #200110
|
||||
* Rewrote the longitude-guessing code, now it just depends on time_t being
|
||||
an arithmetic type (which mkgmtime() did already).
|
||||
* Replace the old b0rken/mktime.c with the one from GNU tar. The old one has
|
||||
a SysVism that wasn't working too well for BSD people, who need the
|
||||
replacement because mktime() on BSD fails for 'impossible' times (i.e. the
|
||||
hour skipped when DST begins).
|
||||
* Change forecast URIs, because NOAA changed them.
|
||||
* Add a 'forget-warning-zones' option, which IMO adequately covers Debian
|
||||
bug #214482. And it allows you to override zones on the command line too.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Tue, 28 Oct 2003 13:35:24 -0500
|
||||
|
||||
wmweather+ (2.4) unstable; urgency=low
|
||||
|
||||
* Remove a bunch of unused variables.
|
||||
* Initialize a few things the compiler can't tell will always be initialized
|
||||
before they're used.
|
||||
- dock.c update_dock(): i will be initialized if either j&1 or j&2, and
|
||||
only used if j&3. j is not volatile, so this will always initialize i.
|
||||
- forecast.c locate_current(): current is set to NULL at the beginning of
|
||||
the function. curdiff is set whenever current is, and is only used when
|
||||
current!=NULL.
|
||||
* Added .nf commands to the manpage, so man won't complain about long
|
||||
pseudo-URLs (Fixes Debian bug #184306).
|
||||
* Fixed various assumptions about char signedness (i.e. I made them
|
||||
explicitly signed char) (Fixes Debian bug #181245).
|
||||
* Added multiple warning zones, so for example you can look at both kyz036
|
||||
and kyc209 for warnings (Partially fixes Debian bug #185651).
|
||||
- The summary isn't so much a warning summary, as a summary of the weather
|
||||
over the past day or so.
|
||||
- Unless those "warnings not in the expected place" were due to the kyc209
|
||||
versus kyz036 issue, I can't determine where the files might actually
|
||||
have been. Sorry.
|
||||
* Updated some of the docs.
|
||||
* autoconf changed the name of the malloc cache variable...
|
||||
* Added a replacement mktime. Hopefully it works right.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sat, 22 Mar 2003 12:45:10 -0500
|
||||
|
||||
wmweather+ (2.3) unstable; urgency=low
|
||||
|
||||
* Fix a compiler warning, thanks to Martin Godisch
|
||||
* Remove the debian directory at the request of the Debian maintainer; if
|
||||
you want those files, they are available at debian.org
|
||||
* Removed documentation of useless -geometry option
|
||||
* Fixed crash on right-click when no warning zone was given
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Tue, 28 Jan 2003 12:47:07 -0500
|
||||
|
||||
wmweather+ (2.2) unstable; urgency=low
|
||||
|
||||
* It seems I forgot to create a b0rken/malloc.c
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Tue, 1 Oct 2002 16:36:12 -0400
|
||||
|
||||
wmweather+ (2.1) unstable; urgency=low
|
||||
|
||||
* Make the 'malformed location' error message more clear.
|
||||
* Fix stupid crash in forecast.c (didn't wrap properly when iterating over
|
||||
an array)
|
||||
* Fix is_forecast_current, mktime wants 0-based month.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Mon, 30 Sep 2002 15:02:29 -0400
|
||||
|
||||
wmweather+ (2.0) unstable; urgency=low
|
||||
|
||||
* In no particular order:
|
||||
* Animations can now display a label indicating the percent being shown. The
|
||||
forecast window uses this extensively.
|
||||
* All URIs can now be changed via command line/config file options.
|
||||
* Added ./configure checks for b0rken snprintf/vsnprintf.
|
||||
* Added ETA forecasts. These are mixed in with the AVN forecasts in the
|
||||
rotation, sorted by time.
|
||||
* Added display of the forecast type, which shows up at the bottom of the
|
||||
forecast window where wind chill, heat index, and so on appear.
|
||||
* When not animating, the percent chance cutoff can be adjusted using the
|
||||
mouse wheel (as mapped to buttons 4 and 5).
|
||||
* Made all forecast and warning options optional. Thus, if you don't specify
|
||||
e.g. avn-station, no AVN forecasts will be downloaded.
|
||||
* Regularized options: -radar is now -radar-uri, and -zone is now
|
||||
-warning-zone.
|
||||
* Support for POST for the radar image.
|
||||
* Support for system-wide configs.
|
||||
* -email is now optional too.
|
||||
* Lots of code cleanups.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sun, 22 Sep 2002 14:25:58 -0400
|
||||
|
||||
wmweather+ (1.11) unstable; urgency=low
|
||||
|
||||
* Fix a few URIs.
|
||||
* Fix rounding errors in the pressure conversion functions (returned floats
|
||||
don't need to be rounded, damnit!)
|
||||
* Fix a bug in the warning code (displaying the wrong warnings)
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sun, 15 Sep 2002 18:35:18 -0400
|
||||
|
||||
wmweather+ (1.10) unstable; urgency=low
|
||||
|
||||
* Handle libwww fds going bad, so the select will still function.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sun, 8 Sep 2002 11:22:05 -0400
|
||||
|
||||
wmweather+ (1.9) unstable; urgency=low
|
||||
|
||||
* Remove dependancy on libftp, we use libwww's FTP module now.
|
||||
* Rewrote the file downloader to take advantage of libwww's callbacks
|
||||
(instead of waiting for the file to appear).
|
||||
* Adjusted the m4 files to be more informative, and to check for libwraster
|
||||
in /usr/X11R6 (stupid place for it, but oh well).
|
||||
* Add some international METAR support. Mainly things reported in different
|
||||
units.
|
||||
* Make dock.c signals safe!
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Thu, 5 Sep 2002 22:01:42 -0400
|
||||
|
||||
wmweather+ (1.8) unstable; urgency=low
|
||||
|
||||
* Added failure conditions to configure.ac.
|
||||
* Actually use LIBOBJS. Change to automake-1.6 since 1.4 is b0rken.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Sun, 1 Sep 2002 20:31:55 -0400
|
||||
|
||||
wmweather+ (1.7) unstable; urgency=low
|
||||
|
||||
* Initial Debianization
|
||||
* Autoconfiscated
|
||||
* Updated wmgeneral from wmpasman
|
||||
* Fixed a bug in createXBMfromXPM
|
||||
* Use createXBMfromXPM to get the mask. It's easier.
|
||||
|
||||
-- Brad Jorsch <anomie@users.sourceforge.net> Thu, 15 Aug 2002 15:31:46 -0400
|
||||
|
||||
version 1.6
|
||||
|
||||
* Apparently, AVN uses JUNE instead of JUN. Let's guess it uses JULY too
|
||||
while we're at it.
|
||||
|
||||
-- Tue, 18 Jun 2002 08:52:27 -0500
|
||||
|
||||
version 1.5
|
||||
|
||||
* Fixed heat index so it'll display when the temp is below 100 ;)
|
||||
|
||||
-- Tue, 16 Apr 2002 21:22:07 -0500
|
||||
|
||||
version 1.4
|
||||
|
||||
* Changed the METAR display around a little bit. Local time is now primary.
|
||||
* Changed the warning output to indicate the file the warning is from.
|
||||
* minor code cleanups
|
||||
|
||||
-- Sat, 8 Sep 2001 17:14:32 -0500
|
||||
|
||||
version 1.3
|
||||
|
||||
* Display a moon instead of a sun when it's supposed to be night. We even
|
||||
calculate a rough moon phase and calculate the solar zenith to determine
|
||||
whether the sun is up or not.
|
||||
* Adjusted some of the graphics again. master is even smaller now!
|
||||
* Make the forecast bottom line change priority every few seconds (in other
|
||||
words, if more than one line could be displayed it will alternate between
|
||||
them).
|
||||
|
||||
-- Thu, 6 Sep 2001 22:55:10 -0500
|
||||
|
||||
version 1.2
|
||||
|
||||
* Fixed SEPT bug
|
||||
|
||||
-- Sat, 1 Sep 2001 21:10:22 -0500
|
||||
|
||||
version 1.1
|
||||
|
||||
* Made the master xpm smaller.
|
||||
* Changed the font handling so only 1 copy of the characters is needed.
|
||||
* Changed some of the wmgeneral stuff more.
|
||||
|
||||
-- Tue, 28 Aug 2001 12:46:54 -0500
|
||||
|
||||
version 1.0
|
||||
|
||||
* Wrote the thing over the past few weeks. I probably should have been
|
||||
adding changelog entries all along, oh well.
|
||||
|
||||
-- Tue, 21 Aug 2001 18:36:32 -0500
|
|
@ -1,74 +0,0 @@
|
|||
Hints for wmweather+
|
||||
|
||||
(blatantly copied from the Hints for WMPPP ;)
|
||||
|
||||
Generic
|
||||
--------------------------------------------------------------
|
||||
wmweather+ supports various commandline options, 'wmweather+ -h' prints
|
||||
help about them. Actually, any unrecognized option will print the same help.
|
||||
|
||||
WindowMaker
|
||||
--------------------------------------------------------------
|
||||
WindowMaker users simply drag and drop the wmweather+ dock.app on
|
||||
the WindowMaker Dock (preferred) or the Clip.
|
||||
|
||||
Now press the rightmouse button on wmweather+'s outer edges and
|
||||
select "Settings..." from the popup menu that appears.
|
||||
|
||||
Enable the 'Start when WindowMaker is started' option, then
|
||||
click on the 'OK' button in the Docked Applications Panel.
|
||||
|
||||
Afterstep
|
||||
--------------------------------------------------------------
|
||||
Afterstep users put something like this in their .steprc
|
||||
"Wharf wmweather+ - MaxSwallow "wmweather+" wmweather+ &"
|
||||
|
||||
Other WindowManagers
|
||||
--------------------------------------------------------------
|
||||
For other windowmanagers, wmweather+ runs nicely as a 64x64
|
||||
pixel shaped icon on your desktop.
|
||||
|
||||
BTW, FVWM can swallow it too, so we've heard ;-)
|
||||
|
||||
Dragging wmweather+
|
||||
--------------------------------------------------------------
|
||||
Be sure to drag wmweather+ on it's outer edges, wmweather+ is a bit
|
||||
picky due to the large gfx pixmap it keeps ;-)
|
||||
|
||||
Network Usage
|
||||
--------------------------------------------------------------
|
||||
wmweather+ is really rather useless without network access, since it
|
||||
has to download everything it wants to display...
|
||||
|
||||
Command Line
|
||||
--------------------------------------------------------------
|
||||
Remember to quote your arguments properly. For example, this command:
|
||||
wmweather+ -s KORD -location 48N 78W
|
||||
Will be interpreted as passing the value "48N" to the "-location" option.
|
||||
wmweather+ will then complain that the location is badly formed. Instead, try
|
||||
quoting any options containing spaces like this:
|
||||
wmweather+ -s KORD -location "48N 78W"
|
||||
|
||||
Config File
|
||||
--------------------------------------------------------------
|
||||
You may have noticed wmweather+ has an insane number of command line
|
||||
options. You may also have noticed the comment in the manpage along the
|
||||
lines of "The configuration file is simply one option (with value if
|
||||
necessary) per line, leading dashes optional. Empty lines and lines
|
||||
beginning with the '#' character are ignored." This means just what it says:
|
||||
your configuration file should contain your command line options, with one
|
||||
option per line.
|
||||
|
||||
See the file example.conf for a sample configuration file.
|
||||
|
||||
Font Size
|
||||
--------------------------------------------------------------
|
||||
If you think the fonts are too small, you are welcome to redesign the
|
||||
display and the font. Please keep in mind the following constraints:
|
||||
* The window size is limited to 64x64. Taking off the border, that means
|
||||
you get about 54x54 pixels to work with.
|
||||
* I require the app to display at least the station ID, the effective
|
||||
date and time of the observarion/forecast, the weather graphic, the
|
||||
temperature (and high and low for forecasts), the relative humidity, and
|
||||
the wind speed+direction. At least one extra line is needed for
|
||||
pressure/heat index/wind chill/precip amount as appropriate.
|
|
@ -1,21 +0,0 @@
|
|||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = b0rken m4 wmgeneral
|
||||
|
||||
bin_PROGRAMS = wmweather+
|
||||
|
||||
wmweather__SOURCES = animation.c animation.h avn.c avn.h convert.c convert.h \
|
||||
die.c die.h diff.c diff.h dock.c dock.h download.c download.h \
|
||||
eta.c eta.h font.c font.h forecast.c forecast.h getLine.c getLine.h \
|
||||
metar.c metar.h moon.c moon.h mrf.c mrf.h radar.c radar.h subst.c \
|
||||
subst.h sunzenith.c sunzenith.h warnings.c warnings.h wmweather+.c \
|
||||
wmweather+.h characters.xpm wmweather_master.xpm
|
||||
wmweather__LDADD = wmgeneral/libwmgeneral.a wmgeneral/libwmgeneral-x11.a b0rken/libb0rken.a @XLIBS@
|
||||
|
||||
man_MANS = wmweather+.1
|
||||
EXTRA_DIST = HINTS bootstrap example.conf $(man_MANS)
|
||||
|
||||
reallyclean: distclean
|
||||
-rm -rf autom4te.cache
|
||||
-rm Makefile.in */Makefile.in aclocal.m4 config.h.in* config.guess config.sub configure install-sh ltmain.sh missing mkinstalldirs stamp-h.in
|
|
@ -1,43 +0,0 @@
|
|||
COMPILATION
|
||||
===========
|
||||
|
||||
You will need the following libraries (with proper headers) installed
|
||||
in order to compile this app. If you're using Debian, try packages like
|
||||
the ones indicated.
|
||||
libwraster libwraster2, libwraster2-dev
|
||||
libpcre libpcre3, libpcre3-dev
|
||||
libm libc6, libc6-dev
|
||||
libXpm xlibs, xlibs-dev
|
||||
libX11 xlibs, xlibs-dev
|
||||
libcurl libcurl4, libcurl4-dev
|
||||
|
||||
For the most part, you should just have to do "./configure && make install"
|
||||
and the thing will build everything and install it.
|
||||
|
||||
The only really interesting compile-time parameters would be the P and X
|
||||
variables in animation.c, if you don't like the 10-second cycle or
|
||||
something.
|
||||
|
||||
If you get errors about a missing libwraster, check the following:
|
||||
1) Do you have both the library AND the header installed? If the command
|
||||
"locate wraster.h" doesn't come back with a header file in one of the
|
||||
normal places, you'll have trouble.
|
||||
2) Check for a line like the following in your ./configure output:
|
||||
checking if libwraster is wanted... yes: libraries /usr/lib includes /usr/include
|
||||
In this case, we will look for the files /usr/lib/libwraster.so and
|
||||
/usr/include/wraster.h. If for some reason you have these files in a
|
||||
place other than ./configure looks for them, use the --with-libwraster
|
||||
option to specify the proper prefix. If you have something really dumb
|
||||
like /usr/include/wraster.h and /usr/X11R6/lib/libwraster.so, try adding
|
||||
specific -I and -L options to your CFLAGS variable.
|
||||
|
||||
If you get errors about a missing pcre.h, and you have your header in
|
||||
/usr/include/pcre/pcre.h instead of /usr/include/pcre.h, you will have to
|
||||
add "-I/usr/include/pcre" to your CFLAGS variable when running ./configure.
|
||||
|
||||
If you get an error about anything missing in the b0rken subdirectory, the
|
||||
problem is most likely that some library function or another is broken on
|
||||
your system, configure detected this fact, a replacement was requested, and
|
||||
no replacement is available. You are welcome to submit a patch.
|
||||
|
||||
For run-time hints, please see the HINTS file.
|
|
@ -1,138 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "wmgeneral/wmgeneral-x11.h"
|
||||
#include "wmgeneral/xpm_trans.h"
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "animation.h"
|
||||
#include "moon.h"
|
||||
#include "font.h"
|
||||
|
||||
#define P 4 /* Percent to increment by */
|
||||
#define X 4 /* Frames to wait before incrementing */
|
||||
#define M (((100/P)+1)*X)
|
||||
|
||||
static int heights[5]={ 11, 12, 14, 14, 19 };
|
||||
|
||||
void SetAnimation(struct animation *a, int x, int y, int sky, int obs, int vis,
|
||||
int frz, int snow, int rain, int tstorm, int svtstorm,
|
||||
double moon){
|
||||
int i;
|
||||
|
||||
a->changed=1;
|
||||
a->active=1;
|
||||
a->x=x;
|
||||
a->y=y;
|
||||
if(sky>=0 && sky<6) a->sky=sky*27;
|
||||
else a->sky=-1;
|
||||
if(vis<7 && obs>0 && vis>0 && obs<4){
|
||||
a->obs=obs*27-27;
|
||||
a->vis=256-236*(vis-1)/6;
|
||||
} else a->vis=0;
|
||||
|
||||
a->items[0]=frz;
|
||||
a->items[1]=snow;
|
||||
a->items[2]=rain;
|
||||
a->items[3]=tstorm;
|
||||
a->items[4]=svtstorm;
|
||||
for(i=0; i<5; i++){
|
||||
if(a->items[i]==0) continue;
|
||||
if(a->items[i]%P) a->items[i]=a->items[i]/P+1;
|
||||
else a->items[i]=a->items[i]/P;
|
||||
a->items[i]*=X;
|
||||
if(a->items[i]!=0) a->changed=1;
|
||||
}
|
||||
a->ac=0;
|
||||
a->moon=moon;
|
||||
}
|
||||
|
||||
void DoAnimation(struct animation *a){
|
||||
int i;
|
||||
int top, h;
|
||||
|
||||
/* Turned off? */
|
||||
if(!a->active) return;
|
||||
|
||||
/* Any parameters changed? If yes, draw */
|
||||
if(a->changed) goto doit;
|
||||
|
||||
/* Nothing changed, quit if not animating */
|
||||
if(!a->do_animate) return;
|
||||
|
||||
/* We are animating. If it's the first frame of a cycle, draw it */
|
||||
a->ac++; if(a->ac>=M){ a->ac=0; goto doit; }
|
||||
|
||||
/* Not the first frame, see if anything changed. If so, draw it */
|
||||
for(i=0; i<5; i++){
|
||||
if(a->ac>=a->items[i] && a->ac<=a->items[i]+X) goto doit;
|
||||
}
|
||||
|
||||
/* Just draw the counter... */
|
||||
if(a->show_counter) goto do_counter;
|
||||
|
||||
/* Nothing to draw, quit */
|
||||
return;
|
||||
|
||||
doit:
|
||||
if(a->min_pct!=a->old_pct){
|
||||
if(a->min_pct%P) a->pct=(a->min_pct/P+1)*X;
|
||||
else a->pct=(a->min_pct/P)*X;
|
||||
a->old_pct=a->min_pct;
|
||||
}
|
||||
a->changed=0;
|
||||
|
||||
if(!a->do_animate) a->ac=a->pct;
|
||||
copyPixmapArea(124, 18, 26, 31, a->x, a->y);
|
||||
if(a->sky!=-1){
|
||||
copySunMoon(a->x, a->y, a->moon);
|
||||
combineWithTrans(a->sky, 64, 26, 25, a->x, a->y);
|
||||
}
|
||||
if(a->vis>0) combineWithOpacity(a->obs, 89, 26, 25, a->x, a->y, a->vis);
|
||||
for(i=0; i<5; i++){
|
||||
if(a->items[i]==0 || a->ac>=a->items[i]+X) continue;
|
||||
h=heights[i];
|
||||
top=h;
|
||||
if(a->ac<X){
|
||||
h=h*a->ac/X;
|
||||
} else if(a->ac>=a->items[i] && a->ac<a->items[i]+X){
|
||||
h-=h*(a->ac%X)/X;
|
||||
top=h;
|
||||
}
|
||||
combineWithTrans(i*27, 129-top, 26, h, a->x, a->y+31-top);
|
||||
}
|
||||
if(a->show_counter){{
|
||||
char foo[5];
|
||||
do_counter:
|
||||
if(!a->do_animate){
|
||||
snprintf(foo, 5, "%d%%", a->min_pct);
|
||||
} else {
|
||||
for(i=0; i<100 && a->ac>((i+P-1)/P)*X; i++);
|
||||
snprintf(foo, 5, "%d%%", i);
|
||||
}
|
||||
i=GetStringWidth(foo);
|
||||
copyPixmapArea(124, 18, i+2, 7, a->x+(26-i-2)/2, a->y+12);
|
||||
DrawString(a->x+(26-i)/2, a->y+13, foo, 2);
|
||||
}}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
struct animation {
|
||||
int do_animate:1; /* animate, or use min_pct? */
|
||||
int show_counter:1; /* display the percentage counter? */
|
||||
unsigned int min_pct:7; /* when not animating, show any occurence with more
|
||||
than this percent chance */
|
||||
int changed:1; /* Set this if you change any of the above */
|
||||
|
||||
int active:1;
|
||||
int x, y;
|
||||
int sky;
|
||||
int obs;
|
||||
int vis;
|
||||
int items[5];
|
||||
int ac;
|
||||
double moon;
|
||||
unsigned int old_pct:7;
|
||||
int pct;
|
||||
};
|
||||
|
||||
void SetAnimation(struct animation *a, int x, int y, int sky, int obs, int vis,
|
||||
int frz, int snow, int rain, int tstorm, int svtstorm,
|
||||
double moon);
|
||||
void DoAnimation(struct animation *a);
|
373
wmweather+/avn.c
373
wmweather+/avn.c
|
@ -1,373 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "forecast.h"
|
||||
#include "getLine.h"
|
||||
#include "convert.h"
|
||||
#include "download.h"
|
||||
#include "diff.h"
|
||||
#include "die.h"
|
||||
#include "sunzenith.h"
|
||||
#include "moon.h"
|
||||
#include "subst.h"
|
||||
|
||||
/* Important variables */
|
||||
#define AVN_MAX 21
|
||||
static time_t avn_time=0;
|
||||
static char *avn_file=NULL;
|
||||
static char *avn_newfile=NULL;
|
||||
static char *avn_req[2]={ NULL, NULL };
|
||||
static struct forecast forecasts[AVN_MAX];
|
||||
|
||||
|
||||
/********* init functions ************/
|
||||
static int parse_avn(char *file);
|
||||
|
||||
static void reset_avn(void){
|
||||
int i;
|
||||
|
||||
for(i=0; i<AVN_MAX; i++) reset_forecast(&forecasts[i]);
|
||||
}
|
||||
|
||||
void init_avn(void){
|
||||
char *e;
|
||||
int i;
|
||||
struct subst_val subs[]={
|
||||
{ 's', STRING, &avn_station },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
strncpy(bigbuf, avn_station, BIGBUF_LEN-14);
|
||||
bigbuf[BIGBUF_LEN-14]='\0';
|
||||
for(e=bigbuf; *e!='\0'; e++);
|
||||
strcpy(e, ".avn.txt");
|
||||
avn_file=get_pid_filename(bigbuf);
|
||||
strcpy(e, ".new-avn.txt");
|
||||
avn_newfile=get_pid_filename(bigbuf);
|
||||
|
||||
if((avn_req[0]=subst(avn_uri, subs))==NULL) die("init_avn");
|
||||
if(avn_post!=NULL && (avn_req[1]=subst(avn_post, subs))==NULL) die("init_avn");
|
||||
avn_time=0;
|
||||
|
||||
/* Remove stale file */
|
||||
unlink(avn_file);
|
||||
unlink(avn_newfile);
|
||||
reset_avn();
|
||||
for(i=0; i<AVN_MAX; i++) add_forecast(&forecasts[i], "AVN", avn_station);
|
||||
}
|
||||
|
||||
|
||||
/********* download functions ************/
|
||||
|
||||
static void avn_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(avn_newfile, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& diff(avn_newfile, avn_file) && parse_avn(avn_newfile)){
|
||||
avn_time=find_next_time(avn_newfile, "MOS GUIDANCE", 720);
|
||||
rename(avn_newfile, avn_file);
|
||||
} else {
|
||||
unlink(avn_newfile);
|
||||
if(!parse_avn(avn_file)) reset_avn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void avn_cleanup(void){
|
||||
if(avn_file==NULL) return;
|
||||
unlink(avn_newfile);
|
||||
unlink(avn_file);
|
||||
}
|
||||
|
||||
void update_avn(int force){
|
||||
time_t t;
|
||||
|
||||
if(avn_file==NULL) return;
|
||||
|
||||
t=time(NULL)/60;
|
||||
if(!force && avn_time>t) return;
|
||||
|
||||
avn_time=find_next_time(avn_file, "MOS GUIDANCE", 15);
|
||||
download_file(avn_newfile, avn_req[0], avn_req[1], force?DOWNLOAD_KILL_OTHER_REQUESTS:0, avn_callback, NULL);
|
||||
}
|
||||
|
||||
|
||||
/********* parse functions ************/
|
||||
|
||||
#define NEXT(s) free(s); \
|
||||
len=getLine(&s, fp); \
|
||||
if(strstr(s, "</PRE>")!=NULL) len=0;
|
||||
|
||||
#define DIE() return (free(s), fclose(fp), 0)
|
||||
#define SPLIT(s) { \
|
||||
ID[0]=s[0]; \
|
||||
ID[1]=s[1]; \
|
||||
ID[2]=s[2]; \
|
||||
ID[3]='\0'; \
|
||||
for(n=0, c=s+4; c<s+len && n<AVN_MAX; n++, c+=3){ \
|
||||
split[n][0]=c[0]; \
|
||||
split[n][1]=c[1]; \
|
||||
split[n][2]=c[2]; \
|
||||
split[n][3]='\0'; \
|
||||
} \
|
||||
}
|
||||
#define ASSIGN(field) \
|
||||
for(n=0; n<AVN_MAX; n++) forecasts[n].field=atoi(split[n]);
|
||||
|
||||
#define ASSIGN2(field, inval) \
|
||||
for(n=0; n<AVN_MAX; n++){ \
|
||||
i=atoi(split[n]); \
|
||||
if(i!=inval) forecasts[n].field=i; \
|
||||
}
|
||||
|
||||
static int parse_avn(char *file){
|
||||
FILE *fp;
|
||||
char *s, *c;
|
||||
int len;
|
||||
int mon, day;
|
||||
int h, i=0, j, k, m, n, x, y, z;
|
||||
char ID[4];
|
||||
char split[AVN_MAX][4];
|
||||
|
||||
reset_avn();
|
||||
if((fp=fopen(file, "r"))==NULL) return 0;
|
||||
|
||||
/* Look for something like an AVN coded forecast */
|
||||
c=NULL;
|
||||
while(!feof(fp)){
|
||||
len=getLine(&s, fp);
|
||||
if((c=strstr(s, "MOS GUIDANCE"))!=NULL) break;
|
||||
free(s);
|
||||
}
|
||||
if(c==NULL) return (fclose(fp), 0);
|
||||
c=strchr(c, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
m=atoi(c-2);
|
||||
c=strchr(c+1, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
y=atoi(c+1)-1900;
|
||||
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
if(strncmp(s, "DT ", 3)) DIE();
|
||||
mon=13;
|
||||
c=s;
|
||||
i=4;
|
||||
while(mon>12){
|
||||
c=strchr(c+1, '/');
|
||||
if(c==NULL) DIE();
|
||||
for(mon=1; mon<=12; mon++){
|
||||
if(!strncmp(c+1, monthnames[mon], 3) && isspace(*(c+4))) break;
|
||||
if(!strncmp(c+1, monthnames2[mon], 4) && isspace(*(c+5))){
|
||||
i=5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
day=atoi(c+i);
|
||||
if(day<1) DIE();
|
||||
if(c>s+4) day--;
|
||||
if(mon<m) y++;
|
||||
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
if(strncmp(s, "HR ", 3)) DIE();
|
||||
x=day;
|
||||
m=mon;
|
||||
SPLIT(s);
|
||||
for(n=0; n<AVN_MAX; n++){
|
||||
i=atoi(split[n]);
|
||||
if(i==0){
|
||||
x++;
|
||||
fix_date(&mon, &x, &y, NULL);
|
||||
}
|
||||
m=mon;
|
||||
j=x;
|
||||
z=y;
|
||||
h=utc2local(i*100, &m, &j, &z, &k)/100;
|
||||
forecasts[n].month=m;
|
||||
forecasts[n].day=j;
|
||||
forecasts[n].year=z;
|
||||
forecasts[n].hour=h;
|
||||
forecasts[n].wday=k;
|
||||
if(latitude!=999 && calcSolarZenith(latitude, longitude, y, mon, x, i*60)>90)
|
||||
forecasts[n].moon=calc_moon(m, j, z, h*100);
|
||||
}
|
||||
|
||||
while(1){
|
||||
NEXT(s);
|
||||
if(len<=10) break;
|
||||
SPLIT(s);
|
||||
|
||||
if(!strcmp(ID, "X/N")) j=1;
|
||||
else if(!strcmp(ID, "N/X")) j=2;
|
||||
else j=0;
|
||||
if(j!=0){
|
||||
for(n=0; n<AVN_MAX; n++){
|
||||
if(!isdigit(split[n][2])) continue;
|
||||
i=atoi(split[n]);
|
||||
k=day+(j>>1);
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if((j&1)==1 &&
|
||||
((forecasts[m].day==k-1 && forecasts[m].hour>=19)
|
||||
|| (forecasts[m].day==k && forecasts[m].hour<19)))
|
||||
forecasts[m].high=i;
|
||||
if((j&1)==0 &&
|
||||
((forecasts[m].day==k-1 && forecasts[m].hour>=8)
|
||||
|| (forecasts[m].day==k && forecasts[m].hour<8)))
|
||||
forecasts[m].low=i;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "TMP")){
|
||||
ASSIGN(temp);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "DPT")){
|
||||
ASSIGN(dewpt);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "WDR")){
|
||||
for(n=0; n<AVN_MAX; n++){
|
||||
i=atoi(split[n]);
|
||||
if(i==99) forecasts[n].winddir=0;
|
||||
else forecasts[n].winddir=((int)((i+1.125)/2.25))%16+1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "WSP")){
|
||||
ASSIGN2(windspeed, 99);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "P06")){
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]);
|
||||
if(i!=999){
|
||||
forecasts[m].pcp_total=i;
|
||||
/* AVN_MAX-2 because the last 2
|
||||
* are already 6-hour intervals */
|
||||
if(m>0 && m<AVN_MAX-2) forecasts[m-1].pcp_total=i;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "T06")){
|
||||
for(m=1; m<AVN_MAX; m+=2){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]); if(i==999) i=0;
|
||||
j=atoi(split[m+1]+1); if(j==99) j=0;
|
||||
j=i*j/100;
|
||||
forecasts[m].tstorm=forecasts[m+1].tstorm=i;
|
||||
forecasts[m].svtstorm=forecasts[m+1].svtstorm=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "Q06")){
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]);
|
||||
if(i!=999){
|
||||
forecasts[m].precipamt=i;
|
||||
/* AVN_MAX-2 because the last 2
|
||||
* are already 6-hour intervals */
|
||||
if(m>0 && m<AVN_MAX-2) forecasts[m-1].precipamt=i;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "SNW")){
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]);
|
||||
if(i!=9){
|
||||
j=forecasts[m].hour;
|
||||
k=forecasts[m].day;
|
||||
for(n=m; n>=0; n--){
|
||||
if(forecasts[n].day<k && forecasts[n].hour<j) break;
|
||||
forecasts[n].snowamt=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "CLD")){
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if(split[m][1]=='C') forecasts[m].sky=0;
|
||||
if(split[m][1]=='F') forecasts[m].sky=1;
|
||||
if(split[m][1]=='S') forecasts[m].sky=2;
|
||||
if(split[m][1]=='B') forecasts[m].sky=3;
|
||||
if(split[m][1]=='O') forecasts[m].sky=4;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "VIS")){
|
||||
ASSIGN2(vis, 9);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "OBV")){
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
if(split[m][2]=='N') forecasts[m].obs=0;
|
||||
if(split[m][2]=='R' || split[m][2]=='G') forecasts[m].obs=1;
|
||||
if(split[m][2]=='Z') forecasts[m].obs=2;
|
||||
if(split[m][2]=='L') forecasts[m].obs=3;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "POZ")){
|
||||
ASSIGN2(frz, 999);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "POS")){
|
||||
ASSIGN2(snow, 999);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
free(s);
|
||||
fclose(fp);
|
||||
|
||||
for(m=0; m<AVN_MAX; m++){
|
||||
forecasts[m].rh=rh_F(forecasts[m].temp, forecasts[m].dewpt);
|
||||
forecasts[m].heatindex=heatindex_F(forecasts[m].temp, forecasts[m].rh);
|
||||
forecasts[m].windchill=windchill_F(forecasts[m].temp, forecasts[m].windspeed);
|
||||
forecasts[m].rain=93-forecasts[m].frz-forecasts[m].snow;
|
||||
forecasts[m].rain=forecasts[m].rain*forecasts[m].pcp_total/93;
|
||||
forecasts[m].snow=forecasts[m].snow*forecasts[m].pcp_total/93;
|
||||
forecasts[m].frz=forecasts[m].frz*forecasts[m].pcp_total/93;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#undef NEXT
|
||||
#undef DIE
|
||||
#undef SPLIT
|
||||
#undef ASSIGN
|
||||
#undef ASSIGN2
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef AVN_H
|
||||
#define AVN_H
|
||||
|
||||
void init_avn(void);
|
||||
void update_avn(int force);
|
||||
void avn_cleanup(void);
|
||||
|
||||
#endif
|
|
@ -1,3 +0,0 @@
|
|||
noinst_LIBRARIES = libb0rken.a
|
||||
libb0rken_a_SOURCES =
|
||||
libb0rken_a_LIBADD = @LIBOBJS@
|
|
@ -1 +0,0 @@
|
|||
/* We never really use lstat, so... */
|
|
@ -1,15 +0,0 @@
|
|||
/* Version of malloc that avoids the malloc(0) bug */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#undef malloc
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void *malloc();
|
||||
|
||||
void *rpl_malloc(size_t size){
|
||||
if(size==0) size=1;
|
||||
return malloc(size);
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/* Cheapo version of memcmp */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n){
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<n; i++){
|
||||
j=((unsigned char *)s1)[i]-((unsigned char *)s2)[i];
|
||||
if(j) return j;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,527 +0,0 @@
|
|||
/* Convert a `struct tm' to a time_t value.
|
||||
Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Eggert (eggert@twinsun.com).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Define this to have a standalone program to test this implementation of
|
||||
mktime. */
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define HAVE_LIMITS_H 1
|
||||
# define STDC_HEADERS 1
|
||||
#endif
|
||||
|
||||
/* Assume that leap seconds are possible, unless told otherwise.
|
||||
If the host has a `zic' command with a `-L leapsecondfilename' option,
|
||||
then it supports leap seconds; otherwise it probably doesn't. */
|
||||
#ifndef LEAP_SECONDS_POSSIBLE
|
||||
# define LEAP_SECONDS_POSSIBLE 1
|
||||
#endif
|
||||
|
||||
#include <sys/types.h> /* Some systems define `time_t' here. */
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
# include <stdio.h>
|
||||
# if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
/* Make it work even if the system's libc has its own mktime routine. */
|
||||
# define mktime my_mktime
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef __P
|
||||
# if defined __GNUC__ || (defined __STDC__ && __STDC__)
|
||||
# define __P(args) args
|
||||
# else
|
||||
# define __P(args) ()
|
||||
# endif /* GCC. */
|
||||
#endif /* Not __P. */
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
/* The extra casts work around common compiler bugs. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
|
||||
It is necessary at least when t == time_t. */
|
||||
#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
|
||||
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
|
||||
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
|
||||
|
||||
#ifndef INT_MIN
|
||||
# define INT_MIN TYPE_MINIMUM (int)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
# define INT_MAX TYPE_MAXIMUM (int)
|
||||
#endif
|
||||
|
||||
#ifndef TIME_T_MIN
|
||||
# define TIME_T_MIN TYPE_MINIMUM (time_t)
|
||||
#endif
|
||||
#ifndef TIME_T_MAX
|
||||
# define TIME_T_MAX TYPE_MAXIMUM (time_t)
|
||||
#endif
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
|
||||
#ifndef __isleap
|
||||
/* Nonzero if YEAR is a leap year (every 4 years,
|
||||
except every 100th isn't, and every 400th is). */
|
||||
# define __isleap(year) \
|
||||
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
|
||||
#endif
|
||||
|
||||
/* How many days come before each month (0-12). */
|
||||
const unsigned short int __mon_yday[2][13] =
|
||||
{
|
||||
/* Normal years. */
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
/* Leap years. */
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
|
||||
#ifdef _LIBC
|
||||
# define my_mktime_localtime_r __localtime_r
|
||||
#else
|
||||
/* If we're a mktime substitute in a GNU program, then prefer
|
||||
localtime to localtime_r, since many localtime_r implementations
|
||||
are buggy. */
|
||||
static struct tm *
|
||||
my_mktime_localtime_r (const time_t *t, struct tm *tp)
|
||||
{
|
||||
struct tm *l = localtime (t);
|
||||
if (! l)
|
||||
return 0;
|
||||
*tp = *l;
|
||||
return tp;
|
||||
}
|
||||
#endif /* ! _LIBC */
|
||||
|
||||
|
||||
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
|
||||
measured in seconds, ignoring leap seconds.
|
||||
YEAR uses the same numbering as TM->tm_year.
|
||||
All values are in range, except possibly YEAR.
|
||||
If TP is null, return a nonzero value.
|
||||
If overflow occurs, yield the low order bits of the correct answer. */
|
||||
static time_t
|
||||
ydhms_tm_diff (int year, int yday, int hour, int min, int sec,
|
||||
const struct tm *tp)
|
||||
{
|
||||
if (!tp)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
/* Compute intervening leap days correctly even if year is negative.
|
||||
Take care to avoid int overflow. time_t overflow is OK, since
|
||||
only the low order bits of the correct time_t answer are needed.
|
||||
Don't convert to time_t until after all divisions are done, since
|
||||
time_t might be unsigned. */
|
||||
int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
|
||||
int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
|
||||
int a100 = a4 / 25 - (a4 % 25 < 0);
|
||||
int b100 = b4 / 25 - (b4 % 25 < 0);
|
||||
int a400 = a100 >> 2;
|
||||
int b400 = b100 >> 2;
|
||||
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
|
||||
time_t years = year - (time_t) tp->tm_year;
|
||||
time_t days = (365 * years + intervening_leap_days
|
||||
+ (yday - tp->tm_yday));
|
||||
return (60 * (60 * (24 * days + (hour - tp->tm_hour))
|
||||
+ (min - tp->tm_min))
|
||||
+ (sec - tp->tm_sec));
|
||||
}
|
||||
}
|
||||
|
||||
/* Use CONVERT to convert *T to a broken down time in *TP.
|
||||
If *T is out of range for conversion, adjust it so that
|
||||
it is the nearest in-range value and then convert that. */
|
||||
static struct tm *
|
||||
ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
|
||||
time_t *t, struct tm *tp)
|
||||
{
|
||||
struct tm *r;
|
||||
|
||||
if (! (r = (*convert) (t, tp)) && *t)
|
||||
{
|
||||
time_t bad = *t;
|
||||
time_t ok = 0;
|
||||
struct tm tm;
|
||||
|
||||
/* BAD is a known unconvertible time_t, and OK is a known good one.
|
||||
Use binary search to narrow the range between BAD and OK until
|
||||
they differ by 1. */
|
||||
while (bad != ok + (bad < 0 ? -1 : 1))
|
||||
{
|
||||
time_t mid = *t = (bad < 0
|
||||
? bad + ((ok - bad) >> 1)
|
||||
: ok + ((bad - ok) >> 1));
|
||||
if ((r = (*convert) (t, tp)))
|
||||
{
|
||||
tm = *r;
|
||||
ok = mid;
|
||||
}
|
||||
else
|
||||
bad = mid;
|
||||
}
|
||||
|
||||
if (!r && ok)
|
||||
{
|
||||
/* The last conversion attempt failed;
|
||||
revert to the most recent successful attempt. */
|
||||
*t = ok;
|
||||
*tp = tm;
|
||||
r = tp;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Convert *TP to a time_t value, inverting
|
||||
the monotonic and mostly-unit-linear conversion function CONVERT.
|
||||
Use *OFFSET to keep track of a guess at the offset of the result,
|
||||
compared to what the result would be for UTC without leap seconds.
|
||||
If *OFFSET's guess is correct, only one CONVERT call is needed. */
|
||||
time_t
|
||||
__mktime_internal (struct tm *tp,
|
||||
struct tm *(*convert) (const time_t *, struct tm *),
|
||||
time_t *offset)
|
||||
{
|
||||
time_t t, dt, t0, t1, t2;
|
||||
struct tm tm;
|
||||
|
||||
/* The maximum number of probes (calls to CONVERT) should be enough
|
||||
to handle any combinations of time zone rule changes, solar time,
|
||||
leap seconds, and oscillations around a spring-forward gap.
|
||||
POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
|
||||
int remaining_probes = 6;
|
||||
|
||||
/* Time requested. Copy it in case CONVERT modifies *TP; this can
|
||||
occur if TP is localtime's returned value and CONVERT is localtime. */
|
||||
int sec = tp->tm_sec;
|
||||
int min = tp->tm_min;
|
||||
int hour = tp->tm_hour;
|
||||
int mday = tp->tm_mday;
|
||||
int mon = tp->tm_mon;
|
||||
int year_requested = tp->tm_year;
|
||||
int isdst = tp->tm_isdst;
|
||||
|
||||
/* Ensure that mon is in range, and set year accordingly. */
|
||||
int mon_remainder = mon % 12;
|
||||
int negative_mon_remainder = mon_remainder < 0;
|
||||
int mon_years = mon / 12 - negative_mon_remainder;
|
||||
int year = year_requested + mon_years;
|
||||
|
||||
/* The other values need not be in range:
|
||||
the remaining code handles minor overflows correctly,
|
||||
assuming int and time_t arithmetic wraps around.
|
||||
Major overflows are caught at the end. */
|
||||
|
||||
/* Calculate day of year from year, month, and day of month.
|
||||
The result need not be in range. */
|
||||
int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
|
||||
[mon_remainder + 12 * negative_mon_remainder])
|
||||
+ mday - 1);
|
||||
|
||||
int sec_requested = sec;
|
||||
#if LEAP_SECONDS_POSSIBLE
|
||||
/* Handle out-of-range seconds specially,
|
||||
since ydhms_tm_diff assumes every minute has 60 seconds. */
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
if (59 < sec)
|
||||
sec = 59;
|
||||
#endif
|
||||
|
||||
/* Invert CONVERT by probing. First assume the same offset as last time.
|
||||
Then repeatedly use the error to improve the guess. */
|
||||
|
||||
tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
|
||||
tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||
t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
|
||||
|
||||
for (t = t1 = t2 = t0 + *offset;
|
||||
(dt = ydhms_tm_diff (year, yday, hour, min, sec,
|
||||
ranged_convert (convert, &t, &tm)));
|
||||
t1 = t2, t2 = t, t += dt)
|
||||
if (t == t1 && t != t2
|
||||
&& (isdst < 0 || tm.tm_isdst < 0
|
||||
|| (isdst != 0) != (tm.tm_isdst != 0)))
|
||||
/* We can't possibly find a match, as we are oscillating
|
||||
between two values. The requested time probably falls
|
||||
within a spring-forward gap of size DT. Follow the common
|
||||
practice in this case, which is to return a time that is DT
|
||||
away from the requested time, preferring a time whose
|
||||
tm_isdst differs from the requested value. In practice,
|
||||
this is more useful than returning -1. */
|
||||
break;
|
||||
else if (--remaining_probes == 0)
|
||||
return -1;
|
||||
|
||||
/* If we have a match, check whether tm.tm_isdst has the requested
|
||||
value, if any. */
|
||||
if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
|
||||
{
|
||||
/* tm.tm_isdst has the wrong value. Look for a neighboring
|
||||
time with the right value, and use its UTC offset.
|
||||
Heuristic: probe the previous three calendar quarters (approximately),
|
||||
looking for the desired isdst. This isn't perfect,
|
||||
but it's good enough in practice. */
|
||||
int quarter = 7889238; /* seconds per average 1/4 Gregorian year */
|
||||
int i;
|
||||
|
||||
/* If we're too close to the time_t limit, look in future quarters. */
|
||||
if (t < TIME_T_MIN + 3 * quarter)
|
||||
quarter = -quarter;
|
||||
|
||||
for (i = 1; i <= 3; i++)
|
||||
{
|
||||
time_t ot = t - i * quarter;
|
||||
struct tm otm;
|
||||
ranged_convert (convert, &ot, &otm);
|
||||
if (otm.tm_isdst == isdst)
|
||||
{
|
||||
/* We found the desired tm_isdst.
|
||||
Extrapolate back to the desired time. */
|
||||
t = ot + ydhms_tm_diff (year, yday, hour, min, sec, &otm);
|
||||
ranged_convert (convert, &t, &tm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*offset = t - t0;
|
||||
|
||||
#if LEAP_SECONDS_POSSIBLE
|
||||
if (sec_requested != tm.tm_sec)
|
||||
{
|
||||
/* Adjust time to reflect the tm_sec requested, not the normalized value.
|
||||
Also, repair any damage from a false match due to a leap second. */
|
||||
t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
|
||||
if (! (*convert) (&t, &tm))
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
|
||||
{
|
||||
/* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
|
||||
so check for major overflows. A gross check suffices,
|
||||
since if t has overflowed, it is off by a multiple of
|
||||
TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
|
||||
the difference that is bounded by a small value. */
|
||||
|
||||
double dyear = (double) year_requested + mon_years - tm.tm_year;
|
||||
double dday = 366 * dyear + mday;
|
||||
double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
|
||||
|
||||
/* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
|
||||
correct results, ie., it erroneously gives a positive value
|
||||
of 715827882. Setting a variable first then doing math on it
|
||||
seems to work. (ghazi@caip.rutgers.edu) */
|
||||
|
||||
const time_t time_t_max = TIME_T_MAX;
|
||||
const time_t time_t_min = TIME_T_MIN;
|
||||
|
||||
if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp = tm;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
static time_t localtime_offset;
|
||||
|
||||
/* Convert *TP to a time_t value. */
|
||||
time_t
|
||||
mktime (tp)
|
||||
struct tm *tp;
|
||||
{
|
||||
#ifdef _LIBC
|
||||
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
|
||||
time zone names contained in the external variable `tzname' shall
|
||||
be set as if the tzset() function had been called. */
|
||||
__tzset ();
|
||||
#endif
|
||||
|
||||
return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
|
||||
}
|
||||
|
||||
#ifdef weak_alias
|
||||
weak_alias (mktime, timelocal)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
|
||||
static int
|
||||
not_equal_tm (a, b)
|
||||
struct tm *a;
|
||||
struct tm *b;
|
||||
{
|
||||
return ((a->tm_sec ^ b->tm_sec)
|
||||
| (a->tm_min ^ b->tm_min)
|
||||
| (a->tm_hour ^ b->tm_hour)
|
||||
| (a->tm_mday ^ b->tm_mday)
|
||||
| (a->tm_mon ^ b->tm_mon)
|
||||
| (a->tm_year ^ b->tm_year)
|
||||
| (a->tm_mday ^ b->tm_mday)
|
||||
| (a->tm_yday ^ b->tm_yday)
|
||||
| (a->tm_isdst ^ b->tm_isdst));
|
||||
}
|
||||
|
||||
static void
|
||||
print_tm (tp)
|
||||
struct tm *tp;
|
||||
{
|
||||
if (tp)
|
||||
printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
|
||||
tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec,
|
||||
tp->tm_yday, tp->tm_wday, tp->tm_isdst);
|
||||
else
|
||||
printf ("0");
|
||||
}
|
||||
|
||||
static int
|
||||
check_result (tk, tmk, tl, lt)
|
||||
time_t tk;
|
||||
struct tm tmk;
|
||||
time_t tl;
|
||||
struct tm *lt;
|
||||
{
|
||||
if (tk != tl || !lt || not_equal_tm (&tmk, lt))
|
||||
{
|
||||
printf ("mktime (");
|
||||
print_tm (&tmk);
|
||||
printf (")\nyields (");
|
||||
print_tm (lt);
|
||||
printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int status = 0;
|
||||
struct tm tm, tmk, tml;
|
||||
struct tm *lt;
|
||||
time_t tk, tl;
|
||||
char trailer;
|
||||
|
||||
if ((argc == 3 || argc == 4)
|
||||
&& (sscanf (argv[1], "%d-%d-%d%c",
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
|
||||
== 3)
|
||||
&& (sscanf (argv[2], "%d:%d:%d%c",
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
|
||||
== 3))
|
||||
{
|
||||
tm.tm_year -= TM_YEAR_BASE;
|
||||
tm.tm_mon--;
|
||||
tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
|
||||
tmk = tm;
|
||||
tl = mktime (&tmk);
|
||||
lt = localtime (&tl);
|
||||
if (lt)
|
||||
{
|
||||
tml = *lt;
|
||||
lt = &tml;
|
||||
}
|
||||
printf ("mktime returns %ld == ", (long) tl);
|
||||
print_tm (&tmk);
|
||||
printf ("\n");
|
||||
status = check_result (tl, tmk, tl, lt);
|
||||
}
|
||||
else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
|
||||
{
|
||||
time_t from = atol (argv[1]);
|
||||
time_t by = atol (argv[2]);
|
||||
time_t to = atol (argv[3]);
|
||||
|
||||
if (argc == 4)
|
||||
for (tl = from; tl <= to; tl += by)
|
||||
{
|
||||
lt = localtime (&tl);
|
||||
if (lt)
|
||||
{
|
||||
tmk = tml = *lt;
|
||||
tk = mktime (&tmk);
|
||||
status |= check_result (tk, tmk, tl, tml);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("localtime (%ld) yields 0\n", (long) tl);
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (tl = from; tl <= to; tl += by)
|
||||
{
|
||||
/* Null benchmark. */
|
||||
lt = localtime (&tl);
|
||||
if (lt)
|
||||
{
|
||||
tmk = tml = *lt;
|
||||
tk = tl;
|
||||
status |= check_result (tk, tmk, tl, tml);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("localtime (%ld) yields 0\n", (long) tl);
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
printf ("Usage:\
|
||||
\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
|
||||
\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
|
||||
\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
|
||||
argv[0], argv[0], argv[0]);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
|
||||
End:
|
||||
*/
|
|
@ -1,43 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(HAVE_WORKING_SNPRINTF)
|
||||
|
||||
/* snprintf works, nothing to do */
|
||||
|
||||
#else
|
||||
|
||||
/* snprintf is b0rken, use vsnprintf */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int rpl_snprintf(char *str, size_t size, const char *format, ...){
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
fprintf(stderr, "Using snprintf replacement\n");
|
||||
|
||||
va_start(ap, format);
|
||||
r=vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
#error Please supply a version of stat.
|
|
@ -1 +0,0 @@
|
|||
#error Please supply a version of strtod.
|
|
@ -1,95 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef vsnprintf
|
||||
# undef vsnprintf
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(HAVE_WORKING_VSNPRINTF)
|
||||
|
||||
/* vsnprintf works, nothing to do */
|
||||
|
||||
#elif !defined(VSNPRINTF_BOGUS_RETVAL)
|
||||
|
||||
/* vsnprintf is b0rken, but the return value is ok (thus, the only problem is
|
||||
* NULL) */
|
||||
|
||||
int rpl_vsnprintf(char *str, size_t size, const char *format, va_list ap){
|
||||
if(str==NULL || size==0){{
|
||||
char foo[3];
|
||||
return vsnprintf(foo, 3, format, ap);
|
||||
}} else {
|
||||
return vsnprintf(str, size, format, ap);
|
||||
}
|
||||
}
|
||||
|
||||
#elif !defined(VSNPRINTF_IS_VSPRINTF) && defined(HAVE_VPRINTF)
|
||||
|
||||
/* vsnprintf's retval is bogus, so we compensate. */
|
||||
|
||||
static FILE *devnull;
|
||||
|
||||
#ifndef va_copy
|
||||
# ifdef __va_copy
|
||||
# define va_copy(dest, src) __va_copy(dest, src)
|
||||
# else
|
||||
# include <string.h>
|
||||
# define va_copy(dest, src) memcpy(&dest, &src, sizeof(va_list))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int rpl_vsnprintf(char *str, size_t size, const char *format, va_list ap){
|
||||
va_list ap2;
|
||||
int r;
|
||||
|
||||
va_copy(ap2, ap);
|
||||
|
||||
#ifdef VSNPRINTF_NULL_OK
|
||||
vsnprintf(str, size, format, ap);
|
||||
#else
|
||||
if(str==NULL || size==0){{
|
||||
char foo[3];
|
||||
vsnprintf(foo, 3, format, ap);
|
||||
}} else {
|
||||
vsnprintf(str, size, format, ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(devnull==NULL){
|
||||
if((devnull=fopen("/dev/null", "w"))==NULL){
|
||||
perror("Couldn't open /dev/null for writing");
|
||||
exit(72);
|
||||
}
|
||||
}
|
||||
|
||||
r=vfprintf(devnull, format, ap2);
|
||||
va_end(ap2);
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* OK, we're screwed */
|
||||
|
||||
# error "vsnprintf is so broken we can't compensate. Sorry."
|
||||
|
||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
aclocal-1.10 -I m4 \
|
||||
&& autoheader \
|
||||
&& automake-1.10 --gnu --add-missing \
|
||||
&& autoconf
|
|
@ -1,15 +0,0 @@
|
|||
/* XPM */
|
||||
static char * characters_xpm[] = {
|
||||
"179 7 5 1",
|
||||
" c None",
|
||||
". c #000000 s Background",
|
||||
"+ c #0C4E66 s Low",
|
||||
"@ c #1EC3FF s High",
|
||||
"# c #127599 s Mid",
|
||||
"...................................................................................................................................................................................",
|
||||
".+@+.@@+..@@.@@..@@@.@@@..@@.@.@.@@@...@.@.@.@.....@.@...#@#.@@+.+@+.@@+.+@@.@@@.@.@.@.@.@.#.@.@.@.@.@@@.+@+..@..@@+.@@+.@.@.@@@..@..@@@.+@+.#@#...@.@..@.@..@.@..@.+.......@.@..@.",
|
||||
".@.@.@.@.@...@.@.@...@...@...@.@..@....@.@.@.@....@...@..@.@.@.@.@.@.@.@.@....@..@.@.@.@...@.@.@.@.@.+#@.@.@..@....@...@.@.@.@...@.....@.@.@.@.@...@.@@@@.@@.@.@..@.@......@...@.@.",
|
||||
".@@@.@@+.@...@.@.@@..@@..@.@.@@@..@....@.@@..@...@.....@.@.@.@@+.@.@.@@+.+@+..@..@.@.@.@..@...@...@..+@..@.@..@...@+.#@+.@@@.@@+.@@#..@..#@#.#@@..@..@##@.@.@@.@##@.....@@.@...@...",
|
||||
".@.@.@.@.@...@.@.@...@...@.@.@.@..@..@.@.@.@.@....@...@..@.@.@...@@@.@.@...@..@..@.@.@.@.@...@.@..@..@...@.@..@..@.....@...@...@.@.@..@..@.@...@.@...@..@.@..@.@@@@.@.+....@...@...",
|
||||
".@.@.@@+..@@.@@..@@@.@....@@.@.@.@@@.+@+.@.@.@@@...@.@...#@#.@...+@@.@.@.@@+..@..@@@..@..#.@.@.@..@..@@@.+@+..@..@@@.@@+...@.@@+.#@#..@..+@+..@..@...@..@.@..@.@..@.+.@.....@.@....",
|
||||
"..................................................................................................................................................................................."};
|
|
@ -1,84 +0,0 @@
|
|||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(wmweather+.c)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AM_INIT_AUTOMAKE(wmweather+, 2.12)
|
||||
|
||||
# We need GNU sources for certain features
|
||||
AH_VERBATIM([_GNU_SOURCE],
|
||||
[/* Enable GNU extensions on systems that have them */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif])
|
||||
|
||||
DATE=`date '+%B %e, %Y'`
|
||||
AC_SUBST(DATE)
|
||||
AC_SUBST(VERSION)
|
||||
|
||||
# for wmgeneral
|
||||
WMGENERAL_GUI="libwmgeneral-x11.a"
|
||||
AC_SUBST(WMGENERAL_GUI)
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB([m],[cos])
|
||||
CHECK_LIBPCRE(, AC_MSG_ERROR(libpcre is required))
|
||||
LIBCURL_CHECK_CONFIG(yes,,,AC_MSG_ERROR(libcurl is required))
|
||||
|
||||
# Checks for header files.
|
||||
AC_PATH_XTRA
|
||||
AC_FIND_XPM
|
||||
if test "$LINK_XPM" = ""; then
|
||||
AC_MSG_ERROR(cannot find libxpm)
|
||||
fi
|
||||
CHECK_LIBWRASTER(, AC_MSG_ERROR(libwraster is required))
|
||||
AC_HEADER_STDC
|
||||
if test "$ac_cv_header_stdc" != "yes"; then AC_MSG_WARN(standard C headers not found); fi
|
||||
AC_HEADER_SYS_WAIT
|
||||
if test "$ac_cv_header_sys_wait_h" != "yes"; then AC_MSG_WARN(sys/wait.h not found); fi
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h stdlib.h string.h unistd.h sys/time.h],, AC_MSG_WARN($ac_header not found))
|
||||
AC_HEADER_TIME
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_CHECK_TYPES([ssize_t])
|
||||
AH_BOTTOM(
|
||||
[#if !HAVE_SSIZE_T
|
||||
typedef signed ssize_t;
|
||||
#endif])
|
||||
AC_STRUCT_TM
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
if test "$ac_cv_func_fork_works" != "yes"; then AC_MSG_WARN(fork() doesn't seem to work); fi
|
||||
AC_FUNC_MALLOC
|
||||
if test "$ac_cv_func_malloc_0_nonnull" != "yes"; then AC_MSG_WARN(malloc() doesn't seem to work); fi
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_MKTIME
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_STAT
|
||||
AC_FUNC_STRTOD
|
||||
AC_FUNC_VPRINTF
|
||||
if test "$ac_cv_func_vprintf" != "yes"; then AC_MSG_WARN(vprintf() doesn't seem to exist); fi
|
||||
AC_CHECK_FUNCS([atexit dup2 mkdir pow select strchr strcspn strdup strerror strrchr strspn strstr strtol],, AC_MSG_WARN($ac_func doesn't seem to be available))
|
||||
FUNC_SNPRINTF_LIBOBJ
|
||||
FUNC_VSNPRINTF_LIBOBJ
|
||||
|
||||
CFLAGS="$CFLAGS \$(X_CFLAGS) \$(LIBCURL_CPPFLAGS)"
|
||||
LIBS="$LIBS \$(LIBCURL)"
|
||||
XLIBS="\$(X_PRE_LIBS) \$(X_LIBS) \$(LINK_XPM) -lX11 -lXext \$(X_EXTRA_LIBS)"
|
||||
AC_SUBST(XLIBS)
|
||||
|
||||
AC_CONFIG_FILES([Makefile wmweather+.1])
|
||||
AC_CONFIG_FILES([b0rken/Makefile])
|
||||
AC_CONFIG_FILES([m4/Makefile])
|
||||
AC_CONFIG_FILES([wmgeneral/Makefile])
|
||||
AC_OUTPUT
|
|
@ -1,443 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "convert.h"
|
||||
|
||||
/*
|
||||
* To indicate unavailable data
|
||||
* 999 is used for temperature
|
||||
* x<0 is used for rh, pressure, and windspeed
|
||||
*/
|
||||
|
||||
|
||||
/* Calculations */
|
||||
|
||||
int rh_C(int temp_C, int dewpt_C){
|
||||
float f;
|
||||
|
||||
if(temp_C==999 || dewpt_C==999) return 999;
|
||||
|
||||
f=1782.75*(dewpt_C-temp_C)/((237.7+dewpt_C)*(237.7+temp_C));
|
||||
return round(pow(10, f+2));
|
||||
}
|
||||
|
||||
int rh_F(int temp_F, int dewpt_F){
|
||||
float f;
|
||||
|
||||
if(temp_F==999 || dewpt_F==999) return 999;
|
||||
|
||||
f=3208.95*(dewpt_F-temp_F)/((395.86+dewpt_F)*(395.86+temp_F));
|
||||
return round(pow(10, f+2));
|
||||
}
|
||||
|
||||
int heatindex_C(int temp_C, int rh){
|
||||
#if 1
|
||||
if(temp_C==999 || temp_C<21 || rh<0) return 999;
|
||||
return heatindex_F(temp_C2F(temp_C), rh);
|
||||
#else
|
||||
int temp2, rh2;
|
||||
|
||||
if(temp_C==999 || temp_C<38 || rh<0) return 999;
|
||||
|
||||
temp2=temp_C*temp_C;
|
||||
rh2=rh*rh;
|
||||
return round(16.18754948 + 2.900509394*temp_C - 0.0221545692*temp2 + 4.20938791*rh - 0.26300889*temp_C*rh + 0.0039811176*temp2*rh - 0.02956469*rh2 + 0.001305828*temp_C*rh2 - 6.4476e-06*temp2*rh2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int heatindex_F(int temp_F, int rh){
|
||||
int temp2, temp3, rh2, rh3;
|
||||
|
||||
if(temp_F==999 || temp_F<70 || rh<0) return 999;
|
||||
|
||||
temp2=temp_F*temp_F;
|
||||
temp3=temp2*temp_F;
|
||||
rh2=rh*rh;
|
||||
rh3=rh2*rh;
|
||||
return round(16.923 + .185212*temp_F + 5.37941*rh - .100254*temp_F*rh + (9.41695e-3)*temp2 + (7.28898e-3)*rh2 + (3.45372e-4)*temp2*rh - (8.14971e-4)*temp_F*rh2 + (1.02102e-5)*temp2*rh2 - (3.8646e-5)*temp3 + (2.91583e-5)*rh3 + (1.42721e-6)*temp3*rh + (1.97483e-7)*temp_F*rh3 - (2.18429e-8)*temp3*rh2 + (8.43296e-10)*temp2*rh3 - (4.81975e-11)*temp3*rh3);
|
||||
#if 0
|
||||
return round(-42.379 + 2.04901523*temp_F + 10.14333127*rh - 0.22475541*temp_F*rh - .00683783*temp2 - .05481717*rh2 + .00122874*temp2*rh + .00085282*temp_F*rh2 - .00000199*temp2*rh2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int windchill_C(int temp_C, int windspeed){
|
||||
if(temp_C==999 || windspeed<0) return 999;
|
||||
|
||||
return windchill_F(temp_C2F(temp_C), windspeed);
|
||||
}
|
||||
|
||||
int windchill_F(int temp_F, int windspeed){
|
||||
double ret;
|
||||
if(temp_F==999 || windspeed<0) return 999;
|
||||
|
||||
ret=35.74 + 0.6215*temp_F + (-35.75 + 0.4275*temp_F)*pow(windspeed*50292/57875.0, 0.16);
|
||||
if(ret>temp_F) return temp_F;
|
||||
return round(ret);
|
||||
}
|
||||
|
||||
/* Length Conversions */
|
||||
|
||||
int in2cm(int in){
|
||||
if(in<0) return in;
|
||||
return round(in*2.54);
|
||||
}
|
||||
|
||||
float m2mi(int meters){
|
||||
if(meters<0) return meters;
|
||||
return meters*125/201168;
|
||||
}
|
||||
|
||||
/* Windspeed Conversions */
|
||||
|
||||
int knots2mph(int knots){
|
||||
if(knots<0) return knots;
|
||||
return round(knots*57875/50292.0);
|
||||
}
|
||||
|
||||
int knots2kph(int knots){
|
||||
if(knots<0) return knots;
|
||||
return round(knots*463/250.0);
|
||||
}
|
||||
|
||||
int kph2knots(int kph){
|
||||
if(kph<0) return kph;
|
||||
return round(kph*250/463.0);
|
||||
}
|
||||
|
||||
int knots2mps(int knots){
|
||||
if(knots<0) return knots;
|
||||
return round(knots*463/900.0);
|
||||
}
|
||||
|
||||
int mps2knots(int mps){
|
||||
if(mps<0) return mps;
|
||||
return round(mps*900/463.0);
|
||||
}
|
||||
|
||||
int knots2beaufort(int knots){
|
||||
if(knots<0) return knots;
|
||||
if(knots<1) return 0;
|
||||
if(knots<=3) return 1;
|
||||
if(knots<=6) return 2;
|
||||
if(knots<=10) return 3;
|
||||
if(knots<=16) return 4;
|
||||
if(knots<=21) return 5;
|
||||
if(knots<=27) return 6;
|
||||
if(knots<=33) return 7;
|
||||
if(knots<=40) return 8;
|
||||
if(knots<=47) return 9;
|
||||
if(knots<=55) return 10;
|
||||
if(knots<=63) return 11;
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
/* Temperature Conversions */
|
||||
|
||||
int temp_C2F(int temp_C){
|
||||
if(temp_C==999) return 999;
|
||||
return round(temp_C*9/5.0+32);
|
||||
}
|
||||
|
||||
int temp_F2C(int temp_F){
|
||||
if(temp_F==999) return 999;
|
||||
return round((temp_F-32)*5/9.0);
|
||||
}
|
||||
|
||||
|
||||
/* Pressure Conversions */
|
||||
|
||||
float inHg2mmHg(float inHg){
|
||||
if(inHg<0) return inHg;
|
||||
return inHg*25.4;
|
||||
}
|
||||
|
||||
float inHg2hPa(float inHg){
|
||||
if(inHg<0) return inHg;
|
||||
return inHg*33.8639;
|
||||
}
|
||||
|
||||
float inHg2atm(float inHg){
|
||||
if(inHg<0) return inHg;
|
||||
return inHg*.033421052632;
|
||||
}
|
||||
|
||||
float hPa2inHg(float hPa){
|
||||
if(hPa<0) return hPa;
|
||||
return hPa/33.8639;
|
||||
}
|
||||
|
||||
|
||||
/* Time Conversions */
|
||||
|
||||
/* NOTE: y%400==100 because y=year-1900 */
|
||||
#define is_leap(y) (y%4==0 && (y%100!=0 || y%400==100))
|
||||
|
||||
/* mktime for UTC, more or less.
|
||||
* Differences:
|
||||
* - no range checking
|
||||
* - never recalculates tm_wday or tm_yday
|
||||
*/
|
||||
time_t mkgmtime(struct tm *tm){
|
||||
static long msec[]={0, 2678400, 5097600, 7776000, 10368000, 13046400, 15638400, 18316800, 20995200, 23587200, 26265600, 28857600};
|
||||
time_t t;
|
||||
int i;
|
||||
|
||||
t=0;
|
||||
if(tm->tm_year>70){
|
||||
for(i=70; i<tm->tm_year; i++){
|
||||
t+=31536000;
|
||||
if(is_leap(i)) t+=86400;
|
||||
}
|
||||
} else if(tm->tm_year<70){
|
||||
for(i=69; i>=tm->tm_year; i--){
|
||||
t-=31536000;
|
||||
if(is_leap(i)) t-=86400;
|
||||
}
|
||||
}
|
||||
t+=msec[tm->tm_mon];
|
||||
if(tm->tm_mon>1 && is_leap(tm->tm_year)) t+=86400;
|
||||
t+=(((tm->tm_mday-1)*24+tm->tm_hour)*60+tm->tm_min)*60+tm->tm_sec;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int utc2local(int hm, int *month, int *day, int *year, int *wday){
|
||||
time_t t=time(NULL);
|
||||
struct tm *tm;
|
||||
|
||||
tm=gmtime(&t);
|
||||
tm->tm_hour=hm/100;
|
||||
tm->tm_min=hm%100;
|
||||
if(month!=NULL && *month!=-1) tm->tm_mon=*month-1;
|
||||
if(day!=NULL && *day!=-1) tm->tm_mday=*day;
|
||||
if(year!=NULL && *year!=-1) tm->tm_year=*year;
|
||||
|
||||
t=mkgmtime(tm);
|
||||
tm=localtime(&t);
|
||||
|
||||
if(month!=NULL) *month=tm->tm_mon+1;
|
||||
if(day!=NULL) *day=tm->tm_mday;
|
||||
if(year!=NULL) *year=tm->tm_year;
|
||||
if(wday!=NULL) *wday=tm->tm_wday;
|
||||
return tm->tm_hour*100+tm->tm_min;
|
||||
}
|
||||
|
||||
int local2utc(int hm, int *month, int *day, int *year, int *wday){
|
||||
time_t t=time(NULL);
|
||||
struct tm *tm;
|
||||
|
||||
tm=localtime(&t);
|
||||
tm->tm_hour=hm/100;
|
||||
tm->tm_min=hm%100;
|
||||
if(month!=NULL && *month!=-1) tm->tm_mon=*month-1;
|
||||
if(day!=NULL && *day!=-1) tm->tm_mday=*day;
|
||||
if(year!=NULL && *year!=-1) tm->tm_year=*year;
|
||||
|
||||
t=mktime(tm);
|
||||
tm=gmtime(&t);
|
||||
|
||||
if(month!=NULL) *month=tm->tm_mon+1;
|
||||
if(day!=NULL) *day=tm->tm_mday;
|
||||
if(year!=NULL) *year=tm->tm_year;
|
||||
if(wday!=NULL) *wday=tm->tm_wday;
|
||||
return tm->tm_hour*100+tm->tm_min;
|
||||
}
|
||||
|
||||
void fix_date(int *month, int *day, int *year, int *wday){
|
||||
time_t t=time(NULL);
|
||||
struct tm *tm;
|
||||
|
||||
tm=gmtime(&t);
|
||||
if(month!=NULL && *month!=-1) tm->tm_mon=*month-1;
|
||||
if(day!=NULL && *day!=-1) tm->tm_mday=*day;
|
||||
if(year!=NULL && *year!=-1) tm->tm_year=*year;
|
||||
|
||||
t=mkgmtime(tm);
|
||||
tm=gmtime(&t);
|
||||
|
||||
if(month!=NULL) *month=tm->tm_mon+1;
|
||||
if(day!=NULL) *day=tm->tm_mday;
|
||||
if(year!=NULL) *year=tm->tm_year;
|
||||
if(wday!=NULL) *wday=tm->tm_wday;
|
||||
}
|
||||
|
||||
int hm2min(int hm){
|
||||
return hm/100*60+hm%100;
|
||||
}
|
||||
|
||||
/* Letter Case (destructive!) */
|
||||
|
||||
char *str_upper(char *str){
|
||||
char *c;
|
||||
|
||||
for(c=str; *c!='\0'; c++){
|
||||
*c=toupper(*c);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char *str_lower(char *str){
|
||||
char *c;
|
||||
|
||||
for(c=str; *c!='\0'; c++){
|
||||
*c=tolower(*c);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/* Angle conversions */
|
||||
|
||||
/* Convert radian angle to degrees */
|
||||
double rad2deg(double angle) {
|
||||
return 180.0*angle/PI;
|
||||
}
|
||||
|
||||
/* Convert degree angle to radians */
|
||||
double deg2rad(double angle) {
|
||||
return PI*angle/180.0;
|
||||
}
|
||||
|
||||
|
||||
/* Date conversions */
|
||||
|
||||
/* Numerical day-of-year from month, day and year */
|
||||
int mdy2doy(int mn, int dy, int y) {
|
||||
return 275*mn/9 - ((y%4==0 && (y%100!=0 || y%400==100))?1:2)*(mn + 9)/12 + dy-30;
|
||||
}
|
||||
|
||||
/* Julian day from month/day/year */
|
||||
double mdy2jd(int year, int month, int day) {
|
||||
int A, B;
|
||||
|
||||
year+=1900;
|
||||
if (month <= 2) {
|
||||
year -= 1;
|
||||
month += 12;
|
||||
}
|
||||
A=year/100;
|
||||
B=2 - A + A/4;
|
||||
|
||||
return (int)(365.25*(year + 4716)) + (int)(30.6001*(month+1)) + day + B - 1524.5;
|
||||
}
|
||||
|
||||
/* convert Julian Day to centuries since J2000.0. */
|
||||
double jd2jcent(double jd) {
|
||||
return (jd - 2451545.0)/36525.0;
|
||||
}
|
||||
|
||||
/* convert centuries since J2000.0 to Julian Day. */
|
||||
double jcent2jd(double t) {
|
||||
return t * 36525.0 + 2451545.0;
|
||||
}
|
||||
|
||||
|
||||
/* Lat/Long conversions */
|
||||
|
||||
static double parse_dd_or_dms(char *s, char **e){
|
||||
double deg;
|
||||
|
||||
*e=s;
|
||||
if(strchr(s, 'x') || strchr(s, 'X')) return NAN;
|
||||
if(!strchr(s, '\'')){
|
||||
if(!isdigit(*s) && *s!='.') return NAN;
|
||||
return strtod(s, e);
|
||||
}
|
||||
|
||||
if(!isdigit(*s)) return NAN;
|
||||
deg=strtol(s, e, 10);
|
||||
if(*e==s || *e==NULL || **e!='\'') return deg;
|
||||
s=++(*e);
|
||||
if(!isdigit(*s)) return deg;
|
||||
deg+=strtol(s, e, 10)/60.0;
|
||||
if(*e==s || *e==NULL || **e!='\'') return deg;
|
||||
s=++(*e);
|
||||
if(!isdigit(*s) && *s!='.') return NAN;
|
||||
deg+=strtod(s, e)/3600.0;
|
||||
if(*e!=s && *e!=NULL && **e=='\'') (*e)++;
|
||||
return deg;
|
||||
}
|
||||
|
||||
int str2dd(char *s, double *lat, double *lon){
|
||||
char *e;
|
||||
int dir=0;
|
||||
char c;
|
||||
|
||||
c=toupper(*s);
|
||||
if(c=='+' || c=='N'){
|
||||
s++; dir=1;
|
||||
}
|
||||
if(c=='-' || c=='S'){
|
||||
s++; dir=-1;
|
||||
}
|
||||
|
||||
*lat=parse_dd_or_dms(s, &e);
|
||||
if(isnan(*lat) || e==NULL || e==s || *e=='\0') return 0;
|
||||
if(!dir){
|
||||
c=toupper(*e);
|
||||
if(c=='N') dir=1;
|
||||
if(c=='S') dir=-1;
|
||||
if(dir) e++;
|
||||
}
|
||||
if(dir<0) *lat=-*lat;
|
||||
|
||||
while(isspace(*e)) e++;
|
||||
if(*e=='\0') return 0;
|
||||
|
||||
s=e; dir=0;
|
||||
c=toupper(*s);
|
||||
if(c=='+' || c=='W'){
|
||||
s++; dir=1;
|
||||
}
|
||||
if(c=='-' || c=='E'){
|
||||
s++; dir=-1;
|
||||
}
|
||||
|
||||
*lon=parse_dd_or_dms(s, &e);
|
||||
if(isnan(*lon) || e==s) return 0;
|
||||
if(e==NULL || *e=='\0') return 1;
|
||||
if(dir==0){
|
||||
c=toupper(*e);
|
||||
if(c=='W') dir=1;
|
||||
if(c=='E') dir=-1;
|
||||
if(dir!=0) e++;
|
||||
}
|
||||
if(dir<0) *lon=-*lon;
|
||||
|
||||
return (*e=='\0');
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
#ifndef PI
|
||||
# define PI 3.1415926535897932384626433832795029L
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that all floating point calculations are rounded with .5 going up.
|
||||
* Since C automatically truncates, adding .5 to every calculation does
|
||||
* rounding for us nicely.
|
||||
*
|
||||
* To indicate unavailable data
|
||||
* 999 is used for temperature
|
||||
* x<0 is used for rh, pressure, and windspeed
|
||||
*/
|
||||
|
||||
/* Calculations */
|
||||
int rh_C(int temp_C, int dewpt_C);
|
||||
int rh_F(int temp_F, int dewpt_F);
|
||||
int heatindex_C(int temp_C, int rh);
|
||||
int heatindex_F(int temp_F, int rh);
|
||||
int windchill_C(int temp_C, int windspeed); /* knots */
|
||||
int windchill_F(int temp_F, int windspeed); /* knots */
|
||||
|
||||
/* Length Conversions */
|
||||
int in2cm(int in);
|
||||
float m2mi(int meters);
|
||||
|
||||
/* Windspeed Conversions */
|
||||
int knots2mph(int knots);
|
||||
int knots2kph(int knots);
|
||||
int knots2mps(int knots);
|
||||
int knots2beaufort(int knots);
|
||||
int kph2knots(int kph);
|
||||
int mps2knots(int mps);
|
||||
|
||||
/* Temperature Conversions */
|
||||
int temp_C2F(int temp_C);
|
||||
int temp_F2C(int temp_F);
|
||||
|
||||
/* Pressure Conversions */
|
||||
float inHg2mmHg(float inHg);
|
||||
float inHg2hPa(float inHg);
|
||||
float inHg2atm(float inHg);
|
||||
float hPa2inHg(float hPa);
|
||||
|
||||
/* Time Conversions */
|
||||
time_t mkgmtime(struct tm *tm);
|
||||
int utc2local(int hm, int *mon, int *day, int *year, int *wday);
|
||||
int local2utc(int hm, int *mon, int *day, int *year, int *wday);
|
||||
void fix_date(int *month, int *day, int *year, int *wday);
|
||||
int hm2min(int hm);
|
||||
|
||||
/* Letter Case (destructive!) */
|
||||
char *str_upper(char *str);
|
||||
char *str_lower(char *str);
|
||||
|
||||
/* Angle conversions */
|
||||
double rad2deg(double angle);
|
||||
double deg2rad(double angle);
|
||||
|
||||
/* Date conversions */
|
||||
int mdy2doy(int mn, int dy, int y);
|
||||
double mdy2jd(int year, int month, int day);
|
||||
double jd2jcent(double jd);
|
||||
double jcent2jd(double t);
|
||||
|
||||
/* Lat/Long conversions */
|
||||
int str2dd(char *s, double *lat, double *lon);
|
|
@ -1,57 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "die.h"
|
||||
|
||||
void vwarn(char *fmt, va_list ap){
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (errno) fprintf(stderr, ": %s", strerror(errno));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void warn(char *fmt, ...){
|
||||
va_list argv;
|
||||
|
||||
va_start(argv, fmt);
|
||||
vwarn(fmt, argv);
|
||||
va_end(argv);
|
||||
}
|
||||
|
||||
|
||||
void vdie(char *fmt, va_list ap){
|
||||
vwarn(fmt, ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void die(char *fmt, ...){
|
||||
va_list argv;
|
||||
|
||||
va_start(argv, fmt);
|
||||
vwarn(fmt, argv);
|
||||
va_end(argv);
|
||||
exit(1);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
void warn(char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void die(char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__));
|
||||
|
||||
void vwarn(char *fmt, va_list ap) __attribute__ ((__format__ (__printf__, 1, 0)));
|
||||
void vdie(char *fmt, va_list ap) __attribute__ ((__format__ (__printf__, 1, 0), __noreturn__));
|
|
@ -1,62 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
|
||||
int diff(char *file1, char *file2){
|
||||
FILE *fp1, *fp2;
|
||||
size_t len1, len2;
|
||||
struct stat statbuf;
|
||||
int ret;
|
||||
int len=BIGBUF_LEN/2;
|
||||
char *s1=(char *)bigbuf, *s2=(char *)(bigbuf+len);
|
||||
|
||||
if((fp1=fopen(file1, "r"))==NULL) return -1;
|
||||
if((fp2=fopen(file2, "r"))==NULL){ fclose(fp1); return -1; }
|
||||
if(fstat(fileno(fp1), &statbuf)<0 || !S_ISREG(statbuf.st_mode)){
|
||||
fclose(fp1);
|
||||
fclose(fp2);
|
||||
return -1;
|
||||
}
|
||||
len1=statbuf.st_size;
|
||||
if(fstat(fileno(fp2), &statbuf)<0 || !S_ISREG(statbuf.st_mode)){
|
||||
fclose(fp1);
|
||||
fclose(fp2);
|
||||
return -1;
|
||||
}
|
||||
len2=statbuf.st_size;
|
||||
if(len1!=len2){ fclose(fp1); fclose(fp2); return 1; }
|
||||
if(len1==0){ fclose(fp1); fclose(fp2); return 0; }
|
||||
while(!feof(fp1) && !feof(fp2)){
|
||||
len1=fread(s1, sizeof(char), len, fp1);
|
||||
len2=fread(s2, sizeof(char), len, fp2);
|
||||
if(len1!=len2 || memcmp(s1, s2, len1)){
|
||||
fclose(fp1); fclose(fp2); return 1;
|
||||
}
|
||||
}
|
||||
ret=(!feof(fp1) || !feof(fp2));
|
||||
fclose(fp1);
|
||||
fclose(fp2);
|
||||
return ret;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
/* Returns 0 if the files are identical
|
||||
* 1 if they differ
|
||||
* -1 if fopen or fstat fails, or if files are not both regular files
|
||||
*/
|
||||
int diff(char *file1, char *file2);
|
|
@ -1,773 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "wmgeneral/wmgeneral-x11.h"
|
||||
#include "wmgeneral/mouse_regions.h"
|
||||
#include "wmgeneral/xpm_trans.h"
|
||||
|
||||
#include "wmweather_master.xpm"
|
||||
static int wmweather_mask_width;
|
||||
static int wmweather_mask_height;
|
||||
static char *wmweather_mask_bits;
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "convert.h"
|
||||
#include "metar.h"
|
||||
#include "avn.h"
|
||||
#include "eta.h"
|
||||
#include "mrf.h"
|
||||
#include "warnings.h"
|
||||
#include "forecast.h"
|
||||
#include "radar.h"
|
||||
#include "animation.h"
|
||||
#include "die.h"
|
||||
#include "font.h"
|
||||
|
||||
/* Globals */
|
||||
int current_mode;
|
||||
struct forecast *cur_forecast;
|
||||
int window_X, window_Y;
|
||||
|
||||
#define X 4
|
||||
#define P 4
|
||||
#define M (((100/P)+1)*X)
|
||||
static struct forecast *last_fcst;
|
||||
static int last_font=-1;
|
||||
static time_t last_time=0;
|
||||
static int but_stat=-1;
|
||||
static int dclick=0;
|
||||
static int dclick_counter=-1;
|
||||
static time_t update_time;
|
||||
static int forecast_priority, last_priority;
|
||||
static struct animation anim;
|
||||
static int counter_timer=0;
|
||||
static int show_counter;
|
||||
static int min_pct;
|
||||
static int sigs=0;
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
void DrawDisplay(int force);
|
||||
|
||||
|
||||
/* Functions */
|
||||
|
||||
void sigusr2(int i){
|
||||
sigs |= 2;
|
||||
if(signal(SIGUSR2, sigusr2)==SIG_ERR)
|
||||
warn("Error setting SIGUSR2 signal handler!");
|
||||
}
|
||||
|
||||
void sigusr1(int i){
|
||||
sigs |= 1;
|
||||
if(signal(SIGUSR1, sigusr1)==SIG_ERR)
|
||||
warn("Error setting SIGUSR1 signal handler!");
|
||||
}
|
||||
|
||||
void sigfunc(int i){
|
||||
sigs |= i<<8;
|
||||
if(signal(i, sigfunc)==SIG_ERR)
|
||||
warn("Error setting %d signal handler!", i);
|
||||
}
|
||||
|
||||
void do_cleanup(void){
|
||||
metar_cleanup();
|
||||
warnings_cleanup();
|
||||
avn_cleanup();
|
||||
eta_cleanup();
|
||||
mrf_cleanup();
|
||||
radar_cleanup();
|
||||
}
|
||||
|
||||
void init_dock(int argc, char **argv){
|
||||
sscanf(wmweather_master_xpm[0], "%d %d %*s", &wmweather_mask_width, &wmweather_mask_height);
|
||||
wmweather_mask_bits=malloc((wmweather_mask_width+7)/8*wmweather_mask_height);
|
||||
if(!wmweather_mask_bits) die("malloc failed");
|
||||
createXBMfromXPM(wmweather_mask_bits, wmweather_master_xpm, wmweather_mask_width, wmweather_mask_height);
|
||||
openDockWindow(argc, argv, wmweather_master_xpm, wmweather_mask_bits, wmweather_mask_width, wmweather_mask_height);
|
||||
|
||||
AddMouseRegion(0, 5, 5, 23, 14); /* Cur button */
|
||||
AddMouseRegion(1, 23, 5, 41, 14); /* Fcst burron */
|
||||
AddMouseRegion(2, 41, 5, 59, 14); /* Map button */
|
||||
AddMouseRegion(3, 5, 17, 59, 59); /* Large window */
|
||||
AddMouseRegion(4, 5, 17, 11, 24); /* left forecast arrow */
|
||||
AddMouseRegion(5, 53, 17, 59, 24); /* right forecast arrow */
|
||||
AddMouseRegion(6, 14, 17, 50, 24); /* forecast little window */
|
||||
AddMouseRegion(7, 5, 27, 59, 59); /* forecast big window */
|
||||
|
||||
init_metar();
|
||||
if(warning_zones) init_warnings();
|
||||
if(avn_station) init_avn();
|
||||
if(eta_station) init_eta();
|
||||
if(mrf_station) init_mrf();
|
||||
init_radar();
|
||||
errno=0;
|
||||
if(atexit(do_cleanup)) warn("atexit() failed, files will not be cleaned up\n");
|
||||
|
||||
current_mode=starting_mode;
|
||||
window_X=0; window_Y=0;
|
||||
cur_forecast=NULL;
|
||||
last_fcst=NULL;
|
||||
last_font=-1;
|
||||
last_time=0;
|
||||
anim.do_animate=start_do_animation;
|
||||
anim.show_counter=0;
|
||||
anim.changed=1;
|
||||
anim.min_pct=1;
|
||||
anim.old_pct=0;
|
||||
min_pct=20;
|
||||
show_counter=0;
|
||||
but_stat=-1;
|
||||
dclick=0;
|
||||
dclick_counter=-1;
|
||||
update_time=0;
|
||||
forecast_priority=4;
|
||||
last_priority=-1;
|
||||
|
||||
if(signal(SIGUSR1, sigusr1)==SIG_ERR)
|
||||
warn("Error setting SIGUSR1 signal handler!");
|
||||
if(signal(SIGUSR2, sigusr2)==SIG_ERR)
|
||||
warn("Error setting SIGUSR2 signal handler!");
|
||||
if(signal(SIGHUP, sigfunc)==SIG_ERR)
|
||||
warn("Error setting SIGHUP signal handler!");
|
||||
if(signal(SIGINT, sigfunc)==SIG_ERR)
|
||||
warn("Error setting SIGINT signal handler!");
|
||||
if(signal(SIGPIPE, sigfunc)==SIG_ERR)
|
||||
warn("Error setting SIGPIPE signal handler!");
|
||||
if(signal(SIGTERM, sigfunc)==SIG_ERR)
|
||||
warn("Error setting SIGTERM signal handler!");
|
||||
|
||||
DrawDisplay(1);
|
||||
}
|
||||
|
||||
|
||||
void update_dock(){
|
||||
XEvent Event;
|
||||
int i=0, j;
|
||||
int exposeflag=0;
|
||||
|
||||
j=sigs;
|
||||
sigs=0;
|
||||
if(j){
|
||||
if(j&~3) exit(j);
|
||||
if(j&1) i=current_mode;
|
||||
if(j&2) i=-1;
|
||||
if(j&3){
|
||||
switch(i){
|
||||
case 0:
|
||||
update_metar(1);
|
||||
break;
|
||||
case 1:
|
||||
update_avn(1);
|
||||
update_eta(1);
|
||||
update_mrf(1);
|
||||
break;
|
||||
case 2:
|
||||
update_radar(1);
|
||||
break;
|
||||
default:
|
||||
update_metar(1);
|
||||
update_avn(1);
|
||||
update_eta(1);
|
||||
update_mrf(1);
|
||||
update_radar(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(update_time<time(NULL)){
|
||||
update_time=time(NULL)+2;
|
||||
update_metar(0);
|
||||
update_avn(0);
|
||||
update_eta(0);
|
||||
update_mrf(0);
|
||||
update_radar(0);
|
||||
forecast_priority=(forecast_priority+1)%5;
|
||||
DrawDisplay(0);
|
||||
}
|
||||
if(counter_timer>0) if(!--counter_timer){
|
||||
anim.changed=1;
|
||||
show_counter=anim.show_counter=0;
|
||||
}
|
||||
|
||||
if(dclick_counter>-1) dclick_counter--;
|
||||
|
||||
while(XPending(display)){
|
||||
XNextEvent(display, &Event);
|
||||
switch (Event.type){
|
||||
case GraphicsExpose:
|
||||
case NoExpose:
|
||||
case Expose:
|
||||
exposeflag=1;
|
||||
break;
|
||||
case DestroyNotify:
|
||||
XCloseDisplay(display);
|
||||
exit(0);
|
||||
break;
|
||||
case ButtonPress:
|
||||
but_stat = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
|
||||
if((dclick!=but_stat+1 && dclick!=-but_stat-1) || dclick_counter<0){
|
||||
dclick=-but_stat-1;
|
||||
dclick_counter=4;
|
||||
} else if(dclick==-but_stat-1) dclick=but_stat+1;
|
||||
|
||||
switch(but_stat){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
if(current_mode!=but_stat){
|
||||
current_mode=but_stat;
|
||||
if(!anim.do_animate && !show_counter){
|
||||
show_counter=1;
|
||||
counter_timer=10;
|
||||
}
|
||||
DrawDisplay(1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 7:
|
||||
switch(Event.xbutton.button){
|
||||
case 2:
|
||||
if(current_mode==2){
|
||||
if(radar_cross!=NULL){
|
||||
do_radar_cross=1;
|
||||
DrawDisplay(1);
|
||||
}
|
||||
} else {
|
||||
anim.changed=1;
|
||||
anim.show_counter=0;
|
||||
anim.do_animate=!anim.do_animate;
|
||||
anim.min_pct=1;
|
||||
if(!anim.do_animate && current_mode==1){
|
||||
anim.min_pct=min_pct;
|
||||
show_counter=anim.show_counter=1;
|
||||
counter_timer=20;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if(current_mode==1 && !anim.do_animate && min_pct<100){
|
||||
if(Event.xbutton.state&ShiftMask){
|
||||
min_pct+=10;
|
||||
if(min_pct>100) min_pct=100;
|
||||
} else min_pct++;
|
||||
anim.min_pct=min_pct;
|
||||
show_counter=anim.show_counter=1;
|
||||
counter_timer=20;
|
||||
anim.changed=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if(current_mode==1 && !anim.do_animate && min_pct>0){
|
||||
if(Event.xbutton.state&ShiftMask){
|
||||
min_pct-=10;
|
||||
if(min_pct<0) min_pct=0;
|
||||
} else min_pct--;
|
||||
anim.min_pct=min_pct;
|
||||
anim.show_counter=1;
|
||||
counter_timer=20;
|
||||
anim.changed=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if(current_mode==1){
|
||||
show_counter=anim.show_counter=1;
|
||||
anim.changed=1;
|
||||
counter_timer=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
copyPixmapArea(123, 96, 6, 7, 65, 17);
|
||||
break;
|
||||
case 5:
|
||||
copyPixmapArea(129, 96, 6, 7, 113, 17);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
|
||||
if(dclick_counter<0) dclick=0;
|
||||
|
||||
if(but_stat==4){
|
||||
copyPixmapArea(123, 89, 6, 7, 65, 17);
|
||||
}
|
||||
if(but_stat==5){
|
||||
copyPixmapArea(129, 89, 6, 7, 113, 17);
|
||||
}
|
||||
if(current_mode==2 && (but_stat==3 || but_stat==7)
|
||||
&& Event.xbutton.button==2){
|
||||
do_radar_cross=0;
|
||||
DrawDisplay(1);
|
||||
}
|
||||
|
||||
if(but_stat == i && but_stat >= 0){
|
||||
switch(but_stat){
|
||||
case 3:
|
||||
case 7:
|
||||
if(Event.xbutton.button==1){
|
||||
if(dclick==but_stat+1) kill(getpid(), SIGUSR1);
|
||||
else if(warning_zones) output_warnings(0);
|
||||
}
|
||||
if(Event.xbutton.button==2){
|
||||
if(dclick==but_stat+1 && current_mode==1){
|
||||
show_counter=anim.show_counter=!anim.show_counter;
|
||||
anim.changed=1;
|
||||
counter_timer=0;
|
||||
}
|
||||
}
|
||||
if(Event.xbutton.button==3 && warning_zones) output_warnings(1);
|
||||
if(Event.xbutton.button==6){
|
||||
show_counter=anim.show_counter=0;
|
||||
anim.changed=1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
current_forecast_next(-1);
|
||||
forecast_priority=4;
|
||||
last_priority=0;
|
||||
DrawDisplay(0);
|
||||
break;
|
||||
case 5:
|
||||
current_forecast_next(1);
|
||||
forecast_priority=4;
|
||||
last_priority=0;
|
||||
DrawDisplay(0);
|
||||
break;
|
||||
case 6:
|
||||
if(Event.xbutton.button==3) current_forecast_next(-1);
|
||||
if(Event.xbutton.button==2){{
|
||||
struct forecast *f=current_forecast_get();
|
||||
struct forecast *g;
|
||||
current_forecast_next(1);
|
||||
while((g=current_forecast_get())!=f){
|
||||
if((f->hour<0 && g->hour>=0) ||
|
||||
(f->hour>=0 && g->hour<0)) break;
|
||||
current_forecast_next(1);
|
||||
}
|
||||
}}
|
||||
if(Event.xbutton.button==1) current_forecast_next(1);
|
||||
forecast_priority=4;
|
||||
last_priority=0;
|
||||
DrawDisplay(0);
|
||||
break;
|
||||
}
|
||||
but_stat=-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(exposeflag){
|
||||
setMaskXY(-window_X, -window_Y);
|
||||
RedrawWindowXY(window_X, window_Y);
|
||||
}
|
||||
DoAnimation(&anim);
|
||||
}
|
||||
|
||||
|
||||
void DrawDisplay(int force){
|
||||
int font=0;
|
||||
int x, y, z;
|
||||
struct forecast *f;
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
|
||||
if(current_warnings) font=1;
|
||||
if(force || last_font!=font) last_time=-1;
|
||||
last_font=font;
|
||||
|
||||
switch(current_mode){
|
||||
case 0:
|
||||
if(last_time==current.last_update) break;
|
||||
last_time=current.last_update;
|
||||
EnableMouseRegion(3);
|
||||
DisableMouseRegion(4);
|
||||
DisableMouseRegion(5);
|
||||
DisableMouseRegion(6);
|
||||
DisableMouseRegion(7);
|
||||
window_X=0; window_Y=0;
|
||||
|
||||
copyPixmapArea(124, 0, 54, 9, 5, 5);
|
||||
copyPixmapArea(124, 9, 18, 9, 5, 5);
|
||||
copyPixmapArea(124, 18, 54, 42, 5, 17);
|
||||
|
||||
DrawString(7, 17, metar_station, font+1);
|
||||
if(current.month>0 && current.month<13 && current.date!=-1){
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%s %d", monthnames[(int)current.month], current.date);
|
||||
DrawString(32, 17, bigbuf, font+1);
|
||||
}
|
||||
if(current.time!=-1){
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%04dL (%04dZ)", current.time, local2utc(current.time, NULL, NULL, NULL, NULL));
|
||||
DrawString(7, 23, bigbuf, font+1);
|
||||
}
|
||||
if(current.temp!=999){
|
||||
x=(temp_mode==0)?temp_C2F(current.temp):current.temp;
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%d", x);
|
||||
DrawString(32, 29, bigbuf, font);
|
||||
}
|
||||
if(current.rh!=-1){
|
||||
DrawChar(55, 29, '%', font);
|
||||
DrawNumber(54, 29, current.rh, font);
|
||||
}
|
||||
if(current.windspeed==0){
|
||||
x=GetStringWidth("CALM");
|
||||
DrawString(32+(26-x)/2, 35, "CALM", font);
|
||||
} else {
|
||||
if(current.winddir>=0 && current.winddir<=16){
|
||||
x=GetStringWidth(directions[current.winddir]);
|
||||
DrawString(45-x, 35, directions[current.winddir], font);
|
||||
}
|
||||
switch(windspeed_mode){
|
||||
case 0:
|
||||
x=knots2mph(current.windspeed);
|
||||
break;
|
||||
case 1:
|
||||
x=knots2kph(current.windspeed);
|
||||
break;
|
||||
case 3:
|
||||
x=knots2mps(current.windspeed);
|
||||
break;
|
||||
case 4:
|
||||
x=knots2beaufort(current.windspeed);
|
||||
break;
|
||||
}
|
||||
if(x>=0 && x<1000)
|
||||
DrawNumber(58, 35, x, font);
|
||||
}
|
||||
if(current.pressure>0){
|
||||
switch(pressure_mode){
|
||||
case 1:
|
||||
snprintf(bigbuf, BIGBUF_LEN, "P:%4.0f", inHg2hPa(current.pressure));
|
||||
break;
|
||||
case 2:
|
||||
snprintf(bigbuf, BIGBUF_LEN, "P:%5.1f", inHg2mmHg(current.pressure));
|
||||
break;
|
||||
case 3:
|
||||
snprintf(bigbuf, BIGBUF_LEN, "P:%5.3f", inHg2atm(current.pressure));
|
||||
break;
|
||||
default:
|
||||
snprintf(bigbuf, BIGBUF_LEN, "P:%5.2f", current.pressure);
|
||||
break;
|
||||
}
|
||||
DrawString(32, 41, bigbuf, font);
|
||||
}
|
||||
if(current.heatindex!=999){
|
||||
x=(temp_mode==0)?current.heatindex:temp_F2C(current.heatindex);
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
snprintf(bigbuf, BIGBUF_LEN, "HI: %d", x);
|
||||
DrawString(32, 47, bigbuf, font);
|
||||
}
|
||||
if(current.windchill!=999){
|
||||
x=(temp_mode==0)?current.windchill:temp_F2C(current.windchill);
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
snprintf(bigbuf, BIGBUF_LEN, "WC: %d", x);
|
||||
DrawString(32, 53, bigbuf, font);
|
||||
}
|
||||
|
||||
anim.show_counter=0;
|
||||
anim.min_pct=1;
|
||||
SetAnimation(&anim, 5, 28, current.sky, current.obs, current.vis,
|
||||
current.frz, current.snow, current.rain, current.tstorm, 0,
|
||||
current.moon);
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
f=current_forecast_get();
|
||||
if(last_fcst!=f) last_time=-1;
|
||||
last_fcst=f;
|
||||
if(f!=NULL){
|
||||
if(last_time==f->last_update)
|
||||
goto case_1_end; /* still check bottom line priority */
|
||||
else last_time=f->last_update;
|
||||
}
|
||||
|
||||
DisableMouseRegion(3);
|
||||
EnableMouseRegion(4);
|
||||
EnableMouseRegion(5);
|
||||
EnableMouseRegion(6);
|
||||
EnableMouseRegion(7);
|
||||
window_X=60; window_Y=0;
|
||||
last_priority=-1;
|
||||
|
||||
copyPixmapArea(124, 0, 54, 9, 65, 5);
|
||||
copyPixmapArea(142, 9, 18, 9, 83, 5);
|
||||
copyPixmapArea(123, 89, 6, 7, 65, 17);
|
||||
copyPixmapArea(129, 89, 6, 7, 113, 17);
|
||||
copyPixmapArea(124, 18, 36, 7, 74, 17);
|
||||
copyPixmapArea(124, 18, 54, 32, 65, 27);
|
||||
|
||||
if(f==NULL) break;
|
||||
|
||||
t=time(NULL);
|
||||
tm=localtime(&t);
|
||||
bigbuf[0]='\0';
|
||||
if(tm->tm_mon+1==f->month && tm->tm_mday==f->day){
|
||||
if(f->hour<0) snprintf(bigbuf, BIGBUF_LEN, "TODAY");
|
||||
else snprintf(bigbuf, BIGBUF_LEN, "TODAY %dL", f->hour);
|
||||
} else {
|
||||
x=tm->tm_mon+1;
|
||||
y=tm->tm_mday+1;
|
||||
fix_date(&x, &y, NULL, NULL);
|
||||
if(x==f->month && y==f->day){
|
||||
if(f->hour<0) snprintf(bigbuf, BIGBUF_LEN, "TOMORROW");
|
||||
else snprintf(bigbuf, BIGBUF_LEN, "TMRW %dL", f->hour);
|
||||
} else {
|
||||
z=0;
|
||||
if(f->wday!=-1){
|
||||
for(z=0; z<5; z++){
|
||||
y++;
|
||||
fix_date(&x, &y, NULL, NULL);
|
||||
if(x==f->month && y==f->day){
|
||||
if(f->hour<0) snprintf(bigbuf, BIGBUF_LEN, "%s",
|
||||
wdaynames[(int)f->wday]);
|
||||
else snprintf(bigbuf, BIGBUF_LEN, "%.3s %dL",
|
||||
wdaynames[(int)f->wday], f->hour);
|
||||
z=99;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(z<99 && f->month>0 && f->day>0){
|
||||
if(f->hour<0)
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%.3s %d",
|
||||
monthnames[(int)f->month], f->day);
|
||||
else snprintf(bigbuf, BIGBUF_LEN, "%.3s %d %dL",
|
||||
monthnames[(int)f->month], f->day,
|
||||
f->hour);
|
||||
}
|
||||
}
|
||||
}
|
||||
x=GetStringWidth(bigbuf);
|
||||
DrawString(60+(64-x)/2, 18, bigbuf, font);
|
||||
|
||||
x=GetStringWidth(f->station);
|
||||
DrawString(118-x, 28, f->station, font+1);
|
||||
|
||||
if(f->high!=999 || f->low!=999){
|
||||
DrawChar(104, 35, '/', font);
|
||||
if(f->high!=999){
|
||||
x=(temp_mode==0)?f->high:temp_F2C(f->high);
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
DrawNumber(103, 35, x, font);
|
||||
}
|
||||
if(f->low!=999){
|
||||
x=(temp_mode==0)?f->low:temp_F2C(f->low);
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
DrawNumber(118, 35, x, font);
|
||||
}
|
||||
}
|
||||
if(f->temp!=999){
|
||||
x=(temp_mode==0)?f->temp:temp_F2C(f->temp);
|
||||
if(x<-99) x=-99;
|
||||
if(x>199) x=199;
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%d", x);
|
||||
DrawString(92, 41, bigbuf, font);
|
||||
}
|
||||
if(f->rh!=-1){
|
||||
DrawChar(115, 41, '%', font);
|
||||
DrawNumber(114, 41, f->rh, font);
|
||||
}
|
||||
if(f->windspeed==0){
|
||||
x=GetStringWidth("CALM");
|
||||
DrawString(92+(26-x)/2, 47, "CALM", font);
|
||||
} else {
|
||||
if(f->winddir>=0 && f->winddir<=16){
|
||||
x=GetStringWidth(directions[f->winddir]);
|
||||
DrawString(105-x, 47, directions[f->winddir], font);
|
||||
}
|
||||
switch(windspeed_mode){
|
||||
case 0:
|
||||
x=knots2mph(f->windspeed);
|
||||
break;
|
||||
case 1:
|
||||
x=knots2kph(f->windspeed);
|
||||
break;
|
||||
case 3:
|
||||
x=knots2mps(f->windspeed);
|
||||
break;
|
||||
case 4:
|
||||
x=knots2beaufort(f->windspeed);
|
||||
break;
|
||||
}
|
||||
if(x>=0 && x<1000)
|
||||
DrawNumber(118, 47, x, font);
|
||||
}
|
||||
|
||||
anim.show_counter=show_counter;
|
||||
anim.min_pct=min_pct;
|
||||
SetAnimation(&anim, 65, 28, f->sky, f->obs, f->vis,
|
||||
f->frz, f->snow, f->rain, f->tstorm, f->svtstorm,
|
||||
f->moon);
|
||||
|
||||
case_1_end:
|
||||
if(f==NULL || forecast_priority==last_priority) break;
|
||||
|
||||
/* This is a little tricky. We use the switch as a calculated goto
|
||||
* (ick) to determine which order to try things in. Fall-through is
|
||||
* intended. */
|
||||
switch(forecast_priority){
|
||||
default:
|
||||
/* WTF? Oh well, just start at the beginning */
|
||||
|
||||
case 0:
|
||||
if(f->heatindex>=80 && f->heatindex!=999){
|
||||
copyPixmapArea(124, 18, 26, 5, 92, 53);
|
||||
x=(temp_mode==0)?f->heatindex:temp_F2C(f->heatindex);
|
||||
snprintf(bigbuf, BIGBUF_LEN, "HI: %d", x);
|
||||
DrawString(92, 53, bigbuf, font);
|
||||
forecast_priority=0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
if(f->windchill<=40 && f->windchill!=999){
|
||||
copyPixmapArea(124, 18, 26, 5, 92, 53);
|
||||
x=(temp_mode==0)?f->windchill:temp_F2C(f->windchill);
|
||||
snprintf(bigbuf, BIGBUF_LEN, "WC: %d", x);
|
||||
DrawString(92, 53, bigbuf, font);
|
||||
forecast_priority=1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
if(f->snowamt>0){
|
||||
copyPixmapArea(124, 18, 26, 5, 92, 53);
|
||||
if(f->snowamt==1){ x=1; y=2; }
|
||||
else if(f->snowamt==8){ x=8; y=-1; }
|
||||
else { x=f->snowamt; y=x+2; }
|
||||
if(length_mode==1){
|
||||
x=in2cm(x); y=in2cm(y);
|
||||
}
|
||||
if(x>9 && y>9) x=9;
|
||||
if(y==-1) snprintf(bigbuf, BIGBUF_LEN, "SN:>%d", x);
|
||||
else snprintf(bigbuf, BIGBUF_LEN, "SN:%d-%d", x, y);
|
||||
DrawString(92, 53, bigbuf, font);
|
||||
forecast_priority=2;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
if(f->precipamt>0){
|
||||
copyPixmapArea(124, 18, 26, 5, 92, 53);
|
||||
switch(f->precipamt){
|
||||
case 1:
|
||||
if(length_mode==0) DrawString(92, 53, "P:.01-.1", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P: 0-.25", font);
|
||||
break;
|
||||
case 2:
|
||||
if(length_mode==0) DrawString(92, 53, "P:.1-.25", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P:.25-.6", font);
|
||||
break;
|
||||
case 3:
|
||||
if(length_mode==0) DrawString(92, 53, "P:.25-.5", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P:.6-1.3", font);
|
||||
break;
|
||||
case 4:
|
||||
if(length_mode==0) DrawString(92, 53, "P: .5-1", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P: 1-2.5", font);
|
||||
break;
|
||||
case 5:
|
||||
if(length_mode==0) DrawString(92, 53, "P: 1-2", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P: 2.5-5", font);
|
||||
break;
|
||||
case 6:
|
||||
if(length_mode==0) DrawString(92, 53, "P: >2", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P: >5", font);
|
||||
break;
|
||||
case 7:
|
||||
if(length_mode==0) DrawString(92, 53, "P: >3", font);
|
||||
if(length_mode==1) DrawString(92, 53, "P: >7.6", font);
|
||||
break;
|
||||
}
|
||||
forecast_priority=3;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
copyPixmapArea(124, 18, 26, 5, 92, 53);
|
||||
x=GetStringWidth("<")+1;
|
||||
y=GetStringWidth(f->ID)+1;
|
||||
z=GetStringWidth(">");
|
||||
DrawChar(118-x-y-z, 53, '<', font+1);
|
||||
DrawString(118-y-z, 53, f->ID, font+1);
|
||||
DrawChar(118-z, 53, '>', font+1);
|
||||
forecast_priority=4;
|
||||
break;
|
||||
}
|
||||
last_priority=forecast_priority;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(last_time==radar_update_time) break;
|
||||
last_time=radar_update_time;
|
||||
EnableMouseRegion(3);
|
||||
DisableMouseRegion(4);
|
||||
DisableMouseRegion(5);
|
||||
DisableMouseRegion(6);
|
||||
DisableMouseRegion(7);
|
||||
window_X=0; window_Y=0;
|
||||
|
||||
copyPixmapArea(124, 0, 54, 9, 5, 5);
|
||||
copyPixmapArea(160, 9, 18, 9, 41, 5);
|
||||
put_radar(6, 18, font);
|
||||
|
||||
anim.active=0;
|
||||
break;
|
||||
}
|
||||
DoAnimation(&anim);
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
void init_dock(int argc, char **argv);
|
||||
void update_dock();
|
|
@ -1,267 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "die.h"
|
||||
#include "download.h"
|
||||
|
||||
static CURLM *multi_handle=NULL;
|
||||
static int still_running=0;
|
||||
struct download_info {
|
||||
CURL *handle;
|
||||
FILE *fp;
|
||||
void (*callback)(char *filename, void *data);
|
||||
char *filename;
|
||||
void *data;
|
||||
int flags;
|
||||
struct download_info *next;
|
||||
struct download_info *prev;
|
||||
};
|
||||
static struct download_info *active_list=NULL;
|
||||
|
||||
static void add_active(struct download_info *d){
|
||||
d->next=active_list;
|
||||
d->prev=NULL;
|
||||
if(active_list!=NULL) active_list->prev=d;
|
||||
active_list=d;
|
||||
}
|
||||
|
||||
static void remove_active(struct download_info *d){
|
||||
if(active_list==d) active_list=d->next;
|
||||
if(d->prev!=NULL) d->prev->next=d->next;
|
||||
if(d->next!=NULL) d->next->prev=d->prev;
|
||||
d->next=NULL;
|
||||
d->prev=NULL;
|
||||
}
|
||||
|
||||
static struct download_info *find_active_file(char *f){
|
||||
struct download_info *d;
|
||||
for(d=active_list; d!=NULL; d=d->next){
|
||||
if(!strcmp(d->filename,f)) return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void handle_done(CURLMsg *msg){
|
||||
struct download_info *info;
|
||||
long status;
|
||||
|
||||
if(curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &info)!=CURLE_OK || info==NULL){
|
||||
warn("Could not retrieve info handle from CURL handle. WTF?");
|
||||
for(info=active_list; info && info->handle!=msg->easy_handle; info=info->next);
|
||||
if(info==NULL){
|
||||
warn("Could not find it in the active list either. WTF?");
|
||||
curl_multi_remove_handle(multi_handle, msg->easy_handle);
|
||||
curl_easy_cleanup(msg->easy_handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
remove_active(info);
|
||||
curl_multi_remove_handle(multi_handle, info->handle);
|
||||
fclose(info->fp);
|
||||
|
||||
if(msg->data.result!=CURLE_OK){
|
||||
if(msg->data.result==CURLE_HTTP_RETURNED_ERROR){
|
||||
if(curl_easy_getinfo(info->handle, CURLINFO_RESPONSE_CODE, &status)!=CURLE_OK) status=600;
|
||||
if(status!=404 || !(info->flags&DOWNLOAD_NO_404))
|
||||
warn("HTTP download of %s returned %d", info->filename, status);
|
||||
} else {
|
||||
warn("Download of %s failed: %s", info->filename, curl_easy_strerror(msg->data.result));
|
||||
}
|
||||
unlink(info->filename);
|
||||
} else {
|
||||
(*info->callback)(info->filename, info->data);
|
||||
}
|
||||
|
||||
curl_easy_cleanup(info->handle);
|
||||
free(info->filename);
|
||||
free(info);
|
||||
}
|
||||
|
||||
|
||||
void download_init(char *email){
|
||||
if(multi_handle==NULL){
|
||||
if(curl_global_init(CURL_GLOBAL_ALL))
|
||||
die("Could not initialize CURL");
|
||||
multi_handle=curl_multi_init();
|
||||
if(multi_handle==NULL) die("Could not create a CURL multihandle");
|
||||
}
|
||||
}
|
||||
|
||||
void download_process(unsigned long sleeptime){
|
||||
fd_set rd, wr, er;
|
||||
struct timeval tv;
|
||||
int maxfd, n, x;
|
||||
CURLMsg *msg;
|
||||
|
||||
if(sleeptime>0){
|
||||
FD_ZERO(&rd);
|
||||
FD_ZERO(&wr);
|
||||
FD_ZERO(&er);
|
||||
curl_multi_fdset(multi_handle, &rd, &wr, &er, &maxfd);
|
||||
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=sleeptime;
|
||||
if(sleeptime>=1000000){
|
||||
tv.tv_sec=sleeptime/1000000;
|
||||
tv.tv_usec=sleeptime%1000000;
|
||||
}
|
||||
|
||||
n=select(maxfd+1, &rd, &wr, &er, &tv);
|
||||
if(n==0) return;
|
||||
if(n<0){
|
||||
switch(errno){
|
||||
case EINTR:
|
||||
case ENOMEM:
|
||||
/* transient errors, hope it's good next time */
|
||||
break;
|
||||
|
||||
default:
|
||||
warn("WTF? select errno=%d", errno);
|
||||
break;
|
||||
}
|
||||
usleep(sleeptime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(curl_multi_perform(multi_handle, &x)==CURLM_CALL_MULTI_PERFORM);
|
||||
while((msg=curl_multi_info_read(multi_handle, &x))){
|
||||
switch(msg->msg){
|
||||
case CURLMSG_DONE:
|
||||
handle_done(msg);
|
||||
break;
|
||||
default:
|
||||
warn("Unknown CURL message type %d", msg->msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int download_kill(char *filename){
|
||||
struct download_info *info;
|
||||
info=find_active_file(filename);
|
||||
if(info==NULL) return ENOENT;
|
||||
remove_active(info);
|
||||
curl_multi_remove_handle(multi_handle, info->handle);
|
||||
warn("Download of %s interrupted", info->filename);
|
||||
unlink(info->filename);
|
||||
curl_easy_cleanup(info->handle);
|
||||
free(info->filename);
|
||||
fclose(info->fp);
|
||||
free(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int download_file(char *filename, char *from_addr, char *postdata, int flags, void (*callback)(char *filename, void *data), void *data){
|
||||
struct download_info *info=NULL;
|
||||
FILE *fp;
|
||||
|
||||
if(callback==NULL || filename==NULL || from_addr==NULL) return 1;
|
||||
|
||||
if(flags&DOWNLOAD_KILL_OTHER_REQUESTS){
|
||||
download_kill(filename);
|
||||
} else {
|
||||
info=find_active_file(filename);
|
||||
if(info!=NULL){
|
||||
errno=0;
|
||||
warn("Cannot download %s: download already in progress", filename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if((info=malloc(sizeof(*info)))==NULL){
|
||||
warn("Malloc error in download_file");
|
||||
goto fail;
|
||||
}
|
||||
info->handle=NULL;
|
||||
info->fp=NULL;
|
||||
info->callback=callback;
|
||||
info->filename=NULL;
|
||||
info->data=data;
|
||||
info->flags=flags;
|
||||
info->next=NULL;
|
||||
info->prev=NULL;
|
||||
|
||||
if((info->filename=strdup(filename))==NULL) goto fail;
|
||||
if((info->fp=fopen(info->filename, "wb"))==NULL){
|
||||
warn("Error opening %s for output", info->filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
info->handle=curl_easy_init();
|
||||
if(info->handle==NULL){
|
||||
warn("Error creating a CURL handle");
|
||||
goto fail;
|
||||
}
|
||||
if(curl_easy_setopt(info->handle, CURLOPT_URL, from_addr)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_NOPROGRESS, 1)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_NOSIGNAL, 1)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_WRITEDATA, info->fp)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_FAILONERROR, 1)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_AUTOREFERER, 1)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_FOLLOWLOCATION, 1)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_TIMEOUT, 10*60)!=CURLE_OK ||
|
||||
curl_easy_setopt(info->handle, CURLOPT_PRIVATE, info)!=CURLE_OK
|
||||
){
|
||||
warn("Error setting CURL options");
|
||||
goto fail;
|
||||
}
|
||||
if(postdata!=NULL){
|
||||
if(curl_easy_setopt(info->handle, CURLOPT_COPYPOSTFIELDS, postdata)!=CURLE_OK
|
||||
){
|
||||
warn("Error setting CURL post options");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if(curl_multi_add_handle(multi_handle, info->handle)!=CURLM_OK){
|
||||
warn("Could not add handle for %s to multihandle", info->filename);
|
||||
goto fail;
|
||||
}
|
||||
add_active(info);
|
||||
|
||||
/* Call download_process with 0 to force at least one call to
|
||||
* curl_multi_process, because curl won't actually create a socket until
|
||||
* that function is called and download_process won't otherwise call
|
||||
* curl_multi_process until the socket is created...
|
||||
*/
|
||||
download_process(0);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if(info){
|
||||
if(info->handle) curl_easy_cleanup(info->handle);
|
||||
info->handle=NULL;
|
||||
if(info->fp) fclose(info->fp);
|
||||
info->fp=NULL;
|
||||
if(info->filename){
|
||||
unlink(info->filename);
|
||||
free(info->filename);
|
||||
}
|
||||
info->filename=NULL;
|
||||
free(info);
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef DOWNLOAD_H
|
||||
#define DOWNLOAD_H
|
||||
|
||||
/* flags for download_file */
|
||||
#define DOWNLOAD_NO_404 1
|
||||
#define DOWNLOAD_KILL_OTHER_REQUESTS 2
|
||||
|
||||
void download_init(char *email);
|
||||
void download_process(unsigned long sleep_time);
|
||||
int download_kill(char *filename);
|
||||
int download_file(char *filename, char *from_addr, char *postdata, int flags, void (*callback)(char *filename, void *data), void *data);
|
||||
|
||||
#endif
|
365
wmweather+/eta.c
365
wmweather+/eta.c
|
@ -1,365 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "forecast.h"
|
||||
#include "getLine.h"
|
||||
#include "convert.h"
|
||||
#include "download.h"
|
||||
#include "diff.h"
|
||||
#include "die.h"
|
||||
#include "sunzenith.h"
|
||||
#include "moon.h"
|
||||
#include "subst.h"
|
||||
|
||||
/* Important variables */
|
||||
#define ETA_MAX 21
|
||||
static time_t eta_time=0;
|
||||
static char *eta_file=NULL;
|
||||
static char *eta_newfile=NULL;
|
||||
static char *eta_req[2]={ NULL, NULL };
|
||||
static struct forecast forecasts[ETA_MAX];
|
||||
|
||||
|
||||
/********* init functions ************/
|
||||
static int parse_eta(char *file);
|
||||
|
||||
static void reset_eta(void){
|
||||
int i;
|
||||
|
||||
for(i=0; i<ETA_MAX; i++) reset_forecast(&forecasts[i]);
|
||||
}
|
||||
|
||||
void init_eta(void){
|
||||
char *e;
|
||||
int i;
|
||||
struct subst_val subs[]={
|
||||
{ 's', STRING, &eta_station },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
strncpy(bigbuf, eta_station, BIGBUF_LEN-14);
|
||||
bigbuf[BIGBUF_LEN-14]='\0';
|
||||
for(e=bigbuf; *e!='\0'; e++);
|
||||
strcpy(e, ".eta.txt");
|
||||
eta_file=get_pid_filename(bigbuf);
|
||||
strcpy(e, ".new-eta.txt");
|
||||
eta_newfile=get_pid_filename(bigbuf);
|
||||
|
||||
if((eta_req[0]=subst(eta_uri, subs))==NULL) die("init_eta");
|
||||
if(eta_post!=NULL && (eta_req[1]=subst(eta_post, subs))==NULL) die("init_eta");
|
||||
eta_time=0;
|
||||
|
||||
/* Remove stale file */
|
||||
unlink(eta_file);
|
||||
unlink(eta_newfile);
|
||||
reset_eta();
|
||||
for(i=0; i<ETA_MAX; i++) add_forecast(&forecasts[i], "ETA", eta_station);
|
||||
}
|
||||
|
||||
|
||||
/********* download functions ************/
|
||||
|
||||
static void eta_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(eta_newfile, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& diff(eta_newfile, eta_file) && parse_eta(eta_newfile)){
|
||||
eta_time=find_next_time(eta_newfile, "MOS GUIDANCE", 720);
|
||||
rename(eta_newfile, eta_file);
|
||||
} else {
|
||||
unlink(eta_newfile);
|
||||
if(!parse_eta(eta_file)) reset_eta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eta_cleanup(void){
|
||||
if(eta_file==NULL) return;
|
||||
unlink(eta_newfile);
|
||||
unlink(eta_file);
|
||||
}
|
||||
|
||||
void update_eta(int force){
|
||||
time_t t;
|
||||
|
||||
if(eta_file==NULL) return;
|
||||
|
||||
t=time(NULL)/60;
|
||||
if(!force && eta_time>t) return;
|
||||
|
||||
eta_time=find_next_time(eta_file, "MOS GUIDANCE", 15);
|
||||
download_file(eta_newfile, eta_req[0], eta_req[1], force?DOWNLOAD_KILL_OTHER_REQUESTS:0, eta_callback, NULL);
|
||||
}
|
||||
|
||||
|
||||
/********* parse functions ************/
|
||||
|
||||
#define NEXT(s) free(s); \
|
||||
len=getLine(&s, fp); \
|
||||
if(strstr(s, "</PRE>")!=NULL) len=0;
|
||||
|
||||
#define DIE() return (free(s), fclose(fp), 0)
|
||||
#define SPLIT(s) { \
|
||||
ID[0]=s[0]; \
|
||||
ID[1]=s[1]; \
|
||||
ID[2]=s[2]; \
|
||||
ID[3]='\0'; \
|
||||
memset(split,'\0',sizeof(split)); \
|
||||
for(n=0, c=s+4; c<s+len && n<ETA_MAX; n++, c+=3){ \
|
||||
split[n][0]=c[0]; \
|
||||
split[n][1]=c[1]; \
|
||||
split[n][2]=c[2]; \
|
||||
split[n][3]='\0'; \
|
||||
} \
|
||||
}
|
||||
#define ASSIGN(field) \
|
||||
for(n=0; n<ETA_MSG_MAX; n++) forecasts[n].field=atoi(split[n]);
|
||||
|
||||
#define ASSIGN2(field, inval) \
|
||||
for(n=0; n<ETA_MSG_MAX; n++){ \
|
||||
i=atoi(split[n]); \
|
||||
if(i!=inval) forecasts[n].field=i; \
|
||||
}
|
||||
|
||||
static int parse_eta(char *file){
|
||||
int ETA_MSG_MAX = ETA_MAX;
|
||||
FILE *fp;
|
||||
char *s, *c;
|
||||
int len;
|
||||
int mon, day;
|
||||
int h, i=0, j, k, m, n, x, y, z;
|
||||
char ID[4];
|
||||
char split[ETA_MAX][4];
|
||||
|
||||
reset_eta();
|
||||
if((fp=fopen(file, "r"))==NULL) return 0;
|
||||
|
||||
/* Look for something like an ETA coded forecast */
|
||||
c=NULL;
|
||||
while(!feof(fp)){
|
||||
len=getLine(&s, fp);
|
||||
if((c=strstr(s, "MOS GUIDANCE"))!=NULL) break;
|
||||
free(s);
|
||||
}
|
||||
if(c==NULL) return (fclose(fp), 0);
|
||||
c=strchr(c, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
m=atoi(c-2);
|
||||
c=strchr(c+1, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
y=atoi(c+1)-1900;
|
||||
|
||||
/* get first date */
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
if(strncmp(s, "DT ", 3)) DIE();
|
||||
mon=13;
|
||||
c=s;
|
||||
i=4;
|
||||
while(mon>12){
|
||||
c=strchr(c+1, '/');
|
||||
if(c==NULL) DIE();
|
||||
for(mon=1; mon<=12; mon++){
|
||||
if(!strncmp(c+1, monthnames[mon], 3) && isspace(*(c+4))) break;
|
||||
if(!strncmp(c+1, monthnames2[mon], 4) && isspace(*(c+5))){
|
||||
i=5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
day=atoi(c+i);
|
||||
if(day<1) DIE();
|
||||
if(c>s+4) day--;
|
||||
if(mon<m) y++;
|
||||
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
if(strncmp(s, "HR ", 3)) DIE();
|
||||
x=day;
|
||||
m=mon;
|
||||
SPLIT(s);
|
||||
for(n=0; n<ETA_MAX; n++){
|
||||
if(split[n][0]=='\0'){
|
||||
ETA_MSG_MAX = n;
|
||||
break;
|
||||
}
|
||||
i=atoi(split[n]);
|
||||
if(i==0){
|
||||
x++;
|
||||
fix_date(&mon, &x, &y, NULL);
|
||||
}
|
||||
m=mon;
|
||||
j=x;
|
||||
z=y;
|
||||
h=utc2local(i*100, &m, &j, &z, &k)/100;
|
||||
forecasts[n].month=m;
|
||||
forecasts[n].day=j;
|
||||
forecasts[n].year=z;
|
||||
forecasts[n].hour=h;
|
||||
forecasts[n].wday=k;
|
||||
if(latitude!=999 && calcSolarZenith(latitude, longitude, y, mon, x, i*60)>90)
|
||||
forecasts[n].moon=calc_moon(m, j, z, h*100);
|
||||
}
|
||||
|
||||
while(1){
|
||||
NEXT(s);
|
||||
if(len<=10) break;
|
||||
SPLIT(s);
|
||||
|
||||
if(!strcmp(ID, "X/N")) j=1;
|
||||
else if(!strcmp(ID, "N/X")) j=2;
|
||||
else j=0;
|
||||
if(j!=0){
|
||||
for(n=0; n<ETA_MSG_MAX; n++){
|
||||
if(!isdigit(split[n][2])) continue;
|
||||
i=atoi(split[n]);
|
||||
k=day+(j>>1);
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
if((j&1)==1 &&
|
||||
((forecasts[m].day==k-1 && forecasts[m].hour>=19)
|
||||
|| (forecasts[m].day==k && forecasts[m].hour<19)))
|
||||
forecasts[m].high=i;
|
||||
if((j&1)==0 &&
|
||||
((forecasts[m].day==k-1 && forecasts[m].hour>=8)
|
||||
|| (forecasts[m].day==k && forecasts[m].hour<8)))
|
||||
forecasts[m].low=i;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "TMP")){
|
||||
ASSIGN(temp);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "DPT")){
|
||||
ASSIGN(dewpt);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "WDR")){
|
||||
for(n=0; n<ETA_MSG_MAX; n++){
|
||||
i=atoi(split[n]);
|
||||
if(i==99) forecasts[n].winddir=0;
|
||||
else forecasts[n].winddir=((int)((i+1.125)/2.25))%16+1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "WSP")){
|
||||
ASSIGN2(windspeed, 99);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "P06")){
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]);
|
||||
if(i!=999){
|
||||
forecasts[m].pcp_total=i;
|
||||
/* ETA_MSG_MAX-2 because the last 2
|
||||
* are already 6-hour intervals */
|
||||
if(m>0 && m<ETA_MSG_MAX-2) forecasts[m-1].pcp_total=i;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "T06")){
|
||||
for(m=1; m<ETA_MSG_MAX; m+=2){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]); if(i==999) i=0;
|
||||
j=atoi(split[m+1]+1); if(j==99) j=0;
|
||||
j=i*j/100;
|
||||
forecasts[m].tstorm=forecasts[m+1].tstorm=i;
|
||||
forecasts[m].svtstorm=forecasts[m+1].svtstorm=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "Q06")){
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
if(!isdigit(split[m][2])) continue;
|
||||
i=atoi(split[m]);
|
||||
if(i!=999){
|
||||
forecasts[m].precipamt=i;
|
||||
/* ETA_MSG_MAX-2 because the last 2
|
||||
* are already 6-hour intervals */
|
||||
if(m>0 && m<ETA_MSG_MAX-2) forecasts[m-1].precipamt=i;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "CLD")){
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
if(split[m][1]=='C') forecasts[m].sky=0;
|
||||
if(split[m][1]=='F') forecasts[m].sky=1;
|
||||
if(split[m][1]=='S') forecasts[m].sky=2;
|
||||
if(split[m][1]=='B') forecasts[m].sky=3;
|
||||
if(split[m][1]=='O') forecasts[m].sky=4;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "VIS")){
|
||||
ASSIGN2(vis, 9);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "OBV")){
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
if(split[m][2]=='N') forecasts[m].obs=0;
|
||||
if(split[m][2]=='R' || split[m][2]=='G') forecasts[m].obs=1;
|
||||
if(split[m][2]=='Z') forecasts[m].obs=2;
|
||||
if(split[m][2]=='L') forecasts[m].obs=3;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "POZ")){
|
||||
ASSIGN2(frz, 999);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(ID, "POS")){
|
||||
ASSIGN2(snow, 999);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
free(s);
|
||||
fclose(fp);
|
||||
|
||||
for(m=0; m<ETA_MSG_MAX; m++){
|
||||
forecasts[m].rh=rh_F(forecasts[m].temp, forecasts[m].dewpt);
|
||||
forecasts[m].heatindex=heatindex_F(forecasts[m].temp, forecasts[m].rh);
|
||||
forecasts[m].windchill=windchill_F(forecasts[m].temp, forecasts[m].windspeed);
|
||||
forecasts[m].rain=93-forecasts[m].frz-forecasts[m].snow;
|
||||
forecasts[m].rain=forecasts[m].rain*forecasts[m].pcp_total/93;
|
||||
forecasts[m].snow=forecasts[m].snow*forecasts[m].pcp_total/93;
|
||||
forecasts[m].frz=forecasts[m].frz*forecasts[m].pcp_total/93;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#undef NEXT
|
||||
#undef DIE
|
||||
#undef SPLIT
|
||||
#undef ASSIGN
|
||||
#undef ASSIGN2
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef ETA_H
|
||||
#define ETA_H
|
||||
|
||||
void init_eta(void);
|
||||
void update_eta(int force);
|
||||
void eta_cleanup(void);
|
||||
|
||||
#endif
|
|
@ -1,9 +0,0 @@
|
|||
# Sample configuration file for the Chicago, IL area
|
||||
# Note that there are several other possible stations to choose from
|
||||
|
||||
email you@example.com
|
||||
station KORD
|
||||
warning-zone ilz014
|
||||
radar-uri http://image.weather.com/web/radar/us_ord_closeradar_small_usen.jpg
|
||||
radar-crop 81x55+104+80
|
||||
radar-cross 42x25
|
|
@ -1,147 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#include "wmgeneral/wmgeneral-x11.h"
|
||||
extern XpmIcon wmgen;
|
||||
extern GC NormalGC;
|
||||
extern Window Root;
|
||||
|
||||
#include "characters.xpm"
|
||||
|
||||
static Pixmap fonts[3]={ None, None, None };
|
||||
static char *colors[3][4]={
|
||||
{ "#000000", "#0C4E66", "#127599", "#1EC3FF" },
|
||||
{ "#000000", "#664D0B", "#997411", "#FFC21D" },
|
||||
{ "#000000", "#662B31", "#99414A", "#FF6D7B" }
|
||||
};
|
||||
|
||||
void init_font(int i){
|
||||
XpmIcon x;
|
||||
XpmColorSymbol cols[4]={
|
||||
{"Background", NULL, 0},
|
||||
{"Low", NULL, 0},
|
||||
{"Mid", NULL, 0},
|
||||
{"High", NULL, 0}
|
||||
};
|
||||
int j;
|
||||
|
||||
if(fonts[i]!=None) return;
|
||||
for(j=0; j<4; j++){
|
||||
cols[j].pixel=GetColor(colors[i][j]);
|
||||
}
|
||||
x.attributes.numsymbols=5;
|
||||
x.attributes.colorsymbols=cols;
|
||||
x.attributes.exactColors=False;
|
||||
x.attributes.closeness=40000;
|
||||
x.attributes.valuemask=(XpmColorSymbols | XpmExactColors | XpmCloseness);
|
||||
GetXPM(&x, characters_xpm);
|
||||
fonts[i]=x.pixmap;
|
||||
XFreePixmap(display, x.mask);
|
||||
}
|
||||
|
||||
int DrawString(int x, int y, char *str, int font){
|
||||
int w;
|
||||
char *c;
|
||||
|
||||
w=0;
|
||||
for(c=str; *c!='\0'; c++){
|
||||
w+=DrawChar(x+w, y, *c, font);
|
||||
w++;
|
||||
}
|
||||
|
||||
return w-1;
|
||||
}
|
||||
|
||||
int GetStringWidth(char *str){
|
||||
int w;
|
||||
char *c;
|
||||
|
||||
w=0;
|
||||
for(c=str; *c!='\0'; c++){
|
||||
w+=DrawChar(-1, -1, *c, -1);
|
||||
w++;
|
||||
}
|
||||
|
||||
return w-1;
|
||||
}
|
||||
|
||||
int DrawNumber(int x, int y, int n, int font){
|
||||
int w;
|
||||
int flag=0;
|
||||
char c;
|
||||
|
||||
if(n<0){
|
||||
flag=1;
|
||||
n=-n;
|
||||
}
|
||||
|
||||
w=0;
|
||||
do {
|
||||
w+=3;
|
||||
c='0'+(n%10);
|
||||
DrawChar(x-w, y, c, font);
|
||||
n/=10;
|
||||
w++;
|
||||
} while(n>0);
|
||||
if(flag){
|
||||
w+=2;
|
||||
DrawChar(x-w, y, '-', font);
|
||||
w++;
|
||||
}
|
||||
|
||||
return w-1;
|
||||
}
|
||||
|
||||
int DrawChar(int x, int y, char c, int font){
|
||||
int sx, w;
|
||||
|
||||
c=toupper(c);
|
||||
w=3;
|
||||
if(c>='A' && c<='Z'){
|
||||
sx=(c-'A')*4+1;
|
||||
if(c=='M'){ w=4; sx=149; }
|
||||
if(c=='N'){ w=4; sx=154; }
|
||||
if(c=='W'){ w=4; sx=159; }
|
||||
} else if(c>='0' && c<='9') sx=(c-'0')*4+105;
|
||||
else if(c==':'){ w=1; sx=164; }
|
||||
else if(c=='('){ w=2; sx=171; }
|
||||
else if(c==')'){ w=2; sx=174; }
|
||||
else if(c=='%') sx=89;
|
||||
else if(c=='-'){ w=2; sx=168; }
|
||||
else if(c=='.'){ w=1; sx=166; }
|
||||
else if(c=='<') sx=49;
|
||||
else if(c=='>') sx=53;
|
||||
else if(c=='/') sx=145;
|
||||
else if(c=='\''){ w=1; sx=177; }
|
||||
else return 0;
|
||||
|
||||
if(x>=0 && y>=0 && x+w<192 && y<174 && font>=0 && font<3){
|
||||
init_font(font);
|
||||
XCopyArea(display, fonts[font], wmgen.pixmap, NormalGC, sx, 1, w, 5, x, y);
|
||||
}
|
||||
return w;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
int DrawString(int x, int y, char *str, int font);
|
||||
int GetStringWidth(char *str);
|
||||
int DrawNumber(int x, int y, int n, int font);
|
||||
int DrawChar(int x, int y, char c, int font);
|
||||
|
||||
/* This is called automatically if necessary */
|
||||
void init_font(int i);
|
|
@ -1,311 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <pcre.h>
|
||||
|
||||
#include "forecast.h"
|
||||
#include "convert.h"
|
||||
#include "getLine.h"
|
||||
#include "die.h"
|
||||
|
||||
/* Important variables */
|
||||
static struct forecast **forecasts=NULL;
|
||||
static int num_forecasts=0;
|
||||
static pcre *date=NULL;
|
||||
static int ovecsize=1;
|
||||
static int changed=0;
|
||||
|
||||
/* functions */
|
||||
|
||||
time_t find_next_time(char *file, char *pat, int minutes){
|
||||
FILE *fp;
|
||||
char *s;
|
||||
time_t t, mintime;
|
||||
|
||||
mintime=time(NULL)/60+15;
|
||||
if((fp=fopen(file, "r"))==NULL) return mintime;
|
||||
|
||||
s=NULL;
|
||||
while(!feof(fp)){
|
||||
getLine(&s, fp);
|
||||
if(strstr(s, pat)!=NULL) break;
|
||||
free(s);
|
||||
s=NULL;
|
||||
}
|
||||
fclose(fp);
|
||||
if(s==NULL) return mintime;
|
||||
t=parse_time_string(s)/60+minutes;
|
||||
free(s);
|
||||
return (t>mintime)?t:mintime;
|
||||
}
|
||||
|
||||
time_t parse_time_string(char *s){
|
||||
struct tm tm;
|
||||
int ovector[ovecsize];
|
||||
int ovalue;
|
||||
char *e;
|
||||
int i;
|
||||
|
||||
if(date==NULL){
|
||||
date=pcre_compile("\\b(\\d+)/(\\d+)/(\\d+)\\s+(\\d\\d)(\\d\\d)\\s*UTC\\b", 0, (const char **)&e, &i, NULL);
|
||||
if(date==NULL){
|
||||
warn("find_next PCRE error: %s at %i", e, i);
|
||||
return -1;
|
||||
}
|
||||
pcre_fullinfo(date, NULL, PCRE_INFO_CAPTURECOUNT, &ovecsize);
|
||||
ovecsize=(ovecsize+1)*3;
|
||||
return parse_time_string(s);
|
||||
}
|
||||
|
||||
ovalue=pcre_exec(date, NULL, s, strlen(s), 0, 0, ovector, ovecsize);
|
||||
if(ovalue<=0) return -1;
|
||||
|
||||
if(pcre_get_substring(s, ovector, ovalue, 1, (const char **)&e)<0) return 0;
|
||||
tm.tm_mon=atoi(e)-1;
|
||||
pcre_free_substring(e);
|
||||
if(pcre_get_substring(s, ovector, ovalue, 2, (const char **)&e)<0) return 0;
|
||||
tm.tm_mday=atoi(e);
|
||||
pcre_free_substring(e);
|
||||
if(pcre_get_substring(s, ovector, ovalue, 3, (const char **)&e)<0) return 0;
|
||||
tm.tm_year=atoi(e)-1900;
|
||||
pcre_free_substring(e);
|
||||
if(pcre_get_substring(s, ovector, ovalue, 4, (const char **)&e)<0) return 0;
|
||||
tm.tm_hour=atoi(e);
|
||||
pcre_free_substring(e);
|
||||
if(pcre_get_substring(s, ovector, ovalue, 5, (const char **)&e)<0) return 0;
|
||||
tm.tm_min=atoi(e);
|
||||
pcre_free_substring(e);
|
||||
tm.tm_sec=0;
|
||||
|
||||
return mkgmtime(&tm);
|
||||
}
|
||||
|
||||
void add_forecast(struct forecast *f, char *ID, char *station){
|
||||
if((forecasts=realloc(forecasts, ++num_forecasts*sizeof(*forecasts)))==NULL)
|
||||
die("realloc in add_forecast");
|
||||
|
||||
if(ID==NULL){
|
||||
memset(f->ID, '\0', 4);
|
||||
} else {
|
||||
strncpy(f->ID, ID, 3);
|
||||
f->ID[3]='\0';
|
||||
}
|
||||
f->station=station;
|
||||
forecasts[num_forecasts-1]=f;
|
||||
changed=1;
|
||||
}
|
||||
|
||||
void reset_forecast(struct forecast *f){
|
||||
f->last_update=time(NULL);
|
||||
f->month=0;
|
||||
f->day=-1;
|
||||
f->year=SHRT_MIN;
|
||||
f->wday=-1;
|
||||
f->hour=-1;
|
||||
f->low=999;
|
||||
f->high=999;
|
||||
f->temp=999;
|
||||
f->dewpt=999;
|
||||
f->rh=-1;
|
||||
f->winddir=-1;
|
||||
f->windspeed=-1;
|
||||
f->heatindex=999;
|
||||
f->windchill=999;
|
||||
f->precipamt=-1;
|
||||
f->snowamt=-1;
|
||||
f->sky=-1;
|
||||
f->vis=7;
|
||||
f->obs=0;
|
||||
f->pcp_total=0;
|
||||
f->frz=0;
|
||||
f->snow=0;
|
||||
f->rain=0;
|
||||
f->tstorm=0;
|
||||
f->svtstorm=0;
|
||||
f->moon=NAN;
|
||||
f->time=-1;
|
||||
changed=1;
|
||||
}
|
||||
|
||||
static int is_forecast_valid(const struct forecast *a){
|
||||
return (a->ID[0]!='\0' &&
|
||||
a->month>0 && a->month<=12 &&
|
||||
a->day>0 && a->day<=31 &&
|
||||
a->year!=SHRT_MIN);
|
||||
}
|
||||
|
||||
static int is_forecast_current(struct forecast *f, time_t now){
|
||||
time_t t;
|
||||
|
||||
t=forecast_time(f);
|
||||
t+=(f->hour<0)?86399:3599;
|
||||
return t>now;
|
||||
}
|
||||
|
||||
static int compar(const void *aa, const void *bb){
|
||||
struct forecast *a=*(struct forecast **)aa;
|
||||
struct forecast *b=*(struct forecast **)bb;
|
||||
int i, j;
|
||||
|
||||
/* First, any undefined forecast is greater than any defined forecast */
|
||||
i=is_forecast_valid(a);
|
||||
j=is_forecast_valid(b);
|
||||
if(!i && !j) return 0; /* all undef forecasts are equal */
|
||||
if(!i) return 1;
|
||||
if(!j) return -1;
|
||||
|
||||
/* Any whole-day forecast is greater than any partial forecast */
|
||||
if(a->hour<0 && b->hour>=0) return 1;
|
||||
if(a->hour>=0 && b->hour<0) return -1;
|
||||
|
||||
/* Ok, compare dates now */
|
||||
if(a->year>b->year) return 1;
|
||||
if(a->year<b->year) return -1;
|
||||
if(a->month>b->month) return 1;
|
||||
if(a->month<b->month) return -1;
|
||||
if(a->day>b->day) return 1;
|
||||
if(a->day<b->day) return -1;
|
||||
if(a->hour>b->hour) return 1;
|
||||
if(a->hour<b->hour) return -1;
|
||||
|
||||
/* Last resort, sort in alphabetical order by ID */
|
||||
return strcasecmp(a->ID, b->ID);
|
||||
}
|
||||
|
||||
static void sort_forecasts(void){
|
||||
if(forecasts==NULL) return;
|
||||
qsort(forecasts, num_forecasts, sizeof(struct forecast *), compar);
|
||||
changed=0;
|
||||
}
|
||||
|
||||
time_t forecast_time(struct forecast *f){
|
||||
struct tm tm;
|
||||
|
||||
if(f->time!=-1) return f->time;
|
||||
tm.tm_year=f->year;
|
||||
tm.tm_mon=f->month-1;
|
||||
tm.tm_mday=f->day;
|
||||
tm.tm_hour=(f->hour<0)?0:f->hour;
|
||||
tm.tm_min=tm.tm_sec=0;
|
||||
return (f->time=mktime(&tm));
|
||||
}
|
||||
|
||||
static char current_ID[4]={ '\0', '\0', '\0', '\0' };
|
||||
static int current_index=-1;
|
||||
static struct forecast *current=NULL;
|
||||
static time_t current_time=0;
|
||||
static int current_hour=0;
|
||||
|
||||
static void set_current(int i){
|
||||
current_index=i;
|
||||
if(i<0 || i>num_forecasts){
|
||||
current=NULL;
|
||||
memset(current_ID, 0, 4);
|
||||
current_time=0;
|
||||
current_hour=0;
|
||||
} else {
|
||||
current=forecasts[i];
|
||||
memcpy(current_ID, current->ID, 4);
|
||||
current_time=forecast_time(current);
|
||||
current_hour=current->hour;
|
||||
}
|
||||
}
|
||||
|
||||
static void locate_current(void){
|
||||
int i;
|
||||
time_t now, target;
|
||||
int target_hour;
|
||||
long curdiff=0;
|
||||
long tmpdiff;
|
||||
char target_ID[4];
|
||||
|
||||
now=time(NULL);
|
||||
if(!changed && current!=NULL && is_forecast_current(current, now)) return;
|
||||
|
||||
sort_forecasts();
|
||||
target=current_time;
|
||||
target_hour=current_hour;
|
||||
memcpy(target_ID, current_ID, 4);
|
||||
set_current(-1);
|
||||
|
||||
for(i=0; i<num_forecasts; i++){
|
||||
if(!is_forecast_valid(forecasts[i])) continue;
|
||||
if(!is_forecast_current(forecasts[i], now)) continue;
|
||||
tmpdiff=abs(forecast_time(forecasts[i])-target);
|
||||
if((target_hour<0 && forecasts[i]->hour>=0) ||
|
||||
(target_hour>=0 && forecasts[i]->hour<0))
|
||||
tmpdiff+=31556926;
|
||||
if(memcmp(forecasts[i]->ID, target_ID, 4)) tmpdiff++;
|
||||
if(current==NULL || tmpdiff<curdiff){
|
||||
set_current(i);
|
||||
curdiff=tmpdiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct forecast *current_forecast_get(void){
|
||||
locate_current();
|
||||
return current;
|
||||
}
|
||||
|
||||
static inline int mod(int i, int n){
|
||||
i=i%n; if(i<0) i+=n;
|
||||
return i;
|
||||
}
|
||||
|
||||
void current_forecast_next(int dir){
|
||||
int i;
|
||||
time_t now;
|
||||
|
||||
if(num_forecasts==0) return;
|
||||
|
||||
locate_current();
|
||||
now=time(NULL);
|
||||
|
||||
if(current_index<0 || current_index>num_forecasts) current_index=0;
|
||||
for(i=mod(current_index+dir, num_forecasts); ; i=mod(i+dir, num_forecasts)){
|
||||
if(is_forecast_valid(forecasts[i]) && is_forecast_current(forecasts[i], now)){
|
||||
set_current(i);
|
||||
return;
|
||||
}
|
||||
if(i==current_index){
|
||||
set_current(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef FORECAST_H
|
||||
#define FORECAST_H
|
||||
|
||||
/* functions to manage the 'current forecast' */
|
||||
struct forecast *current_forecast_get(void);
|
||||
void current_forecast_next(int dir);
|
||||
|
||||
struct forecast {
|
||||
char ID[4]; /* Forecast type ("AVN", "MRF", etc) */
|
||||
char *station; /* station name */
|
||||
time_t last_update; /* last updated time */
|
||||
signed char month; /* 0, 1 - 12 */
|
||||
signed char day; /* -1, 1 - 31 */
|
||||
short year; /* -1, number */
|
||||
signed char wday; /* -1, 0-6 */
|
||||
signed char hour; /* -1, 0 - 23 (local) */
|
||||
short low; /* 999, -210 - 390 (degrees F) */
|
||||
short high; /* 999, -210 - 390 (degrees F) */
|
||||
short temp; /* 999, -210 - 390 (degrees F) */
|
||||
short dewpt; /* 999, -210 - 390 (degrees F) */
|
||||
signed char rh; /* -1, 0 - 100 (%) */
|
||||
short winddir; /* -1, 0 - 16 (direction) */
|
||||
short windspeed; /* -1, 0 - MAX */
|
||||
short heatindex; /* 999, -99 - 199 (degrees F) */
|
||||
short windchill; /* 999, -99 - 199 (degrees F) */
|
||||
short precipamt; /* -1, 0 - 7 (amount code) */
|
||||
short snowamt; /* -1, 0 - 8 (amount code) */
|
||||
signed char sky; /* -1, 0-4 (condition) */
|
||||
signed char vis; /* 7, 1-7 (status code) */
|
||||
signed char obs; /* 0, 0-3 (type) */
|
||||
signed char pcp_total; /* 0, 0-100 (percent chance) */
|
||||
signed char frz; /* 0, 0-100 (percent chance) */
|
||||
signed char snow; /* 0, 0-100 (percent chance) */
|
||||
signed char rain; /* 0, 0-100 (percent chance) */
|
||||
signed char tstorm; /* 0, 0-100 (percent chance) */
|
||||
signed char svtstorm; /* 0, 0-100 (percent chance) */
|
||||
double moon; /* NAN, -1 - 1 (percent and wax/wane) */
|
||||
time_t time; /* -1, time_t value */
|
||||
};
|
||||
|
||||
void add_forecast(struct forecast *f, char *ID, char *station);
|
||||
time_t forecast_time(struct forecast *f);
|
||||
time_t parse_time_string(char *s);
|
||||
time_t find_next_time(char *file, char *pat, int minutes);
|
||||
void reset_forecast(struct forecast *f);
|
||||
|
||||
#endif
|
|
@ -1,67 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2000 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* inspired by read_line from Eric S. Raymond's fetchmail program, by
|
||||
* way of Aaron Sethman's odsclient. */
|
||||
int getLine(char **s, FILE *fd){
|
||||
int len=8196;
|
||||
int toread=len;
|
||||
int l=0;
|
||||
char *ptr, *p, *q;
|
||||
|
||||
*s=NULL;
|
||||
if(feof(fd)) return -1;
|
||||
|
||||
q=ptr=malloc(len);
|
||||
if(ptr==NULL) return -1;
|
||||
*q=0;
|
||||
p=q=ptr;
|
||||
while(fgets(p, toread, fd)!=NULL){
|
||||
l=strlen(ptr);
|
||||
q=strchr(p, '\n');
|
||||
if(q!=NULL){ l=q-ptr+1; break; }
|
||||
len*=2;
|
||||
toread=len-l;
|
||||
p=realloc(ptr, len);
|
||||
if(p==NULL){
|
||||
free(ptr);
|
||||
return -1;
|
||||
}
|
||||
ptr=p;
|
||||
q=p=ptr+l;
|
||||
}
|
||||
while(q>ptr && (*q=='\0' || isspace(*q))){
|
||||
*q='\0';
|
||||
l--;
|
||||
q--;
|
||||
}
|
||||
for(p=ptr; isspace(*p); p++, l--);
|
||||
if((*s=malloc(l+1))==NULL){
|
||||
free(ptr);
|
||||
return -1;
|
||||
}
|
||||
memcpy(*s, p, l+1);
|
||||
free(ptr);
|
||||
return l;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/* Gets a single line of input, stripping leading and trailing whitespace */
|
||||
int getLine(char **s, FILE *fd);
|
|
@ -1,2 +0,0 @@
|
|||
SUBDIRS =
|
||||
EXTRA_DIST = libpcre.m4 libwraster.m4 snprintf.m4 vsnprintf.m4 xpm.m4
|
|
@ -1,57 +0,0 @@
|
|||
dnl @synopsis CHECK_LIBPCRE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl
|
||||
dnl This macro searches for an installed libpcre library. If nothing
|
||||
dnl was specified when calling configure, it searches first in /usr/local
|
||||
dnl and then in /usr. If the --with-libpcre=DIR is specified, it will try
|
||||
dnl to find it in DIR/include/pcre.h and DIR/lib/libpcre.a. If --without-libpcre
|
||||
dnl is specified, the library is not searched at all.
|
||||
dnl
|
||||
dnl It defines the symbol HAVE_LIBPCRE if the library is found. You should
|
||||
dnl use autoheader to include a definition for this symbol in a config.h
|
||||
dnl file.
|
||||
dnl
|
||||
dnl Sources files should then use something like
|
||||
dnl
|
||||
dnl #ifdef HAVE_LIBPCRE
|
||||
dnl #include <pcre.h>
|
||||
dnl #endif /* HAVE_LIBPCRE */
|
||||
dnl
|
||||
dnl @version 1.0
|
||||
dnl based on CHECK_ZLIB by Loic Dachary <loic@senga.org>
|
||||
dnl
|
||||
|
||||
AC_DEFUN([CHECK_LIBPCRE],
|
||||
#
|
||||
# Handle user hints
|
||||
#
|
||||
[AC_MSG_CHECKING(if libpcre is wanted)
|
||||
AC_ARG_WITH(libpcre,
|
||||
[ --with-libpcre=DIR root directory path of libpcre installation [defaults to
|
||||
/usr/local or /usr if not found in /usr/local]
|
||||
--without-libpcre to disable libpcre usage completely],
|
||||
[if test "$withval" != no ; then
|
||||
LIBPCRE_HOME="$withval"
|
||||
AC_MSG_RESULT([yes: libraries ${LIBPCRE_HOME}/lib includes ${LIBPCRE_HOME}/include])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi],
|
||||
[LIBPCRE_HOME=/usr/local
|
||||
if test ! -f "${LIBPCRE_HOME}/include/pcre.h"
|
||||
then
|
||||
LIBPCRE_HOME=/usr
|
||||
fi
|
||||
AC_MSG_RESULT([yes: libraries ${LIBPCRE_HOME}/lib includes ${LIBPCRE_HOME}/include])
|
||||
])
|
||||
|
||||
#
|
||||
# Locate libpcre, if wanted
|
||||
#
|
||||
if test -n "${LIBPCRE_HOME}"
|
||||
then
|
||||
LDFLAGS="$LDFLAGS -L${LIBPCRE_HOME}/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I${LIBPCRE_HOME}/include"
|
||||
AC_CHECK_LIB(pcre, pcre_compile, $1, $2)
|
||||
else
|
||||
$2
|
||||
fi
|
||||
])
|
|
@ -1,61 +0,0 @@
|
|||
dnl @synopsis CHECK_LIBWRASTER([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl
|
||||
dnl This macro searches for an installed libwraster library. If nothing
|
||||
dnl was specified when calling configure, it searches first in /usr/local
|
||||
dnl and then in /usr. If the --with-libwraster=DIR is specified, it will try
|
||||
dnl to find it in DIR/include/wraster.h and DIR/lib/libwraster.a. If --without-libwraster
|
||||
dnl is specified, the library is not searched at all.
|
||||
dnl
|
||||
dnl It defines the symbol HAVE_LIBWRASTER if the library is found. You should
|
||||
dnl use autoheader to include a definition for this symbol in a config.h
|
||||
dnl file.
|
||||
dnl
|
||||
dnl Sources files should then use something like
|
||||
dnl
|
||||
dnl #ifdef HAVE_LIBWRASTER
|
||||
dnl #include <wraster.h>
|
||||
dnl #endif /* HAVE_LIBWRASTER */
|
||||
dnl
|
||||
dnl @version 1.0
|
||||
dnl based on CHECK_ZLIB by Loic Dachary <loic@senga.org>
|
||||
dnl
|
||||
|
||||
AC_DEFUN([CHECK_LIBWRASTER],
|
||||
#
|
||||
# Handle user hints
|
||||
#
|
||||
[AC_MSG_CHECKING(if libwraster is wanted)
|
||||
AC_ARG_WITH(libwraster,
|
||||
[ --with-libwraster=DIR root directory path of libwraster installation [defaults to
|
||||
/usr/local or /usr if not found in /usr/local]
|
||||
--without-libwraster to disable libwraster usage completely],
|
||||
[if test "$withval" != no ; then
|
||||
LIBWRASTER_HOME="$withval"
|
||||
AC_MSG_RESULT([yes: libraries ${LIBWRASTER_HOME}/lib includes ${LIBWRASTER_HOME}/include])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi],
|
||||
[LIBWRASTER_HOME=/usr/local
|
||||
if test ! -f "${LIBWRASTER_HOME}/include/wraster.h"
|
||||
then
|
||||
LIBWRASTER_HOME=/usr
|
||||
if test ! -f "${LIBWRASTER_HOME}/include/wraster.h"
|
||||
then
|
||||
LIBWRASTER_HOME=/usr/X11R6
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([yes: libraries ${LIBWRASTER_HOME}/lib includes ${LIBWRASTER_HOME}/include])
|
||||
])
|
||||
|
||||
#
|
||||
# Locate libwraster, if wanted
|
||||
#
|
||||
if test -n "${LIBWRASTER_HOME}"
|
||||
then
|
||||
LDFLAGS="$LDFLAGS -L${LIBWRASTER_HOME}/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I${LIBWRASTER_HOME}/include"
|
||||
AC_CHECK_LIB(wraster, RCreateContext, $1, $2)
|
||||
else
|
||||
$2
|
||||
fi
|
||||
])
|
|
@ -1,120 +0,0 @@
|
|||
# FUNC_SNPRINTF_EXISTS
|
||||
# --------------------
|
||||
# Checks if snprintf exists. x_cv_func_snprintf_exists is set.
|
||||
AC_DEFUN([FUNC_SNPRINTF_EXISTS],
|
||||
[AC_CHECK_FUNC(snprintf, [x_cv_func_snprintf_exists=yes], [x_cv_func_snprintf_exists=no])])# FUNC_SNPRINTF_EXISTS
|
||||
|
||||
# FUNC_SNPRINTF_SIZE
|
||||
# ------------------
|
||||
# Checks if snprintf honors its size argument. SNPRINTF_IS_SPRINTF is defined
|
||||
# if not. x_cv_func_snprintf_size is set to yes or no.
|
||||
#
|
||||
# Note that this depends on FUNC_SNPRINTF_EXISTS, so if that fails this will
|
||||
# also fail (and define SNPRINTF_IS_SPRINTF).
|
||||
AC_DEFUN([FUNC_SNPRINTF_SIZE],
|
||||
[AC_REQUIRE([FUNC_SNPRINTF_EXISTS])
|
||||
if test $x_cv_func_snprintf_exists != yes; then x_cv_func_snprintf_size=no; else
|
||||
AC_CACHE_CHECK([if snprintf honors the size argument], x_cv_func_snprintf_size,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
]],
|
||||
[[char foo[]="ABC"; snprintf(foo, 2, "%d", 12);
|
||||
exit((foo[0]=='1' && foo[1]=='\0' && foo[2]=='C')?0:1);]])],
|
||||
[x_cv_func_snprintf_size=yes],
|
||||
[x_cv_func_snprintf_size=no],
|
||||
[x_cv_func_snprintf_size=no])])
|
||||
fi
|
||||
test $x_cv_func_snprintf_size != yes && AC_DEFINE(SNPRINTF_IS_SPRINTF, 1, [Define if snprintf ignores the size argument])
|
||||
])# FUNC_SNPRINTF_SIZE
|
||||
|
||||
# FUNC_SNPRINTF_RETVAL
|
||||
# ------------------
|
||||
# Checks if snprintf returns the number of bytes that would have been written,
|
||||
# as specified by C99. SNPRINTF_BOGUS_RETVAL is defined if not.
|
||||
# x_cv_func_snprintf_retval is set to yes or no.
|
||||
#
|
||||
# Note that this depends on FUNC_SNPRINTF_SIZE, so if that fails this will fail
|
||||
# too and SNPRINTF_BOGUS_RETVAL will be set.
|
||||
AC_DEFUN([FUNC_SNPRINTF_RETVAL],
|
||||
[AC_REQUIRE([FUNC_SNPRINTF_SIZE])
|
||||
if test $x_cv_func_snprintf_size != yes; then x_cv_func_snprintf_retval=no; else
|
||||
AC_CACHE_CHECK([if snprintf return value is sane], x_cv_func_snprintf_retval,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
]],
|
||||
[[char foo[10]; exit((snprintf(foo, 1, "%d", 9876)==4)?0:1);]])],
|
||||
[x_cv_func_snprintf_retval=yes],
|
||||
[x_cv_func_snprintf_retval=no],
|
||||
[x_cv_func_snprintf_retval=no])])
|
||||
fi
|
||||
test $x_cv_func_snprintf_retval != yes && AC_DEFINE(SNPRINTF_BOGUS_RETVAL, 1, [Define if snprintf's return value isn't as specified by C99])
|
||||
])# FUNC_SNPRINTF_RETVAL
|
||||
|
||||
# FUNC_SNPRINTF_NULL_OK
|
||||
# ---------------------
|
||||
# Checks whether snprintf acceps a NULL string if size is zero. Sets
|
||||
# x_cv_func_snprintf_null_ok. If so, define SNPRINTF_NULL_OK.
|
||||
#
|
||||
# Note that this depends on FUNC_SNPRINTF_SIZE, so if that fails this will fail
|
||||
# too and SNPRINTF_BOGUS_RETVAL will be set.
|
||||
AC_DEFUN([FUNC_SNPRINTF_NULL_OK],
|
||||
[AC_REQUIRE([FUNC_SNPRINTF_SIZE])
|
||||
if test $x_cv_func_snprintf_size != yes; then x_cv_func_snprintf_null_ok=no; else
|
||||
AC_CACHE_CHECK([if snprintf(NULL, 0, ...) works], x_cv_func_snprintf_null_ok,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
#endif
|
||||
]],
|
||||
[int r=snprintf(NULL, 0, "%d", 100); exit((r==3 || r==-1)?0:1);])],
|
||||
[x_cv_func_snprintf_null_ok=yes],
|
||||
[x_cv_func_snprintf_null_ok=no],
|
||||
[x_cv_func_snprintf_null_ok=no])])
|
||||
fi
|
||||
test $x_cv_func_snprintf_null_ok = yes && AC_DEFINE(SNPRINTF_NULL_OK, 1, [Define if snprintf(NULL, 0, ...) works properly])
|
||||
])# FUNC_SNPRINTF_NULL_OK
|
||||
|
||||
# FUNC_SNPRINTF([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
# -------------
|
||||
# Checks various aspects of snprintf. In particular:
|
||||
# * Does it exist?
|
||||
# * Is the size honored?
|
||||
# * Is the return value correct?
|
||||
# * Is NULL with length 0 ok?
|
||||
# If all the above pass, HAVE_WORKING_SNPRINTF is defined and
|
||||
# x_cv_func_snprintf_working is set to yes. Otherwise, it's set to no.
|
||||
AC_DEFUN([FUNC_SNPRINTF],
|
||||
[AC_REQUIRE([FUNC_SNPRINTF_RETVAL])
|
||||
AC_REQUIRE([FUNC_SNPRINTF_NULL_OK])
|
||||
if test $x_cv_func_snprintf_retval = yes -a $x_cv_func_snprintf_null_ok = yes; then
|
||||
AC_DEFINE(HAVE_WORKING_SNPRINTF, 1, [Define if snprintf works properly])
|
||||
x_cv_func_snprintf_working=yes
|
||||
$1
|
||||
else
|
||||
x_cv_func_snprintf_working=no
|
||||
$2
|
||||
fi
|
||||
])# FUNC_SNPRINTF
|
||||
|
||||
# FUNC_SNPRINTF_LIBOBJ
|
||||
# --------------------
|
||||
# If FUNC_SNPRINTF fails, does AC_LIBOBJ
|
||||
AC_DEFUN([FUNC_SNPRINTF_LIBOBJ],
|
||||
[FUNC_SNPRINTF(, [AC_LIBOBJ([snprintf])
|
||||
AC_DEFINE([snprintf], [rpl_snprintf], [Define to rpl_snprintf if the replacement function should be used.])])])
|
||||
])#FUNC_SNPRINTF_LIBOBJ
|
||||
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
# FUNC_VSNPRINTF_EXISTS
|
||||
# --------------------
|
||||
# Checks if vsnprintf exists. x_cv_func_vsnprintf_exists is set.
|
||||
AC_DEFUN([FUNC_VSNPRINTF_EXISTS],
|
||||
[AC_REQUIRE([AC_FUNC_VPRINTF])
|
||||
if test $ac_cv_func_vprintf != yes; then x_cv_func_vsnprintf_exists=no; else
|
||||
AC_CHECK_FUNC(vsnprintf, [x_cv_func_vsnprintf_exists=yes], [x_cv_func_vsnprintf_exists=no])
|
||||
fi
|
||||
])# FUNC_VSNPRINTF_EXISTS
|
||||
|
||||
# FUNC_VSNPRINTF_SIZE
|
||||
# ------------------
|
||||
# Checks if vsnprintf honors its size argument. VSNPRINTF_IS_VSPRINTF is defined
|
||||
# if not. x_cv_func_vsnprintf_size is set to yes or no.
|
||||
#
|
||||
# Note that this depends on FUNC_VSNPRINTF_EXISTS, so if that fails this will
|
||||
# also fail (and define VSNPRINTF_IS_VSPRINTF).
|
||||
AC_DEFUN([FUNC_VSNPRINTF_SIZE],
|
||||
[AC_REQUIRE([FUNC_VSNPRINTF_EXISTS])
|
||||
if test $x_cv_func_vsnprintf_exists != yes; then x_cv_func_vsnprintf_size=no; else
|
||||
AC_CACHE_CHECK([if vsnprintf honors the size argument], x_cv_func_vsnprintf_size,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <stdarg.h>
|
||||
#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
#endif
|
||||
int doit(char *str, size_t size, const char *format, ...){
|
||||
va_list ap;
|
||||
int r;
|
||||
va_start(ap, format);
|
||||
r=vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
]],
|
||||
[[char foo[]="ABC"; doit(foo, 2, "%d", 12);
|
||||
exit((foo[0]=='1' && foo[1]=='\0' && foo[2]=='C')?0:1);]])],
|
||||
[x_cv_func_vsnprintf_size=yes],
|
||||
[x_cv_func_vsnprintf_size=no],
|
||||
[x_cv_func_vsnprintf_size=no])])
|
||||
fi
|
||||
test $x_cv_func_vsnprintf_size != yes && AC_DEFINE(VSNPRINTF_IS_VSPRINTF, 1, [Define if vsnprintf ignores the size argument])
|
||||
])# FUNC_VSNPRINTF_SIZE
|
||||
|
||||
# FUNC_VSNPRINTF_RETVAL
|
||||
# ------------------
|
||||
# Checks if vsnprintf returns the number of bytes that would have been written,
|
||||
# as specified by C99. VSNPRINTF_BOGUS_RETVAL is defined if not.
|
||||
# x_cv_func_vsnprintf_retval is set to yes or no.
|
||||
#
|
||||
# Note that this depends on FUNC_VSNPRINTF_SIZE, so if that fails this will fail
|
||||
# too and VSNPRINTF_BOGUS_RETVAL will be set.
|
||||
AC_DEFUN([FUNC_VSNPRINTF_RETVAL],
|
||||
[AC_REQUIRE([FUNC_VSNPRINTF_SIZE])
|
||||
if test $x_cv_func_vsnprintf_size != yes; then x_cv_func_vsnprintf_retval=no; else
|
||||
AC_CACHE_CHECK([if vsnprintf return value is sane], x_cv_func_vsnprintf_retval,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <stdarg.h>
|
||||
#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
#endif
|
||||
int doit(char *str, size_t size, const char *format, ...){
|
||||
va_list ap;
|
||||
int r;
|
||||
va_start(ap, format);
|
||||
r=vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
]],
|
||||
[[char foo[10]; exit((doit(foo, 1, "%d", 9876)==4)?0:1);]])],
|
||||
[x_cv_func_vsnprintf_retval=yes],
|
||||
[x_cv_func_vsnprintf_retval=no],
|
||||
[x_cv_func_vsnprintf_retval=no])])
|
||||
fi
|
||||
test $x_cv_func_vsnprintf_retval != yes && AC_DEFINE(VSNPRINTF_BOGUS_RETVAL, 1, [Define if vsnprintf's return value isn't as specified by C99])
|
||||
])# FUNC_VSNPRINTF_RETVAL
|
||||
|
||||
# FUNC_VSNPRINTF_NULL_OK
|
||||
# ---------------------
|
||||
# Checks whether vsnprintf acceps a NULL string if size is zero. Sets
|
||||
# x_cv_func_vsnprintf_null_ok. If so, define VSNPRINTF_NULL_OK.
|
||||
#
|
||||
# Note that this depends on FUNC_VSNPRINTF_SIZE, so if that fails this will
|
||||
# fail too and VSNPRINTF_NULL_OK will not be set.
|
||||
AC_DEFUN([FUNC_VSNPRINTF_NULL_OK],
|
||||
[AC_REQUIRE([FUNC_VSNPRINTF_SIZE])
|
||||
if test $x_cv_func_vsnprintf_size != yes; then x_cv_func_vsnprintf_null_ok=no; else
|
||||
AC_CACHE_CHECK([if vsnprintf(NULL, 0, ...) works], x_cv_func_vsnprintf_null_ok,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <stdarg.h>
|
||||
#if STDC_HEADERS || HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#else
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
#endif
|
||||
int doit(char *str, size_t size, const char *format, ...){
|
||||
va_list ap;
|
||||
int r;
|
||||
va_start(ap, format);
|
||||
r=vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
]],
|
||||
[int r=doit(NULL, 0, "%d", 100); exit((r==3 || r==-1)?0:1);])],
|
||||
[x_cv_func_vsnprintf_null_ok=yes],
|
||||
[x_cv_func_vsnprintf_null_ok=no],
|
||||
[x_cv_func_vsnprintf_null_ok=no])])
|
||||
fi
|
||||
test $x_cv_func_vsnprintf_null_ok = yes && AC_DEFINE(VSNPRINTF_NULL_OK, 1, [Define if vsnprintf(NULL, 0, ...) works properly])
|
||||
])# FUNC_VSNPRINTF_NULL_OK
|
||||
|
||||
# FUNC_VSNPRINTF([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
# -------------
|
||||
# Checks various aspects of vsnprintf. In particular:
|
||||
# * Does it exist?
|
||||
# * Is the size honored?
|
||||
# * Is the return value correct?
|
||||
# * Is NULL with length 0 ok?
|
||||
# If all the above pass, HAVE_WORKING_VSNPRINTF is defined and
|
||||
# x_cv_func_vsnprintf_working is set to yes. Otherwise, it's set to no.
|
||||
AC_DEFUN([FUNC_VSNPRINTF],
|
||||
[AC_REQUIRE([FUNC_VSNPRINTF_RETVAL])
|
||||
AC_REQUIRE([FUNC_VSNPRINTF_NULL_OK])
|
||||
if test $x_cv_func_vsnprintf_retval = yes -a $x_cv_func_vsnprintf_null_ok = yes; then
|
||||
AC_DEFINE(HAVE_WORKING_VSNPRINTF, 1, [Define if vsnprintf works properly])
|
||||
x_cv_func_snprintf_working=yes
|
||||
$1
|
||||
else
|
||||
x_cv_func_snprintf_working=no
|
||||
$2
|
||||
fi
|
||||
])# FUNC_VSNPRINTF
|
||||
|
||||
# FUNC_VSNPRINTF_LIBOBJ
|
||||
# --------------------
|
||||
# If FUNC_VSNPRINTF fails, does AC_LIBOBJ.
|
||||
AC_DEFUN([FUNC_VSNPRINTF_LIBOBJ],
|
||||
[FUNC_VSNPRINTF(, [AC_LIBOBJ([vsnprintf])
|
||||
AC_DEFINE([vsnprintf], [rpl_vsnprintf], [Define to rpl_vsnprintf if the replacement function should be used.])])])
|
||||
])#FUNC_VSNPRINTF_LIBOBJ
|
|
@ -1,190 +0,0 @@
|
|||
dnl AC_FIND_XPM
|
||||
dnl ---------------
|
||||
dnl
|
||||
dnl Find Xpm libraries and headers.
|
||||
dnl Put Xpm include directory in xpm_includes,
|
||||
dnl put Xpm library directory in xpm_libraries,
|
||||
dnl and add appropriate flags to X_CFLAGS and X_LIBS.
|
||||
dnl
|
||||
dnl
|
||||
AC_DEFUN([AC_FIND_XPM],
|
||||
[
|
||||
AC_REQUIRE([AC_PATH_XTRA])
|
||||
xpm_includes=
|
||||
xpm_libraries=
|
||||
AC_ARG_WITH(xpm,
|
||||
[ --without-xpm do not use the Xpm library])
|
||||
dnl Treat --without-xpm like
|
||||
dnl --without-xpm-includes --without-xpm-libraries.
|
||||
if test "$with_xpm" = "no"
|
||||
then
|
||||
xpm_includes=no
|
||||
xpm_libraries=no
|
||||
fi
|
||||
AC_ARG_WITH(xpm-includes,
|
||||
[ --with-xpm-includes=DIR Xpm include files are in DIR],
|
||||
xpm_includes="$withval")
|
||||
AC_ARG_WITH(xpm-libraries,
|
||||
[ --with-xpm-libraries=DIR
|
||||
Xpm libraries are in DIR],
|
||||
xpm_libraries="$withval")
|
||||
AC_MSG_CHECKING(for Xpm)
|
||||
#
|
||||
#
|
||||
# Search the include files. Note that XPM can come in <X11/xpm.h> (as
|
||||
# in X11R6) or in <xpm.h> if installed locally.
|
||||
#
|
||||
if test "$xpm_includes" = ""; then
|
||||
AC_CACHE_VAL(ice_cv_xpm_includes,
|
||||
[
|
||||
ice_xpm_save_LIBS="$LIBS"
|
||||
ice_xpm_save_CFLAGS="$CFLAGS"
|
||||
ice_xpm_save_CPPFLAGS="$CPPFLAGS"
|
||||
ice_xpm_save_LDFLAGS="$LDFLAGS"
|
||||
#
|
||||
LIBS="$X_PRE_LIBS -lXpm -lXt -lX11 $X_EXTRA_LIBS $LIBS"
|
||||
CFLAGS="$X_CFLAGS $CFLAGS"
|
||||
CPPFLAGS="$X_CFLAGS $CPPFLAGS"
|
||||
LDFLAGS="$X_LIBS $LDFLAGS"
|
||||
#
|
||||
AC_TRY_COMPILE([
|
||||
#include <X11/xpm.h>
|
||||
],[int a;],
|
||||
[
|
||||
# X11/xpm.h is in the standard search path.
|
||||
ice_cv_xpm_includes=
|
||||
],
|
||||
[
|
||||
# X11/xpm.h is not in the standard search path.
|
||||
# Locate it and put its directory in `xpm_includes'
|
||||
#
|
||||
# /usr/include/Motif* are used on HP-UX (Motif).
|
||||
# /usr/include/X11* are used on HP-UX (X and Xaw).
|
||||
# /usr/dt is used on Solaris (Motif).
|
||||
# /usr/openwin is used on Solaris (X and Xaw).
|
||||
# Other directories are just guesses.
|
||||
for dir in "$x_includes" "${prefix}/include" /usr/include /usr/local/include \
|
||||
/usr/include/Motif2.0 /usr/include/Motif1.2 /usr/include/Motif1.1 \
|
||||
/usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 \
|
||||
/usr/dt/include /usr/openwin/include \
|
||||
/usr/dt/*/include /opt/*/include /usr/include/Motif* \
|
||||
/usr/*/include/X11R6 /usr/*/include/X11R5 /usr/*/include/X11R4 \
|
||||
"${prefix}"/*/include /usr/*/include /usr/local/*/include \
|
||||
"${prefix}"/include/* /usr/include/* /usr/local/include/*; do
|
||||
if test -f "$dir/X11/xpm.h" || test -f "$dir/xpm.h"; then
|
||||
ice_cv_xpm_includes="$dir"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test "$ice_cv_xpm_includes" = "/usr/include"; then
|
||||
ice_cv_xpm_includes=
|
||||
fi
|
||||
])
|
||||
#
|
||||
LIBS="$ice_xpm_save_LIBS"
|
||||
CFLAGS="$ice_xpm_save_CFLAGS"
|
||||
CPPFLAGS="$ice_xpm_save_CPPFLAGS"
|
||||
LDFLAGS="$ice_xpm_save_LDFLAGS"
|
||||
])
|
||||
xpm_includes="$ice_cv_xpm_includes"
|
||||
fi
|
||||
#
|
||||
#
|
||||
# Now for the libraries.
|
||||
#
|
||||
if test "$xpm_libraries" = ""; then
|
||||
AC_CACHE_VAL(ice_cv_xpm_libraries,
|
||||
[
|
||||
ice_xpm_save_LIBS="$LIBS"
|
||||
ice_xpm_save_CFLAGS="$CFLAGS"
|
||||
ice_xpm_save_CPPFLAGS="$CPPFLAGS"
|
||||
ice_xpm_save_LDFLAGS="$LDFLAGS"
|
||||
#
|
||||
LIBS="$X_PRE_LIBS -lXpm -lXt -lX11 $X_EXTRA_LIBS $LIBS"
|
||||
CFLAGS="$X_CFLAGS $CFLAGS"
|
||||
CPPFLAGS="$X_CFLAGS $CPPFLAGS"
|
||||
LDFLAGS="$X_LIBS $LDFLAGS"
|
||||
#
|
||||
#
|
||||
# We use XtToolkitInitialize() here since it takes no arguments
|
||||
# and thus also works with a C++ compiler.
|
||||
AC_TRY_LINK([
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/xpm.h>
|
||||
],[XtToolkitInitialize();],
|
||||
[
|
||||
# libxpm.a is in the standard search path.
|
||||
ice_cv_xpm_libraries=
|
||||
],
|
||||
[
|
||||
# libXpm.a is not in the standard search path.
|
||||
# Locate it and put its directory in `xpm_libraries'
|
||||
#
|
||||
#
|
||||
# /usr/lib/Motif* are used on HP-UX (Motif).
|
||||
# /usr/lib/X11* are used on HP-UX (X and Xpm).
|
||||
# /usr/dt is used on Solaris (Motif).
|
||||
# /usr/openwin is used on Solaris (X and Xpm).
|
||||
# Other directories are just guesses.
|
||||
for dir in "$x_libraries" "${prefix}/lib" /usr/lib /usr/local/lib \
|
||||
/usr/lib/Motif2.0 /usr/lib/Motif1.2 /usr/lib/Motif1.1 \
|
||||
/usr/lib/X11R6 /usr/lib/X11R5 /usr/lib/X11R4 /usr/lib/X11 \
|
||||
/usr/dt/lib /usr/openwin/lib \
|
||||
/usr/dt/*/lib /opt/*/lib /usr/lib/Motif* \
|
||||
/usr/*/lib/X11R6 /usr/*/lib/X11R5 /usr/*/lib/X11R4 /usr/*/lib/X11 \
|
||||
"${prefix}"/*/lib /usr/*/lib /usr/local/*/lib \
|
||||
"${prefix}"/lib/* /usr/lib/* /usr/local/lib/*; do
|
||||
if test -d "$dir" && test "`ls $dir/libXpm.* 2> /dev/null`" != ""; then
|
||||
ice_cv_xpm_libraries="$dir"
|
||||
break
|
||||
fi
|
||||
done
|
||||
])
|
||||
#
|
||||
LIBS="$ice_xpm_save_LIBS"
|
||||
CFLAGS="$ice_xpm_save_CFLAGS"
|
||||
CPPFLAGS="$ice_xpm_save_CPPFLAGS"
|
||||
LDFLAGS="$ice_xpm_save_LDFLAGS"
|
||||
])
|
||||
#
|
||||
xpm_libraries="$ice_cv_xpm_libraries"
|
||||
fi
|
||||
#
|
||||
# Add Xpm definitions to X flags
|
||||
#
|
||||
if test "$xpm_includes" != "" && test "$xpm_includes" != "$x_includes" && test "$xpm_includes" != "no"
|
||||
then
|
||||
X_CFLAGS="-I$xpm_includes $X_CFLAGS"
|
||||
fi
|
||||
if test "$xpm_libraries" != "" && test "$xpm_libraries" != "$x_libraries" && test "$xpm_libraries" != "no"
|
||||
then
|
||||
case "$X_LIBS" in
|
||||
*-R\ *) X_LIBS="-L$xpm_libraries -R $xpm_libraries $X_LIBS";;
|
||||
*-R*) X_LIBS="-L$xpm_libraries -R$xpm_libraries $X_LIBS";;
|
||||
*) X_LIBS="-L$xpm_libraries $X_LIBS";;
|
||||
esac
|
||||
fi
|
||||
#
|
||||
#
|
||||
xpm_libraries_result="$xpm_libraries"
|
||||
xpm_includes_result="$xpm_includes"
|
||||
|
||||
if test "$xpm_libraries_result" != "no" && test "$xpm_includes_result" != "no"
|
||||
then AC_DEFINE(HAVE_XPM, 1, "Define if you have libxpm")
|
||||
LINK_XPM="-lXpm"
|
||||
else LINK_XPM=""
|
||||
fi
|
||||
|
||||
AC_SUBST(LINK_XPM)
|
||||
|
||||
test "$xpm_libraries_result" = "" &&
|
||||
xpm_libraries_result="in default path"
|
||||
test "$xpm_includes_result" = "" &&
|
||||
xpm_includes_result="in default path"
|
||||
test "$xpm_libraries_result" = "no" &&
|
||||
xpm_libraries_result="(none)"
|
||||
test "$xpm_includes_result" = "no" &&
|
||||
xpm_includes_result="(none)"
|
||||
AC_MSG_RESULT(
|
||||
[libraries $xpm_libraries_result, headers $xpm_includes_result])
|
||||
])dnl
|
|
@ -1,436 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "metar.h"
|
||||
#include "warnings.h"
|
||||
#include "download.h"
|
||||
#include "convert.h"
|
||||
#include "die.h"
|
||||
#include "sunzenith.h"
|
||||
#include "moon.h"
|
||||
#include "subst.h"
|
||||
|
||||
/* Important variables */
|
||||
static time_t metar_time=0;
|
||||
|
||||
static char *metar_newfile=NULL;
|
||||
static char *metar_file=NULL;
|
||||
static char *metar_req[2]={ NULL, NULL };
|
||||
|
||||
struct current_weather current;
|
||||
|
||||
/* Regular Expressions */
|
||||
static pcre *station_time;
|
||||
static pcre *wind;
|
||||
static pcre *weather;
|
||||
static pcre *vis[4];
|
||||
static pcre *temp;
|
||||
static pcre *pressure;
|
||||
static int ovecsize;
|
||||
|
||||
/* prototypes */
|
||||
static int parse_metar(char *file);
|
||||
|
||||
/* functions */
|
||||
|
||||
static void reset_current(struct current_weather *c){
|
||||
c->last_update=time(NULL);
|
||||
c->month=0;
|
||||
c->date=-1;
|
||||
c->time=-1;
|
||||
c->temp=999;
|
||||
c->rh=-1;
|
||||
c->winddir=-1;
|
||||
c->windspeed=-1;
|
||||
c->pressure=-1;
|
||||
c->heatindex=999;
|
||||
c->windchill=999;
|
||||
c->sky=-1;
|
||||
c->vis=7;
|
||||
c->obs=0;
|
||||
c->frz=0;
|
||||
c->snow=0;
|
||||
c->rain=0;
|
||||
c->tstorm=0;
|
||||
c->moon=NAN;
|
||||
}
|
||||
|
||||
#define compile(var, re) \
|
||||
var=pcre_compile(re, 0, (const char **)&e, &i, NULL); \
|
||||
if(var==NULL) die("init_metar PCRE error: %s at %i", e, i); \
|
||||
pcre_fullinfo(var, NULL, PCRE_INFO_CAPTURECOUNT, &i); \
|
||||
if(i>ovecsize) ovecsize=i;
|
||||
|
||||
void init_metar(void){
|
||||
int i;
|
||||
char *e;
|
||||
struct subst_val subs[]={
|
||||
{ 's', STRING, &metar_station },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%s.metar.txt", metar_station);
|
||||
metar_file=get_pid_filename(bigbuf);
|
||||
snprintf(bigbuf, BIGBUF_LEN, "%s.new-metar.txt", metar_station);
|
||||
metar_newfile=get_pid_filename(bigbuf);
|
||||
|
||||
if((metar_req[0]=subst(metar_uri, subs))==NULL) die("init_metar");
|
||||
if(metar_post!=NULL && (metar_req[1]=subst(metar_post, subs))==NULL) die("init_metar");
|
||||
|
||||
metar_time=0;
|
||||
|
||||
ovecsize=0;
|
||||
|
||||
strncpy(bigbuf, metar_station, BIGBUF_LEN-25);
|
||||
bigbuf[BIGBUF_LEN-25]='\0';
|
||||
strcat(bigbuf, " ((?:\\d\\d)?)(\\d\\d\\d\\d)Z( .* )");
|
||||
compile(station_time, bigbuf);
|
||||
compile(wind, " (VRB|\\d\\d\\d)(\\d\\d\\d?)(?:G\\d\\d\\d?)?(KT|MPS|KMH)((?: \\d\\d\\dV\\d\\d\\d)?) ");
|
||||
compile(weather, " ((?:-|\\+|VC)?)((?:MI|PR|BC|DR|BL|SH|TS|FZ)?)((?:DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP){0,3})((?:BR|FG|FU|VA|DU|SA|HZ|PY)?)((?:PO|SQ|FC|SS|DS)?)\\b");
|
||||
compile(vis[0], " (\\d+)SM ");
|
||||
compile(vis[1], " (\\d+)/(\\d+)SM ");
|
||||
compile(vis[2], " (\\d+) (\\d+)/(\\d+)SM ");
|
||||
compile(vis[3], " (\\d{4})[NS]?[EW]? ");
|
||||
compile(temp, " (M?\\d\\d\\d?)/((?:M?\\d\\d\\d?)?) ");
|
||||
compile(pressure, " ([AQ])(\\d\\d\\d\\d) ");
|
||||
|
||||
ovecsize=(ovecsize+1)*3;
|
||||
|
||||
/* Remove stale file */
|
||||
unlink(metar_file);
|
||||
unlink(metar_newfile);
|
||||
reset_current(¤t);
|
||||
current.last_update = 0; // This was not a real "update", just an init
|
||||
}
|
||||
#undef compile
|
||||
|
||||
static void metar_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(metar_newfile, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& parse_metar(metar_newfile)){
|
||||
rename(metar_newfile, metar_file);
|
||||
} else {
|
||||
unlink(metar_newfile);
|
||||
if(!parse_metar(metar_file)) reset_current(¤t);
|
||||
}
|
||||
}
|
||||
|
||||
update_warnings(v!=NULL);
|
||||
}
|
||||
|
||||
void metar_cleanup(void){
|
||||
unlink(metar_newfile);
|
||||
unlink(metar_file);
|
||||
}
|
||||
|
||||
void update_metar(int force){
|
||||
time_t t;
|
||||
|
||||
t=time(NULL)/60;
|
||||
if(!force && metar_time>t) return;
|
||||
|
||||
metar_time=t+15;
|
||||
download_file(metar_newfile, metar_req[0], metar_req[1], force?DOWNLOAD_KILL_OTHER_REQUESTS:0, metar_callback, force?"":NULL);
|
||||
}
|
||||
|
||||
|
||||
#define get_substr(n, c) \
|
||||
if(pcre_get_substring(s, ovector, ovalue, n, (const char **)&c)<0){ pcre_free_substring(s); return 0; }
|
||||
|
||||
static int parse_metar(char *file){
|
||||
FILE *fp;
|
||||
char *s, *c;
|
||||
int ovector[ovecsize];
|
||||
int ovalue;
|
||||
int len;
|
||||
float f;
|
||||
int i, j;
|
||||
|
||||
reset_current(¤t);
|
||||
if((fp=fopen(file, "r"))==NULL) return 0;
|
||||
len=fread(bigbuf, sizeof(char), BIGBUF_LEN-2, fp);
|
||||
fclose(fp);
|
||||
if(len<1) return 0;
|
||||
for(i=0; i<len; i++){
|
||||
if(isspace(bigbuf[i])) bigbuf[i]=' ';
|
||||
}
|
||||
c=strstr(bigbuf, " RMK");
|
||||
if(c!=NULL) *(c+1)='\0';
|
||||
c=strstr(bigbuf, " TEMPO");
|
||||
s=strstr(bigbuf, " BECMG");
|
||||
if(c!=NULL) *(c+1)='\0';
|
||||
if(s!=NULL) *(s+1)='\0';
|
||||
/* XXX: parse trend forecast data? */
|
||||
|
||||
len=strlen(bigbuf);
|
||||
if(bigbuf[len-1]!=' '){
|
||||
bigbuf[len++]=' ';
|
||||
bigbuf[len]='\0';
|
||||
}
|
||||
|
||||
/* Look for something like a METAR coded report */
|
||||
ovalue=pcre_exec(station_time, NULL, bigbuf, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue<=0) return 0;
|
||||
if(pcre_get_substring(bigbuf, ovector, ovalue, 1, (const char **)&c)<0) return 0;
|
||||
if(c[0]!='\0') current.date=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
if(pcre_get_substring(bigbuf, ovector, ovalue, 2, (const char **)&c)<0) return 0;
|
||||
current.time=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
|
||||
/* Chop off extraneous stuff */
|
||||
if(pcre_get_substring(bigbuf, ovector, ovalue, 3, (const char **)&s)<0) return 0;
|
||||
|
||||
/* windspeed, winddir */
|
||||
ovalue=pcre_exec(wind, NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(4, c);
|
||||
if(c[0]!='\0'){
|
||||
current.winddir=0;
|
||||
} else {
|
||||
pcre_free_substring(c);
|
||||
get_substr(1, c);
|
||||
if(c[0]=='V') current.winddir=0;
|
||||
else current.winddir=((int)((atoi(c)+11.25)/22.5))%16+1;
|
||||
}
|
||||
pcre_free_substring(c);
|
||||
get_substr(2, c);
|
||||
current.windspeed=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(3, c);
|
||||
if(c[0]=='M'){ /* MPS */
|
||||
current.windspeed=mps2knots(current.windspeed);
|
||||
} else if(c[0]=='K' && c[1]=='M'){ /* KMH */
|
||||
current.windspeed=kph2knots(current.windspeed);
|
||||
}
|
||||
}
|
||||
|
||||
/* vis */
|
||||
f=99;
|
||||
c=strstr(s, " M1/4SM ");
|
||||
if(c!=NULL){
|
||||
f=0;
|
||||
goto wind_done;
|
||||
}
|
||||
ovalue=pcre_exec(vis[2], NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(2, c);
|
||||
i=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(3, c);
|
||||
j=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(1, c);
|
||||
f=atoi(c)+(float)i/j;
|
||||
pcre_free_substring(c);
|
||||
goto wind_done;
|
||||
}
|
||||
ovalue=pcre_exec(vis[1], NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(2, c);
|
||||
i=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(1, c);
|
||||
f=(float)atoi(c)/i;
|
||||
pcre_free_substring(c);
|
||||
goto wind_done;
|
||||
}
|
||||
ovalue=pcre_exec(vis[0], NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(1, c);
|
||||
f=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
goto wind_done;
|
||||
}
|
||||
c=strstr(s, " CAVOK ");
|
||||
if(c!=NULL){
|
||||
f=99;
|
||||
current.sky=0;
|
||||
goto wind_done;
|
||||
}
|
||||
ovalue=pcre_exec(vis[3], NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(1, c);
|
||||
f=m2mi(atoi(c));
|
||||
pcre_free_substring(c);
|
||||
goto wind_done;
|
||||
}
|
||||
wind_done:
|
||||
if(f<=6) current.vis=6;
|
||||
if(f<=5) current.vis=5;
|
||||
if(f<3) current.vis=4;
|
||||
if(f<1) current.vis=3;
|
||||
if(f<=.5) current.vis=2;
|
||||
if(f<=.25) current.vis=1;
|
||||
|
||||
/* temp, rh */
|
||||
ovalue=pcre_exec(temp, NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(1, c);
|
||||
if(c[0]=='M') c[0]='-';
|
||||
current.temp=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(2, c);
|
||||
if(c[0]!='\0'){
|
||||
if(c[0]=='M') c[0]='-';
|
||||
current.rh=rh_C(current.temp, atoi(c));
|
||||
}
|
||||
pcre_free_substring(c);
|
||||
}
|
||||
|
||||
/* pressure */
|
||||
ovalue=pcre_exec(pressure, NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0){
|
||||
get_substr(2, c);
|
||||
i=atoi(c);
|
||||
pcre_free_substring(c);
|
||||
get_substr(1, c);
|
||||
if(c[0]=='Q'){
|
||||
current.pressure=hPa2inHg(i);
|
||||
} else {
|
||||
current.pressure=i/100.0;
|
||||
}
|
||||
pcre_free_substring(c);
|
||||
}
|
||||
|
||||
/* sky */
|
||||
if(strstr(s, " SKC")!=NULL || strstr(s, " CLR")!=NULL) current.sky=0;
|
||||
if(strstr(s, " FEW")!=NULL) current.sky=1;
|
||||
if(strstr(s, " SCT")!=NULL) current.sky=2;
|
||||
if(strstr(s, " BKN")!=NULL) current.sky=3;
|
||||
if(strstr(s, " OVC")!=NULL || strstr(s, " VV")!=NULL) current.sky=4;
|
||||
|
||||
/* obs, frz, snow, rain, tstorm */
|
||||
/* There can be multiple weather chunks, so we while loop */
|
||||
j=0;
|
||||
while((ovalue=pcre_exec(weather, NULL, s, len, j, 0, ovector, ovecsize))>0){{
|
||||
char *in, *de, *pp, *ob, *ot;
|
||||
|
||||
j=ovector[0]+1;
|
||||
get_substr(0, c);
|
||||
i=(c[1]=='\0');
|
||||
pcre_free_substring(c);
|
||||
if(i) continue;
|
||||
|
||||
|
||||
get_substr(1, in);
|
||||
get_substr(2, de);
|
||||
get_substr(3, pp);
|
||||
get_substr(4, ob);
|
||||
get_substr(5, ot);
|
||||
|
||||
#define IN(haystack, needle) ((needle[0]=='\0')?0:strstr(haystack, needle))
|
||||
if(current.obs<1 && strcmp(de, "FZ") && IN("BR|FG", ob))
|
||||
current.obs=1;
|
||||
if(current.obs<2 && IN("FU|VA|DU|SA|HZ|PY", ob))
|
||||
current.obs=2;
|
||||
if(current.obs<3 && IN("PO|SS|DS", ot))
|
||||
current.obs=3;
|
||||
if(current.obs<3 && IN("DR|BL", de)
|
||||
&& (strstr(pp, "SN") || IN("DU|SA|PY", ob)))
|
||||
current.obs=3;
|
||||
if(!strcmp(ot, "FC")){
|
||||
current.sky=5;
|
||||
current.obs=99;
|
||||
current.vis=7;
|
||||
}
|
||||
#undef IN
|
||||
|
||||
i=66;
|
||||
if(in[0]=='-' || in[0]=='V') i=33;
|
||||
if(in[0]=='+') i=99;
|
||||
if(!strcmp(de, "SH")) i=33;
|
||||
if(current.frz<i
|
||||
&& ((!strcmp(de, "FZ") && (strstr(pp, "DZ") || strstr(pp, "RA")))
|
||||
|| strstr(pp, "IC") || strstr(pp, "PE") || strstr(pp, "PL")
|
||||
|| strstr(pp, "GR") || strstr(pp, "GS")))
|
||||
current.frz=i;
|
||||
if(current.snow<i && strcmp(de, "BL")
|
||||
&& (strstr(pp, "SN") || strstr(pp, "SG")))
|
||||
current.snow=i;
|
||||
if(current.rain<i && (strstr(pp, "UP")
|
||||
|| (strcmp(de, "FZ")
|
||||
&& (strstr(pp, "DZ") || strstr(pp, "RA")))))
|
||||
current.rain=i;
|
||||
if(current.tstorm<i && !strcmp(de, "TS"))
|
||||
current.tstorm=i;
|
||||
|
||||
pcre_free_substring(in);
|
||||
pcre_free_substring(de);
|
||||
pcre_free_substring(pp);
|
||||
pcre_free_substring(ob);
|
||||
pcre_free_substring(ot);
|
||||
}}
|
||||
if(current.obs==99) current.obs=0;
|
||||
|
||||
pcre_free_substring(s); /* Done parsing! Just a few final calculations... */
|
||||
|
||||
current.heatindex=heatindex_C(current.temp, current.rh);
|
||||
current.windchill=windchill_C(current.temp, current.windspeed);
|
||||
|
||||
/* Figure out the proper month... */
|
||||
{
|
||||
int mon, day, year, time2; /* holds UTC */
|
||||
int y; /* with current.*, holds local time */
|
||||
time_t t=time(NULL);
|
||||
struct tm *tm=gmtime(&t);
|
||||
current.month=tm->tm_mon+1;
|
||||
if(tm->tm_mday<current.date) current.month--;
|
||||
if(current.month<1){ current.month+=12; tm->tm_year--; }
|
||||
y=year=tm->tm_year;
|
||||
mon=current.month;
|
||||
day=current.date;
|
||||
time2=current.time;
|
||||
current.time=utc2local((int)current.time, ¤t.month, ¤t.date, &y, NULL);
|
||||
|
||||
if(latitude!=999 && calcSolarZenith(latitude, longitude, year, mon, day, hm2min(time2))>90)
|
||||
current.moon=calc_moon(current.month, current.date, y, current.time);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#undef get_substr
|
|
@ -1,27 +0,0 @@
|
|||
struct current_weather {
|
||||
time_t last_update;
|
||||
int month; /* 0, 1 - 12 */
|
||||
int date; /* -1, 1 - 31 (GMT) */
|
||||
short time; /* -1, 0000 - 2359 */
|
||||
short temp; /* 999, -210 - 390 (degrees C) */
|
||||
signed char rh; /* -1, 0 - 100 (%) */
|
||||
short winddir; /* -1, 0 - 16 (direction) */
|
||||
short windspeed; /* -1, 0 - MAX (knots) */
|
||||
float pressure; /* -1, 0 - MAX (inHg) */
|
||||
short heatindex; /* 999, -99 - 199 (degrees F) */
|
||||
short windchill; /* 999, -99 - 199 (degrees F) */
|
||||
signed char sky; /* -1, 0-4 (condition) */
|
||||
signed char vis; /* 7, 1-7 (status code) */
|
||||
signed char obs; /* 0, 0-3 (type) */
|
||||
signed char frz; /* 0, 0, 33, 66, 99 (intensity) */
|
||||
signed char snow; /* 0, 0, 33, 66, 99 (intensity) */
|
||||
signed char rain; /* 0, 0, 33, 66, 99 (intensity) */
|
||||
signed char tstorm; /* 0, 0, 33, 66, 99 (intensity) */
|
||||
double moon; /* NAN, -1 - 1 (percent and wax/wane) */
|
||||
};
|
||||
|
||||
extern struct current_weather current;
|
||||
|
||||
void init_metar(void);
|
||||
void update_metar(int force);
|
||||
void metar_cleanup(void);
|
|
@ -1,179 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* One-line algorithm from http://www.moonstick.com/moon_phase_emergency.htm
|
||||
* It's a bit rough, but it works well enough */
|
||||
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "convert.h"
|
||||
|
||||
#include "wmgeneral/wmgeneral-x11.h"
|
||||
|
||||
static double fpart(double t){
|
||||
return t-trunc(t);
|
||||
}
|
||||
|
||||
double calc_moon(int month, int day, int year, int hm){
|
||||
time_t t=time(NULL);
|
||||
struct tm *tm;
|
||||
double p;
|
||||
|
||||
tm=gmtime(&t);
|
||||
tm->tm_hour=hm/100;
|
||||
tm->tm_min=hm%100;
|
||||
tm->tm_sec=0;
|
||||
tm->tm_mon=month-1;
|
||||
tm->tm_mday=day;
|
||||
tm->tm_year=year;
|
||||
t=mkgmtime(tm);
|
||||
|
||||
/* This next line is the algorithm. */
|
||||
p=fpart(((t/86400.0-11323.0)*850.0+5130.5769)/25101.0);
|
||||
if(p>.5) return -.5+cos(2*PI*p)/2;
|
||||
return .5-cos(2*PI*p)/2;
|
||||
}
|
||||
|
||||
|
||||
#define darkside 0.19921875
|
||||
#define lightside (1-0.19921875)
|
||||
#define maxwidth 17
|
||||
static int widths[]={ 7, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 7, -1 };
|
||||
extern int screen;
|
||||
extern XpmIcon wmgen;
|
||||
extern GC NormalGC;
|
||||
|
||||
/* Duplicates quite a bit of code from combineWithOpacity for speed */
|
||||
void copySunMoon(int x, int y, double percent){
|
||||
XImage *pix;
|
||||
unsigned int w, h, bar;
|
||||
int foo;
|
||||
Window baz;
|
||||
int rmask, gmask, bmask;
|
||||
unsigned long spixel;
|
||||
int xx, terminator, oflag;
|
||||
int flag;
|
||||
double frac;
|
||||
|
||||
if(isnan(percent)){
|
||||
copyPixmapArea(164, 64, 26, 25, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
XGetGeometry(display, wmgen.pixmap, &baz, &foo, &foo, &w, &h, &bar, &bar);
|
||||
pix=XGetImage(display, wmgen.pixmap, 0, 0, w, h, AllPlanes, ZPixmap);
|
||||
|
||||
if (pix->depth == DefaultDepth(display, screen)) {{
|
||||
Visual *visual=DefaultVisual(display, screen);
|
||||
rmask = visual->red_mask;
|
||||
gmask = visual->green_mask;
|
||||
bmask = visual->blue_mask;
|
||||
}} else {
|
||||
rmask = pix->red_mask;
|
||||
gmask = pix->green_mask;
|
||||
bmask = pix->blue_mask;
|
||||
}
|
||||
|
||||
x+=4; y+=4;
|
||||
flag=(percent<0);
|
||||
if(flag) percent=-percent;
|
||||
for(h=0; widths[h]>0; h++){
|
||||
xx=(maxwidth-widths[h])>>1;
|
||||
if(flag){
|
||||
oflag=1;
|
||||
terminator=widths[h]*percent;
|
||||
} else {
|
||||
oflag=0;
|
||||
terminator=widths[h]-widths[h]*percent;
|
||||
}
|
||||
frac=lightside*fpart(widths[h]*percent)+darkside;
|
||||
for(w=0; w<widths[h]; w++){
|
||||
spixel=XGetPixel(pix, 168+xx+w, 93+h);
|
||||
if(w==terminator){
|
||||
oflag=!oflag;
|
||||
XPutPixel(pix, x+xx+w, y+h,
|
||||
(((unsigned long)((spixel&rmask)*frac))&rmask) |
|
||||
(((unsigned long)((spixel&gmask)*frac))&gmask) |
|
||||
(((unsigned long)((spixel&bmask)*frac))&bmask));
|
||||
} else if(oflag){
|
||||
XPutPixel(pix, x+xx+w, y+h, spixel);
|
||||
} else {
|
||||
XPutPixel(pix, x+xx+w, y+h,
|
||||
(((unsigned long)((spixel&rmask)*darkside))&rmask) |
|
||||
(((unsigned long)((spixel&gmask)*darkside))&gmask) |
|
||||
(((unsigned long)((spixel&bmask)*darkside))&bmask));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XPutImage(display, wmgen.pixmap, NormalGC, pix, 0, 0, 0, 0, pix->width, pix->height);
|
||||
|
||||
XDestroyImage(pix);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void copySunMoon(int x, int y, double percent){
|
||||
int w, h;
|
||||
int xx;
|
||||
int frac;
|
||||
int flag;
|
||||
|
||||
if(isnan(percent)){
|
||||
copyPixmapArea(164, 64, 26, 25, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
combineWithOpacity(164, 89, 26, 25, x, y, 51);
|
||||
x+=4; y+=4;
|
||||
flag=(percent<0);
|
||||
if(flag) percent=-percent;
|
||||
for(h=0; h<=8; h++){
|
||||
w=widths[h]*percent;
|
||||
frac=(widths[h]*percent-w)*100;
|
||||
if(flag) xx=(17-widths[h])/2;
|
||||
else xx=(17+widths[h])/2-w;
|
||||
copyPixmapArea(141+xx, 93+h, w, 1, x+xx, y+h);
|
||||
copyPixmapArea(141+xx, 109-h, w, 1, x+xx, y+16-h);
|
||||
if(flag){
|
||||
combineWithOpacity(141+xx+w, 93+h, 1, 1, x+xx+w, y+h, frac);
|
||||
combineWithOpacity(141+xx+w, 109-h, 1, 1, x+xx+w, y+16-h, frac);
|
||||
} else {
|
||||
combineWithOpacity(141+xx-1, 93+h, 1, 1, x+xx-1, y+h, frac);
|
||||
combineWithOpacity(141+xx-1, 109-h, 1, 1, x+xx-1, y+16-h, frac);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
double calc_moon(int month, int day, int year, int hm);
|
||||
void copySunMoon(int x, int y, double percent);
|
318
wmweather+/mrf.c
318
wmweather+/mrf.c
|
@ -1,318 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "forecast.h"
|
||||
#include "getLine.h"
|
||||
#include "convert.h"
|
||||
#include "download.h"
|
||||
#include "diff.h"
|
||||
#include "die.h"
|
||||
#include "subst.h"
|
||||
|
||||
/* Important variables */
|
||||
#define MRF_MAX 7
|
||||
static time_t mrf_time=0;
|
||||
static char *mrf_file=NULL;
|
||||
static char *mrf_newfile=NULL;
|
||||
static char *mrf_req[2]={ NULL, NULL };
|
||||
static struct forecast forecasts[MRF_MAX];
|
||||
|
||||
|
||||
/********* init functions ************/
|
||||
static int parse_mrf(char *file);
|
||||
|
||||
static void reset_mrf(void){
|
||||
int i;
|
||||
|
||||
for(i=0; i<MRF_MAX; i++) reset_forecast(&forecasts[i]);
|
||||
}
|
||||
|
||||
void init_mrf(void){
|
||||
int i;
|
||||
char *e;
|
||||
struct subst_val subs[]={
|
||||
{ 's', STRING, &mrf_station },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
strncpy(bigbuf, mrf_station, BIGBUF_LEN-14);
|
||||
bigbuf[BIGBUF_LEN-14]='\0';
|
||||
for(e=bigbuf; *e!='\0'; e++);
|
||||
strcpy(e, ".mrf.txt");
|
||||
mrf_file=get_pid_filename(bigbuf);
|
||||
strcpy(e, ".new-mrf.txt");
|
||||
mrf_newfile=get_pid_filename(bigbuf);
|
||||
|
||||
if((mrf_req[0]=subst(mrf_uri, subs))==NULL) die("init_mrf");
|
||||
if(mrf_post!=NULL && (mrf_req[1]=subst(mrf_post, subs))==NULL) die("init_mrf");
|
||||
mrf_time=0;
|
||||
|
||||
/* Remove stale file */
|
||||
unlink(mrf_file);
|
||||
unlink(mrf_newfile);
|
||||
reset_mrf();
|
||||
for(i=0; i<MRF_MAX; i++) add_forecast(&forecasts[i], "MRF", mrf_station);
|
||||
}
|
||||
|
||||
static void mrf_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(mrf_newfile, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& diff(mrf_newfile, mrf_file) && parse_mrf(mrf_newfile)){
|
||||
mrf_time=find_next_time(mrf_newfile, "MOS GUIDANCE", 1440);
|
||||
rename(mrf_newfile, mrf_file);
|
||||
} else {
|
||||
unlink(mrf_newfile);
|
||||
if(!parse_mrf(mrf_file)) reset_mrf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mrf_cleanup(void){
|
||||
if(mrf_file==NULL) return;
|
||||
unlink(mrf_newfile);
|
||||
unlink(mrf_file);
|
||||
}
|
||||
|
||||
void update_mrf(int force){
|
||||
time_t t;
|
||||
|
||||
if(mrf_file==NULL) return;
|
||||
|
||||
t=time(NULL)/60;
|
||||
if(!force && mrf_time>t) return;
|
||||
|
||||
mrf_time=find_next_time(mrf_file, "MOS GUIDANCE", 15);
|
||||
download_file(mrf_newfile, mrf_req[0], mrf_req[1], 0, mrf_callback, NULL);
|
||||
}
|
||||
|
||||
|
||||
#define NEXT(s) free(s); \
|
||||
len=getLine(&s, fp); \
|
||||
if(strstr(s, "</PRE>")!=NULL) len=0;
|
||||
|
||||
#define DIE() return (free(s), fclose(fp), 0)
|
||||
#define INT(c) (tmp[0]=*c, tmp[1]=*(c+1), tmp[2]=*(c+2), tmp[3]=0, atoi(tmp))
|
||||
|
||||
static int parse_mrf(char *file){
|
||||
FILE *fp;
|
||||
char *s, *c;
|
||||
int len;
|
||||
int mon, day;
|
||||
int i, j, m, x, y;
|
||||
int flag;
|
||||
char tmp[4]={0, 0, 0, 0};
|
||||
|
||||
flag=0;
|
||||
reset_mrf();
|
||||
if((fp=fopen(file, "r"))==NULL) return 0;
|
||||
|
||||
/* Look for something like an MRF coded forecast */
|
||||
c=NULL;
|
||||
while(!feof(fp)){
|
||||
len=getLine(&s, fp);
|
||||
if((c=strstr(s, "MOS GUIDANCE"))!=NULL) break;
|
||||
free(s);
|
||||
}
|
||||
if(c==NULL) return (fclose(fp), 0);
|
||||
c=strchr(c, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
mon=atoi(c-2);
|
||||
x=atoi(c+1);
|
||||
if(mon<1 || mon>12 || x<1 || x>31) DIE();
|
||||
c=strchr(c+1, '/');
|
||||
if(c==NULL || !isdigit(*(c-1)) || !isdigit(*(c+1))) DIE();
|
||||
y=atoi(c+1)-1900;
|
||||
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
if(strncmp(s, "FHR", 3)) DIE();
|
||||
|
||||
NEXT(s);
|
||||
if(len<10) DIE();
|
||||
for(i=0; i<7; i++){
|
||||
if(!strncmp(s, wdaynames[i], 3)) break;
|
||||
}
|
||||
if(i>=7) DIE();
|
||||
day=atoi(s+4);
|
||||
if(x>25 && day<5) mon++;
|
||||
if(x<5 && day>25) mon--;
|
||||
for(m=0; m<MRF_MAX; m++){
|
||||
day++;
|
||||
i++; i%=7;
|
||||
fix_date(&mon, &day, &y, &j);
|
||||
if(j!=i){
|
||||
warn("Something wicked happened with the mrf_parse dates...");
|
||||
DIE();
|
||||
}
|
||||
forecasts[m].month=mon;
|
||||
forecasts[m].day=day;
|
||||
forecasts[m].year=y;
|
||||
forecasts[m].wday=i;
|
||||
forecasts[m].hour=-1;
|
||||
}
|
||||
|
||||
while(1){
|
||||
NEXT(s);
|
||||
if(len<=10) break;
|
||||
|
||||
if(!strncmp(s, "X/N", 3)){
|
||||
for(c=s+12, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
forecasts[m].high=INT(c);
|
||||
if(c+4<s+len) forecasts[m].low=INT((c+4));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "TMP", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].temp=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].temp=i;
|
||||
else if(j!=999) forecasts[m].temp=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "DPT", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].dewpt=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].dewpt=i;
|
||||
else if(j!=999) forecasts[m].dewpt=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "WND", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].windspeed=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].windspeed=i;
|
||||
else if(j!=999) forecasts[m].windspeed=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "T24", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=atoi(c);
|
||||
if(i!=999) forecasts[m].tstorm=i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "Q24", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=atoi(c);
|
||||
if(i!=9) forecasts[m].precipamt=i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "SNW", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=atoi(c);
|
||||
if(i!=9) forecasts[m].snowamt=i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "CLD", 3)){
|
||||
for(c=s+13, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
if(*c=='C') forecasts[m].sky=0;
|
||||
if(*c=='P'){
|
||||
if(*(c-4)=='C') forecasts[m].sky=2;
|
||||
else if(*(c-4)=='O') forecasts[m].sky=3;
|
||||
else if(c+4<s+len && *(c+4)=='C') forecasts[m].sky=2;
|
||||
else if(c+4<s+len && *(c+4)=='O') forecasts[m].sky=3;
|
||||
else forecasts[m].sky=3;
|
||||
}
|
||||
if(*c=='O') forecasts[m].sky=4;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "PZP", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].frz=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].frz=i;
|
||||
else if(j!=999) forecasts[m].frz=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "PSN", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].snow=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].snow=i;
|
||||
else if(j!=999) forecasts[m].snow=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "PRS", 3)){
|
||||
/* stick "rain & snow" prob into rain for later */
|
||||
flag=1;
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=INT(c); j=INT((c+4));
|
||||
if(i!=999 && j!=999) forecasts[m].rain=(i+j)/2;
|
||||
else if(i!=999) forecasts[m].rain=i;
|
||||
else if(j!=999) forecasts[m].rain=j;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(s, "P24", 3)){
|
||||
for(c=s+8, m=0; c<s+len && m<MRF_MAX; c+=8, m++){
|
||||
i=atoi(c);
|
||||
if(i!=999) forecasts[m].pcp_total=i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
free(s);
|
||||
fclose(fp);
|
||||
|
||||
for(m=0; m<MRF_MAX; m++){
|
||||
forecasts[m].rh=rh_F(forecasts[m].temp, forecasts[m].dewpt);
|
||||
forecasts[m].heatindex=heatindex_F(forecasts[m].temp, forecasts[m].rh);
|
||||
forecasts[m].windchill=windchill_F(forecasts[m].temp, forecasts[m].windspeed);
|
||||
/* real rain = 100 - frz - snow
|
||||
* real snow = snow + "rain & snow"
|
||||
*/
|
||||
i=100-forecasts[m].frz-forecasts[m].snow;
|
||||
forecasts[m].snow+=forecasts[m].rain;
|
||||
forecasts[m].rain=i;
|
||||
forecasts[m].rain=forecasts[m].rain*forecasts[m].pcp_total/100;
|
||||
forecasts[m].snow=forecasts[m].snow*forecasts[m].pcp_total/100;
|
||||
forecasts[m].frz=forecasts[m].frz*forecasts[m].pcp_total/100;
|
||||
|
||||
/* These aren't really useful here... */
|
||||
forecasts[m].temp=999;
|
||||
forecasts[m].dewpt=999;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#undef NEXT
|
||||
#undef DIE
|
||||
#undef INT
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef MRF_H
|
||||
#define MRF_H
|
||||
|
||||
void init_mrf(void);
|
||||
void update_mrf(int force);
|
||||
void mrf_cleanup(void);
|
||||
|
||||
#endif
|
|
@ -1,266 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <wraster.h>
|
||||
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "wmgeneral/wmgeneral-x11.h"
|
||||
#include "wmgeneral/xpm_trans.h"
|
||||
#include "download.h"
|
||||
#include "radar.h"
|
||||
#include "die.h"
|
||||
|
||||
/* Important variables */
|
||||
static time_t radar_time=0;
|
||||
static char *radar_file=NULL;
|
||||
static char *radar_newfile=NULL;
|
||||
static int cropx, cropy, cropw, croph;
|
||||
static int crossx, crossy;
|
||||
time_t radar_update_time;
|
||||
Pixmap radar;
|
||||
int do_radar_cross;
|
||||
|
||||
extern XpmIcon wmgen;
|
||||
extern GC NormalGC;
|
||||
extern int screen;
|
||||
extern int d_depth;
|
||||
|
||||
/* prototypes */
|
||||
static int parse_radar(char *file);
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void reset_radar(Pixmap *r){
|
||||
XCopyArea(display, wmgen.pixmap, *r, NormalGC, 124, 18, 52, 40, 0, 0);
|
||||
XCopyArea(display, wmgen.pixmap, *r, NormalGC, 108, 89, 15, 14, 18, 13);
|
||||
}
|
||||
|
||||
|
||||
static void parse_cross(void){
|
||||
char *p1, *p2;
|
||||
|
||||
if(radar_cross==NULL) return;
|
||||
crossx=strtol(radar_cross, &p1, 10);
|
||||
if(crossx<0 || crossx>=52 || p1==NULL || p1==radar_cross || *p1!='x'){
|
||||
radar_cross=NULL;
|
||||
return;
|
||||
}
|
||||
crossy=strtol(++p1, &p2, 10);
|
||||
if(crossy<0 || crossy>=40 || (p2!=NULL && *p2!='\0')){
|
||||
radar_cross=NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_crop(void){
|
||||
char *p1, *p2;
|
||||
|
||||
if(radar_crop==NULL) return;
|
||||
cropx=strtol(radar_crop, &p1, 10);
|
||||
if(p1==NULL || p1==radar_crop || *p1!='x'){
|
||||
radar_crop=NULL;
|
||||
return;
|
||||
}
|
||||
cropy=strtol(++p1, &p2, 10);
|
||||
if(p2==NULL || p2==p1 || *p2!='+'){
|
||||
radar_crop=NULL;
|
||||
return;
|
||||
}
|
||||
cropw=strtol(p2, &p1, 10);
|
||||
if(cropw<1 || p1==NULL || *p1!='+'){
|
||||
radar_crop=NULL;
|
||||
return;
|
||||
}
|
||||
croph=strtol(p1, &p2, 10);
|
||||
if(croph<1 || (p2!=NULL && *p2!='\0')){
|
||||
radar_crop=NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init_radar(void){
|
||||
char *e;
|
||||
|
||||
radar=XCreatePixmap(display, wmgen.pixmap, 52, 40, d_depth);
|
||||
reset_radar(&radar);
|
||||
|
||||
if(radar_uri==NULL) return;
|
||||
|
||||
e=strrchr(radar_uri, '/');
|
||||
if(e==NULL) e=radar_uri;
|
||||
else e++;
|
||||
snprintf(bigbuf, BIGBUF_LEN-21, "%s.", e);
|
||||
for(e=bigbuf; *e!='\0'; e++){
|
||||
if(!isalnum(*e) && *e!='.' && *e!='-' && *e!='+' && *e!='%'
|
||||
&& *e!='?' && *e!='=' && *e!='&') *e='_';
|
||||
}
|
||||
strcpy(e, "radar-image");
|
||||
radar_file=get_pid_filename(bigbuf);
|
||||
strcpy(e, "new-radar-image");
|
||||
radar_newfile=get_pid_filename(bigbuf);
|
||||
|
||||
radar_update_time=radar_time==0;
|
||||
|
||||
parse_crop();
|
||||
parse_cross();
|
||||
do_radar_cross=0;
|
||||
|
||||
/* Delete stale files, if any */
|
||||
unlink(radar_file);
|
||||
unlink(radar_newfile);
|
||||
}
|
||||
|
||||
static void radar_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(radar_newfile, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& parse_radar(radar_newfile)){
|
||||
rename(radar_newfile, radar_file);
|
||||
} else {
|
||||
unlink(radar_newfile);
|
||||
if(!parse_radar(radar_file)) reset_radar(&radar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void radar_cleanup(void){
|
||||
if(radar_file==NULL) return;
|
||||
unlink(radar_newfile);
|
||||
unlink(radar_file);
|
||||
}
|
||||
|
||||
void update_radar(int force){
|
||||
time_t t;
|
||||
|
||||
if(radar_file==NULL) return;
|
||||
|
||||
t=time(NULL)/60;
|
||||
if(!force && radar_time>t) return;
|
||||
|
||||
radar_time=t+30;
|
||||
download_file(radar_newfile, radar_uri, radar_post, force?DOWNLOAD_KILL_OTHER_REQUESTS:0, radar_callback, NULL);
|
||||
}
|
||||
|
||||
static RContext *rc=NULL;
|
||||
|
||||
static int parse_radar(char *file){
|
||||
RImage *r, *n;
|
||||
float w, h;
|
||||
RColor col={ 0, 0, 0, 255};
|
||||
int x, y, ww, hh;
|
||||
|
||||
errno=0;
|
||||
radar_update_time=time(NULL);
|
||||
reset_radar(&radar);
|
||||
if(rc==NULL){
|
||||
rc=RCreateContext(display, screen, NULL);
|
||||
if(rc==NULL){
|
||||
warn("parse_radar context creation: %s", RMessageForError(RErrorCode));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r=RLoadImage(rc, file, 0);
|
||||
if(!r) return 0;
|
||||
|
||||
if(radar_crop!=NULL){
|
||||
x=cropx; y=cropy;
|
||||
ww=cropw; hh=croph;
|
||||
if(x<0) x+=r->width;
|
||||
if(y<0) y+=r->height;
|
||||
if(x<0){ ww+=x; x=0; }
|
||||
if(y<0){ hh+=y; y=0; }
|
||||
|
||||
if(x>=r->width || y>=r->width || ww<=0 || hh<=0){
|
||||
RReleaseImage(r);
|
||||
warn("parse_radar radar_crop exceeds image dimensions");
|
||||
return 0;
|
||||
}
|
||||
|
||||
n=RGetSubImage(r, x, y, ww, hh);
|
||||
RReleaseImage(r);
|
||||
r=n;
|
||||
if(!r){
|
||||
warn("parse_radar crop: %s", RMessageForError(RErrorCode));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(r->width>52 || r->height>40 || (r->width!=52 && r->height!=40)){
|
||||
w=r->width/52;
|
||||
h=r->height/40;
|
||||
if(w>h) h=w;
|
||||
else w=h;
|
||||
|
||||
n=RSmoothScaleImage(r, r->width/w, r->height/h);
|
||||
RReleaseImage(r);
|
||||
r=n;
|
||||
if(!r){
|
||||
warn("parse_radar scale: %s", RMessageForError(RErrorCode));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(r->width!=52 || r->height!=40){
|
||||
n=RMakeCenteredImage(r, 52, 40, &col);
|
||||
RReleaseImage(r);
|
||||
r=n;
|
||||
if(!r){
|
||||
warn("parse_radar center: %s", RMessageForError(RErrorCode));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!RConvertImage(rc, r, &radar)){
|
||||
RReleaseImage(r);
|
||||
warn("parse_radar convert: %s", RMessageForError(RErrorCode));
|
||||
return 0;
|
||||
}
|
||||
RReleaseImage(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void put_radar(int x, int y, int font){
|
||||
int i;
|
||||
|
||||
XCopyArea(display, radar, wmgen.pixmap, NormalGC, 0, 0, 52, 40, x, y);
|
||||
if(font==0) i=0;
|
||||
else i=1;
|
||||
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 124, 60+i, 54, 1, x-1, y-1);
|
||||
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 124, 60+i, 54, 1, x-1, y+40);
|
||||
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 162+i, 64, 1, 40, x-1, y);
|
||||
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 162+i, 64, 1, 40, x+52, y);
|
||||
if(radar_cross && do_radar_cross){
|
||||
combineWithOpacity(124, 60+i, 52, 1, x, y+crossy, 128);
|
||||
combineWithOpacity(162+i, 64, 1, 40, x+crossx, y, 128);
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#include <X11/xpm.h>
|
||||
|
||||
extern time_t radar_update_time;
|
||||
extern Pixmap radar;
|
||||
extern int do_radar_cross;
|
||||
|
||||
void init_radar(void);
|
||||
void update_radar(int force);
|
||||
void put_radar(int x, int y, int font);
|
||||
void radar_cleanup(void);
|
|
@ -1,188 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "die.h"
|
||||
#include "subst.h"
|
||||
|
||||
#define GROW(var, len){{ \
|
||||
void *c; \
|
||||
len<<=1; \
|
||||
if(len==0) len=1; \
|
||||
if((var=realloc(c=var, len))==NULL){ \
|
||||
out=c; \
|
||||
warn("realloc error"); \
|
||||
goto fail; \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define COPY(c) { \
|
||||
if(k>=formatlen) GROW(format, formatlen); \
|
||||
format[k++]=c; \
|
||||
}
|
||||
|
||||
char *subst(const char *s, struct subst_val *substitutes){
|
||||
int i, j, k, n, m;
|
||||
char *out=NULL;
|
||||
size_t outlen=0;
|
||||
char *format=NULL;
|
||||
size_t formatlen=0;
|
||||
int flags;
|
||||
ssize_t str_start;
|
||||
|
||||
for(i=j=0; s[i]!='\0'; i++){
|
||||
if(s[i]!='%'){
|
||||
if(j>=outlen) GROW(out, outlen);
|
||||
out[j++]=s[i];
|
||||
continue;
|
||||
}
|
||||
if(s[i+1]=='%'){
|
||||
if(j>=outlen) GROW(out, outlen);
|
||||
out[j++]=s[i++];
|
||||
continue;
|
||||
}
|
||||
|
||||
n=i;
|
||||
k=0;
|
||||
COPY('%');
|
||||
|
||||
/* skip flags */
|
||||
flags=0;
|
||||
while(strchr("#0- +'!", s[++n])){
|
||||
if(s[n]=='!'){
|
||||
flags|=1;
|
||||
} else {
|
||||
COPY(s[n]);
|
||||
}
|
||||
}
|
||||
|
||||
/* min width? */
|
||||
if(isdigit(s[n]) && s[n]!='0'){
|
||||
COPY(s[n]);
|
||||
while(isdigit(s[++n])){ COPY(s[n]); }
|
||||
}
|
||||
|
||||
/* precision? */
|
||||
if(s[n]=='.'){
|
||||
COPY('.');
|
||||
while(isdigit(s[++n])){ COPY(s[n]); }
|
||||
}
|
||||
|
||||
str_start=0;
|
||||
if(s[n]=='>'){
|
||||
if(s[n+1]=='-'){
|
||||
flags|=2;
|
||||
n++;
|
||||
}
|
||||
while(isdigit(s[++n])){
|
||||
str_start=str_start*10+s[n]-'0';
|
||||
}
|
||||
if(flags&2) str_start=-str_start;
|
||||
}
|
||||
|
||||
for(m=0; s[n]!=substitutes[m].id && substitutes[m].id!='\0'; m++);
|
||||
if(substitutes[m].id=='\0'){
|
||||
warn("Unknown substitition character '%c' (at %d)\n", s[n], i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch(substitutes[m].type){
|
||||
case HEX:
|
||||
case FLOAT_E:
|
||||
case FLOAT_F:
|
||||
case FLOAT_G:
|
||||
case FLOAT_A:
|
||||
if(flags&1){
|
||||
COPY(toupper(substitutes[m].type));
|
||||
break;
|
||||
}
|
||||
/* fall through*/
|
||||
|
||||
default:
|
||||
COPY(substitutes[m].type);
|
||||
break;
|
||||
}
|
||||
COPY('\0');
|
||||
|
||||
#define PRINT(var) { while((k=j+snprintf(out+j, outlen-j, format, var))>=outlen) GROW(out, outlen); j=k; }
|
||||
switch(substitutes[m].type){
|
||||
case INT:
|
||||
PRINT(*(signed int *)substitutes[m].val);
|
||||
break;
|
||||
|
||||
case UINT:
|
||||
case OCTAL:
|
||||
case HEX:
|
||||
PRINT(*(unsigned int *)substitutes[m].val);
|
||||
break;
|
||||
|
||||
case FLOAT_E:
|
||||
case FLOAT_F:
|
||||
case FLOAT_G:
|
||||
case FLOAT_A:
|
||||
PRINT(*(double *)substitutes[m].val);
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
PRINT(*(char *)substitutes[m].val);
|
||||
if(flags&1) out[j-1]=toupper(out[j-1]);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
{
|
||||
char *s=*(char **)substitutes[m].val;
|
||||
if(str_start<0){
|
||||
str_start+=strlen(s);
|
||||
if(str_start<0) str_start=0;
|
||||
} else if(str_start>strlen(s)){
|
||||
s="";
|
||||
str_start=0;
|
||||
}
|
||||
s+=str_start;
|
||||
i=j;
|
||||
PRINT(s);
|
||||
if(flags&1){
|
||||
for(; i<j; i++) out[i]=toupper(out[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
warn("Unknown substitution type '%c'\n", substitutes[m].type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
i=n;
|
||||
}
|
||||
|
||||
free(format);
|
||||
if(j>=outlen) GROW(out, outlen);
|
||||
out[j]='\0';
|
||||
return out;
|
||||
|
||||
fail:
|
||||
free(format);
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef SUBST_H
|
||||
#define SUBST_H
|
||||
|
||||
struct subst_val {
|
||||
char id; /* if id=='X', %X will be substituted */
|
||||
enum {
|
||||
INT ='i', /* val => signed int */
|
||||
UINT ='u', /* val => unsigned int */
|
||||
OCTAL ='o', /* val => unsigned int */
|
||||
HEX ='x', /* val => unsigned int */
|
||||
FLOAT_E ='e', /* val => double */
|
||||
FLOAT_F ='f', /* val => double */
|
||||
FLOAT_G ='g', /* val => double */
|
||||
FLOAT_A ='a', /* val => double */
|
||||
CHAR ='c', /* val => char */
|
||||
STRING ='s' /* val => char * */
|
||||
} type;
|
||||
void *val;
|
||||
};
|
||||
|
||||
char *subst(const char *s, struct subst_val *substitutes);
|
||||
|
||||
#endif
|
|
@ -1,138 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Algorithms from http://www.srrb.noaa.gov/highlights/sunrise/azel.html */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "convert.h"
|
||||
|
||||
/* Purpose: calculate the Geometric Mean Longitude of the Sun (degrees) */
|
||||
double calcGeomMeanLongSun(double t) {
|
||||
double L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
|
||||
while(L0 > 360.0) {
|
||||
L0 -= 360.0;
|
||||
}
|
||||
while(L0 < 0.0) {
|
||||
L0 += 360.0;
|
||||
}
|
||||
return L0;
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the Geometric Mean Anomaly of the Sun (degrees) */
|
||||
double calcGeomMeanAnomalySun(double t) {
|
||||
return 357.52911 + t * (35999.05029 - 0.0001537 * t);
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the eccentricity of earth's orbit */
|
||||
double calcEccentricityEarthOrbit(double t) {
|
||||
return 0.016708634 - t * (0.000042037 + 0.0000001267 * t);
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the equation of center for the sun (degrees) */
|
||||
double calcSunEqOfCenter(double t) {
|
||||
double m = deg2rad(calcGeomMeanAnomalySun(t));
|
||||
|
||||
return sin(m) * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin(m+m) * (0.019993 - 0.000101 * t) + sin(m+m+m) * 0.000289;
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the true longitude of the sun (degrees) */
|
||||
double calcSunTrueLong(double t) {
|
||||
return calcGeomMeanLongSun(t) + calcSunEqOfCenter(t);
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the apparent longitude of the sun (degrees) */
|
||||
double calcSunApparentLong(double t) {
|
||||
return calcSunTrueLong(t) - 0.00569 - 0.00478 * sin(deg2rad(125.04-1934.136*t));
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the mean obliquity of the ecliptic (degrees) */
|
||||
double calcMeanObliquityOfEcliptic(double t) {
|
||||
return 23.0 + (26.0 + ((21.448 - t*(46.8150 + t*(0.00059 - t*(0.001813))))/60.0))/60.0;
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the corrected obliquity of the ecliptic (degrees) */
|
||||
double calcObliquityCorrection(double t) {
|
||||
return calcMeanObliquityOfEcliptic(t) + 0.00256*cos(deg2rad(125.04-1934.136*t));
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the declination of the sun (degrees) */
|
||||
double calcSunDeclination(double t) {
|
||||
return rad2deg(asin(sin(deg2rad(calcObliquityCorrection(t))) *
|
||||
sin(deg2rad(calcSunApparentLong(t)))));
|
||||
}
|
||||
|
||||
|
||||
/* Purpose: calculate the difference between true solar time and mean
|
||||
* solar time (minutes)
|
||||
*/
|
||||
double calcEquationOfTime(double t) {
|
||||
double l0 = deg2rad(calcGeomMeanLongSun(t));
|
||||
double e = calcEccentricityEarthOrbit(t);
|
||||
double m = deg2rad(calcGeomMeanAnomalySun(t));
|
||||
double y = tan(deg2rad(calcObliquityCorrection(t))/2.0);
|
||||
double sinm = sin(m);
|
||||
|
||||
y *= y;
|
||||
|
||||
return rad2deg(y*sin(2.0*l0) - 2.0*e*sinm + 4.0*e*y*sinm*cos(2.0*l0)
|
||||
- 0.5*y*y*sin(4.0*l0) - 1.25*e*e*sin(2.0*m))*4.0;
|
||||
}
|
||||
|
||||
|
||||
double calcSolarZenith(double latitude, double longitude, int year, int month, int day, int timeUTC){
|
||||
double T, trueSolarTime, hourAngle, solarDec, csz, zenith, exoatmElevation, te, refractionCorrection;
|
||||
|
||||
T=jd2jcent(mdy2jd(year, month, day) + timeUTC/1440.0);
|
||||
trueSolarTime = timeUTC + calcEquationOfTime(T) - 4.0 * longitude;
|
||||
hourAngle = trueSolarTime / 4.0 - 180.0;
|
||||
solarDec = calcSunDeclination(T);
|
||||
csz = sin(deg2rad(latitude)) * sin(deg2rad(solarDec)) +
|
||||
cos(deg2rad(latitude)) * cos(deg2rad(solarDec)) *
|
||||
cos(deg2rad(hourAngle));
|
||||
zenith=rad2deg(acos(csz));
|
||||
exoatmElevation = 90.0 - zenith;
|
||||
if (exoatmElevation > 85.0) {
|
||||
refractionCorrection = 0.0;
|
||||
} else {
|
||||
te = tan(deg2rad(exoatmElevation));
|
||||
if (exoatmElevation > 5.0) {
|
||||
refractionCorrection = 58.1/te - 0.07/(te*te*te) +
|
||||
0.000086/(te*te*te*te*te);
|
||||
} else if (exoatmElevation > -0.575) {
|
||||
refractionCorrection = 1735.0 + exoatmElevation*(-518.2 + exoatmElevation*(103.4 + exoatmElevation*(-12.79 + exoatmElevation*0.711)));
|
||||
} else {
|
||||
refractionCorrection = -20.774 / te;
|
||||
}
|
||||
refractionCorrection = refractionCorrection / 3600.0;
|
||||
}
|
||||
return zenith - refractionCorrection;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
double calcSolarZenith(double latitude, double longitude, int year, int month, int day, int timeUTC);
|
|
@ -1,306 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "download.h"
|
||||
#include "getLine.h"
|
||||
#include "diff.h"
|
||||
#include "die.h"
|
||||
#include "subst.h"
|
||||
|
||||
/* Important variables */
|
||||
static char *warning_filename1=NULL;
|
||||
static char *warning_endptr1=NULL;
|
||||
|
||||
static char *filenames[]={
|
||||
"tornado", "flash_flood>warning", "flash_flood>watch",
|
||||
"flash_flood>statement", "flood>warning", "flood>coastal",
|
||||
"flood>statement", "severe_weather_stmt", "special_weather_stmt",
|
||||
"thunderstorm", "special_marine", "urgent_weather_message", "non_precip",
|
||||
"fire_weather", "lake_shore", NULL
|
||||
};
|
||||
static char **reqs[sizeof(filenames)/sizeof(*filenames)-1][2];
|
||||
|
||||
unsigned long current_warnings;
|
||||
static unsigned long *zone_current_warnings;
|
||||
|
||||
/* Regular Expressions */
|
||||
static pcre *expires;
|
||||
static int ovecsize;
|
||||
|
||||
/* prototypes */
|
||||
static int check_warning(char *file);
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
#define compile(var, re) \
|
||||
var=pcre_compile(re, 0, (const char **)&e, &i, NULL); \
|
||||
if(var==NULL) die("init_warnings PCRE error: %s at %i", e, i); \
|
||||
pcre_fullinfo(var, NULL, PCRE_INFO_CAPTURECOUNT, &i); \
|
||||
if(i>ovecsize) ovecsize=i;
|
||||
|
||||
void init_warnings(void){
|
||||
int i, j, z=0;
|
||||
char *e;
|
||||
struct subst_val subs[]={
|
||||
{ 'z', STRING, NULL },
|
||||
{ 'f', STRING, &bigbuf },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* Count zones, and find length of longest */
|
||||
for(i=0; warning_zones[i]!=NULL; i++){
|
||||
j=strlen(warning_zones[i]);
|
||||
if(j>z) z=j;
|
||||
}
|
||||
|
||||
/* Allocate char ptrs for each filename for each zone */
|
||||
for(j=0; filenames[j]!=NULL; j++){
|
||||
reqs[j][0]=malloc(sizeof(char *)*i);
|
||||
reqs[j][1]=malloc(sizeof(char *)*i);
|
||||
if(reqs[j][0]==NULL || reqs[j][1]==NULL) die("init_warnings malloc");
|
||||
}
|
||||
zone_current_warnings=calloc(i, sizeof(*zone_current_warnings));
|
||||
if(zone_current_warnings==NULL) die("init_warnings malloc");
|
||||
|
||||
/* Allocate filename base */
|
||||
e=get_pid_filename("");
|
||||
i=strlen(e);
|
||||
warning_filename1=malloc(i+z+32);
|
||||
if(warning_filename1==NULL)
|
||||
die("init_warnings malloc");
|
||||
|
||||
strcpy(warning_filename1, e);
|
||||
free(e);
|
||||
warning_endptr1=warning_filename1+i;
|
||||
|
||||
/* Setup misc vars */
|
||||
current_warnings=0;
|
||||
ovecsize=0;
|
||||
compile(expires, "Expires:(\\d+)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d);");
|
||||
ovecsize=(ovecsize+1)*3;
|
||||
|
||||
/* Remove stale files, and allocate URIs */
|
||||
for(z=0; warning_zones[z]!=NULL; z++){
|
||||
subs[0].val=warning_zones+z;
|
||||
for(i=0; filenames[i]!=NULL; i++){
|
||||
sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
|
||||
unlink(warning_filename1);
|
||||
sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
|
||||
unlink(warning_filename1);
|
||||
strncpy(bigbuf, filenames[i], BIGBUF_LEN);
|
||||
bigbuf[BIGBUF_LEN-1]='\0';
|
||||
for(j=0; bigbuf[j]; j++){
|
||||
if(bigbuf[j]=='>') bigbuf[j]='/';
|
||||
}
|
||||
if((reqs[i][0][z]=subst(warning_uri, subs))==NULL) die("init_warning");
|
||||
reqs[i][1][z]=NULL;
|
||||
if(warning_post!=NULL && (reqs[i][1][z]=subst(warning_post, subs))==NULL) die("init_warning");
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef compile
|
||||
|
||||
struct callback_data {
|
||||
int zone;
|
||||
int warning;
|
||||
};
|
||||
|
||||
static void warning_callback(char *filename, void *v){
|
||||
struct stat statbuf;
|
||||
struct callback_data *d=(struct callback_data *)v;
|
||||
|
||||
sprintf(warning_endptr1, "%s.%s.txt", warning_zones[d->zone], filenames[d->warning]);
|
||||
if(stat(filename, &statbuf)>=0){
|
||||
if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
|
||||
&& check_warning(filename)
|
||||
&& diff(filename, warning_filename1)){
|
||||
current_warnings|=1<<d->warning;
|
||||
zone_current_warnings[d->zone]|=1<<d->warning;
|
||||
rename(filename, warning_filename1);
|
||||
} else {
|
||||
unlink(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void warnings_cleanup(void){
|
||||
int i, z;
|
||||
|
||||
if(warning_filename1==NULL) return;
|
||||
for(z=0; warning_zones[z]!=NULL; z++){
|
||||
for(i=0; filenames[i]!=NULL; i++){
|
||||
sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
|
||||
unlink(warning_filename1);
|
||||
sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
|
||||
unlink(warning_filename1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_warnings(int force){
|
||||
// time_t t;
|
||||
struct stat statbuf;
|
||||
int i, z;
|
||||
struct callback_data *d;
|
||||
|
||||
if(warning_filename1==NULL) return;
|
||||
// t=time(NULL)/60;
|
||||
// if(!force && warning_time>t) return;
|
||||
|
||||
// warning_time=t+15;
|
||||
|
||||
for(z=0; warning_zones[z]!=NULL; z++){
|
||||
for(i=0; filenames[i]!=NULL; i++){
|
||||
/* expire old wanrings */
|
||||
sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
|
||||
if(stat(warning_filename1, &statbuf)>=0){
|
||||
if(!S_ISREG(statbuf.st_mode) || statbuf.st_size==0
|
||||
|| !check_warning(warning_filename1)){
|
||||
unlink(warning_filename1);
|
||||
current_warnings&=~(1<<i);
|
||||
zone_current_warnings[z]&=~(1<<i);
|
||||
}
|
||||
} else {
|
||||
current_warnings&=~(1<<i);
|
||||
zone_current_warnings[z]&=~(1<<i);
|
||||
}
|
||||
|
||||
if((d=malloc(sizeof(*d)))==NULL) continue;
|
||||
sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
|
||||
d->zone=z;
|
||||
d->warning=i;
|
||||
download_file(warning_filename1, reqs[i][0][z], reqs[i][1][z], DOWNLOAD_NO_404, warning_callback, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define get_substr(n, c) \
|
||||
if(pcre_get_substring(s, ovector, ovalue, n, (const char **)&c)<0){ free(s); return 0; }
|
||||
|
||||
static int check_warning(char *file){
|
||||
FILE *fp;
|
||||
char *s, *c;
|
||||
int len;
|
||||
int i;
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
int ovector[ovecsize];
|
||||
int ovalue;
|
||||
|
||||
if((fp=fopen(file, "r"))==NULL) return 0;
|
||||
ovalue=-1;
|
||||
while((len=getLine(&s, fp))>0){
|
||||
ovalue=pcre_exec(expires, NULL, s, len, 0, 0, ovector, ovecsize);
|
||||
if(ovalue>0) break;
|
||||
free(s);
|
||||
}
|
||||
fclose(fp);
|
||||
if(ovalue<=0) return 0;
|
||||
|
||||
t=time(NULL);
|
||||
tm=gmtime(&t);
|
||||
get_substr(1, c); i=atoi(c)-1900; pcre_free_substring(c);
|
||||
if(tm->tm_year<i){ free(s); return 1; }
|
||||
if(tm->tm_year>i){ free(s); return 0; }
|
||||
get_substr(2, c); i=atoi(c)-1; pcre_free_substring(c);
|
||||
if(tm->tm_mon<i){ free(s); return 1; }
|
||||
if(tm->tm_mon>i){ free(s); return 0; }
|
||||
get_substr(3, c); i=atoi(c); pcre_free_substring(c);
|
||||
if(tm->tm_mday<i){ free(s); return 1; }
|
||||
if(tm->tm_mday>i){ free(s); return 0; }
|
||||
get_substr(4, c); i=atoi(c); pcre_free_substring(c);
|
||||
if(tm->tm_hour<i){ free(s); return 1; }
|
||||
if(tm->tm_hour>i){ free(s); return 0; }
|
||||
get_substr(5, c); i=atoi(c); pcre_free_substring(c);
|
||||
if(tm->tm_min<=i){ free(s); return 1; }
|
||||
free(s); return 0;
|
||||
}
|
||||
|
||||
void output_warnings(int all){
|
||||
FILE *fp;
|
||||
int i, z, len;
|
||||
pid_t pid;
|
||||
int pipefd[2];
|
||||
|
||||
if(!all && current_warnings==0) return;
|
||||
|
||||
if(pipe(pipefd)) die("output_warnings pipe creation");
|
||||
|
||||
/* Fork to display the file */
|
||||
pid=fork();
|
||||
if(pid==-1){
|
||||
warn("output_warnings fork");
|
||||
return;
|
||||
}
|
||||
/* CHILD: Redirects stdin/stderr/stdout and execs the viewer */
|
||||
if(pid==0){
|
||||
close(pipefd[1]);
|
||||
dup2(pipefd[0], STDIN_FILENO);
|
||||
dup2(devnull, STDOUT_FILENO);
|
||||
execl("/bin/sh", "/bin/sh", "-c", viewer, NULL);
|
||||
die("output_warnings exec");
|
||||
}
|
||||
|
||||
/* PARENT writes warnings to the pipe and returns */
|
||||
close(pipefd[0]);
|
||||
for(z=0; warning_zones[z]!=NULL; z++){
|
||||
if(!zone_current_warnings[z]) continue;
|
||||
for(i=0; filenames[i]!=NULL; i++){
|
||||
if(!all && !(zone_current_warnings[z]&(1<<i))) continue;
|
||||
|
||||
sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
|
||||
if((fp=fopen(warning_filename1, "r"))==NULL) continue;
|
||||
snprintf(bigbuf, BIGBUF_LEN, "======== BEGIN %s %s ========\n", warning_zones[z], filenames[i]);
|
||||
write(pipefd[1], bigbuf, strlen(bigbuf));
|
||||
while(!feof(fp)){
|
||||
len=fread(bigbuf, sizeof(char), BIGBUF_LEN, fp);
|
||||
write(pipefd[1], bigbuf, len);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
if(!all) zone_current_warnings[z]=0;
|
||||
}
|
||||
close(pipefd[1]);
|
||||
if(!all) current_warnings=0;
|
||||
return;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
extern unsigned long current_warnings;
|
||||
|
||||
void init_warnings(void);
|
||||
void update_warnings(int force);
|
||||
void output_warnings(int all);
|
||||
void warnings_cleanup(void);
|
|
@ -1,10 +0,0 @@
|
|||
EXTRA_LIBRARIES = libwmgeneral-gtk.a libwmgeneral-x11.a
|
||||
noinst_LIBRARIES = libwmgeneral.a @WMGENERAL_GUI@
|
||||
|
||||
libwmgeneral_a_SOURCES = wmgeneral.c \
|
||||
mouse_regions.c mouse_regions.h rcfile.c rcfile.h
|
||||
|
||||
libwmgeneral_gtk_a_SOURCES = wmgeneral-gtk.c wmgeneral-gtk.h
|
||||
|
||||
libwmgeneral_x11_a_SOURCES = wmgeneral-x11.c wmgeneral-x11.h \
|
||||
xpm_trans.c xpm_trans.h
|
|
@ -1,131 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
wmgeneral was taken from wmppp.
|
||||
|
||||
It has a lot of routines which most of the wm* programs use.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Martijn Pieterse (pieterse@xs4all.nl)
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Moved all the mouse region related stuff to mouse_regions.[ch]
|
||||
|
||||
28/08/2001 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Added EnableMouseRegion and DisableMouseRegion
|
||||
* Got annoyed with the 81-character lines. Fixed it. If you don't like
|
||||
it, find a different copy of wmgeneral.c ;)
|
||||
* GraphicsExpose events are enabled here.
|
||||
* GetXPM is exported. It optionally takes an XpmColorSymbol array.
|
||||
* GetColor is exported.
|
||||
|
||||
30/09/2000 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* You know, wmgen.mask sounds like a much nicer place to store the
|
||||
mask... why don't we do that?
|
||||
|
||||
21/09/1999 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Changed openXwindow to use only the filename, sans path,
|
||||
as the name and class properties of the app.
|
||||
|
||||
14/09/1998 (Dave Clark, clarkd@skyia.com)
|
||||
* Updated createXBMfromXPM routine
|
||||
* Now supports >256 colors
|
||||
11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Removed a bug from parse_rcfile. You could
|
||||
not use "start" in a command if a label was
|
||||
also start.
|
||||
* Changed the needed geometry string.
|
||||
We don't use window size, and don't support
|
||||
negative positions.
|
||||
03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added parse_rcfile2
|
||||
02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added -geometry support (untested)
|
||||
28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added createXBMfromXPM routine
|
||||
* Saves a lot of work with changing xpm's.
|
||||
02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
|
||||
* debugged the parse_rc file.
|
||||
30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Ripped similar code from all the wm* programs,
|
||||
and put them in a single file.
|
||||
|
||||
*/
|
||||
|
||||
#include "mouse_regions.h"
|
||||
|
||||
/*****************/
|
||||
/* Mouse Regions */
|
||||
/*****************/
|
||||
|
||||
typedef struct {
|
||||
int enable;
|
||||
int top;
|
||||
int bottom;
|
||||
int left;
|
||||
int right;
|
||||
} MOUSE_REGION;
|
||||
|
||||
MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
|
||||
|
||||
/******************************************************************************\
|
||||
|* AddMouseRegion *|
|
||||
\******************************************************************************/
|
||||
|
||||
void AddMouseRegion(int index, int left, int top, int right, int bottom) {
|
||||
|
||||
if (index < MAX_MOUSE_REGION) {
|
||||
mouse_region[index].enable = 1;
|
||||
mouse_region[index].top = top;
|
||||
mouse_region[index].left = left;
|
||||
mouse_region[index].bottom = bottom;
|
||||
mouse_region[index].right = right;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* CheckMouseRegion *|
|
||||
\******************************************************************************/
|
||||
|
||||
int CheckMouseRegion(int x, int y) {
|
||||
int i;
|
||||
int found;
|
||||
|
||||
found = 0;
|
||||
|
||||
for (i=0; i<MAX_MOUSE_REGION && !found; i++) {
|
||||
if (mouse_region[i].enable==1 &&
|
||||
x <= mouse_region[i].right &&
|
||||
x >= mouse_region[i].left &&
|
||||
y <= mouse_region[i].bottom &&
|
||||
y >= mouse_region[i].top)
|
||||
found = 1;
|
||||
}
|
||||
if (!found) return -1;
|
||||
return (i-1);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* EnableMouseRegion *|
|
||||
\******************************************************************************/
|
||||
|
||||
void EnableMouseRegion(int i) {
|
||||
if(i<MAX_MOUSE_REGION && mouse_region[i].enable==2)
|
||||
mouse_region[i].enable=1;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* DisableMouseRegion *|
|
||||
\******************************************************************************/
|
||||
|
||||
void DisableMouseRegion(int i) {
|
||||
if(i<MAX_MOUSE_REGION && mouse_region[i].enable==1)
|
||||
mouse_region[i].enable=2;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef MOUSE_REGIONS_H_INCLUDED
|
||||
#define MOUSE_REGIONS_H_INCLUDED
|
||||
|
||||
/***********/
|
||||
/* Defines */
|
||||
/***********/
|
||||
|
||||
#define MAX_MOUSE_REGION (16)
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
/***********************/
|
||||
|
||||
void AddMouseRegion(int index, int left, int top, int right, int bottom);
|
||||
int CheckMouseRegion(int x, int y);
|
||||
void EnableMouseRegion(int index);
|
||||
void DisableMouseRegion(int index);
|
||||
|
||||
#endif
|
|
@ -1,134 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
wmgeneral was taken from wmppp.
|
||||
|
||||
It has a lot of routines which most of the wm* programs use.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Martijn Pieterse (pieterse@xs4all.nl)
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Moved all the rc-file related stuff to rcfile.[ch]
|
||||
|
||||
28/08/2001 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Added EnableMouseRegion and DisableMouseRegion
|
||||
* Got annoyed with the 81-character lines. Fixed it. If you don't like
|
||||
it, find a different copy of wmgeneral.c ;)
|
||||
* GraphicsExpose events are enabled here.
|
||||
* GetXPM is exported. It optionally takes an XpmColorSymbol array.
|
||||
* GetColor is exported.
|
||||
|
||||
30/09/2000 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* You know, wmgen.mask sounds like a much nicer place to store the
|
||||
mask... why don't we do that?
|
||||
|
||||
21/09/1999 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Changed openXwindow to use only the filename, sans path,
|
||||
as the name and class properties of the app.
|
||||
|
||||
14/09/1998 (Dave Clark, clarkd@skyia.com)
|
||||
* Updated createXBMfromXPM routine
|
||||
* Now supports >256 colors
|
||||
11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Removed a bug from parse_rcfile. You could
|
||||
not use "start" in a command if a label was
|
||||
also start.
|
||||
* Changed the needed geometry string.
|
||||
We don't use window size, and don't support
|
||||
negative positions.
|
||||
03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added parse_rcfile2
|
||||
02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added -geometry support (untested)
|
||||
28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added createXBMfromXPM routine
|
||||
* Saves a lot of work with changing xpm's.
|
||||
02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
|
||||
* debugged the parse_rc file.
|
||||
30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Ripped similar code from all the wm* programs,
|
||||
and put them in a single file.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rcfile.h"
|
||||
|
||||
/******************************************************************************\
|
||||
|* parse_rcfile *|
|
||||
\******************************************************************************/
|
||||
|
||||
void parse_rcfile(const char *filename, rckeys *keys) {
|
||||
|
||||
char *p,*q;
|
||||
char temp[128];
|
||||
char *tokens = " :\t\n";
|
||||
FILE *fp;
|
||||
int i,key;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp) {
|
||||
while (fgets(temp, 128, fp)) {
|
||||
key = 0;
|
||||
q = strdup(temp);
|
||||
q = strtok(q, tokens);
|
||||
while (key >= 0 && keys[key].label) {
|
||||
if ((!strcmp(q, keys[key].label))) {
|
||||
p = strstr(temp, keys[key].label);
|
||||
p += strlen(keys[key].label);
|
||||
p += strspn(p, tokens);
|
||||
if ((i = strcspn(p, "#\n"))) p[i] = 0;
|
||||
free(*keys[key].var);
|
||||
*keys[key].var = strdup(p);
|
||||
key = -1;
|
||||
} else key++;
|
||||
}
|
||||
free(q);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* parse_rcfile2 *|
|
||||
\******************************************************************************/
|
||||
|
||||
void parse_rcfile2(const char *filename, rckeys2 *keys) {
|
||||
|
||||
char *p;
|
||||
char temp[128];
|
||||
char *tokens = " :\t\n";
|
||||
FILE *fp;
|
||||
int i,key;
|
||||
char *family = NULL;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp) {
|
||||
while (fgets(temp, 128, fp)) {
|
||||
key = 0;
|
||||
while (key >= 0 && keys[key].label) {
|
||||
if ((p = strstr(temp, keys[key].label))) {
|
||||
p += strlen(keys[key].label);
|
||||
p += strspn(p, tokens);
|
||||
if ((i = strcspn(p, "#\n"))) p[i] = 0;
|
||||
free(*keys[key].var);
|
||||
*keys[key].var = strdup(p);
|
||||
key = -1;
|
||||
} else key++;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
free(family);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef RCFILE_H_INCLUDED
|
||||
#define RCFILE_H_INCLUDED
|
||||
|
||||
/************/
|
||||
/* Typedefs */
|
||||
/************/
|
||||
|
||||
typedef struct _rckeys rckeys;
|
||||
|
||||
struct _rckeys {
|
||||
const char *label;
|
||||
char **var;
|
||||
};
|
||||
|
||||
typedef struct _rckeys2 rckeys2;
|
||||
|
||||
struct _rckeys2 {
|
||||
const char *family;
|
||||
const char *label;
|
||||
char **var;
|
||||
};
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
/***********************/
|
||||
|
||||
void parse_rcfile(const char *, rckeys *);
|
||||
|
||||
#endif
|
|
@ -1,192 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
wmgeneral was taken from wmppp.
|
||||
|
||||
It has a lot of routines which most of the wm* programs use.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Brad Jorsch, anomie@users.sourceforge.net
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
15/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Pulled createXBMfromXPM into its own file, because it's the same in
|
||||
both -gtk and -x11.
|
||||
|
||||
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* This is based on wmgeneral-x11.c (formerly wmgeneral.c), it
|
||||
implements a subset of the interface using Gtk+ 2.0
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "wmgeneral-gtk.h"
|
||||
|
||||
/******************/
|
||||
/* Gtk+ Variables */
|
||||
/******************/
|
||||
|
||||
static GtkWidget *dockwin, *iconwin;
|
||||
static GdkPixmap *pixmap, *mask;
|
||||
static GdkGC *pixmap_gc, *mask_gc;
|
||||
static void (*click_func)(GdkEventButton *ev);
|
||||
|
||||
/******************************************************************************\
|
||||
|* RedrawWindow *|
|
||||
\******************************************************************************/
|
||||
|
||||
void RedrawWindow(void) {
|
||||
gdk_draw_drawable(dockwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
|
||||
gdk_draw_drawable(iconwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
|
||||
}
|
||||
|
||||
static gint redraw_dock(gpointer d){
|
||||
RedrawWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* RedrawWindowXY *|
|
||||
\******************************************************************************/
|
||||
|
||||
void RedrawWindowXY(int x, int y) {
|
||||
gdk_draw_drawable(dockwin->window, pixmap_gc, pixmap, x, y, 0, 0, 64, 64);
|
||||
gdk_draw_drawable(iconwin->window, pixmap_gc, pixmap, x, y, 0, 0, 64, 64);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* copyXPMArea *|
|
||||
\******************************************************************************/
|
||||
|
||||
void copyPixmapArea(int sx, int sy, int w, int h, int dx, int dy){
|
||||
gdk_draw_drawable(pixmap, pixmap_gc, pixmap, sx, sy, dx, dy, w, h);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* copyXBMArea *|
|
||||
\******************************************************************************/
|
||||
|
||||
void copyMaskArea(int sx, int sy, int w, int h, int dx, int dy){
|
||||
gdk_draw_drawable(mask, mask_gc, mask, sx, sy, dx, dy, w, h);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
|* setMaskXY *|
|
||||
\******************************************************************************/
|
||||
|
||||
void setMaskXY(int x, int y) {
|
||||
gtk_widget_shape_combine_mask(dockwin, mask, x, y);
|
||||
gtk_widget_shape_combine_mask(iconwin, mask, x, y);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* setClickCallback *|
|
||||
\******************************************************************************/
|
||||
void setClickCallback(void (*func)(GdkEventButton *ev)){
|
||||
click_func=func;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* openXwindow *|
|
||||
\******************************************************************************/
|
||||
|
||||
static GdkWindow *get_gdk_leader(GdkWindow *win){
|
||||
GdkAtom atom, type;
|
||||
gint len;
|
||||
guchar *data;
|
||||
GdkWindow *leader=NULL;
|
||||
|
||||
atom=gdk_atom_intern("WM_CLIENT_LEADER", TRUE);
|
||||
type=gdk_atom_intern("WINDOW", TRUE);
|
||||
if(atom==GDK_NONE || type==GDK_NONE) return NULL;
|
||||
if(!gdk_property_get(win, atom, type, 0, 4, FALSE, NULL, NULL, &len, &data)) return NULL; if(len==4) leader=gdk_window_foreign_new(*(GdkNativeWindow *)data);
|
||||
g_free(data);
|
||||
return leader;
|
||||
}
|
||||
|
||||
static GdkFilterReturn button_filter(XEvent *x, GdkEvent *ev, gpointer data){
|
||||
/* Bleh, Gdk insists on trying to translate buttons 4-7 into Scroll events.
|
||||
* Which would be ok, except for the part where it just _throws_ _away_ the
|
||||
* releases! Damnit... So, we cheat and change any buttons >3 into
|
||||
* button+4, and change it back in the click handler. */
|
||||
if((x->type==ButtonPress || x->type==ButtonRelease) && x->xbutton.button>3){
|
||||
x->xbutton.button+=4;
|
||||
}
|
||||
return GDK_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
static void dock_click(GtkWidget *w, GdkEventButton *ev, gpointer d){
|
||||
if(ev->button>7) ev->button-=4;
|
||||
if(click_func!=NULL) click_func(ev);
|
||||
}
|
||||
|
||||
#define die(args...) { fprintf(stderr, args); exit(1); }
|
||||
|
||||
void openDockWindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height){
|
||||
GdkColormap *cmap;
|
||||
GdkColor white, black;
|
||||
GdkWindow *leader;
|
||||
XWMHints hints;
|
||||
|
||||
click_func=NULL;
|
||||
if((dockwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
|
||||
if((iconwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
|
||||
gtk_widget_set_size_request(dockwin, 64, 64);
|
||||
gtk_widget_set_size_request(iconwin, 64, 64);
|
||||
gtk_widget_set_app_paintable(dockwin, TRUE);
|
||||
gtk_widget_set_app_paintable(iconwin, TRUE);
|
||||
gtk_widget_add_events(dockwin, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
|
||||
gtk_widget_add_events(iconwin, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
|
||||
g_signal_connect(G_OBJECT(dockwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
|
||||
g_signal_connect(G_OBJECT(iconwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
|
||||
g_signal_connect(G_OBJECT(dockwin), "button-press-event", G_CALLBACK(dock_click), NULL);
|
||||
g_signal_connect(G_OBJECT(iconwin), "button-press-event", G_CALLBACK(dock_click), NULL);
|
||||
g_signal_connect(G_OBJECT(dockwin), "button-release-event", G_CALLBACK(dock_click), NULL);
|
||||
g_signal_connect(G_OBJECT(iconwin), "button-release-event", G_CALLBACK(dock_click), NULL);
|
||||
g_signal_connect(G_OBJECT(dockwin), "destroy", G_CALLBACK(exit), NULL);
|
||||
g_signal_connect(G_OBJECT(iconwin), "destroy", G_CALLBACK(exit), NULL);
|
||||
gtk_widget_realize(dockwin);
|
||||
gtk_widget_realize(iconwin);
|
||||
gdk_window_add_filter(dockwin->window, (GdkFilterFunc)button_filter, NULL);
|
||||
gdk_window_add_filter(iconwin->window, (GdkFilterFunc)button_filter, NULL);
|
||||
if((leader=get_gdk_leader(dockwin->window))==NULL) die("Couldn't obtain Gdk leader window");
|
||||
gdk_window_set_icon(leader, iconwin->window, NULL, NULL);
|
||||
gdk_window_reparent(iconwin->window, leader, 0, 0);
|
||||
gdk_window_unref(leader);
|
||||
|
||||
hints.initial_state = WithdrawnState;
|
||||
hints.flags = StateHint;
|
||||
XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(dockwin->window), &hints);
|
||||
|
||||
cmap=gdk_colormap_get_system();
|
||||
white.red=65535;
|
||||
white.green=65535;
|
||||
white.blue=65535;
|
||||
black.red=0;
|
||||
black.green=0;
|
||||
black.blue=0;
|
||||
gdk_color_alloc(cmap, &white);
|
||||
gdk_color_alloc(cmap, &black);
|
||||
mask=gdk_pixmap_create_from_data(NULL, pixmask_bits, pixmask_width, pixmask_height, 1, &white, &black);
|
||||
pixmap=gdk_pixmap_colormap_create_from_xpm_d(NULL, cmap, NULL, NULL, pixmap_bytes);
|
||||
|
||||
pixmap_gc=gdk_gc_new(iconwin->window);
|
||||
mask_gc=gdk_gc_new(mask);
|
||||
|
||||
setMaskXY(0, 0);
|
||||
RedrawWindow();
|
||||
|
||||
gtk_widget_show(iconwin);
|
||||
gtk_widget_show(dockwin);
|
||||
gdk_window_withdraw(dockwin->window);
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef WMGENERAL_GTK_H_INCLUDED
|
||||
#define WMGENERAL_GTK_H_INCLUDED
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
/***********************/
|
||||
|
||||
void openDockWindow(int argc, char *argv[], char **, char *, int, int);
|
||||
void RedrawWindow(void);
|
||||
void RedrawWindowXY(int x, int y);
|
||||
void setClickCallback(void (*func)(GdkEventButton *ev));
|
||||
|
||||
void createXBMfromXPM(char *, char **, int, int);
|
||||
void copyPixmapArea(int, int, int, int, int, int);
|
||||
void copyMaskArea(int, int, int, int, int, int);
|
||||
void setMaskXY(int, int);
|
||||
|
||||
#endif
|
|
@ -1,343 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
wmgeneral was taken from wmppp.
|
||||
|
||||
It has a lot of routines which most of the wm* programs use.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Martijn Pieterse (pieterse@xs4all.nl)
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
15/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Pulled createXBMfromXPM into its own file, because it's the same in
|
||||
both -gtk and -x11.
|
||||
|
||||
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Removed the rc-file and mouse region stuff to their own files.
|
||||
* Renamed this file to "wmgeneral-x11.c"
|
||||
* Renamed a few of the functions
|
||||
|
||||
28/08/2001 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Added EnableMouseRegion and DisableMouseRegion
|
||||
* Got annoyed with the 81-character lines. Fixed it. If you don't like
|
||||
it, find a different copy of wmgeneral.c ;)
|
||||
* GraphicsExpose events are enabled here.
|
||||
* GetXPM is exported. It optionally takes an XpmColorSymbol array.
|
||||
* GetColor is exported.
|
||||
|
||||
30/09/2000 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* You know, wmgen.mask sounds like a much nicer place to store the
|
||||
mask... why don't we do that?
|
||||
|
||||
21/09/1999 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Changed openXwindow to use only the filename, sans path,
|
||||
as the name and class properties of the app.
|
||||
|
||||
14/09/1998 (Dave Clark, clarkd@skyia.com)
|
||||
* Updated createXBMfromXPM routine
|
||||
* Now supports >256 colors
|
||||
11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Removed a bug from parse_rcfile. You could
|
||||
not use "start" in a command if a label was
|
||||
also start.
|
||||
* Changed the needed geometry string.
|
||||
We don't use window size, and don't support
|
||||
negative positions.
|
||||
03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added parse_rcfile2
|
||||
02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added -geometry support (untested)
|
||||
28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added createXBMfromXPM routine
|
||||
* Saves a lot of work with changing xpm's.
|
||||
02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
|
||||
* debugged the parse_rc file.
|
||||
30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Ripped similar code from all the wm* programs,
|
||||
and put them in a single file.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
#include "wmgeneral-x11.h"
|
||||
|
||||
/*****************/
|
||||
/* X11 Variables */
|
||||
/*****************/
|
||||
|
||||
Window Root;
|
||||
int screen;
|
||||
int x_fd;
|
||||
int d_depth;
|
||||
XSizeHints mysizehints;
|
||||
XWMHints mywmhints;
|
||||
Pixel back_pix, fore_pix;
|
||||
char *Geometry = "";
|
||||
Window iconwin, win;
|
||||
GC NormalGC;
|
||||
GC RedrawGC;
|
||||
XpmIcon wmgen;
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
/***********************/
|
||||
|
||||
void RedrawWindow(void);
|
||||
|
||||
/******************************************************************************\
|
||||
|* GetXPM *|
|
||||
\******************************************************************************/
|
||||
|
||||
void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) {
|
||||
|
||||
XWindowAttributes attributes;
|
||||
int err;
|
||||
|
||||
/* For the colormap */
|
||||
XGetWindowAttributes(display, Root, &attributes);
|
||||
|
||||
wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
|
||||
err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
|
||||
&(wmgen->mask), &(wmgen->attributes));
|
||||
|
||||
if (err != XpmSuccess) {
|
||||
fprintf(stderr, "Not enough free colorcells.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* GetColor *|
|
||||
\******************************************************************************/
|
||||
|
||||
Pixel GetColor(char *name) {
|
||||
|
||||
XColor color;
|
||||
XWindowAttributes attributes;
|
||||
|
||||
XGetWindowAttributes(display, Root, &attributes);
|
||||
|
||||
color.pixel = 0;
|
||||
if (!XParseColor(display, attributes.colormap, name, &color)) {
|
||||
fprintf(stderr, "wm.app: can't parse %s.\n", name);
|
||||
} else if (!XAllocColor(display, attributes.colormap, &color)) {
|
||||
fprintf(stderr, "wm.app: can't allocate %s.\n", name);
|
||||
}
|
||||
return color.pixel;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* flush_expose *|
|
||||
\******************************************************************************/
|
||||
|
||||
static int flush_expose(Window w) {
|
||||
|
||||
XEvent dummy;
|
||||
int i=0;
|
||||
|
||||
while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* RedrawWindow *|
|
||||
\******************************************************************************/
|
||||
|
||||
void RedrawWindow(void) {
|
||||
|
||||
flush_expose(iconwin);
|
||||
XCopyArea(display, wmgen.pixmap, iconwin, RedrawGC,
|
||||
0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
|
||||
flush_expose(win);
|
||||
XCopyArea(display, wmgen.pixmap, win, RedrawGC,
|
||||
0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* RedrawWindowXY *|
|
||||
\******************************************************************************/
|
||||
|
||||
void RedrawWindowXY(int x, int y) {
|
||||
|
||||
flush_expose(iconwin);
|
||||
XCopyArea(display, wmgen.pixmap, iconwin, RedrawGC,
|
||||
x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
|
||||
flush_expose(win);
|
||||
XCopyArea(display, wmgen.pixmap, win, RedrawGC,
|
||||
x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* copyXPMArea *|
|
||||
\******************************************************************************/
|
||||
|
||||
void copyPixmapArea(int x, int y, int sx, int sy, int dx, int dy) {
|
||||
|
||||
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* copyXBMArea *|
|
||||
\******************************************************************************/
|
||||
|
||||
void copyMaskArea(int x, int y, int sx, int sy, int dx, int dy) {
|
||||
|
||||
XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
|* setMaskXY *|
|
||||
\******************************************************************************/
|
||||
|
||||
void setMaskXY(int x, int y) {
|
||||
|
||||
XShapeCombineMask(display, win, ShapeBounding, x, y, wmgen.mask, ShapeSet);
|
||||
XShapeCombineMask(display, iconwin, ShapeBounding, x, y, wmgen.mask, ShapeSet);
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
|* openXwindow *|
|
||||
\******************************************************************************/
|
||||
void openDockWindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height) {
|
||||
|
||||
unsigned int borderwidth = 1;
|
||||
XClassHint classHint;
|
||||
char *display_name = NULL;
|
||||
char *wname;
|
||||
XTextProperty name;
|
||||
|
||||
XGCValues gcv;
|
||||
unsigned long gcm;
|
||||
|
||||
char *geometry = NULL;
|
||||
|
||||
int dummy=0;
|
||||
int i, wx, wy;
|
||||
|
||||
wname=strrchr(argv[0], '/');
|
||||
if(wname==NULL) wname=argv[0];
|
||||
else wname++;
|
||||
|
||||
for (i=1; argv[i]; i++) {
|
||||
if (!strcmp(argv[i], "-display")) {
|
||||
display_name = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
if (!strcmp(argv[i], "-geometry")) {
|
||||
geometry = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(display = XOpenDisplay(display_name))) {
|
||||
fprintf(stderr, "%s: can't open display %s\n",
|
||||
wname, XDisplayName(display_name));
|
||||
exit(1);
|
||||
}
|
||||
screen = DefaultScreen(display);
|
||||
Root = RootWindow(display, screen);
|
||||
d_depth = DefaultDepth(display, screen);
|
||||
x_fd = XConnectionNumber(display);
|
||||
|
||||
/* Convert XPM to XImage */
|
||||
GetXPM(&wmgen, pixmap_bytes);
|
||||
|
||||
/* Create a window to hold the stuff */
|
||||
mysizehints.flags = USSize | USPosition;
|
||||
mysizehints.x = 0;
|
||||
mysizehints.y = 0;
|
||||
|
||||
back_pix = GetColor("white");
|
||||
fore_pix = GetColor("black");
|
||||
|
||||
XWMGeometry(display, screen, Geometry, NULL, borderwidth, &mysizehints,
|
||||
&mysizehints.x, &mysizehints.y,&mysizehints.width,&mysizehints.height, &dummy);
|
||||
|
||||
mysizehints.width = 64;
|
||||
mysizehints.height = 64;
|
||||
|
||||
win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
|
||||
mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
|
||||
|
||||
iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
|
||||
mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
|
||||
|
||||
/* Activate hints */
|
||||
XSetWMNormalHints(display, win, &mysizehints);
|
||||
classHint.res_name = wname;
|
||||
classHint.res_class = wname;
|
||||
XSetClassHint(display, win, &classHint);
|
||||
|
||||
XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
|
||||
XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
|
||||
|
||||
if (XStringListToTextProperty(&wname, 1, &name) == 0) {
|
||||
fprintf(stderr, "%s: can't allocate window name\n", wname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XSetWMName(display, win, &name);
|
||||
|
||||
/* Create GC for drawing */
|
||||
|
||||
gcm = GCForeground | GCBackground | GCGraphicsExposures;
|
||||
gcv.foreground = fore_pix;
|
||||
gcv.background = back_pix;
|
||||
gcv.graphics_exposures = True;
|
||||
NormalGC = XCreateGC(display, Root, gcm, &gcv);
|
||||
gcv.graphics_exposures = False;
|
||||
RedrawGC = XCreateGC(display, Root, gcm, &gcv);
|
||||
|
||||
/* ONLYSHAPE ON */
|
||||
|
||||
if(pixmask_bits!=NULL){
|
||||
XFreePixmap(display, wmgen.mask);
|
||||
wmgen.mask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
|
||||
}
|
||||
|
||||
XShapeCombineMask(display, win, ShapeBounding, 0, 0, wmgen.mask, ShapeSet);
|
||||
XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, wmgen.mask, ShapeSet);
|
||||
|
||||
/* ONLYSHAPE OFF */
|
||||
|
||||
mywmhints.initial_state = WithdrawnState;
|
||||
mywmhints.icon_window = iconwin;
|
||||
mywmhints.icon_x = mysizehints.x;
|
||||
mywmhints.icon_y = mysizehints.y;
|
||||
mywmhints.window_group = win;
|
||||
mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
|
||||
|
||||
XSetWMHints(display, win, &mywmhints);
|
||||
|
||||
XSetCommand(display, win, argv, argc);
|
||||
XMapWindow(display, win);
|
||||
|
||||
if (geometry) {
|
||||
if (sscanf(geometry, "+%d+%d", &wx, &wy) != 2) {
|
||||
fprintf(stderr, "Bad geometry string.\n");
|
||||
exit(1);
|
||||
}
|
||||
XMoveWindow(display, win, wx, wy);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef WMGENERAL_X11_H_INCLUDED
|
||||
#define WMGENERAL_X11_H_INCLUDED
|
||||
|
||||
#include <X11/xpm.h>
|
||||
|
||||
/************/
|
||||
/* Typedefs */
|
||||
/************/
|
||||
|
||||
typedef struct {
|
||||
Pixmap pixmap;
|
||||
Pixmap mask;
|
||||
XpmAttributes attributes;
|
||||
} XpmIcon;
|
||||
|
||||
/*******************/
|
||||
/* Global variable */
|
||||
/*******************/
|
||||
|
||||
Display *display;
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
/***********************/
|
||||
|
||||
void openDockWindow(int argc, char *argv[], char **, char *, int, int);
|
||||
void RedrawWindow(void);
|
||||
void RedrawWindowXY(int x, int y);
|
||||
|
||||
Pixel GetColor(char *);
|
||||
void GetXPM(XpmIcon *, char **);
|
||||
void createXBMfromXPM(char *, char **, int, int);
|
||||
void copyPixmapArea(int, int, int, int, int, int);
|
||||
void copyMaskArea(int, int, int, int, int, int);
|
||||
void setMaskXY(int, int);
|
||||
|
||||
#endif
|
|
@ -1,124 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
wmgeneral was taken from wmppp.
|
||||
|
||||
It has a lot of routines which most of the wm* programs use.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Martijn Pieterse (pieterse@xs4all.nl)
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
15/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Updated createXBMfromXPM to handle the case where the XBM is to be
|
||||
wider than the XPM, or the XBM width is not a multiple of 8.
|
||||
* Pulled createXBMfromXPM into its own file, because it's the same in
|
||||
both -gtk and -x11.
|
||||
|
||||
11/08/2002 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Removed the rc-file and mouse region stuff to their own files.
|
||||
* Renamed this file to "wmgeneral-x11.c"
|
||||
* Renamed a few of the functions
|
||||
|
||||
28/08/2001 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Added EnableMouseRegion and DisableMouseRegion
|
||||
* Got annoyed with the 81-character lines. Fixed it. If you don't like
|
||||
it, find a different copy of wmgeneral.c ;)
|
||||
* GraphicsExpose events are enabled here.
|
||||
* GetXPM is exported. It optionally takes an XpmColorSymbol array.
|
||||
* GetColor is exported.
|
||||
|
||||
30/09/2000 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* You know, wmgen.mask sounds like a much nicer place to store the
|
||||
mask... why don't we do that?
|
||||
|
||||
21/09/1999 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Changed openXwindow to use only the filename, sans path,
|
||||
as the name and class properties of the app.
|
||||
|
||||
14/09/1998 (Dave Clark, clarkd@skyia.com)
|
||||
* Updated createXBMfromXPM routine
|
||||
* Now supports >256 colors
|
||||
11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Removed a bug from parse_rcfile. You could
|
||||
not use "start" in a command if a label was
|
||||
also start.
|
||||
* Changed the needed geometry string.
|
||||
We don't use window size, and don't support
|
||||
negative positions.
|
||||
03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added parse_rcfile2
|
||||
02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added -geometry support (untested)
|
||||
28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Added createXBMfromXPM routine
|
||||
* Saves a lot of work with changing xpm's.
|
||||
02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
|
||||
* debugged the parse_rc file.
|
||||
30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
|
||||
* Ripped similar code from all the wm* programs,
|
||||
and put them in a single file.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/******************************************************************************\
|
||||
|* createXBMfromXPM *|
|
||||
\******************************************************************************/
|
||||
void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy) {
|
||||
|
||||
int i,j,k;
|
||||
int width, height, numcol, depth;
|
||||
int zero=0;
|
||||
unsigned char bwrite;
|
||||
int bcount;
|
||||
int curpixel;
|
||||
|
||||
while(sx&7){ sx++; }
|
||||
|
||||
sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
|
||||
width*=depth;
|
||||
|
||||
for (k=0; k!=depth; k++)
|
||||
{
|
||||
zero <<=8;
|
||||
zero |= xpm[1][k];
|
||||
}
|
||||
|
||||
for (i=numcol+1; i < numcol+sy+1; i++) {
|
||||
bcount = 0;
|
||||
bwrite = 0;
|
||||
for (j=0; j<sx*depth; j+=depth) {
|
||||
bwrite >>= 1;
|
||||
|
||||
if(j<width){
|
||||
curpixel=0;
|
||||
for (k=0; k!=depth; k++)
|
||||
{
|
||||
curpixel <<=8;
|
||||
curpixel |= xpm[i][j+k];
|
||||
}
|
||||
} else {
|
||||
curpixel=zero;
|
||||
}
|
||||
|
||||
if ( curpixel != zero ) {
|
||||
bwrite += 128;
|
||||
}
|
||||
bcount++;
|
||||
if (bcount == 8) {
|
||||
*xbm = bwrite;
|
||||
xbm++;
|
||||
bcount = 0;
|
||||
bwrite = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
#include "../config.h"
|
||||
|
||||
/*
|
||||
Best viewed with vim5, using ts=4
|
||||
|
||||
An add-on to wmgeneral to copy XPM areas with transparency and opacity.
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
Author: Brad Jorsch (anomie@users.sourceforge.net)
|
||||
|
||||
---
|
||||
CHANGES:
|
||||
---
|
||||
16/08/2001 (Brad Jorsch, anomie@users.sourceforge.net)
|
||||
* Wrote these routines.
|
||||
|
||||
*/
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "wmgeneral-x11.h"
|
||||
|
||||
extern int screen;
|
||||
extern XpmIcon wmgen;
|
||||
extern GC NormalGC;
|
||||
|
||||
static int get_shift(unsigned mask){
|
||||
int i=0;
|
||||
|
||||
while(!mask&1){
|
||||
mask>>=1;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void combineWithTrans(int sx, int sy, unsigned w, unsigned h, int dx, int dy){
|
||||
XImage *pix, *mask;
|
||||
unsigned int ww, hh, bar;
|
||||
int foo;
|
||||
Window baz;
|
||||
unsigned x, y;
|
||||
|
||||
XGetGeometry(display, wmgen.pixmap, &baz, &foo, &foo, &ww, &hh, &bar, &bar);
|
||||
pix=XGetImage(display, wmgen.pixmap, 0, 0, ww, hh, AllPlanes, ZPixmap);
|
||||
XGetGeometry(display, wmgen.mask, &baz, &foo, &foo, &ww, &hh, &bar, &bar);
|
||||
mask=XGetImage(display, wmgen.mask, 0, 0, ww, hh, AllPlanes, ZPixmap);
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
if(!XGetPixel(mask, sx+x, sy+y)) continue;
|
||||
XPutPixel(pix, dx+x, dy+y, XGetPixel(pix, sx+x, sy+y));
|
||||
}
|
||||
}
|
||||
XPutImage(display, wmgen.pixmap, NormalGC, pix, 0, 0, 0, 0, pix->width, pix->height);
|
||||
|
||||
XDestroyImage(pix);
|
||||
XDestroyImage(mask);
|
||||
}
|
||||
|
||||
void combineWithOpacity(int sx, int sy, unsigned w, unsigned h, int dx, int dy, int o){
|
||||
XImage *pix, *mask;
|
||||
unsigned int ww, hh, bar;
|
||||
int foo;
|
||||
Window baz;
|
||||
int rmask, gmask, bmask;
|
||||
int rshift, gshift, bshift;
|
||||
unsigned long spixel, dpixel;
|
||||
unsigned x, y;
|
||||
int c_o;
|
||||
|
||||
if(o==0) return;
|
||||
if(o==256){
|
||||
combineWithTrans(sx, sy, w, h, dx, dy);
|
||||
return;
|
||||
}
|
||||
|
||||
XGetGeometry(display, wmgen.pixmap, &baz, &foo, &foo, &ww, &hh, &bar, &bar);
|
||||
pix=XGetImage(display, wmgen.pixmap, 0, 0, ww, hh, AllPlanes, ZPixmap);
|
||||
XGetGeometry(display, wmgen.mask, &baz, &foo, &foo, &ww, &hh, &bar, &bar);
|
||||
mask=XGetImage(display, wmgen.mask, 0, 0, ww, hh, AllPlanes, ZPixmap);
|
||||
|
||||
if (pix->depth == DefaultDepth(display, screen)) {{
|
||||
Visual *visual=DefaultVisual(display, screen);
|
||||
rmask = visual->red_mask;
|
||||
gmask = visual->green_mask;
|
||||
bmask = visual->blue_mask;
|
||||
}} else {
|
||||
rmask = pix->red_mask;
|
||||
gmask = pix->green_mask;
|
||||
bmask = pix->blue_mask;
|
||||
}
|
||||
|
||||
c_o=256-o;
|
||||
rshift=get_shift(rmask);
|
||||
gshift=get_shift(gmask);
|
||||
bshift=get_shift(bmask);
|
||||
/* NOTE: >>s then <<s to prevent overflow when multiplying opacity */
|
||||
#define AVG(m, s) ((((((spixel&m)>>s)*o+((dpixel&m)>>s)*c_o)>>8)<<s)&m)
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
if(!XGetPixel(mask, sx+x, sy+y)) continue;
|
||||
spixel=XGetPixel(pix, sx+x, sy+y);
|
||||
if(!XGetPixel(mask, dx+x, dy+y)){
|
||||
XPutPixel(pix, dx+x, dy+y, spixel);
|
||||
} else {
|
||||
dpixel=XGetPixel(pix, dx+x, dy+y);
|
||||
XPutPixel(pix, dx+x, dy+y,
|
||||
AVG(rmask, rshift) |
|
||||
AVG(gmask, gshift) |
|
||||
AVG(bmask, bshift));
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef AVG
|
||||
XPutImage(display, wmgen.pixmap, NormalGC, pix, 0, 0, 0, 0, pix->width, pix->height);
|
||||
|
||||
XDestroyImage(pix);
|
||||
XDestroyImage(mask);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
/* Like copyXPMArea, but only copies non-masked pixels */
|
||||
void combineWithTrans(int sx, int sy, unsigned w, unsigned h, int dx, int dy);
|
||||
|
||||
/* Like combineWithTrans, except it combines pixels by this formula:
|
||||
* new = (src * o + dest * (256 - o)) / 256
|
||||
*/
|
||||
void combineWithOpacity(int sx, int sy, unsigned w, unsigned h, int dx, int dy, int o);
|
|
@ -1,418 +0,0 @@
|
|||
.de Sh
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.TH wmweather+ 1x "@DATE@"
|
||||
.SH NAME
|
||||
wmweather+ \- A dock app for displaying weather information
|
||||
.P
|
||||
.SH SYNOPSIS
|
||||
.B wmweather+
|
||||
.RB [\| options \|]
|
||||
.SH DESCRIPTION
|
||||
\fBwmweather+\fP downloads current conditions, forecast data, and optionally a
|
||||
radar image. It will also watch for various warnings and display them using an
|
||||
external command.
|
||||
.SH OPTIONS
|
||||
Note that later options override earlier ones, and command line options
|
||||
override configuration file options. All multi-character options may be
|
||||
specified with one or two leading dashes. The configuration file is simply one
|
||||
option (with value if necessary) per line, leading dashes optional. Empty lines
|
||||
and lines beginning with the '#' character are ignored.
|
||||
.SS General Options
|
||||
.TP
|
||||
.BI "-display " <display\ name>
|
||||
Name of display to use.
|
||||
.TP
|
||||
.BI "-c " <file>
|
||||
Specify a configuration file instead of the default. This option is ignored in
|
||||
the configuration file.
|
||||
.TP
|
||||
.BI "-display-mode " <string>
|
||||
Specify the starting display mode. Valid values are "cur"/"current",
|
||||
"fcst"/"forecast", and "map"/"radar".
|
||||
.TP
|
||||
.BI "-location " <latitude+longitude>
|
||||
Specify a latitude and longitude, for example "41'59'00N 87'55'00W" or
|
||||
"N41.9833333333333 W87.9166666666667". You may use either the decimal or DMS
|
||||
notation, with either a prefixed sign or a prefixed or suffixed N/S/E/W. If
|
||||
this option isn't given, the program will assume you live on the equator and
|
||||
guess your longitude based on your system timezone offset.
|
||||
.TP
|
||||
.BR "-e\fR,\fP\ -email " <address>
|
||||
Specify the anonymous FTP password.
|
||||
.TP
|
||||
.BR -v ", " -version
|
||||
Display version number and exit.
|
||||
.TP
|
||||
.BI "-viewer " <program>
|
||||
External program for viewing weather warnings. This command must take the text
|
||||
to display from standard input. It will be executed as '/bin/sh -c
|
||||
\fI<program>\fP' with stdout redirected to /dev/null. If not specified, it will
|
||||
default to "xless".
|
||||
.TP
|
||||
.BR -animate ", " -noanimate
|
||||
Turn animation on or off. Animation may still be toggled with the middle mouse
|
||||
button as described below. The default is on.
|
||||
.SS Station Options
|
||||
.TP
|
||||
.BI "-s\fR,\fP\ -station " <ID>
|
||||
Station ID for all stations. Equivalent to
|
||||
.RI "'-metar-station " <ID> " -avn-station " <ID>
|
||||
.RI " -eta-station " <ID> " -mrf-station " <ID> '.
|
||||
.TP
|
||||
.BI "-metar-station " <ID>
|
||||
Station ID for METAR observations. See \fBCurrent Conditions\fP for more
|
||||
information. A value must be provided.
|
||||
.TP
|
||||
.BI "-avn-station " <ID>
|
||||
Station ID for AVN forecasts. See \fBForecasts\fP for more information.
|
||||
.TP
|
||||
.BI "-eta-station " <ID>
|
||||
Station ID for ETA forecasts. See \fBForecasts\fP for more information.
|
||||
.TP
|
||||
.BI "-mrf-station " <ID>
|
||||
Station ID for MRF forecasts. See \fBForecasts\fP for more information.
|
||||
.TP
|
||||
.BI "-warning-zone " <zoneID>
|
||||
Zone ID for weather warnings. See \fBWarnings\fP for more information. This
|
||||
option may be repeated for multiple zones.
|
||||
.TP
|
||||
.BI "-forget-warning-zones"
|
||||
Cause wmweather+ to forget all warning zones found to this point. Useful for
|
||||
user configuration files to override the warning zones specified in the
|
||||
system-wide configuration.
|
||||
.P
|
||||
.BI "-metar-uri " <URI>
|
||||
.br
|
||||
.BI "-avn-uri " <URI>
|
||||
.br
|
||||
.BI "-eta-uri " <URI>
|
||||
.br
|
||||
.BI "-mrf-uri " <URI>
|
||||
.br
|
||||
.BI "-warning-uri " <URI>
|
||||
.RS
|
||||
URI to download the specified data from. See \fBURIs\fP for more information.
|
||||
.RE
|
||||
.P
|
||||
.BI "-metar-post " <DATA>
|
||||
.br
|
||||
.BI "-avn-post " <DATA>
|
||||
.br
|
||||
.BI "-eta-post " <DATA>
|
||||
.br
|
||||
.BI "-mrf-post " <DATA>
|
||||
.br
|
||||
.BI "-warning-post " <DATA>
|
||||
.RS
|
||||
Post data for downloading the specified data. See \fBURIs\fP for more
|
||||
information. Note that the post option must follow the corresponding URI
|
||||
option. Note that the post data will \fInot\fP be URL-encoded for you.
|
||||
.RE
|
||||
.TP
|
||||
.B -noradar
|
||||
Do not display a radar image. This is the default.
|
||||
.P
|
||||
.BI "-radar-uri " <URI>
|
||||
.br
|
||||
.BI "-radar-post " <DATA>
|
||||
.RS
|
||||
Retrieve an image from the specified URI. See \fBRadar Map\fP for more
|
||||
information.
|
||||
.RE
|
||||
.TP
|
||||
.BI "-radar-crop " <string>
|
||||
How to crop the radar image.
|
||||
.IR X x Y + W + H
|
||||
format. See \fBRadar Map\fP for more information.
|
||||
.TP
|
||||
.BI "-radar-cross " <string>
|
||||
Where to draw radar crosshairs.
|
||||
.IR X x Y
|
||||
format. See \fBRadar Map\fP for more
|
||||
information.
|
||||
.SS Measurement Options
|
||||
.TP
|
||||
.BR -m ", " -metric
|
||||
Same as '-cm -hPa -kph -tempc'.
|
||||
.TP
|
||||
.B -in
|
||||
Display precipitation amounts in inches. This is the default.
|
||||
.TP
|
||||
.B -cm
|
||||
Display precipitation amounts in centimeters.
|
||||
.TP
|
||||
.B -inHg
|
||||
Display pressure in inches of mercury. This is the default.
|
||||
.TP
|
||||
.BR -hPa ", " -mbar
|
||||
Display pressure in hectopascal (millibars)
|
||||
.TP
|
||||
.B -mmHg
|
||||
Display pressure in millimeters of mercury.
|
||||
.TP
|
||||
.B -atm
|
||||
Display pressure in atmospheres.
|
||||
.TP
|
||||
.B -mph
|
||||
Display windspeed in miles/hour. This is the default.
|
||||
.TP
|
||||
.B -kph
|
||||
Display windspeed in kilometers/hour.
|
||||
.TP
|
||||
.B -knots
|
||||
Display windspeed in knots.
|
||||
.TP
|
||||
.B -mps
|
||||
Display windspeed in meters/second.
|
||||
.TP
|
||||
.B -beaufort
|
||||
Display windspeed on the Beaufort scale.
|
||||
.TP
|
||||
.B -tempf
|
||||
Display temperature in degrees Fahrenheit. This is the default.
|
||||
.TP
|
||||
.B -tempc
|
||||
Display temperature in degrees Celcius.
|
||||
.SH DISPLAY
|
||||
The dockapp has three display modes: Current Conditions, Forecasts, and Radar
|
||||
Map. Modes are selected by the buttons across the top of the icon. Weather
|
||||
Warning status is indicated by the font color. At any point
|
||||
double-(left)clicking the main display will send SIGUSR1 to the process (see
|
||||
\fBSIGNALS\fP).
|
||||
.Sh "Current Conditions"
|
||||
This mode displays the current conditions as given in the METAR report for the
|
||||
selected station, as downloaded from
|
||||
.UR http://weather.noaa.gov/pub/data/observations/metar/stations/
|
||||
http://weather.noaa.gov/pub/data/observations/metar/stations/
|
||||
.UE
|
||||
.RI .
|
||||
Downloads are attempted every 15 minutes. Find your station at
|
||||
.UR http://www.nws.noaa.gov/tg/siteloc.shtml
|
||||
http://www.nws.noaa.gov/tg/siteloc.shtml
|
||||
.UE
|
||||
.RI .
|
||||
.P
|
||||
The station ID is displayed at the top left of the display. The observation
|
||||
date (local) is to the right, and the time (local and UTC) occupies the line
|
||||
below. Under that, to the right is the temperature and relative humidity, the
|
||||
wind direction and speed, the atmospheric pressure (indicated by "P"), the
|
||||
heat index (indicated by "HI"), and the wind chill (indicated by "WC").
|
||||
.P
|
||||
To the left is a graphical display of the current weather. The sky condition is
|
||||
indicated as clear (sun), partly cloudy (sun with small clouds), mostly cloudy
|
||||
(sun behind a large cloud), or overcast (large cloud). This image may be
|
||||
covered by fog (foggy overlay), dust/sand/haze (brownish particles), or blowing
|
||||
snow/dust/sand (blue wind-lines), with the level of transparency indicating the
|
||||
degree of visibility. If a funnel cloud or tornado was reported, a tornado
|
||||
graphic will be displayed instead of the sky condition.
|
||||
.P
|
||||
Beneath this graphic, icons will depict rain (raindrop), snow (snowflake),
|
||||
freezing precipitation (hailstones), and thunderstorms (lightning bolt). If
|
||||
animation is enabled, the icons will appear and vanish on a ten second cycle
|
||||
to indicate precipitation intensity. Animation may be enabled or disabled by
|
||||
middle-clicking the display.
|
||||
.Sh Forecasts
|
||||
This mode displays the current conditions as given in the AVN, ETA, and MRF
|
||||
data for the selected stations, as downloaded from
|
||||
.UR http://www.nws.noaa.gov/tdl/synop/products/bullform.mav.htm
|
||||
http://www.nws.noaa.gov/tdl/synop/products/bullform.mav.htm
|
||||
.UE
|
||||
.RI ,
|
||||
.UR http://www.nws.noaa.gov/mdl/synop/products/bullform.met.htm
|
||||
http://www.nws.noaa.gov/mdl/synop/products/bullform.met.htm
|
||||
.UE
|
||||
and
|
||||
.UR http://www.nws.noaa.gov/tdl/synop/products/bullform.mex.htm
|
||||
http://www.nws.noaa.gov/tdl/synop/products/bullform.mex.htm
|
||||
.UE
|
||||
.RI .
|
||||
AVN and ETA reports are downloaded at startup, 0000Z, and 1200Z. MRF reports
|
||||
are downloaded at startup and 0000Z. In the event of failure, downloads will be
|
||||
retried every 15 minutes. See the URIs given to find your stations.
|
||||
.P
|
||||
The display is divided into two sections. A small window at the top indicates
|
||||
the date and hour (local time) for which this forecast is valid. Left-clicking
|
||||
this window or clicking the small arrow-button to the right will advance to
|
||||
the next forecast; right-clicking or clicking the small arrow-button to the
|
||||
left will move to the previous forecast. Middle-clicking will return to the
|
||||
first forecast in the list.
|
||||
.P
|
||||
The larger display at the bottom shows the forecast for the selected date and
|
||||
time. To the right from top to bottom are the station ID, the daily high and
|
||||
low temperatures, the predicted temperature and relative humidity, and the
|
||||
wind direction and speed. The final line may display the heat index (HI), the
|
||||
wind chill (WC), the amount of snow to fall in that period (SN), the amount of
|
||||
liquid-equivalent precipitation to fall in that period (P), or the forecast
|
||||
type (e.g. "AVN" or "MRF").
|
||||
.P
|
||||
To the left is a weather display similar to that for the Current Conditions.
|
||||
The animation here indicates the percent chance of rain, snow, freezing
|
||||
precipitation, thunderstorms, and severe thunderstorms (large lightning bolt).
|
||||
Animation may be turned on or off with the middle button. When animation is
|
||||
off, the mouse wheel may be used to adjust the cutoff chance for the display
|
||||
(hold Shift to adjust faster). The cutoff will be displayed briefly when first
|
||||
turning off animation, when first displaying forecasts, whenever button 6
|
||||
(typically, the 'side' button) is held down in the large display. Permanent
|
||||
cutoff display may be toggled by double-middle-clicking the large display.
|
||||
.Sh "Radar Map"
|
||||
The radar image will be downloaded every 30 minutes from the URI specified.
|
||||
Then, if -radar-crop was specified in the form
|
||||
.IR X x Y + W + H ,
|
||||
a subimage of witdh \fIW\fP and height \fIH\fP will be taken, with the
|
||||
upper-left pixel taken from
|
||||
.RI ( X ", " Y ).
|
||||
If \fIX\fP or \fIY\fP is negative, it will be measured from the right/bottom of
|
||||
the image instead of the top/left. The image is then resized to fit within the
|
||||
52x40 rectangle available. A border around the image indicates the current font
|
||||
color. If -radar-cross was specified in the form
|
||||
.IR X x Y ,
|
||||
crosshairs will then be
|
||||
drawn over the pixel
|
||||
.RI ( X ", " Y )
|
||||
when the middle button is held on the radar map.
|
||||
.P
|
||||
If -noradar was specified or no radar data is available, an image to that
|
||||
effect will be displayed instead.
|
||||
.P
|
||||
Some nice images are available from
|
||||
.UR http://weather.noaa.gov/radar/mosaic/DS.p19r0/ar.us.conus.shtml
|
||||
http://weather.noaa.gov/radar/mosaic/DS.p19r0/ar.us.conus.shtml
|
||||
.UE
|
||||
and
|
||||
.UR http://www.weather.com/common/home/maps.html
|
||||
http://www.weather.com/common/home/maps.html
|
||||
.UE
|
||||
.RI .
|
||||
Be kind, since the display is so small pick the smallest version of the image
|
||||
to download.
|
||||
.Sh "Weather Warnings"
|
||||
Various weather warnings, watches, and statements for the specified zone are
|
||||
downloaded from
|
||||
.UR http://weather.noaa.gov/pub/data/watches_warnings/
|
||||
http://weather.noaa.gov/pub/data/watches_warnings/
|
||||
.UE
|
||||
.RI .
|
||||
Downloads are attempted at the same time METAR observations are retrieved. Find
|
||||
your zone at
|
||||
.UR http://weather.noaa.gov/
|
||||
http://weather.noaa.gov/
|
||||
.UE
|
||||
or
|
||||
.UR http://weather.gov/
|
||||
http://weather.gov/
|
||||
.UE
|
||||
.RI .
|
||||
Note that some areas issue weather warnings by multiple geopolitical units
|
||||
(e.g. "zones" and "counties"). The -warning-zone option may be specified
|
||||
multiple times, so all appropriate files may be inspected.
|
||||
.P
|
||||
If any new warnings are downloaded, all text will be displayed in an
|
||||
orange/red scheme instead of the normal blue/orange. The new warnings may then
|
||||
be viewed by left-clicking the large display window in any mode. At any point,
|
||||
all current warnings may be displayed by right-clicking the large display.
|
||||
.SH "URIs"
|
||||
The URIs from which the various observations, forecasts, and images are
|
||||
downloaded can be easily customized by supplying values for the various
|
||||
.I -*-uri
|
||||
options. The following substitution variables are available:
|
||||
.TP
|
||||
.B %s
|
||||
The station ID for the specified data type (note that warnings have no station
|
||||
ID).
|
||||
.TP
|
||||
.B %z
|
||||
The zone ID, for warnings.
|
||||
.TP
|
||||
.B %f
|
||||
The warning type, for warnings (e.g. "tornado", "special_weather_stmt").
|
||||
.P
|
||||
The substitutions can be manipulated with the standard
|
||||
.BR printf (3)
|
||||
modifiers for strings, in particular the
|
||||
.BR # ", " 0 ", " - ", "
|
||||
.BR "' '" ", " + ", and " '
|
||||
flags, the
|
||||
.BR "field width" ,
|
||||
and the
|
||||
.B precision
|
||||
fields are accepted. Also, an additional flag
|
||||
.B !
|
||||
is recognized to use the capitalized versions of various numeric flags (e.g.
|
||||
\fBX\fP versus \fBx\fP) and to capitalize character or string values, and an
|
||||
additional syntax
|
||||
.BI ">" "<offset>"
|
||||
after the precision is recognized to start at an offset into the string value
|
||||
(negative values indicate offset from the end of the string).
|
||||
.P
|
||||
The current defaults are:
|
||||
.TP
|
||||
metar-uri
|
||||
.nf
|
||||
http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT
|
||||
.fi
|
||||
.TP
|
||||
avn-uri
|
||||
.nf
|
||||
http://www.nws.noaa.gov/cgi-bin/mos/getmav.pl?sta=%s
|
||||
.fi
|
||||
.TP
|
||||
eta-uri
|
||||
.nf
|
||||
http://www.nws.noaa.gov/cgi-bin/mos/getmet.pl?sta=%s
|
||||
.fi
|
||||
.TP
|
||||
mrf-uri
|
||||
.nf
|
||||
http://www.nws.noaa.gov/cgi-bin/mos/getmex.pl?sta=%s
|
||||
.fi
|
||||
.TP
|
||||
warning-uri
|
||||
.nf
|
||||
http://weather.noaa.gov/pub/data/watches_warnings/%f/%.2z/%z.txt
|
||||
.fi
|
||||
.SH FILES
|
||||
.TP
|
||||
.I $HOME/.wmweather+/
|
||||
Directory used to store downloaded data files. These files may be deleted at
|
||||
any time.
|
||||
.TP
|
||||
.I $HOME/.wmweather+/conf
|
||||
User configuration.
|
||||
.TP
|
||||
.I /etc/wmweather+.conf
|
||||
System configuration.
|
||||
.TP
|
||||
.I $HOME/.wmweather+/.dir-test
|
||||
Created and deleted to test write access to \fI$HOME/.wmweather+/\fP
|
||||
.SH SIGNALS
|
||||
.TP
|
||||
.I SIGUSR1
|
||||
Forces downloads for the current mode to be attempted immediately.
|
||||
.TP
|
||||
.I SIGUSR2
|
||||
Forces all downloads to be attempted immediately.
|
||||
.SH BUGS
|
||||
Before reporting a bug, please check the HINTS file (in particular,
|
||||
proxy instructions are in that file). Also, please verify that you have
|
||||
the latest version of wmweather+, and that your bug has not already been
|
||||
reported. Bugs may be filed at
|
||||
.UR http://sourceforge.net/tracker/?group_id=60336&atid=493854
|
||||
http://sourceforge.net/tracker/?group_id=60336&atid=493854
|
||||
.UE
|
||||
.RI .
|
||||
.SH AUTHORS
|
||||
\fBwmweather+\fP was written by \fIBrad Jorsch
|
||||
<anomie@users.sourceforge.net>\fP, using the wmgeneral code by \fIMartijn
|
||||
Pieterse <pieterse@xs4all.nl>\fP.
|
||||
.P
|
||||
Email regarding wmweather+ should be sent to
|
||||
\fIanomie@users.sourceforge.net\fP.
|
||||
.SH INSPIRATION
|
||||
wmWeather was a good idea, but it didn't give me enough information. However,
|
||||
no code from wmWeather was used in writing wmweather+.
|
|
@ -1,822 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
/* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#if TM_IN_SYS_TIME
|
||||
# if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "wmweather+.h"
|
||||
#include "convert.h"
|
||||
#include "download.h"
|
||||
#include "dock.h"
|
||||
#include "die.h"
|
||||
#include "animation.h"
|
||||
|
||||
|
||||
char *ProgName;
|
||||
char *bigbuf;
|
||||
int devnull;
|
||||
char *monthnames[]={ "", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
|
||||
char *monthnames2[]={ "", "", "", "", "", "", "JUNE", "JULY", "", "SEPT", "", "", "" };
|
||||
char *wdaynames[]={ "SUNDAY", "MONDAY", "TUESDAY", "WEDN'SDAY", "THURSDAY", "FRIDAY", "SATURDAY"};
|
||||
char *directions[]={"VRB", "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
|
||||
|
||||
char *error;
|
||||
char *unknown_option="Unknown option";
|
||||
|
||||
#define F(a) fprintf(stderr, a "\n");
|
||||
|
||||
/***************************************************
|
||||
* Configuration parameters
|
||||
***************************************************/
|
||||
char *email_address=NULL;
|
||||
char *metar_station=NULL;
|
||||
char *metar_uri=NULL;
|
||||
char *metar_post=NULL;
|
||||
char **warning_zones=NULL;
|
||||
char *warning_uri=NULL;
|
||||
char *warning_post=NULL;
|
||||
char *avn_station=NULL;
|
||||
char *avn_uri=NULL;
|
||||
char *avn_post=NULL;
|
||||
char *eta_station=NULL;
|
||||
char *eta_uri=NULL;
|
||||
char *eta_post=NULL;
|
||||
char *mrf_station=NULL;
|
||||
char *mrf_uri=NULL;
|
||||
char *mrf_post=NULL;
|
||||
char *radar_uri=NULL;
|
||||
char *radar_post=NULL;
|
||||
char *radar_crop=NULL;
|
||||
char *radar_cross=NULL;
|
||||
char *viewer=NULL;
|
||||
int pressure_mode=0;
|
||||
int windspeed_mode=0;
|
||||
int temp_mode=0;
|
||||
int length_mode=0;
|
||||
double latitude=999, longitude=999;
|
||||
int start_do_animation=1;
|
||||
int starting_mode=0;
|
||||
|
||||
|
||||
/**********************************
|
||||
* Prototypes
|
||||
**********************************/
|
||||
void usage(int i) __THROW __attribute__ ((__noreturn__));
|
||||
void printversion(void);
|
||||
int readconf(char *file);
|
||||
int parse_option(char *option, char *value);
|
||||
char *get_filename(char *file);
|
||||
|
||||
/**********************************
|
||||
* Functions
|
||||
**********************************/
|
||||
|
||||
void sigchld(int i){
|
||||
while(waitpid(-1, NULL, WNOHANG)>0);
|
||||
}
|
||||
|
||||
int parse_option(char *option, char *value){
|
||||
int i;
|
||||
void *v;
|
||||
|
||||
errno=0;
|
||||
error=unknown_option;
|
||||
if(option[0]=='-') option++;
|
||||
if(option[0]=='-' && option[1]!='\0' && option[2]!='\0') option++;
|
||||
if(option[0]=='\0') return 0;
|
||||
if(value!=NULL && value[0]=='\0') value=NULL;
|
||||
|
||||
switch (option[0]){
|
||||
case 'a':
|
||||
if(!strncmp(option, "avn-", 4)){
|
||||
if(!strcmp(option+4, "station")){
|
||||
if(value==NULL){
|
||||
error="avn-station given with no station ID";
|
||||
return 0;
|
||||
}
|
||||
if(avn_station!=NULL) free(avn_station);
|
||||
avn_station=strdup(value);
|
||||
if(avn_station==NULL) die("avn-station strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "uri")){
|
||||
if(value==NULL){
|
||||
error="avn-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(avn_uri!=NULL) free(avn_uri);
|
||||
avn_uri=strdup(value);
|
||||
if(avn_uri==NULL) die("avn-uri strdup");
|
||||
if(avn_post!=NULL) free(avn_post);
|
||||
avn_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "post")){
|
||||
if(value==NULL){
|
||||
error="avn-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(avn_uri==NULL){
|
||||
error="avn-post must come after avn-uri";
|
||||
return 0;
|
||||
}
|
||||
if(avn_post!=NULL) free(avn_post);
|
||||
avn_post=strdup(value);
|
||||
if(avn_post==NULL) die("avn-post strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
} else if(!strcmp(option, "atm")){
|
||||
pressure_mode=3;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "animate")){
|
||||
start_do_animation=1;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if(!strcmp(option, "beaufort")){
|
||||
windspeed_mode=4;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if(option[1]=='\0') return 2; /* -c handled earlier */
|
||||
else if(!strcmp(option, "cm")){
|
||||
length_mode=1;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if(!strcmp(option, "display-mode")){
|
||||
if(value==NULL){
|
||||
error="display-mode given with no mode specified";
|
||||
return 0;
|
||||
}
|
||||
if(!strcasecmp(value, "cur") || !strcasecmp(value, "current")){
|
||||
starting_mode=0;
|
||||
return 2;
|
||||
} else if(!strcasecmp(value, "fcst") || !strcasecmp(value, "forecast")){
|
||||
starting_mode=1;
|
||||
return 2;
|
||||
} else if(!strcasecmp(value, "map") || !strcasecmp(value, "radar")){
|
||||
starting_mode=2;
|
||||
return 2;
|
||||
} else {
|
||||
error="display-mode given with unrecognized mode";
|
||||
return 0;
|
||||
}
|
||||
} else if(!strcmp(option, "display")){
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
if(!strncmp(option, "eta-", 4)){
|
||||
if(!strcmp(option+4, "station")){
|
||||
if(value==NULL){
|
||||
error="eta-station given with no station ID";
|
||||
return 0;
|
||||
}
|
||||
if(eta_station!=NULL) free(eta_station);
|
||||
eta_station=strdup(value);
|
||||
if(eta_station==NULL) die("eta-station strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "uri")){
|
||||
if(value==NULL){
|
||||
error="eta-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(eta_uri!=NULL) free(eta_uri);
|
||||
eta_uri=strdup(value);
|
||||
if(eta_uri==NULL) die("eta-uri strdup");
|
||||
if(eta_post!=NULL) free(eta_post);
|
||||
eta_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "post")){
|
||||
if(value==NULL){
|
||||
error="eta-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(eta_uri==NULL){
|
||||
error="eta-post must come after eta-uri";
|
||||
return 0;
|
||||
}
|
||||
if(eta_post!=NULL) free(eta_post);
|
||||
eta_post=strdup(value);
|
||||
if(eta_post==NULL) die("eta-post strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
} else if(option[1]=='\0' || !strcmp(option, "email")){
|
||||
if(value==NULL){
|
||||
error="-e/email given with no address";
|
||||
return 0;
|
||||
}
|
||||
if(email_address!=NULL) free(email_address);
|
||||
email_address=strdup(value);
|
||||
if(email_address==NULL) die("email strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if(!strncmp(option, "forget-", 7)){
|
||||
if(!strcmp(option+7, "warning-zones")){
|
||||
if(warning_zones) free(warning_zones);
|
||||
warning_zones=NULL;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
if(!strcmp(option, "hPa")){
|
||||
pressure_mode=1;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if(!strcmp(option, "inHg")){
|
||||
pressure_mode=0;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "in")){
|
||||
length_mode=0;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
if(!strcmp(option, "kph")){
|
||||
windspeed_mode=1;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "knots")){
|
||||
windspeed_mode=2;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if(!strcmp(option, "location")){
|
||||
if(value==NULL){
|
||||
error="location given with no value";
|
||||
return 0;
|
||||
}
|
||||
if(!str2dd(value, &latitude, &longitude)){
|
||||
error="location should be of the form \"dd'mm'ssN dd'mm'ssW\" or \"dd.ddddN dd.dddddW\"\n Note that, if you're using '-location' on the command line, you will need\n to quote the value, e.g. '-location \"dd.ddddN dd.dddddW\"'";
|
||||
return 0;
|
||||
}
|
||||
if(latitude>90 || latitude<-90 || longitude>180 || longitude<-180){
|
||||
error="latitude or longitude out of range";
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if(option[1]=='\0' || !strcmp(option, "metric")){
|
||||
pressure_mode=windspeed_mode=temp_mode=length_mode=1;
|
||||
return 1;
|
||||
} else if(!strncmp(option, "metar-", 6)){
|
||||
if(!strcmp(option+6, "station")){
|
||||
if(value==NULL){
|
||||
error="metar-station given with no station ID";
|
||||
return 0;
|
||||
}
|
||||
if(metar_station!=NULL) free(metar_station);
|
||||
metar_station=strdup(value);
|
||||
if(metar_station==NULL) die("metar-station strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+6, "uri")){
|
||||
if(value==NULL){
|
||||
error="metar-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(metar_uri!=NULL) free(metar_uri);
|
||||
metar_uri=strdup(value);
|
||||
if(metar_uri==NULL) die("metar-uri strdup");
|
||||
if(metar_post!=NULL) free(metar_post);
|
||||
metar_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+6, "post")){
|
||||
if(value==NULL){
|
||||
error="metar-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(metar_uri==NULL){
|
||||
error="metar-post must come after metar-uri";
|
||||
return 0;
|
||||
}
|
||||
if(metar_post!=NULL) free(metar_post);
|
||||
metar_post=strdup(value);
|
||||
if(metar_post==NULL) die("metar-post strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
} else if(!strncmp(option, "mrf-", 4)){
|
||||
if(!strcmp(option+4, "station")){
|
||||
if(value==NULL){
|
||||
error="mrf-station given with no station ID";
|
||||
return 0;
|
||||
}
|
||||
if(mrf_station!=NULL) free(mrf_station);
|
||||
mrf_station=strdup(value);
|
||||
if(mrf_station==NULL) die("mrf-station strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "uri")){
|
||||
if(value==NULL){
|
||||
error="mrf-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(mrf_uri!=NULL) free(mrf_uri);
|
||||
mrf_uri=strdup(value);
|
||||
if(mrf_uri==NULL) die("mrf-uri strdup");
|
||||
if(mrf_post!=NULL) free(mrf_post);
|
||||
mrf_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+4, "post")){
|
||||
if(value==NULL){
|
||||
error="mrf-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(mrf_uri==NULL){
|
||||
error="mrf-post must come after mrf-uri";
|
||||
return 0;
|
||||
}
|
||||
if(mrf_post!=NULL) free(mrf_post);
|
||||
mrf_post=strdup(value);
|
||||
if(mrf_post==NULL) die("mrf-post strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
} else if(!strcmp(option, "mmHg")){
|
||||
pressure_mode=2;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "mph")){
|
||||
windspeed_mode=0;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "mps")){
|
||||
windspeed_mode=3;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "mbar")){
|
||||
pressure_mode=1;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if(!strcmp(option, "noradar")){
|
||||
if(radar_uri!=NULL) free(radar_uri);
|
||||
radar_uri=NULL;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "noanimate")){
|
||||
start_do_animation=0;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if(!strcmp(option, "radar")){
|
||||
warn("'radar' is deprecated, please use 'radar-uri' instead");
|
||||
return parse_option("radar-uri", value);
|
||||
} else if(!strncmp(option, "radar-", 6)){
|
||||
if(!strcmp(option+6, "uri")){
|
||||
if(value==NULL){
|
||||
error="radar-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(radar_uri!=NULL) free(radar_uri);
|
||||
radar_uri=strdup(value);
|
||||
if(radar_uri==NULL) die("radar-uri strdup");
|
||||
if(radar_post!=NULL) free(radar_post);
|
||||
radar_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+6, "post")){
|
||||
if(value==NULL){
|
||||
error="radar-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(radar_uri==NULL){
|
||||
error="radar-post must come after radar-uri";
|
||||
return 0;
|
||||
}
|
||||
if(radar_post!=NULL) free(radar_post);
|
||||
radar_post=strdup(value);
|
||||
if(radar_post==NULL) die("radar-post strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+6, "crop")){
|
||||
if(value==NULL){
|
||||
error="radar-crop given with no value";
|
||||
return 0;
|
||||
}
|
||||
if(radar_crop!=NULL) free(radar_crop);
|
||||
radar_crop=strdup(value);
|
||||
if(radar_crop==NULL) die("radar-crop strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+6, "cross")){
|
||||
if(value==NULL){
|
||||
error="radar-cross given with no value";
|
||||
return 0;
|
||||
}
|
||||
if(radar_cross!=NULL) free(radar_cross);
|
||||
radar_cross=strdup(value);
|
||||
if(radar_cross==NULL) die("radar-cross strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if(option[1]=='\0' || !strcmp(option, "station")){
|
||||
if(value==NULL){
|
||||
error="-s/station given with no value";
|
||||
return 0;
|
||||
}
|
||||
if(parse_option("metar-station", value)==2
|
||||
&& parse_option("avn-station", value)==2
|
||||
&& parse_option("eta-station", value)==2
|
||||
&& parse_option("mrf-station", value)==2)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if(!strcmp(option, "tempf")){
|
||||
temp_mode=0;
|
||||
return 1;
|
||||
} else if(!strcmp(option, "tempc")){
|
||||
temp_mode=1;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if(option[1]=='\0' || !strcmp(option, "version")){
|
||||
printversion();
|
||||
exit(0);
|
||||
} else if(!strcmp(option, "viewer")){
|
||||
if(value==NULL){
|
||||
error="viewer given with no value";
|
||||
return 0;
|
||||
}
|
||||
if(viewer!=NULL) free(viewer);
|
||||
viewer=strdup(value);
|
||||
if(viewer==NULL) die("viewer strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
if(!strncmp(option, "warning-", 8)){
|
||||
if(!strcmp(option+8, "zone")){
|
||||
if(value==NULL){
|
||||
error="warning-zone given with no zone ID";
|
||||
return 0;
|
||||
}
|
||||
if(warning_zones!=NULL){
|
||||
for(i=0; warning_zones[i]!=NULL; i++);
|
||||
} else {
|
||||
i=0;
|
||||
}
|
||||
v=realloc(warning_zones, sizeof(*warning_zones)*(i+2));
|
||||
if(v==NULL) die("warning-zone realloc");
|
||||
warning_zones=v;
|
||||
warning_zones[i+1]=NULL;
|
||||
warning_zones[i]=strdup(value);
|
||||
if(warning_zones[i]==NULL) die("warning-zone strdup");
|
||||
return 2;
|
||||
} else if(!strcmp(option+8, "uri")){
|
||||
if(value==NULL){
|
||||
error="warning-uri given with no URI";
|
||||
return 0;
|
||||
}
|
||||
if(warning_uri!=NULL) free(warning_uri);
|
||||
warning_uri=strdup(value);
|
||||
if(warning_uri==NULL) die("warning-uri strdup");
|
||||
if(warning_post!=NULL) free(warning_post);
|
||||
warning_post=NULL;
|
||||
return 2;
|
||||
} else if(!strcmp(option+8, "post")){
|
||||
if(value==NULL){
|
||||
error="warning-post given with no data";
|
||||
return 0;
|
||||
}
|
||||
if(warning_uri==NULL){
|
||||
error="warning-post must come after warning-uri";
|
||||
return 0;
|
||||
}
|
||||
if(warning_post!=NULL) free(warning_post);
|
||||
warning_post=strdup(value);
|
||||
if(warning_post==NULL) die("warning-post strdup");
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
if(!strcmp(option, "zone")){
|
||||
warn("'zone' is deprecated, please use 'warning-zone' instead");
|
||||
return parse_option("warning-zone", value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readconf(char *file){
|
||||
char *c, *d;
|
||||
int i, l, flag=1;
|
||||
FILE *fp;
|
||||
|
||||
if(file==NULL){
|
||||
flag=0;
|
||||
file=get_filename("conf");
|
||||
}
|
||||
|
||||
if((fp=fopen(file, "r"))==NULL){
|
||||
if(!flag){
|
||||
free(file);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
l=0;
|
||||
while(fgets(bigbuf, BIGBUF_LEN, fp)!=NULL){
|
||||
l++;
|
||||
for(i=strlen(bigbuf)-1; i>=0; i--){
|
||||
if (!isspace(bigbuf[i])) break;
|
||||
bigbuf[i]='\0';
|
||||
}
|
||||
c=bigbuf+strspn(bigbuf, " \t");
|
||||
if(*c=='#' || *c=='\0') continue;
|
||||
d=c+strcspn(c, " \t");
|
||||
if(*d=='\0') d=NULL;
|
||||
else {
|
||||
*d='\0';
|
||||
d++;
|
||||
d+=strspn(d+1, " \t");
|
||||
if(*d=='\0') d=NULL;
|
||||
}
|
||||
if(!parse_option(c, d)){
|
||||
warn("%s[%d]: %s", file, l, error);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
if(!flag) free(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_dir(void){
|
||||
char *c;
|
||||
struct stat statbuf;
|
||||
int i;
|
||||
|
||||
c=get_filename("");
|
||||
i=stat(c, &statbuf);
|
||||
if(i<0){
|
||||
if(errno==ENOENT){
|
||||
if(mkdir(c, 0777)<0) die("Couldn't create directory %s", c);
|
||||
errno=0;
|
||||
warn("Created directory %s", c);
|
||||
i=stat(c, &statbuf);
|
||||
}
|
||||
if(i<0) die("Couldn't stat %s", c);
|
||||
}
|
||||
if(!S_ISDIR(statbuf.st_mode)) die("%s is not a directory", c);
|
||||
free(c);
|
||||
c=get_filename(".dir-test");
|
||||
if(unlink(c)<0 && errno!=ENOENT) die("Couldn't delete %s", c);
|
||||
if((i=stat(c, &statbuf))!=-1 || errno!=ENOENT){
|
||||
if(i!=-1) errno=EEXIST;
|
||||
die("Couldn't verify nonexistence of %s", c);
|
||||
}
|
||||
if((i=creat(c, 0))<0) die("Couldn't create %s", c);
|
||||
close(i);
|
||||
if(stat(c, &statbuf)<0) die("Couldn't stat %s", c);
|
||||
unlink(c);
|
||||
free(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sigint(int i){
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i, j;
|
||||
char *c;
|
||||
|
||||
ProgName = argv[0];
|
||||
if((c=strrchr(ProgName, '/'))!=NULL && *(c+1)!='\0'){
|
||||
ProgName=c+1;
|
||||
}
|
||||
|
||||
if((bigbuf=malloc(BIGBUF_LEN))==NULL) die("bigbuf malloc");
|
||||
check_dir();
|
||||
|
||||
devnull=open("/dev/null", O_RDWR);
|
||||
if(devnull<0) die("opening /dev/null");
|
||||
/* Parse Command Line */
|
||||
|
||||
c=NULL;
|
||||
for(i=1;i<argc;i++){
|
||||
if(!strcmp(argv[i], "-c")){
|
||||
i++;
|
||||
if(!(i<argc)){
|
||||
F("-c given with no value");
|
||||
exit(1);
|
||||
}
|
||||
c=argv[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(readconf("/etc/wmweather+.conf")>1) exit(1);
|
||||
if((i=readconf(c))==1) warn("Couldn't open %s", c);
|
||||
if(i) exit(1);
|
||||
|
||||
for(i=1;i<argc;i++){
|
||||
char *arg = argv[i];
|
||||
|
||||
if(*arg=='-'){
|
||||
j=parse_option(argv[i], (i+1<argc)?argv[i+1]:NULL);
|
||||
if(j==0){
|
||||
if(error==unknown_option) usage(1);
|
||||
fprintf(stderr, "%s\n", error);
|
||||
exit(1);
|
||||
}
|
||||
i+=j-1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct sigaction act;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_handler=sigchld;
|
||||
act.sa_flags=SA_RESTART;
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
act.sa_handler=sigint;
|
||||
sigaction(SIGINT, &act, NULL);
|
||||
}
|
||||
|
||||
i=0;
|
||||
if(metar_station==NULL){
|
||||
i=1;
|
||||
F("Please specify a METAR station.\n See http://www.nws.noaa.gov/tg/siteloc.shtml\n");
|
||||
}
|
||||
if(latitude==999){{
|
||||
time_t t;
|
||||
int flag=0;
|
||||
|
||||
/* note: if time_t isn't an arithmetic type, mkgmtime is screwed
|
||||
* anyway. So t=0 is as appropriate as anything else. */
|
||||
t=0;
|
||||
longitude=-mkgmtime(localtime(&t))/240.0;
|
||||
latitude=0;
|
||||
if(longitude<0){
|
||||
flag=1;
|
||||
longitude=-longitude;
|
||||
}
|
||||
fprintf(stderr, "-location not given. Guessing you're at 0N %d'%d'%d%c\n", (int)longitude, (int)(longitude*60)%60, (int)(longitude*3600)%60, flag?'E':'W');
|
||||
if(flag) longitude=-longitude;
|
||||
}} else if(latitude>89.8){
|
||||
F("Latitude greater then 89.9N automatically truncated.\n");
|
||||
latitude=89.8;
|
||||
} else if(latitude<-89.8){
|
||||
F("Latitude greater then 89.9S automatically truncated.\n");
|
||||
latitude=-89.8;
|
||||
}
|
||||
if(i) exit(1);
|
||||
if(viewer==NULL) viewer="xless";
|
||||
if(metar_uri==NULL) metar_uri="http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT";
|
||||
if(avn_uri==NULL) avn_uri="http://www.nws.noaa.gov/cgi-bin/mos/getmav.pl?sta=%s";
|
||||
if(eta_uri==NULL) eta_uri="http://www.nws.noaa.gov/cgi-bin/mos/getmet.pl?sta=%s";
|
||||
if(mrf_uri==NULL) mrf_uri="http://www.nws.noaa.gov/cgi-bin/mos/getmex.pl?sta=%s";
|
||||
if(warning_uri==NULL) warning_uri="http://weather.noaa.gov/pub/data/watches_warnings/%f/%.2z/%z.txt";
|
||||
|
||||
download_init(email_address);
|
||||
init_dock(argc, argv);
|
||||
while(1){
|
||||
update_dock();
|
||||
download_process(100000);
|
||||
}
|
||||
}
|
||||
|
||||
void usage(int i) {
|
||||
F("Option Value Description");
|
||||
F("------ ----- -----------");
|
||||
F("-c <file> Specify a configuration file");
|
||||
F("-e <address> Alias for -email");
|
||||
F("-email <address> Specify anonymous FTP password");
|
||||
F("-location <lat+lon> Specify latitude and longitude. See manpage.");
|
||||
F("-v Alias for -version");
|
||||
F("-version Display version number");
|
||||
F("-viewer <program> Program to display text from stdin");
|
||||
F("-[no]animate Turn animation on or off");
|
||||
F("");
|
||||
F("-s <ID> Alias for -station");
|
||||
F("-station <ID> Station ID (all stations)");
|
||||
F("-metar-station <ID> Station ID for METAR observations");
|
||||
F("-avn-station <ID> Station ID for AVN forecasts");
|
||||
F("-eta-station <ID> Station ID for ETA forecasts");
|
||||
F("-mrf-station <ID> Station ID for MRF forecasts");
|
||||
F("-warning-zone <zoneID> Zone ID for weather warnings");
|
||||
F("-*-uri <URI> URI for the weather data (see docs for details)");
|
||||
F("-*-post <DATA> Post data for the weather data (see docs)");
|
||||
F(" '*' can be metar, avn, eta, mrf, warning");
|
||||
F("-noradar Do not display a radar image.");
|
||||
F("-radar-uri <URI> URI for radar image");
|
||||
F("-radar-post <DATA> Post data for radar image");
|
||||
F("-radar-crop <string> How to crop the radar image. XxY+W+H format.");
|
||||
F("-radar-cross <string> Where to draw radar crosshairs. XxY format.");
|
||||
F("");
|
||||
F("-m Alias for -metric");
|
||||
F("-metric Same as -cm -hPa -kph -tempc");
|
||||
F("");
|
||||
F("-in Display precipitation amounts in inches");
|
||||
F("-cm Display precipitation amounts in centimeters");
|
||||
F("");
|
||||
F("-inHg Display pressure in inHg");
|
||||
F("-hPa Display pressure in hPa (millibars)");
|
||||
F("-mbar Alias for -hPa");
|
||||
F("-mmHg Display pressure in mmHg");
|
||||
F("-atm Display pressure in atmospheres");
|
||||
F("");
|
||||
F("-mph Display windspeed in miles/hour");
|
||||
F("-kph Display windspeed in kilometers/hour");
|
||||
F("-knots Display windspeed in knots");
|
||||
F("-mps Display windspeed in meters/second");
|
||||
F("-beaufort Display windspeed on the Beaufort scale");
|
||||
F("");
|
||||
F("-tempf Display temperature in degrees Fahrenheit");
|
||||
F("-tempc Display temperature in degrees Celcius");
|
||||
|
||||
exit(i);
|
||||
}
|
||||
|
||||
void printversion(void) {
|
||||
fprintf(stderr, "%s\n", VERSION);
|
||||
}
|
||||
|
||||
char *get_filename(char *file){
|
||||
char *f, *c;
|
||||
|
||||
c=getenv("HOME");
|
||||
if((f=malloc(strlen(c)+strlen(file)+14))==NULL) die("get_filename");
|
||||
strcpy(f, c);
|
||||
strcat(f, "/.wmweather+/");
|
||||
strcat(f, file);
|
||||
return f;
|
||||
}
|
||||
|
||||
char *get_pid_filename(char *file){
|
||||
char *f, *c;
|
||||
static unsigned short seq=0;
|
||||
char buf[15];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%08X.%04X-", getpid(), seq++);
|
||||
c=getenv("HOME");
|
||||
if((f=malloc(strlen(c)+strlen(file)+14+14))==NULL) die("get_pid_filename");
|
||||
strcpy(f, c);
|
||||
strcat(f, "/.wmweather+/");
|
||||
strcat(f, buf);
|
||||
strcat(f, file);
|
||||
return f;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#define BIGBUF_LEN 4096
|
||||
|
||||
char *get_filename(char *file);
|
||||
char *get_pid_filename(char *file);
|
||||
|
||||
extern char *ProgName;
|
||||
extern int devnull;
|
||||
extern char *bigbuf;
|
||||
extern char *monthnames[];
|
||||
extern char *monthnames2[];
|
||||
extern char *wdaynames[];
|
||||
extern char *directions[];
|
||||
|
||||
extern char *email_address;
|
||||
extern char *metar_station;
|
||||
extern char *metar_uri;
|
||||
extern char *metar_post;
|
||||
extern char **warning_zones;
|
||||
extern char *warning_uri;
|
||||
extern char *warning_post;
|
||||
extern char *avn_station;
|
||||
extern char *avn_uri;
|
||||
extern char *avn_post;
|
||||
extern char *eta_station;
|
||||
extern char *eta_uri;
|
||||
extern char *eta_post;
|
||||
extern char *mrf_station;
|
||||
extern char *mrf_uri;
|
||||
extern char *mrf_post;
|
||||
extern char *radar_uri;
|
||||
extern char *radar_post;
|
||||
extern char *radar_crop;
|
||||
extern char *radar_cross;
|
||||
extern char *viewer;
|
||||
extern int pressure_mode;
|
||||
extern int windspeed_mode;
|
||||
extern int temp_mode;
|
||||
extern int length_mode;
|
||||
extern double latitude, longitude;
|
||||
extern int start_do_animation;
|
||||
extern int starting_mode;
|
|
@ -1,221 +0,0 @@
|
|||
/* XPM */
|
||||
static char * wmweather_master_xpm[] = {
|
||||
"190 129 89 1",
|
||||
" c None",
|
||||
". c #F6F2FE",
|
||||
"+ c #82828A",
|
||||
"@ c #AEAAAE",
|
||||
"# c #020202",
|
||||
"$ c #AAAAAA",
|
||||
"% c #C6C6C6",
|
||||
"& c #CACACA",
|
||||
"* c #1EC2FE",
|
||||
"= c #FE7E7E",
|
||||
"- c #FEFEFE",
|
||||
"; c #FEC202",
|
||||
"> c #B2B2B2",
|
||||
", c #B6B6B6",
|
||||
"' c #767602",
|
||||
") c #C2C202",
|
||||
"! c #FEFA02",
|
||||
"~ c #FEDA02",
|
||||
"{ c #FEFE02",
|
||||
"] c #828202",
|
||||
"^ c #AEAEAF",
|
||||
"/ c #DADADA",
|
||||
"( c #E6E6E6",
|
||||
"_ c #FAFAFA",
|
||||
": c #F2F2F2",
|
||||
"< c #6A5E22",
|
||||
"[ c #D2D2D2",
|
||||
"} c #EAEAEA",
|
||||
"| c #CECECE",
|
||||
"1 c #C2C2C2",
|
||||
"2 c #9AFEFA",
|
||||
"3 c #DEDEDE",
|
||||
"4 c #E2E2E2",
|
||||
"5 c #06021A",
|
||||
"6 c #060216",
|
||||
"7 c #22222A",
|
||||
"8 c #767677",
|
||||
"9 c #D6D6D6",
|
||||
"0 c #828282",
|
||||
"a c #090616",
|
||||
"b c #45464B",
|
||||
"c c #9E9E9F",
|
||||
"d c #929293",
|
||||
"e c #969696",
|
||||
"f c #A2A2A2",
|
||||
"g c #A6A6A6",
|
||||
"h c #5D5E61",
|
||||
"i c #0A0A16",
|
||||
"j c #EEEEEE",
|
||||
"k c #4E4E4E",
|
||||
"l c #9A9A99",
|
||||
"m c #6A6A6B",
|
||||
"n c #626265",
|
||||
"o c #7C7C7A",
|
||||
"p c #F6F6F6",
|
||||
"q c #36363A",
|
||||
"r c #65666A",
|
||||
"s c #565656",
|
||||
"t c #6E6E6F",
|
||||
"u c #89898A",
|
||||
"v c #727273",
|
||||
"w c #161622",
|
||||
"x c #7F7E7E",
|
||||
"y c #8E8E8D",
|
||||
"z c #BABABA",
|
||||
"A c #504F52",
|
||||
"B c #4A4A4B",
|
||||
"C c #5A5A5E",
|
||||
"D c #505056",
|
||||
"E c #BEBEBE",
|
||||
"F c #1E1D21",
|
||||
"G c #EAEAE6",
|
||||
"H c #FA02FE",
|
||||
"I c #323232",
|
||||
"J c #028AFE",
|
||||
"K c #0296FE",
|
||||
"L c #029AFE",
|
||||
"M c #027AFE",
|
||||
"N c #0286FE",
|
||||
"O c #0276FE",
|
||||
"P c #0266E2",
|
||||
"Q c #029EFE",
|
||||
"R c #026EF5",
|
||||
"S c #0292FE",
|
||||
"T c #0282FE",
|
||||
"U c #027EFE",
|
||||
"V c #026AEE",
|
||||
"W c #0262DE",
|
||||
"X c #025ED2",
|
||||
" .................+.................+.................+ ",
|
||||
" .@@@@@@@@@@@@@@@@#.@@@@@@@@@@@@@@@@#.@@@@@@@@@@@@@@@@# ",
|
||||
" .$$$##$#$#$##$$$$#.$###$$##$##$###$#.$$##$##$$#$$##$$# ",
|
||||
" .@@#$$@#@#@#$#@@@#.@#$$@#$$@#$@$#$@#.@@#$#$#@#$#@#$#@# ",
|
||||
" ######################################################## ######################################################## .$$#@$$#$#$##$$$$#.$##$$#@$$##@$#$$#.$$#$#$#$###$##$$# ",
|
||||
" #.................+.................+.................+% #.................+.................+.................+% .@@#$@@#@#@#$#@@@#.@#$@@#$@@$#$@#@@#.@@#@#@#@#$#@#$@@# ",
|
||||
" #.$$$$$$$$$$$$$$$$#.$$$$$$$$$$$$$$$$#.$$$$$$$$$$$$$$$$#& #.$$$$$$$$$$$$$$$$#.$$$$$$$$$$$$$$$$#.$$$$$$$$$$$$$$$$#& .$$@##$###$#$#$$$#.$#$$$@##@##$$#$$#.$$#$#$#$#$#$#$$$# ",
|
||||
" #.@@@##@#@#@##@@@@#.@###@@##@##@###@#.@@##@##@@#@@##@@#% #.@@@##@#@#@##@@@@#.@###@@##@##@###@#.@@##@##@@#@@##@@#% .@@$$$@$$$@$@$@@@#.@$@@@$$$$$$@@$@@#.@@$@$@$@$@$@$@@@# ",
|
||||
" #.$$#$$$#$#$#$#$$$#.$#$$$#$$$#$$$#$$#.$$#$#$#$#$#$#$#$#& #.$$#$$$#$#$#$#$$$#.$#$$$#$$$#$$$#$$#.$$#$#$#$#$#$#$#$#& +#################+#################+################# ",
|
||||
" #.@@#@@@#@#@##$@@@#.@##@@#@@@##@@#@@#.@@#@#@#@###@##$@#% #.@@#@@@#@#@##$@@@#.@##@@#@@@##@@#@@#.@@#@#@#@###@##$@#% #################+#################+#################+ ",
|
||||
" #.$$#$$$#$#$#@#$$$#.$#$$$#$$$$#$$#$$#.$$#$#$#$#$#$#@$$#& #.$$#$$$#$#$#@#$$$#.$#$$$#$$$$#$$#$$#.$$#$#$#$#$#$#@$$#& #$$$$$$$$$$$$$$$$.#$$$$$$$$$$$$$$$$.#$$$$$$$$$$$$$$$$. ",
|
||||
" #.@@$##@###@#$#@@@#.@#@@@$##@##@@#@@#.@@#@#@#@#@#@#$@@#% #.@@$##@###@#$#@@@#.@#@@@$##@##@@#@@#.@@#@#@#@#@#@#$@@#% #@@@##@#@#@##@@@@.#@###@@##@##@###@.#@@##@##@@#@@##@@. ",
|
||||
" #.$@$$$$$$$$@$$$$$#.$$$$@$$$$$$$$$$$#.$$$$$$$$$$$$@$$$#& #.$@$$$$$$$$@$$$$$#.$$$$@$$$$$$$$$$$#.$$$$$$$$$$$$@$$$#& #$$#$$$#$#$#$#$$$.#$#$$$#$$$#$$$#$$.#$$#$#$#$#$#$#$#@. ",
|
||||
" #+#################+#################+#################% #+#################+#################+#################% #@@#@@@#@#@##$@@@.#@##@@#@@@##@@#@@.#@@#@#@#@###@##$$. ",
|
||||
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& #$$#$$$#$#$#@#$$$.#$#$$$#$$$$#$$#$$.#$$#$#$#$#$#$#@@@. ",
|
||||
" #@@$##@###@#$#@@@.#@#@@@$##@##@@#@@.#@@#@#@#@#@#@#$$$. ",
|
||||
" ######################################################## ######## ###################################### ######## #$@$$$$$$$$@$$$$$.#$$$$@$$$$$$$$$$$.#$$$$$$$$$$$$@@@@. ",
|
||||
" #######################################################% #.....+% #####################################% #.....+% +.................+.................+................. ",
|
||||
" #######################################################& #.$$$$#& #####################################& #.$$$$#& ###################################################### ",
|
||||
" #######################################################% #.@@#@#% #####################################% #.@#@@#% ###################################################### ",
|
||||
" #######################################################& #.$##$#% #####################################% #.$##$#& ###################################################### ",
|
||||
" #######################################################% #.@$#@#& #####################################& #.@#$@#% ###################################################### ",
|
||||
" #######################################################& #.@$$$#% #####################################% #.$@$$#& ###################################################### ",
|
||||
" #######################################################% #+#####& #####################################& #+#####% ###################################################### ",
|
||||
" #######################################################& %%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%& ###################################################### ",
|
||||
" #######################################################% ###################################################### ",
|
||||
" #######################################################& ######################################################## ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" #######################################################% #######################################################% ###################################################### ",
|
||||
" #######################################################& #######################################################& ###################################################### ",
|
||||
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ###################################################### ",
|
||||
" ****************************************************** ",
|
||||
" ====================================================== ",
|
||||
" ",
|
||||
" ",
|
||||
" ########-################# #####################-#### *=############;#############",
|
||||
" ######--->################ ########-->>>>>>>>>>-,#### *=############;#############",
|
||||
" ####------>#####>--####### ########,,,,-------->>#### *=######;####;;;####;#######",
|
||||
" ####>-----,>>->-,---###### ########>-->,,,,,,,,,##### *=######;;###;;;###;;#######",
|
||||
" ##--,------,--------###### ########,,,>>>>>->--###### *=######;;;')!!!)';;;#######",
|
||||
" >> ##---,------,--------##### ########>>>,,--,,,>>###### *=#######~!{{{{!{!!~########",
|
||||
" ,,,,,, ,->>>>>> ,>,>>> >>> ##---,------,,--------#### ########,->--,>>>--####### *=##;;##]{{{{{{{{{{{];;;;###",
|
||||
" ,>------, >-------,,------>>--->> > #------------>,,------#### ########>,,,----,,######## *=##;;;~{{{{{{{{{{{{!~;;####",
|
||||
" ------------, ,,--------------------, ^>>>>>> #-------------------->-### ########>---,,,>>>######## *=###;;!{{{{{{{{{{{{{!;#####",
|
||||
" >>,,,,,,,,,,> ,--,>,,,,,,--,,-,,,> >>,----> #---------------,,,----### ########-,>,>>----######## *=####~{{{{{{{{{{{{{{!'#####",
|
||||
" ,> ,> > ,------> >> #,--,,-,------->>-,----### ########>,>---,,,######### *=####){{{{{{{{{{{{{{{)#####",
|
||||
" >,>------,>-> ->----,>---------->,-,#### ########--,,,,>>########## *=##;;!{{{{{{{{{{{{{{{!;;###",
|
||||
" ,>----------->> -,----,----------,>,>>#### ########,>>>>,->########## *=;;;;{{{{{{{{{{{{{{{{{;;;;#",
|
||||
" ,>-------------> -------,,,,,---------->### ########>,,---,########### *=##;;!{{{{{{{{{{{{{{{!;;###",
|
||||
" ,--------------> ----------------------->># ########>-,,,>############ *=####){{{{{{{{{{{{{{{)#####",
|
||||
" ,,,,,, ,,,,,, >>>>>-,-----,,-,,--> ,,-------------------,>### ########-->>-,############ *=####'{{{{{{{{{{{{{{{~#####",
|
||||
" ,>------, ,>------, ,-,-----,,---,>---->> #,,,---------,,,,--,>,#### ########,,,->############# *=####;{{{{{{{{{{{{{{{;#####",
|
||||
" ------------, ------------, >------,,>>--,>------> #>>>,,----,,,>>>>,,>,>#### #########--,,############# *=###;;~{{{{{{{{{{{{{~;;;###",
|
||||
" >>,,,,,,,,,,> >>,,,,,,,,,,> ,-,---------->,-------> #,,>>,,,,>>>,,,,>>,>,##### ########,,>>############## *=##;;##]{{{{{{{{{{{]##;;###",
|
||||
" ,>,---------------,,,, ##>,,>>>>,,,>####,>####### ########>>,############### *=######;~{{{{{{{{{~########",
|
||||
" >,,,,----------,>>>> ######,,>>################ #########>>############### *=######;;;'){{{)';;########",
|
||||
" ,>>>>,,,,,,,,,,>,,,> ########################## ########################## *=######;;###;;;###;;#######",
|
||||
" ,>>>>>>>>>>,>>>, ########################## ########################## *=######;####;;;####;#######",
|
||||
" ,,,,,,,,,> ########################## ########################## *=############;#############",
|
||||
" ########################## ########################## *=############;#############",
|
||||
"&/(____------------:&%%%%> < < < <<<<< <<<< < < < ###-##-##-#####.....+.....+ *=##########################",
|
||||
"[/}----------------:|1111% <<< <<<< << <<< < < < ###--#-#-#-####.$$$$#.$$$$# *=##########################",
|
||||
"[/(_---------------:[%%%1% << << < <<< << << 22222222222 ###-#--#-#-####.@@#$#.@#@$# *=##########################",
|
||||
"|/(_---------------}|%%%%% <<<<<< < < <<< < 22 2222 ###-##-#-#-####.$##@#.$##@# *=##########################",
|
||||
"3_----------------------4% < <<< < < < <<< 222222222 222 ###-##-##-#####.$$#$#.$#$$# *=####566678$&9&^076655#####",
|
||||
"-------------------------/ < << <<<< < 222 ###############.@@$@#.@$@@# *=####55abc$defedg1hi55#####",
|
||||
"-------------------------j <<<< < << < < 222 222 ###############+#####+##### *=####55k8lmn8l^$e$,oi5#####",
|
||||
"-------------------------p < < <<<< < << < << 222222 2222 2 ####################+#####+ *=####aqnmrsntucvod,1h6#####",
|
||||
"-------------------------_ < << < << < << 222222 ################$$$$.#$$$$. *=####wnttrnmxyonn0%zz7#####",
|
||||
"-------------------------p <<<<<< < < 22 22222 --###-##---##-##@@#@.#@#@@. *=####bAmnvvvtcvhhmy$tn#####",
|
||||
"-------------------------p <<< < << < <<<< << 222222 22 22222222 22 -#-#-#-##-##-#-#$##$.#$##$. *=####mbsvuge8tnxskBfru#####",
|
||||
"-------------------------( < << <<< < <<< < < 222222 -#-#---##-##---#@$#@.#@#$@. *=####cBCu0exncl$CDDocg#####",
|
||||
"p-----------------------_[ < < << << << < < 22 22222 222 -#-#-#-##-##-#-#@$$$.#$@$$. *=####gBBhv08yl%EemdvCc#####",
|
||||
"(:_---------------------_% <<<< <<< < < < 22 222 22 --##-#-##-##-#-+.....+..... *=####gCDs8vu^,|E&u^otg#####",
|
||||
"/44j_-------------------_> <<< << < << < < < < << 222 22 22 *=####dd8vnm8d>EE&>0c0d#####",
|
||||
"fffE:__-----------------pe < < < < < < < 222 22 2 2 ####nEcCxxrez,E,zyefn#####",
|
||||
"fff^(__-----------------jt <<<< << << < <<< < << < 2222 222 ####FzE8x08g9[E%%z[zF#####",
|
||||
"fff,4:-----------------pEB < < <<<< << < < << < ####ak1gf$[}G[1E,19s6#####",
|
||||
"f$|jpp_---------------_3%^ << < <<< < < <<<< < < 22 222222222222 ####6at,^E9G4|1E|Era6#####",
|
||||
"z4}:__pp__-----------_j&%^ < B< < < < <<< 222222222 2222 ####65ak^z%4[&1&,ka56#####",
|
||||
"4}}:pp:jpj:_-----_____}%E^ < << < < < < < << 22 2222 ####5666Fmf99[gmF6555#####",
|
||||
"[9/3}}}}}}[}pp}((_ppp:9E^f <<<<< < <<< < < < < 22222 H{{{{H ##########################",
|
||||
"%1%%/(}}}}z1[9334pppp(1^ff << < <B < < < <<<< 2 H{{{{H ##########################",
|
||||
"1%%%&/4}((f0e^%[/jp.4z@ffl < <<< < << << < < << 22222222 H{{{{H ##########################",
|
||||
"E%%%%%|//ECFItd>z13[>fffff < <<< <<< < << < 22222 H{{{{H ##########################",
|
||||
" H{{{H ",
|
||||
" # H{{{H H{{{H ",
|
||||
" #J# H{{{H H{{{H ",
|
||||
" ### # #K# H{{{H H{{{H ",
|
||||
" -- #-#-#-# ##L## H{{{H H{{{H ",
|
||||
" -- -- -- -- #--###--# #KKJ# H{{{H H{{{H ",
|
||||
"-- -- -- -- #--#-#-#--# #KLM# H{{{H H{{{H ",
|
||||
"-- ###-----### #LKM# H{{{H H{{{H ",
|
||||
" -- -- -- #--###-###--# #LLNOP# H{{{{{H H{{{{{H ",
|
||||
" -- -- -- -- -#----#---- - QKNMR# H{{{H H{{{H ",
|
||||
"- -- -- - -- KSTUORP H{{{H H{{{H ",
|
||||
"- -- -- -----## JTTUOVP H{{HH H{{H{{H ",
|
||||
" -- -- -- -- -- -- -#- -- JNTMRVW# H{{H H{{H H{{H ",
|
||||
" -- -- -- -- #-- ##-- MMVWP## H{{H H{{H H{{H ",
|
||||
" -- - - - WXX H{{H H{{H H{{H "};
|
Loading…
Reference in a new issue