/* This is free software. See LICENSE for terms. * Copyright 2004 - 2015, Patricia Kirk. */ #include <stdlib.h> #include <string.h> #include <math.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <sys/param.h> #include <sys/user.h> #include <sys/stat.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #if !defined (__linux__) #include <net/if_media.h> #endif #if defined(__OpenBSD__) #include <sys/socket.h> #endif #include <net/if.h> /* Needs sys/socket.h first on OpenBSD */ #if defined (__linux__) #include <time.h> #include <sys/time.h> #endif #include "proto.h" #include "pixmaps.h" extern struct global g; extern struct data fresh; extern Pixmap icondraw, iconmask, maindraw, mainmask; extern Display *maindisplay; extern Window rootwindow, iconwindow, mainwindow; extern GC icongc, maingc; extern int mainscreen, colordepth; struct pixstack *iconpix=NULL, *mainpix=NULL; char *filename=NULL; char *colornames=NULL; char smalbuf[SMALBUF]; /* Allocate and initialize a pixstack struct and add it to the list. * pix->index = 0 is the background color: backxpm, tile or pixmap or pseudo trans * = 1 is the foreground color: forexpm in the foreground color * = 2 is the shutdown color: forexpm in #fFfF01010101 * = n is forexpm in any additional colors * 1 and 2 are switched in the list when execShutdown() is called. * The returned value is the position on the pixstack * list of the font in the color requested. */ int pixAlloc(char *colorname) { struct pixstack *i, *ipix=NULL, *iprev=NULL, *m, *mpix=NULL, *mprev=NULL; int index=0, found=0; CALLOC(ipix, 1, sizeof(struct pixstack), "pixAlloc"); CALLOC(mpix, 1, sizeof(struct pixstack), "pixAlloc"); STRDUP(ipix->colorname, colorname); STRDUP(mpix->colorname, colorname); if (!iconpix) { ipix->index = index; mpix->index = index; iconpix = ipix; mainpix = mpix; } else { i = iconpix; m = mainpix; while (i && m) { iprev = i; mprev = m; if (!strcasecmp(i->colorname, colorname)) { FREE(ipix->colorname); FREE(mpix->colorname); FREE(ipix); FREE(mpix); found = 1; break; } i = i->next; m = m->next; index++; } if (!found) { ipix->index = index; mpix->index = index; iprev->next = ipix; mprev->next = mpix; } } return index; } /* There's only one mask at pixlist->next. * The others are all freed at startup * since they're all the same. */ void putChar(struct lineopts *line, struct pixstack *pix, int offset, int width, int left) { struct pixstack *list; Pixmap mask, draw; GC gc; int xmag, div; if (!g.iconized || line->panel == 1) { if (!g.iconized) { list = mainpix; mask = mainmask; draw = maindraw; gc = maingc; xmag = g.xmag; div = 1; } else { list = iconpix; mask = iconmask; draw = icondraw; gc = icongc; xmag = 1; div = g.xmag; } /* (display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y) */ if (g.pixmap) XCopyPlane(maindisplay, list->next->mask, mask, gc, ((CHARWIDTH * xmag) * (offset % 10)), ((CHARHEIGHT * xmag) * (offset / 10)), (width * xmag), (CHARHEIGHT * xmag), (line->left + (left * xmag)), (line->upper / div), 1); XCopyArea(maindisplay, pix->pixmap, draw, gc, ((CHARWIDTH * xmag) * (offset % 10)), ((CHARHEIGHT * xmag) * (offset / 10)), (width * xmag), (CHARHEIGHT * xmag), (line->left + (left * xmag)), (line->upper / div)); } } void drawSlider(struct lineopts *line) { struct pixstack *pix, *vpix, *list; Pixmap mask, draw; GC gc; int i, j, xmag, div; static int k, l, m, init=1; static struct pixstack *vipix, *vmpix, *ipix, *mpix; if (init) { /* Use the shutdown color for the * current volume indicator. */ vipix = iconpix->next->next; vmpix = mainpix->next->next; init = line->color ? line->color : FORE; ipix = iconpix; mpix = mainpix; while (init) { ipix = ipix->next; mpix = mpix->next; init--; } k = '|' - ASCEN; l = '.' - ASCEN; m = 'i' - ASCEN; } if (!g.iconized || line->panel == 1) { if (!g.iconized) { list = mainpix; pix = mpix; vpix = vmpix; mask = mainmask; draw = maindraw; gc = maingc; xmag = g.xmag; div = 1; } else { list = iconpix; pix = ipix; vpix = vipix; mask = iconmask; draw = icondraw; gc = icongc; xmag = 1; div = g.xmag; } /* (display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y) */ putChar(line, pix, '<' - ASCEN, CHARWIDTH, 2); /* Add a bar across the open end. */ if (g.pixmap) XCopyPlane(maindisplay, list->next->mask, mask, gc, ((CHARWIDTH * xmag) * (k % 10)), ((CHARHEIGHT * xmag) * (k / 10)), xmag, (CHARHEIGHT * xmag), (line->left + (5 * xmag)), (line->upper / div), 1); XCopyArea(maindisplay, pix->pixmap, draw, gc, ((CHARWIDTH * xmag) * (k % 10)), ((CHARHEIGHT * xmag) * (k / 10)), xmag, (CHARHEIGHT * xmag), (line->left + (5 * xmag)), (line->upper / div)); j = parseStrtol(line->value, TRUE, "drawSlider"); j = (fresh.volume[j] / 2) + 6 + (fresh.volume[j] > 98); for (i = 6; i < 58; i++) { if (i == j) { /* Current volume level marker in red. */ putChar(line, vpix, k, 1, i); } else if ((i - 6) && i < 50 && !((i - 6) % 10)) { /* Make the pips. */ if (g.pixmap) { XCopyPlane(maindisplay, list->next->mask, mask, gc, ((CHARWIDTH * xmag) * (m % 10)), ((CHARHEIGHT * xmag) * (m / 10)) + (4 * xmag), xmag, ((CHARHEIGHT - 4) * xmag), (line->left + (i * xmag)), (line->upper / div) + (4 * xmag), 1); } XCopyArea(maindisplay, pix->pixmap, draw, gc, ((CHARWIDTH * xmag) * (m % 10)), ((CHARHEIGHT * xmag) * (m / 10)) + (4 * xmag), xmag, ((CHARHEIGHT - 4) * xmag), (line->left + (i * xmag)), (line->upper / div) + (4 * xmag)); goto putell; } else { putChar(line, pix, l, 1, i); /* The top line. */ putell: if (g.pixmap) XCopyPlane(maindisplay, list->next->mask, mask, gc, ((CHARWIDTH * xmag) * (l % 10)), ((CHARHEIGHT * xmag) * (l / 10)) + (6 * xmag), xmag, xmag, (line->left + (i * xmag)), (line->upper / div), 1); XCopyArea(maindisplay, pix->pixmap, draw, gc, ((CHARWIDTH * xmag) * (l % 10)), ((CHARHEIGHT * xmag) * (l / 10)) + (6 * xmag), xmag, xmag, (line->left + (i * xmag)), (line->upper / div)); } } putChar(line, pix, '>' - ASCEN, CHARWIDTH, 58); if (g.pixmap) XCopyPlane(maindisplay, list->next->mask, mask, gc, ((CHARWIDTH * xmag) * (k % 10)), ((CHARHEIGHT * xmag) * (k / 10)), xmag, (CHARHEIGHT * xmag), (line->left + (58 * xmag)), (line->upper / div), 1); XCopyArea(maindisplay, pix->pixmap, draw, gc, ((CHARWIDTH * xmag) * (k % 10)), ((CHARHEIGHT * xmag) * (k / 10)), xmag, (CHARHEIGHT * xmag), (line->left + (58 * xmag)), (line->upper / div)); } } /* Copy an updated line into the draw window. */ void lineToDraw(char *buffer, struct lineopts *line) { int i, j, k[SHOWBUF], l=0, m=61, color; struct pixstack *pix; char showbuf[SHOWBUF]; const int charwidth[] = { 5, 5, 0, 1, 3, 5, 5, 5, 5, 1, /* 39 */ 3, 3, 5, 5, 2, 4, 1, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, /* 59 */ 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, /* 79 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 3, 2, 5, 5, 2, 4, 4, 4, /* 99 */ 4, 4, 4, 4, 4, 1, 4, 4, 3, 5, 4, 4, 4, 4, 4, 4, 3, 4, 5, 5, /* 119 */ 5, 5, 5, 4, 1, 4, 5, 3, 0, 0 }; /* First count the unfilled columns and the * number of blank areas indicated with PIPEs. */ for (i = 0; i < SHOWBUF; i++) { if (!(j = buffer[i])) break; if (j == PIPE) l++; else m -= (charwidth[j - 30] + 1); if (m < 0) { m = 0; break; } } /* There may not be a PIPE if it's a user defined line. */ if (l) l = m / l; else l = m; l += !l; m = 2; /* Now l is the width of a blank area and m * is the offset of the first character. * Calc the x offset for each of the * other characters. */ for (i = 0; i < SHOWBUF; i++) { j = buffer[i]; if (!j || m > 61) break; k[i] = m; if (j == PIPE) { m += l; showbuf[i] = SPACE; } else { m += charwidth[j - 30] + 1; showbuf[i] = j; } } showbuf[i] = '\0'; color = line->color ? line->color : FORE; if (g.iconized) pix = iconpix; else pix = mainpix; while (color) { pix = pix->next; color--; } for (i = 0; i < SHOWBUF; i++) { if (!showbuf[i]) break; j = charwidth[(int)showbuf[i] - 30]; while (j && ((j + k[i]) > 62)) j--; if (!j) continue; l = showbuf[i] - ASCEN; putChar(line, pix, l, j, k[i]); } } void formatLine(int direct, struct lineopts *line, double value, char buffer[]) { int display, i, j; if (direct) { /* Used for cpu splits, load averages and * memory when expressed as percentage. */ i = strlen(buffer) - 1; if (buffer[i] == '%') i--; buffer[i--] = ((int)value % 10) + AZERO; /* hundredths */ value /= 10; buffer[i--] = ((int)value % 10) + AZERO; /* tenths */ value /= 10; i--; buffer[i--] = ((int)value % 10) + AZERO; /* ones */ value /= 10; buffer[i--] = (int)value ? ((int)value % 10) + AZERO : SPACE; /* tens */ value /= 10; buffer[i] = (int)value ? ((int)value % 10) + AZERO : SPACE; /* hundreds */ } else { /* Used for free and used memory, free and used swap, * share, buffer and cache memory. First determine * the units of measure and enter it in the * right most space if required. */ if (value > 999999999999LL) { display = value / 1000 / 1000 / 1000; i = GIGS; } else if (value > 999999999L) { display = value / 1000 / 1000; i = MEGS; } else if (value > 999999L) { display = value / 1000; i = KEYS; } else { display = value; i = 0; } j = 12; if (i) buffer[j--] = i; for (i = j; i > 4; i--) { buffer[i] = (display % 10) + AZERO; display /= 10; if (!display) break; } } lineToDraw(buffer, line); } /* Write an entry into .../salmon.log. * If logbeep is set, make a brief * beep noise. */ void logMessage(char *message) { time_t timenow=time(NULL); struct tm *timeptr; char buffer[BUFSIZE]; FILE *logfile; int i, j, k; snprintf(buffer, sizeof(buffer), "%s/salmon.log", g.tempdir); if ((logfile = fopen(buffer, "a"))) { timeptr = localtime(&timenow); strftime(buffer, sizeof(buffer), "%m/%d %H:%M:%S", timeptr); fprintf(logfile, "%s #%05d, %s.\n", buffer, (int)getpid(), message); fclose(logfile); } if (g.logbeep) { snprintf(smalbuf, SMALBUF, "%s", BEEPER); if ((logfile = fopen(smalbuf, "w"))) { #if defined (__OpenBSD__) k = 350; for (i = 0; i < 10000; i++) #else k = 8000; for (i = 0; i < 500; i++) #endif { j = i * k; write(fileno(logfile), &j, 1); } fclose(logfile); } else { g.logbeep = 0; snprintf(smalbuf, SMALBUF, "logbeep failed, %s", strerror(errno)); logMessage(smalbuf); } } } /* Used by CALLOC. */ void allocFailed(char *function) { snprintf(smalbuf, SMALBUF, "%s() failed to allocate memory", function); gdayMate(smalbuf, strerror(errno)); } /* If message == NULL, exit(0) else exit(1) */ void gdayMate(char *message, char *errmsg) { char buffer[BUFSIZE]; bzero(&buffer, BUFSIZE); if (message) snprintf(buffer, BUFSIZE, "%s", message); if (errmsg) { stringcat(buffer, ", ", BUFSIZE); stringcat(buffer, errmsg, BUFSIZE); } if (strlen(buffer)) { logMessage(buffer); fprintf(stderr, "\nsalmon: %s.\n\n", buffer); } if (maindisplay) XCloseDisplay(maindisplay); if (message && getpid() != g.ppid) sleep(1); exit(message != NULL); } int readPixmap(struct pixstack *stack, char *name) { stack->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); return (XpmReadFileToPixmap(maindisplay, rootwindow, name, &stack->pixmap, &stack->mask, &stack->attributes)); } /* colorname is the name of the color from rgb.txt * or hash plus a six or twelve digit hex value * rate is LITE or DARK from salmon.h, 1.00 or 0.55 */ char *getColor(char *colorname, float rate) { XColor color; static char smalbuf[SMALBUF]; bzero(&color, sizeof(color)); if (!XParseColor(maindisplay, DefaultColormap(maindisplay, mainscreen), colorname, &color)) { if (!colornames) { CALLOC(colornames, (20 * SMALBUF), sizeof(char), "getColor"); } if (!strstr(colornames, colorname)) { stringcat(colornames, colorname, (20 * SMALBUF)); snprintf(smalbuf, sizeof(smalbuf), "getColor() can`t parse color \"%s\"", colorname); logMessage(smalbuf); } XParseColor(maindisplay, DefaultColormap(maindisplay, mainscreen), FOREGROUND, &color); } if (!XAllocColor(maindisplay, DefaultColormap(maindisplay, mainscreen), &color)) { snprintf(smalbuf, sizeof(smalbuf), "getColor() can`t allocate color \"%s\"", colorname); logMessage(smalbuf); } if (rate != LITE) { color.red *= rate; color.green *= rate; color.blue *= rate; } snprintf(smalbuf, sizeof(smalbuf), "#%04x%04x%04x", color.red, color.green, color.blue); return smalbuf; } void initPixlist() { struct pixstack *ipix=NULL, *mpix=NULL; int width, height, i, j, k, l, xmag; char **color, **xpm; FILE *fd; if (!filename) { CALLOC(filename, BUFPLUS, sizeof(char), "initPixlist"); } if (!(color = (char **)calloc(3 * SMALBUF, sizeof(char)))) allocFailed("initPixlist"); for (i = 0; i < 3; i++) color[i] = (char *)calloc(SMALBUF, sizeof(char)); snprintf(filename, BUFPLUS, "%s/XXXXXX", g.tempdir); if (mkstemp(filename) == -1) gdayMate("initPixlist() failed to create resize tempfile", strerror(errno)); for (ipix = iconpix, mpix = mainpix; ipix && mpix; ipix = ipix->next, mpix = mpix->next) { xmag = g.xmag; if (g.pixmap && ipix->index) snprintf(color[0], SMALBUF, ". c None"); else /* This is pointing at the background colorname. */ snprintf(color[0], SMALBUF, "%s%s", xpmchars[0], getColor(iconpix->colorname, LITE)); if (!ipix->index) { if (g.pixmap) { FREE(ipix->colorname); FREE(mpix->colorname); snprintf(color[0], SMALBUF, ". c None"); snprintf(color[1], SMALBUF, "# c None"); snprintf(color[2], SMALBUF, "c c None"); if (g.panel) xmag = g.xmag * 2; } else { /* Get the foreground color for the background pixmap border. */ snprintf(color[1], SMALBUF, "%s%s", xpmchars[1], getColor(iconpix->next->colorname, LITE)); snprintf(color[2], SMALBUF, "%s%s", xpmchars[2], getColor(iconpix->next->colorname, DARK)); } xpm = backxpm; } else { snprintf(color[1], SMALBUF, "%s%s", xpmchars[1], getColor(ipix->colorname, LITE)); snprintf(color[2], SMALBUF, "%s%s", xpmchars[2], getColor(ipix->colorname, DARK)); xpm = forexpm; } /* Background or foreground xpm's from pixmaps.h */ width = (int)strtol(xpm[0], NULL, 10); height = (int)strtol(strchr(xpm[0], ' '), NULL, 10); for (i = 0; i < 3; i++) xpm[i + 1] = color[i]; ipix->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); if (XpmCreatePixmapFromData(maindisplay, rootwindow, xpm, &ipix->pixmap, &ipix->mask, &ipix->attributes)) gdayMate("initPixlist() failed to create pixmap", strerror(errno)); if (xmag == 1) { mpix->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); if (XpmCreatePixmapFromData(maindisplay, rootwindow, xpm, &mpix->pixmap, &mpix->mask, &mpix->attributes)) gdayMate("initPixlist() failed to create pixmap", strerror(errno)); } else { if (!(fd = fopen(filename, "w"))) gdayMate("initPixlist() failed to open resize tempfile", strerror(errno)); fprintf(fd, "/* XPM */\nstatic char *salmon[] = {\n\"%d %d 3 1\",\n", width * xmag, height * xmag); for (i = 0; i < 3; i++) fprintf(fd, "\"%s\",\n", color[i]); for (i = 0; i < height; i++) { for (j = 0; j < xmag; j++) { fprintf(fd, "\""); for (k = 0; k < width; k++) { for (l = 0; l < xmag; l++) fprintf(fd, "%c", xpm[i + 4][k]); } fprintf(fd, "\",\n"); } } fprintf(fd, "};\n"); fclose(fd); i = readPixmap(mpix, filename); if (i) gdayMate("initPixlist() failed to read resized pixmap", strerror(errno)); } } if (filename && unlink(filename)) { snprintf(color[0], SMALBUF, "initPixlist() failed to remove tempfile \"%s\"", filename); logMessage(color[0]); } if (g.pixmap && (ipix = iconpix->next->next) && (mpix = mainpix->next->next)) { while (ipix && mpix) { /* The masks are all the same. */ XFreePixmap(maindisplay, ipix->mask); XFreePixmap(maindisplay, mpix->mask); ipix = ipix->next; mpix = mpix->next; } } FREE(color); FREE(colornames); } /* If called with background TRUE, use resize or montage * to prepare the background pixmap. If FALSE, use to * resize the moon graphic. */ void scaleGraphic(int pixmap, int background) { int i, x, y; char *buffer, *tilecmd=NULL; struct stat sb; FILE *fd; if (!filename) { CALLOC(filename, BUFPLUS, sizeof(char), "scaleGraphic"); } CALLOC(buffer, BUFPLUS, sizeof(char), "scaleGraphic"); if (background) { if (pixmap < 0) i = snprintf(filename, BUFPLUS, "%s/t%02d.gz", g.datadir, abs(pixmap)); else i = snprintf(filename, BUFPLUS, "%s/b%02d.gz", g.datadir, pixmap); } else { i = snprintf(filename, BUFPLUS, "%s/%03d.gz", g.datadir, pixmap); } if (i >= BUFPLUS || stat(filename, &sb) == -1) { snprintf(buffer, BUFPLUS, "scaleGraphic() failed to stat pixmap \"%s\"", filename); gdayMate(buffer, strerror(errno)); } snprintf(filename, BUFSIZE, "%s/XXXXXX", g.tempdir); if (mkstemp(filename) == -1) gdayMate("scaleGraphic() failed to create tempfile", strerror(errno)); if (background) { if (pixmap < 0) snprintf(buffer, BUFPLUS, "%s %s/t%02d.gz > %s", g.unzip, g.datadir, abs(pixmap), filename); else snprintf(buffer, BUFPLUS, "%s %s/b%02d.gz > %s", g.unzip, g.datadir, pixmap, filename); } else { snprintf(buffer, BUFPLUS, "%s %s/%03d.gz > %s", g.unzip, g.datadir, pixmap, filename); } if ((fd = popen(buffer, "r"))) pclose(fd); else gdayMate("scaleGraphic() failed to unzip pixmap", strerror(errno)); if (pixmap < 0) { /* Using a tile. The size is correct for the iconpix. * Repeat (xmag * xmag) plus one times to fill mainpix. */ y = readPixmap(iconpix, filename); snprintf(buffer, BUFPLUS, "%s %dx%d ", g.tiler, g.isize, g.isize); x = ((strlen(filename) + 1) * ((g.xmag * g.xmag) + 1)) + strlen(buffer) + 1; CALLOC(tilecmd, x, sizeof(char), "scaleGraphic"); stringcpy(tilecmd, buffer, x); errno = ENAMETOOLONG; for (i = 0; i <= (g.xmag * g.xmag); i++) { stringcat(tilecmd, " ", x); if ((stringcat(tilecmd, filename, x)) < 0) gdayMate("scaleGraphic() tile command line too long", strerror(errno)); } if ((fd = popen(tilecmd, "r"))) pclose(fd); x = readPixmap(mainpix, filename); FREE(tilecmd); } else { if (g.xmag != 5) { snprintf(buffer, BUFPLUS, "%s %dx%d %s", g.resize, g.msize, g.msize, filename); if ((fd = popen(buffer, "r"))) pclose(fd); else gdayMate("scaleGraphic() resize command failed", strerror(errno)); } if (background) x = readPixmap(mainpix, filename); else x = readPixmap(mainpix->next, filename); if (g.isize != g.msize) { if (g.xmag != 5) { /* The image has already been resized once. * Get a new one rather than resize it again. */ if (background) snprintf(buffer, BUFPLUS, "%s %s/b%02d.gz > %s", g.unzip, g.datadir, pixmap, filename); else snprintf(buffer, BUFPLUS, "%s %s/%03d.gz > %s", g.unzip, g.datadir, pixmap, filename); if ((fd = popen(buffer, "r"))) pclose(fd); else gdayMate("scaleGraphic() resize command failed", strerror(errno)); } snprintf(buffer, BUFPLUS, "%s %dx%d %s", g.resize, g.isize, g.isize, filename); if ((fd = popen(buffer, "r"))) pclose(fd); } if (background) y = readPixmap(iconpix, filename); else y = readPixmap(iconpix->next, filename); } if (filename && unlink(filename)) { snprintf(buffer, BUFPLUS, "scaleGraphic() failed to remove tempfile \"%s\"", filename); logMessage(buffer); } FREE(buffer); if (x || y) gdayMate("scaleGraphic() failed to read pixmap", strerror(errno)); } #if WITH_GRAPHICS void checkMoon() { static int init=1; char *smalbuf; int pixmap; /* The moon pixmaps are 320x320 pixels. The * main window will only be the correct size * if g.xmag is 5. The icon window will * always need to be reduced to 64x64. */ if (init) { /* If the moon is new at init, the current pixmap * will be 000.gz and the screen will not be refreshed * because pixmap and fresh.pixmap will match. * Fix it so they never match at init. */ fresh.pixmap = -1; if (g.pixmap) { XSetClipMask(maindisplay, icongc, iconpix->mask); XSetClipMask(maindisplay, maingc, mainpix->mask); /* These are only used once. */ XFreePixmap(maindisplay, iconpix->mask); XFreePixmap(maindisplay, iconpix->pixmap); XFreePixmap(maindisplay, mainpix->mask); XFreePixmap(maindisplay, mainpix->pixmap); } init = 0; } CALLOC(smalbuf, SMALBUF, sizeof(char), "checkMoon"); /* getPhase() returns ASCEN or DSCEN and phase percent in buffer. */ getPhase(time(NULL), smalbuf); pixmap = (int)(roundf(strtof(strchr(smalbuf, ' '), NULL))); if ((int)strtol(smalbuf, NULL, 10) == DSCEN) /* Returned by getPhase(). */ pixmap = 200 - pixmap; FREE(smalbuf); if (pixmap == fresh.pixmap) /* The pixmap hasn`t changed so go back. */ return; fresh.pixmap = pixmap; scaleGraphic(fresh.pixmap, FALSE); /* These don`t change often enough to stay * current when the icon state is switched. */ XCopyArea(maindisplay, iconpix->next->pixmap, icondraw, icongc, 0, 0, g.isize, g.isize, 0, 0); XCopyArea(maindisplay, mainpix->next->pixmap, maindraw, maingc, 0, 0, g.msize, g.msize, 0, 0); } #endif /* WITH_GRAPHICS */ void Redraw() { XWindowAttributes xattribs; XImage *ximage; Pixmap mask; XGetWindowAttributes(maindisplay, iconwindow, &xattribs); g.iconized = xattribs.map_state; if (g.iconized) { if (g.pixmap) { if (!g.moongraphic) { ximage = XGetImage(maindisplay, iconmask, 0, 0, g.isize, g.isize, colordepth, XYPixmap); mask = XCreateBitmapFromData(maindisplay, iconwindow, ximage->data, g.isize, g.isize); XDestroyImage(ximage); XSetClipMask(maindisplay, icongc, mask); XFreePixmap(maindisplay, mask); } XClearWindow(maindisplay, iconwindow); } XCopyArea(maindisplay, icondraw, iconwindow, icongc, 0, 0, g.isize, g.isize, 0, 0); } else { if (g.pixmap) { if (!g.moongraphic) { ximage = XGetImage(maindisplay, mainmask, 0, 0, g.msize, g.msize, colordepth, XYPixmap); mask = XCreateBitmapFromData(maindisplay, mainwindow, ximage->data, g.msize, g.msize); XDestroyImage(ximage); XSetClipMask(maindisplay, maingc, mask); XFreePixmap(maindisplay, mask); } XClearWindow(maindisplay, mainwindow); } XCopyArea(maindisplay, maindraw, mainwindow, maingc, 0, 0, g.msize, g.msize, 0, 0); } g.updaterequest = 0; } void Update() { time_t timenow=time(NULL); if (g.refresh && (timenow - fresh.timeofdata) >= g.refresh) { fresh.timeofdata = timenow - (timenow % g.refresh); #if WITH_TIMESYNC if (g.timeport && !g.timeserver) checkSync(); #endif /* WITH_TIMESYNC */ g.updaterequest = 1; } checkEvents(); #if WITH_REMEXEC || WITH_TIMESYNC /* Check for execute requests and if * time server, check the request queue. */ checkSocket(); #endif /* WITH_REMEXEC || WITH_TIMESYNC */ checkEcho(); #if WITH_CONTROL checkCtl(); #endif /* WITH_CONTROL */ if (g.updaterequest) { #if WITH_GRAPHICS if (g.moongraphic) checkMoon(); else #endif /* WITH_GRAPHICS */ checkLines(); Redraw(); } }