xenocara/app/fvwm/extras/FvwmTaskBar/Goodies.c

425 lines
12 KiB
C

#include "config.h"
#include "fvwmlib.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include "Goodies.h"
#include "minimail.xbm"
extern Display *dpy;
extern Window Root, win;
extern int win_width, win_height, win_y, win_border, d_depth,
ScreenWidth, ScreenHeight, RowHeight;
extern Pixel back, fore;
extern int Clength;
extern GC blackgc, hilite, shadow, checkered;
GC statusgc, dategc;
XFontStruct *StatusFont;
int stwin_width = 100, goodies_width = 0;
int anymail, unreadmail, newmail, mailcleared = 0;
int fontheight, clock_width;
char *mailpath = NULL;
char *clockfmt = NULL;
int BellVolume = DEFAULT_BELL_VOLUME;
Pixmap mailpix, wmailpix, pmask, pclip;
int NoMailCheck = False;
char *DateFore = "black",
*DateBack = "LightYellow",
*MailCmd = "Exec xterm -e mail";
int IgnoreOldMail = False;
int ShowTips = False;
char *statusfont_string = "fixed";
int last_date = -1;
void cool_get_inboxstatus();
#define gray_width 8
#define gray_height 8
extern unsigned char gray_bits[];
/* x y w h tw th open type *text win */
TipStruct Tip = { 0, 0, 0, 0, 0, 0, 0, 0, NULL, None };
/* Parse 'goodies' specific resources */
void GoodiesParseConfig(char *tline, char *Module)
{
if(strncasecmp(tline,CatString3(Module, "BellVolume",""),
Clength+10)==0) {
BellVolume = atoi(&tline[Clength+11]);
} else if(strncasecmp(tline,CatString3(Module, "Mailbox",""),
Clength+11)==0) {
if (strncasecmp(&tline[Clength+11], "None", 4) == 0) {
NoMailCheck = True;
} else {
UpdateString(&mailpath, &tline[Clength+8]);
}
} else if(strncasecmp(tline,CatString3(Module, "ClockFormat",""),
Clength+11)==0) {
UpdateString(&clockfmt, &tline[Clength+12]);
clockfmt[strlen(clockfmt)-1] = 0;
} else if(strncasecmp(tline, CatString3(Module, "StatusFont",""),
Clength+10)==0) {
CopyString(&statusfont_string,&tline[Clength+11]);
} else if(strncasecmp(tline,CatString3(Module, "TipsFore",""),
Clength+8)==0) {
CopyString(&DateFore, &tline[Clength+9]);
} else if(strncasecmp(tline,CatString3(Module, "TipsBack",""),
Clength+8)==0) {
CopyString(&DateBack, &tline[Clength+9]);
} else if(strncasecmp(tline,CatString3(Module, "MailCommand",""),
Clength+11)==0) {
CopyString(&MailCmd, &tline[Clength+12]);
} else if(strncasecmp(tline,CatString3(Module, "IgnoreOldMail",""),
Clength+13)==0) {
IgnoreOldMail = True;
} else if(strncasecmp(tline,CatString3(Module, "ShowTips",""),
Clength+8)==0) {
ShowTips = True;
}
}
void InitGoodies() {
struct passwd *pwent;
char tmp[1024];
XGCValues gcval;
unsigned long gcmask;
if (mailpath == NULL) {
strcpy(tmp, DEFAULT_MAIL_PATH);
pwent = getpwuid(getuid());
strcat(tmp, (char *) (pwent->pw_name));
UpdateString(&mailpath, tmp);
}
if ((StatusFont = XLoadQueryFont(dpy, statusfont_string)) == NULL) {
if ((StatusFont = XLoadQueryFont(dpy, "fixed")) == NULL) {
ConsoleMessage("Couldn't load fixed font. Exiting!\n");
exit(1);
}
}
fontheight = StatusFont->ascent + StatusFont->descent;
gcmask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
gcval.foreground = fore;
gcval.background = back;
gcval.font = StatusFont->fid;
gcval.graphics_exposures = False;
statusgc = XCreateGC(dpy, Root, gcmask, &gcval);
if (!NoMailCheck) {
mailpix = XCreatePixmapFromBitmapData(dpy, win, (char *)minimail_bits,
minimail_width, minimail_height,
fore,back, d_depth);
wmailpix = XCreatePixmapFromBitmapData(dpy, win, (char *)minimail_bits,
minimail_width, minimail_height,
fore,GetColor("white"), d_depth);
goodies_width += minimail_width + 7;
}
if (clockfmt) {
struct tm *tms;
static time_t timer;
static char str[24];
time(&timer);
tms = localtime(&timer);
strftime(str, 24, clockfmt, tms);
clock_width = XTextWidth(StatusFont, str, strlen(str)) + 4;
}
else clock_width = XTextWidth(StatusFont, "XX:XX", 5) + 4;
goodies_width += clock_width;
stwin_width = goodies_width;
}
void Draw3dBox(Window wn, int x, int y, int w, int h)
{
XClearArea(dpy, wn, x, y, w, h, False);
XDrawLine(dpy, win, shadow, x, y, x+w-2, y);
XDrawLine(dpy, win, shadow, x, y, x, y+h-2);
XDrawLine(dpy, win, hilite, x, y+h-1, x+w-1, y+h-1);
XDrawLine(dpy, win, hilite, x+w-1, y+h-1, x+w-1, y);
}
void DrawGoodies() {
struct tm *tms;
static char str[40];
static time_t timer;
static int last_mail_check = -1;
time(&timer);
tms = localtime(&timer);
if (clockfmt) {
strftime(str, 24, clockfmt, tms);
if (str[0] == '0') str[0]=' ';
} else {
strftime(str, 15, "%R", tms);
}
Draw3dBox(win, win_width - stwin_width, 0, stwin_width, RowHeight);
XDrawString(dpy,win,statusgc,
win_width - stwin_width + 4,
((RowHeight - fontheight) >> 1) +StatusFont->ascent,
str, strlen(str));
if (NoMailCheck) return;
if (timer - last_mail_check >= 10) {
cool_get_inboxstatus();
last_mail_check = timer;
if (newmail)
XBell(dpy, BellVolume);
}
if (!mailcleared && (unreadmail || newmail))
XCopyArea(dpy, wmailpix, win, statusgc, 0, 0,
minimail_width, minimail_height,
win_width - stwin_width + clock_width + 3,
((RowHeight - minimail_height) >> 1));
else if (!IgnoreOldMail /*&& !mailcleared*/ && anymail)
XCopyArea(dpy, mailpix, win, statusgc, 0, 0,
minimail_width, minimail_height,
win_width - stwin_width + clock_width + 3,
((RowHeight - minimail_height) >> 1));
if (Tip.open) {
if (Tip.type == DATE_TIP)
if (tms->tm_mday != last_date) /* reflect date change */
CreateDateWindow(); /* This automatically deletes any old window */
last_date = tms->tm_mday;
RedrawTipWindow();
}
}
int MouseInClock(int x, int y) {
int clockl = win_width - stwin_width;
int clockr = win_width - stwin_width + clock_width;
return (x>=clockl && x<clockr && y>1 && y<RowHeight-2);
}
int MouseInMail(int x, int y) {
int maill = win_width - stwin_width + clock_width;
int mailr = win_width;
return (x>=maill && x<mailr && y>1 && y<RowHeight-2);
}
void CreateDateWindow() {
struct tm *tms;
static time_t timer;
static char str[40];
time(&timer);
tms = localtime(&timer);
strftime(str, 40, "%A, %B %d, %Y", tms);
last_date = tms->tm_mday;
PopupTipWindow(win_width, 0, str);
}
void CreateMailTipWindow() {
char str[20];
if (!anymail) return;
sprintf(str, "You have %smail", (newmail || unreadmail) ? "new " : "");
PopupTipWindow(win_width, 0, str);
}
void RedrawTipWindow() {
if (Tip.text) {
XDrawString(dpy, Tip.win, dategc, 3, Tip.th-4,
Tip.text, strlen(Tip.text));
XRaiseWindow(dpy, Tip.win); /*****************/
}
}
void PopupTipWindow(int px, int py, char *text) {
int newx, newy;
Window child;
if (!ShowTips) return;
if (Tip.win != None) DestroyTipWindow();
Tip.tw = XTextWidth(StatusFont, text, strlen(text)) + 6;
Tip.th = StatusFont->ascent + StatusFont->descent + 4;
XTranslateCoordinates(dpy, win, Root, px, py, &newx, &newy, &child);
Tip.x = newx;
if (win_y == win_border)
Tip.y = newy + RowHeight;
else
Tip.y = newy - Tip.th -2;
Tip.w = Tip.tw;
Tip.h = Tip.th;
if (Tip.x+Tip.tw+4 > ScreenWidth-5) Tip.x = ScreenWidth-Tip.tw-9;
if (Tip.x < 5) Tip.x = 5;
UpdateString(&Tip.text, text);
CreateTipWindow(Tip.x, Tip.y, Tip.w, Tip.h);
if (Tip.open) XMapRaised(dpy, Tip.win);
}
void ShowTipWindow(int open) {
if (open) {
if (Tip.win != None) {
XMapRaised(dpy, Tip.win);
}
} else {
XUnmapWindow(dpy, Tip.win);
}
Tip.open = open;
}
void CreateTipWindow(int x, int y, int w, int h) {
unsigned long gcmask;
unsigned long winattrmask = CWBackPixel | CWBorderPixel | CWEventMask |
CWSaveUnder | CWOverrideRedirect;
XSetWindowAttributes winattr;
GC cgc, gc0, gc1;
XGCValues gcval;
Pixmap pchk;
winattr.background_pixel = GetColor(DateBack);
winattr.border_pixel = GetColor("black");
winattr.override_redirect = True;
winattr.save_under = True;
winattr.event_mask = ExposureMask;
Tip.win = XCreateWindow(dpy, Root, x, y, w+4, h+4, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
winattrmask, &winattr);
gcmask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
gcval.graphics_exposures = False;
gcval.foreground = GetColor(DateFore);
gcval.background = GetColor(DateBack);
gcval.font = StatusFont->fid;
dategc = XCreateGC(dpy, Root, gcmask, &gcval);
pmask = XCreatePixmap(dpy, Root, w+4, h+4, 1);
pclip = XCreatePixmap(dpy, Root, w+4, h+4, 1);
gcmask = GCForeground | GCBackground | GCFillStyle | GCStipple |
GCGraphicsExposures;
gcval.foreground = 1;
gcval.background = 0;
gcval.fill_style = FillStippled;
pchk = XCreatePixmapFromBitmapData(dpy, Root, (char *)gray_bits,
gray_width, gray_height, 1, 0, 1);
gcval.stipple = pchk;
cgc = XCreateGC(dpy, pmask, gcmask, &gcval);
gcmask = GCForeground | GCBackground | GCGraphicsExposures | GCFillStyle;
gcval.graphics_exposures = False;
gcval.fill_style = FillSolid;
gcval.foreground = 0;
gcval.background = 0;
gc0 = XCreateGC(dpy, pmask, gcmask, &gcval);
gcval.foreground = 1;
gcval.background = 1;
gc1 = XCreateGC(dpy, pmask, gcmask, &gcval);
XFillRectangle(dpy, pmask, gc0, 0, 0, w+4, h+4);
XFillRectangle(dpy, pmask, cgc, 3, 3, w+4, h+4);
XFillRectangle(dpy, pmask, gc1, 0, 0, w+1, h+1);
XFillRectangle(dpy, pclip, gc0, 0, 0, w+4, h+4);
XFillRectangle(dpy, pclip, gc1, 1, 1, w-1, h-1);
#ifdef SHAPE
XShapeCombineMask(dpy, Tip.win, ShapeBounding, 0, 0, pmask, ShapeSet);
XShapeCombineMask(dpy, Tip.win, ShapeClip, 0, 0, pclip, ShapeSet);
#endif
XFreeGC(dpy, gc0);
XFreeGC(dpy, gc1);
XFreeGC(dpy, cgc);
XFreePixmap(dpy, pchk);
}
void DestroyTipWindow() {
XFreePixmap(dpy, pclip);
XFreePixmap(dpy, pmask);
XFreeGC(dpy, dategc);
XDestroyWindow(dpy, Tip.win);
if (Tip.text) { free(Tip.text); Tip.text = NULL; }
Tip.win = None;
}
/*-----------------------------------------------------*/
/* Get file modification time */
/* (based on the code of 'coolmail' By Byron C. Darrah */
/*-----------------------------------------------------*/
void cool_get_inboxstatus()
{
static off_t oldsize = 0;
off_t newsize;
struct stat st;
int fd;
fd = open (mailpath, O_RDONLY, 0);
if (fd < 0)
{
anymail = 0;
newmail = 0;
unreadmail = 0;
newsize = 0;
}
else
{
fstat(fd, &st);
close(fd);
newsize = st.st_size;
if (newsize > 0)
anymail = 1;
else
anymail = 0;
if (st.st_mtime >= st.st_atime && newsize > 0)
unreadmail = 1;
else
unreadmail = 0;
if (newsize > oldsize && unreadmail) {
newmail = 1;
mailcleared = 0;
}
else
newmail = 0;
}
oldsize = newsize;
}
/*---------------------------------------------------------------------------*/
void HandleMailClick(XEvent event) {
static Time lastclick = 0;
if (event.xbutton.time - lastclick < 250) {
SendFvwmPipe(MailCmd, 0);
}
lastclick = event.xbutton.time;
mailcleared = 1;
}