wmshutdown: Add freedesktop.org desktop entry file.
[dockapps.git] / wmgrabimage / wmGrabImage / wmGrabImage.c
blob072fdfccd3eeb28a915a16fe18a77a1255bd2628
1 /*
3 * wmGrabImage-1.00 (C) 1999 Mike Henderson (mghenderson@lanl.gov)
5 * - Monitors an image on the WWW in a WindowMaker DockApp
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program (see the file COPYING); if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA
26 * Platforms tested on: Linux, Solaris 2.6, IRIX 6.5
29 * ToDo: Add inicator to show if image is uptodate or not
30 * Get rid of GrabImage and put all that stuff in wmGrabImage.c
31 * Center image in icon - this info should be in the returned Attributes struct.
32 * etc...
34 * I am still not sure we are handling color resources properly... Seems to work OK on my 24-bit displays...
39 * Changes:
40 * Version 0.72 - May 27, 2001
41 * Fixed resource leak (XFreeColors)
43 * Version 0.71 - May 24, 2001
44 * Added support for "zooming" the icon display
45 * on a region
47 * Version 0.70 - March 28, 1999.
48 * Added support for local images (e.g. file:///home/mgh/junk.gif.)
50 * Version 0.66 - February 23, 1999.
51 * Added help line for -delay option. And added a man page.
53 * Version 0.65 - February 11, 1999.
54 * Now starts netscape if not already running...
56 * Version 0.64 - February 9, 1999.
57 * Added command-line option for "Time between updates"
59 * Version 0.63 - February 9, 1999.
60 * Fixed (potential) memory leak in the ShapeMask Pixmap
61 * (gets returned only if color None is used in xpm file)
62 * Added XFreeColors call.
64 * Version 0.62 - February 4, 1999.
65 * buf fixes. Added -c option to center vertically.
68 * Version 0.61 - February 2, 1999.
69 * Added Attributes support for Xpm Creation.
70 * Also, added a kludge to GrabImage to stream edit
71 * any "Transparent" colors that may get generated. (Change them
72 * to black.)
74 * Version 0.6 - February 2, 1999.
75 * Some bug fixes. Added Double click support.
76 * Now, DoubleClick's do the following:
78 * Button1: display original size image via xv.
80 * Button2: send another URL (specified with the -http
81 * command line option) to netscape.
83 * Button3: Force Update.
86 * Version 0.5 - initial (very) beta release February 1, 1999.
96 * Includes
98 #include <stdio.h>
99 #include <unistd.h>
100 #include <stdlib.h>
101 #include <string.h>
102 #include <time.h>
103 #include <X11/X.h>
104 #include <X11/xpm.h>
105 #include <sys/types.h>
106 #include <sys/stat.h>
107 #include <fcntl.h>
108 #include "../wmgeneral/wmgeneral.h"
109 #include "wmGrabImage_master.xpm"
110 #include "wmGrabImage_mask.xbm"
115 * Delay between refreshes (in microseconds)
117 #define DELAY 10000L
118 #define WMGRABIMAGE_VERSION "0.72"
124 void ParseCMDLine(int argc, char *argv[]);
125 void pressEvent(XButtonEvent *xev);
126 void print_usage();
129 char ImageURL[1024], XpmFileName[256], ImageFileName[1024];
130 char HttpURL[1024];
131 char *ConvertGeometry= NULL;
132 int UpToDate = 0;
133 int ForceUpdate = 1;
134 int ForceUpdate2 = 1;
135 int GotFirstClick1, GotDoubleClick1;
136 int GotFirstClick2, GotDoubleClick2;
137 int GotFirstClick3, GotDoubleClick3;
138 int DblClkDelay;
139 int CenterImage = 0;
140 long int UpdateDELAY = 600;
147 * main
149 int main(int argc, char *argv[]) {
151 struct tm *gTime, *gmt;
152 struct stat fi;
153 XEvent event;
154 Pixmap NewPixmap, NewShapeMask;
155 XpmAttributes Attributes;
156 Colormap cmap;
157 int n, s, m, dt1, dt2, dt3, len;
158 int Year, Month, Day;
159 int Hours, Mins, Secs;
160 int i, j, Width, Height, yoff, fd, Flag;
161 long CurrentLocalTime;
162 double UT, hour24(), jd(), CurrentJD, OldFileUT, FileUT;
163 char command[1040], ImageName[256];
164 int havePixmap= 0;
176 * Parse any command line arguments.
178 ParseCMDLine(argc, argv);
182 * Figure out what the name of the image xpm file should be...
184 len = strlen(ImageURL);
185 for (j = 0, i=0; i<len; ++i){ if (ImageURL[i] == '/') j = i; }
186 strcpy(ImageName, ImageURL+j+1);
187 sprintf(XpmFileName, "%s/.wmGrabImage/%s.xpm", getenv("HOME"), ImageName);
188 sprintf(ImageFileName, "%s/.wmGrabImage/%s", getenv("HOME"), ImageName);
191 openXwindow(argc, argv, wmGrabImage_master, wmGrabImage_mask_bits, wmGrabImage_mask_width, wmGrabImage_mask_height);
193 cmap = DefaultColormap(display, DefaultScreen(display));
198 * Loop until we die
200 n = 32000;
201 s = 32000;
202 m = 32000;
203 dt1 = 32000;
204 dt2 = 32000;
205 dt3 = 32000;
206 DblClkDelay = 32000;
207 UpToDate = 0;
208 FileUT = -999.0;
209 Flag = 1;
210 NewShapeMask = 0;
211 Attributes.nalloc_pixels = 0;
212 while(1) {
218 * Keep track of # of seconds
220 if (m > 100){
222 m = 0;
223 ++dt1;
224 ++dt2;
225 ++dt3;
227 } else {
230 * Increment counter
232 ++m;
242 * Double Click Delays
243 * Keep track of click events. If Delay too long, set GotFirstClick's to False.
245 if (DblClkDelay > 15) {
247 DblClkDelay = 0;
248 GotFirstClick1 = 0; GotDoubleClick1 = 0;
249 GotFirstClick2 = 0; GotDoubleClick2 = 0;
250 GotFirstClick3 = 0; GotDoubleClick3 = 0;
252 } else {
254 ++DblClkDelay;
272 * Process any pending X events.
274 while(XPending(display)){
275 XNextEvent(display, &event);
276 switch(event.type){
277 case Expose:
278 RedrawWindow();
279 break;
280 case ButtonPress:
281 pressEvent(&event.xbutton);
282 break;
283 case ButtonRelease:
284 break;
300 * Draw window.
302 if (ForceUpdate||Flag){
307 * Compute Current Julian Date
309 CurrentLocalTime = time(CurrentTime);
310 gTime = gmtime(&CurrentLocalTime);
311 Year = gTime->tm_year+1900;
312 Month = gTime->tm_mon+1;
313 Day = gTime->tm_mday;
314 Hours = gTime->tm_hour;
315 Mins = gTime->tm_min;
316 Secs = gTime->tm_sec;
317 UT = (double)Hours + (double)Mins/60.0 + (double)Secs/3600.0;
318 CurrentJD = jd(Year, Month, Day, UT);
322 * Clear window.
324 copyXPMArea(5, 69, 54, 54, 5, 5);
328 if (havePixmap) {
330 * free up the colors, if we alloc'd some before
332 if (Attributes.nalloc_pixels > 0)
333 XFreeColors(display, cmap, Attributes.alloc_pixels,
334 Attributes.nalloc_pixels, 0);
336 * Free last pixmap -- we dont need it anymore...
337 * A ShapeMask is returned if the Pixmap had the color None used.
338 * We could probably change Transparent to None to make use of this, but for now,
339 * lets just ignore it...
341 if ( NewShapeMask != 0 )
342 XFreePixmap(display, NewShapeMask);
343 XFreePixmap(display, NewPixmap);
345 XpmFreeAttributes(&Attributes);
347 havePixmap= 0;
350 * Grab new pixmap. Accept a reasonable color match.
352 Attributes.valuemask = XpmExactColors | XpmCloseness | XpmReturnAllocPixels;
353 Attributes.exactColors = 0;
354 Attributes.closeness = 40000;
355 if (XpmReadFileToPixmap(display, Root, XpmFileName, &NewPixmap, &NewShapeMask, &Attributes) >= 0){
359 Height = Attributes.height;
360 Width = Attributes.width;
361 yoff = (CenterImage) ? (54 - Height)/2 : 0;
362 XCopyArea(display, NewPixmap, wmgen.pixmap, NormalGC, 0, 0, Width, Height, 5, 5+yoff);
365 Flag = 0;
366 ForceUpdate = 0;
367 havePixmap= 1;
376 * Make changes visible
378 RedrawWindow();
389 * Check xpm file status
391 if (dt2 > 1){
393 dt2 = 0;
395 if ( (fd = open(XpmFileName, O_RDONLY)) >= 0 ) {
397 fstat(fd, &fi);
398 close(fd);
399 gmt = gmtime(&fi.st_mtime);
400 OldFileUT = FileUT;
401 FileUT = (double)gmt->tm_hour + (double)gmt->tm_min/60.0 + (double)gmt->tm_sec/3600.0;
402 if (FileUT != OldFileUT) ForceUpdate = 1;
418 * Check every 5 min if the values are not up to date...
421 if (ForceUpdate2||(dt3 > UpdateDELAY)){
423 dt3 = 0;
426 * Execute Perl script to grab the Latest METAR Report
428 if (ConvertGeometry != NULL)
429 sprintf(command, "GrabImage %s %s &", ImageURL, ConvertGeometry);
430 else
431 sprintf(command, "GrabImage %s &", ImageURL);
432 system(command);
434 ForceUpdate = 1;
435 ForceUpdate2 = 0;
444 * Wait for next update
446 usleep(DELAY);
458 * ParseCMDLine()
460 void ParseCMDLine(int argc, char *argv[]) {
462 int i;
464 ImageURL[0] = '\0';
465 for (i = 1; i < argc; i++) {
467 if (!strcmp(argv[i], "-display")){
469 ++i;
471 } else if ((!strcmp(argv[i], "-url"))||(!strcmp(argv[i], "-u"))){
473 strcpy(ImageURL, argv[++i]);
475 } else if (!strcmp(argv[i], "-delay")){
477 UpdateDELAY = atol(argv[++i]);
478 if (UpdateDELAY < 10){
479 printf("Try a longer delay\n");
480 exit(-1);
483 } else if (!strcmp(argv[i], "-http")){
485 strcpy(HttpURL, argv[++i]);
487 } else if (!strcmp(argv[i], "-geom")){
489 ConvertGeometry= argv[++i];
491 } else if (!strcmp(argv[i], "-c")){
493 CenterImage = 1;
496 } else {
497 print_usage();
498 exit(1);
501 if (ImageURL[0] == '\0'){
502 fprintf(stderr, "You must specify an Image URL\n");
503 print_usage();
504 exit(-1);
510 void print_usage(){
512 printf("\nwmGrabImage version: %s\n", WMGRABIMAGE_VERSION);
513 printf("\nusage: wmGrabImage -u <ImageURL> -http <httpURL> -display <Display>] [-h]\n");
514 printf("\t\t[-geom <CroppingGeometry>\n\n");
515 printf("\t-display <Display>\tUse alternate X display.\n");
516 printf("\t-h\t\t\tDisplay help screen.\n");
517 printf("\t-url <ImageURL>\t\tThe URL of image to display.\n\n");
518 printf("\t-delay <Time>\t\tSet time (in seconds) between updates.\n\n");
519 printf("\t-http <httpURL>\t\tThe URL of the WWW page to send to\n\t\t\t\tnetscape with Button2 double click.\n\n");
520 printf("\t-c \tCenter the image vertically in the icon.\n\n");
521 printf("\t-geom <CropGeometry>\tThe geometry to pass to convert\n");
522 printf("\t\t\t\twhen scaling the image..\n\n");
529 * Compute the Julian Day number for the given date.
530 * Julian Date is the number of days since noon of Jan 1 4713 B.C.
532 double jd(ny, nm, nd, UT)
533 int ny, nm, nd;
534 double UT;
536 double A, B, C, D, JD, day;
538 day = nd + UT/24.0;
541 if ((nm == 1) || (nm == 2)){
542 ny = ny - 1;
543 nm = nm + 12;
546 if (((double)ny+nm/12.0+day/365.25)>=(1582.0+10.0/12.0+15.0/365.25)){
547 A = ((int)(ny / 100.0));
548 B = 2.0 - A + (int)(A/4.0);
550 else{
551 B = 0.0;
553 if (ny < 0.0){
554 C = (int)((365.25*(double)ny) - 0.75);
556 else{
557 C = (int)(365.25*(double)ny);
560 D = (int)(30.6001*(double)(nm+1));
563 JD = B + C + D + day + 1720994.5;
564 return(JD);
571 * This routine handles button presses.
573 * Double click on
574 * Mouse Button 1: Display full size image with xv.
575 * Mouse Button 2: Send HttpURL to netscape.
576 * Mouse Button 3: Update image right away (i.e. grab a new one).
580 void pressEvent(XButtonEvent *xev){
582 char Command[512];
585 ForceUpdate = 1;
588 DblClkDelay = 0;
589 if ((xev->button == Button1) && (xev->type == ButtonPress)){
590 if (GotFirstClick1) GotDoubleClick1 = 1;
591 else GotFirstClick1 = 1;
592 } else if ((xev->button == Button2) && (xev->type == ButtonPress)){
593 if (GotFirstClick2) GotDoubleClick2 = 1;
594 else GotFirstClick2 = 1;
595 } else if ((xev->button == Button3) && (xev->type == ButtonPress)){
596 if (GotFirstClick3) GotDoubleClick3 = 1;
597 else GotFirstClick3 = 1;
602 * We got a double click on Mouse Button1 (i.e. the left one)
604 if (GotDoubleClick1) {
605 GotFirstClick1 = 0;
606 GotDoubleClick1 = 0;
607 sprintf(Command, "xv %s &", ImageFileName);
608 system(Command);
613 * We got a double click on Mouse Button2 (i.e. the left one)
615 if (GotDoubleClick2) {
616 GotFirstClick2 = 0;
617 GotDoubleClick2 = 0;
618 sprintf(Command, "netscape -remote 'openURL(%s)' || netscape '%s' &", HttpURL, HttpURL);
619 system(Command);
624 * We got a double click on Mouse Button3 (i.e. the left one)
626 if (GotDoubleClick3) {
627 GotFirstClick3 = 0;
628 GotDoubleClick3 = 0;
629 ForceUpdate2 = 1;
634 return;