wmbutton: New version 0.7.0
[dockapps.git] / wmweather+ / radar.c
blobedf696be4e20ade8d08e01fca71f76792b0d8b3a
1 #include "config.h"
3 /* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <wraster.h>
30 #include <X11/xpm.h>
32 #include "wmweather+.h"
33 #include "wmgeneral/wmgeneral-x11.h"
34 #include "wmgeneral/xpm_trans.h"
35 #include "download.h"
36 #include "radar.h"
37 #include "die.h"
39 /* Important variables */
40 static time_t radar_time=0;
41 static char *radar_file=NULL;
42 static char *radar_newfile=NULL;
43 static int cropx, cropy, cropw, croph;
44 static int crossx, crossy;
45 time_t radar_update_time;
46 Pixmap radar;
47 int do_radar_cross;
49 extern XpmIcon wmgen;
50 extern GC NormalGC;
51 extern int screen;
52 extern int d_depth;
54 /* prototypes */
55 static int parse_radar(char *file);
58 /* functions */
60 static void reset_radar(Pixmap *r){
61 XCopyArea(display, wmgen.pixmap, *r, NormalGC, 124, 18, 52, 40, 0, 0);
62 XCopyArea(display, wmgen.pixmap, *r, NormalGC, 108, 89, 15, 14, 18, 13);
66 static void parse_cross(void){
67 char *p1, *p2;
69 if(radar_cross==NULL) return;
70 crossx=strtol(radar_cross, &p1, 10);
71 if(crossx<0 || crossx>=52 || p1==NULL || p1==radar_cross || *p1!='x'){
72 radar_cross=NULL;
73 return;
75 crossy=strtol(++p1, &p2, 10);
76 if(crossy<0 || crossy>=40 || (p2!=NULL && *p2!='\0')){
77 radar_cross=NULL;
78 return;
82 static void parse_crop(void){
83 char *p1, *p2;
85 if(radar_crop==NULL) return;
86 cropx=strtol(radar_crop, &p1, 10);
87 if(p1==NULL || p1==radar_crop || *p1!='x'){
88 radar_crop=NULL;
89 return;
91 cropy=strtol(++p1, &p2, 10);
92 if(p2==NULL || p2==p1 || *p2!='+'){
93 radar_crop=NULL;
94 return;
96 cropw=strtol(p2, &p1, 10);
97 if(cropw<1 || p1==NULL || *p1!='+'){
98 radar_crop=NULL;
99 return;
101 croph=strtol(p1, &p2, 10);
102 if(croph<1 || (p2!=NULL && *p2!='\0')){
103 radar_crop=NULL;
104 return;
109 void init_radar(void){
110 char *e;
112 radar=XCreatePixmap(display, wmgen.pixmap, 52, 40, d_depth);
113 reset_radar(&radar);
115 if(radar_uri==NULL) return;
117 e=strrchr(radar_uri, '/');
118 if(e==NULL) e=radar_uri;
119 else e++;
120 snprintf(bigbuf, BIGBUF_LEN-21, "%s.", e);
121 for(e=bigbuf; *e!='\0'; e++){
122 if(!isalnum(*e) && *e!='.' && *e!='-' && *e!='+' && *e!='%'
123 && *e!='?' && *e!='=' && *e!='&') *e='_';
125 strcpy(e, "radar-image");
126 radar_file=get_pid_filename(bigbuf);
127 strcpy(e, "new-radar-image");
128 radar_newfile=get_pid_filename(bigbuf);
130 radar_update_time=radar_time==0;
132 parse_crop();
133 parse_cross();
134 do_radar_cross=0;
136 /* Delete stale files, if any */
137 unlink(radar_file);
138 unlink(radar_newfile);
141 static void radar_callback(char *filename, void *v){
142 struct stat statbuf;
144 if(stat(radar_newfile, &statbuf)>=0){
145 if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
146 && parse_radar(radar_newfile)){
147 rename(radar_newfile, radar_file);
148 } else {
149 unlink(radar_newfile);
150 if(!parse_radar(radar_file)) reset_radar(&radar);
155 void radar_cleanup(void){
156 if(radar_file==NULL) return;
157 unlink(radar_newfile);
158 unlink(radar_file);
161 void update_radar(int force){
162 time_t t;
164 if(radar_file==NULL) return;
166 t=time(NULL)/60;
167 if(!force && radar_time>t) return;
169 radar_time=t+30;
170 download_file(radar_newfile, radar_uri, radar_post, force?DOWNLOAD_KILL_OTHER_REQUESTS:0, radar_callback, NULL);
173 static RContext *rc=NULL;
175 static int parse_radar(char *file){
176 RImage *r, *n;
177 float w, h;
178 RColor col={ 0, 0, 0, 255};
179 int x, y, ww, hh;
181 errno=0;
182 radar_update_time=time(NULL);
183 reset_radar(&radar);
184 if(rc==NULL){
185 rc=RCreateContext(display, screen, NULL);
186 if(rc==NULL){
187 warn("parse_radar context creation: %s", RMessageForError(RErrorCode));
188 return 0;
192 r=RLoadImage(rc, file, 0);
193 if(!r) return 0;
195 if(radar_crop!=NULL){
196 x=cropx; y=cropy;
197 ww=cropw; hh=croph;
198 if(x<0) x+=r->width;
199 if(y<0) y+=r->height;
200 if(x<0){ ww+=x; x=0; }
201 if(y<0){ hh+=y; y=0; }
203 if(x>=r->width || y>=r->width || ww<=0 || hh<=0){
204 RReleaseImage(r);
205 warn("parse_radar radar_crop exceeds image dimensions");
206 return 0;
209 n=RGetSubImage(r, x, y, ww, hh);
210 RReleaseImage(r);
211 r=n;
212 if(!r){
213 warn("parse_radar crop: %s", RMessageForError(RErrorCode));
214 return 0;
218 if(r->width>52 || r->height>40 || (r->width!=52 && r->height!=40)){
219 w=r->width/52;
220 h=r->height/40;
221 if(w>h) h=w;
222 else w=h;
224 n=RSmoothScaleImage(r, r->width/w, r->height/h);
225 RReleaseImage(r);
226 r=n;
227 if(!r){
228 warn("parse_radar scale: %s", RMessageForError(RErrorCode));
229 return 0;
233 if(r->width!=52 || r->height!=40){
234 n=RMakeCenteredImage(r, 52, 40, &col);
235 RReleaseImage(r);
236 r=n;
237 if(!r){
238 warn("parse_radar center: %s", RMessageForError(RErrorCode));
239 return 0;
243 if(!RConvertImage(rc, r, &radar)){
244 RReleaseImage(r);
245 warn("parse_radar convert: %s", RMessageForError(RErrorCode));
246 return 0;
248 RReleaseImage(r);
249 return 1;
252 void put_radar(int x, int y, int font){
253 int i;
255 XCopyArea(display, radar, wmgen.pixmap, NormalGC, 0, 0, 52, 40, x, y);
256 if(font==0) i=0;
257 else i=1;
258 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 124, 60+i, 54, 1, x-1, y-1);
259 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 124, 60+i, 54, 1, x-1, y+40);
260 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 162+i, 64, 1, 40, x-1, y);
261 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, 162+i, 64, 1, 40, x+52, y);
262 if(radar_cross && do_radar_cross){
263 combineWithOpacity(124, 60+i, 52, 1, x, y+crossy, 128);
264 combineWithOpacity(162+i, 64, 1, 40, x+crossx, y, 128);