#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USE_SHAPE #ifdef USE_SHAPE #include #endif #define TRACE fprintf(stderr,"%s:%d\n", __FILE__, __LINE__) typedef unsigned long ulong; typedef char Subject[4096]; static Display *display=NULL; static XVisualInfo vinfo; static int screen; static ulong fg; static ulong bg; static Window win; static Pixmap pix; static GC gc; static int width; static int height; static int shape_window; static pthread_mutex_t mbox_mutex = PTHREAD_MUTEX_INITIALIZER; static int mbox_count; static Subject mbox_subject; static const char *mon[]={"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; #define RAD(x) (M_PI/180.0*(x)) #define ANASIZE 100 #define ANAHOUR (ANASIZE/3) #define ANAMIN (ANASIZE/2-5) #define ANASEC (ANASIZE/2) typedef enum {eIC_InboxHack} InboxType; typedef struct { InboxType type; const char *host; const char *port; } ICInboxHack; typedef union { InboxType type; ICInboxHack ic_hack; } ThreadArgs; typedef unsigned char uchar; static uchar font[]= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00, 0x00, 0x10, 0x7c, 0x14, 0x7c, 0x50, 0x7c, 0x10, 0x00, 0x46, 0x26, 0x10, 0x08, 0x64, 0x62, 0x00, 0x00, 0x08, 0x14, 0x08, 0x54, 0x22, 0x5c, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x28, 0x10, 0x7c, 0x10, 0x28, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x3c, 0x62, 0x52, 0x4a, 0x46, 0x3c, 0x00, 0x00, 0x18, 0x14, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x02, 0x7e, 0x00, 0x00, 0x3c, 0x42, 0x30, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x10, 0x18, 0x14, 0x12, 0x7e, 0x10, 0x00, 0x00, 0x7e, 0x02, 0x3e, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x3c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7c, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x3c, 0x42, 0x20, 0x10, 0x00, 0x10, 0x00, 0x00, 0x3c, 0x52, 0x6a, 0x7a, 0x02, 0x3c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00, 0x00, 0x3e, 0x42, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x7e, 0x02, 0x3e, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x7e, 0x02, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x3c, 0x00, 0x00, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x42, 0x66, 0x5a, 0x42, 0x42, 0x42, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x22, 0x42, 0x00, 0x00, 0x3c, 0x02, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x5a, 0x24, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x38, 0x44, 0x1e, 0x04, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x3c, 0x22, 0x3c, 0x00, 0x00, 0x04, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x38, 0x00, 0x00, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x1e, 0x02, 0x3c, 0x00, 0x00, 0x30, 0x08, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x1c, 0x00, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x20, 0x24, 0x18, 0x00, 0x04, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x2a, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x60, 0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x08, 0x1c, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x1c, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x70, 0x10, 0x0c, 0x10, 0x10, 0x70, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x0e, 0x08, 0x30, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, 0x55, 0x49, 0x41, 0x7f, 0x00 }; static void syserr(const char *p) { perror(p); exit(EXIT_FAILURE); } static int Connect(const char *p_hostname, const char *p_port) { struct addrinfo hints = {0}; struct addrinfo *info; int sock; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (getaddrinfo(p_hostname, p_port, &hints, &info) != 0) { syserr("getaddrinfo"); } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { syserr("socket"); } if (connect(sock, info->ai_addr, info->ai_addrlen) == -1) { close(sock); sock = -1; } return sock; } static void SetCount(int p_count) { pthread_mutex_lock(&mbox_mutex); mbox_count = p_count; mbox_subject[0] = 0; pthread_mutex_unlock(&mbox_mutex); } static int GetCount(void) { int c; pthread_mutex_lock(&mbox_mutex); c = mbox_count; pthread_mutex_unlock(&mbox_mutex); return c; } static void SetCountAndSubject(int p_count, Subject p) { pthread_mutex_lock(&mbox_mutex); mbox_count = p_count; strcpy(mbox_subject, p); pthread_mutex_unlock(&mbox_mutex); } static int GetCountAndSubject(Subject p) { int c; pthread_mutex_lock(&mbox_mutex); c = mbox_count; strcpy(p, mbox_subject); pthread_mutex_unlock(&mbox_mutex); return c; } static void InboxHack(ICInboxHack *p) { int fd; char buff[1024]; Subject subject; int i; int cnt = 0; if ((fd = Connect(p->host, p->port)) != -1) { write(fd, "*inbox", 6); i = read(fd, buff, sizeof buff); close(fd); if (i > 0) { int cnt; buff[i] = 0; cnt = atoi(buff); if (cnt && ((fd = Connect(p->host, p->port)) != -1)) { write(fd, "@inbox", 6); i = read(fd, subject, sizeof subject); close(fd); if (i > 0) { subject[i] = 0; SetCountAndSubject(cnt, subject); } else { SetCount(cnt); } } else { SetCount(cnt); } } else { SetCount(0); } } else { SetCount(0); } } static void *ThreadCode(void *p_args) { ThreadArgs *args; int fd; args = p_args; while(1) { switch(args->type) { case eIC_InboxHack: InboxHack(p_args); sleep(10); break; default: sleep(30); break; } } return NULL; } static void XCls() { XSetForeground(display,gc,bg); XFillRectangle(display,pix,gc,0,0,width,height); XSetForeground(display,gc,fg); } static void XClear(int x, int y, int w, int h) { XSetForeground(display,gc,bg); XFillRectangle(display,pix,gc,x,y,w,h); XSetForeground(display,gc,fg); } static void XPlot(int x, int y) { XDrawPoint(display,pix,gc,x,y); } static void XLine(int x1, int y1, int x2, int y2) { XDrawLine(display,pix,gc,x1,y1,x2,y2); } static void XBox(int x, int y, int w, int h) { XFillRectangle(display,pix,gc,x,y,w,h); } static void XEmptyBox(int x, int y, int w, int h) { XDrawRectangle(display,pix,gc,x,y,w,h); } static void XPrint(int x, int y, const char *p) { XDrawString(display,pix,gc,x,y,p,strlen(p)); } static void XPrintf(int x, int y, const char *fmt, ...) { static char buff[1024]; va_list va; va_start(va,fmt); vsprintf(buff,fmt,va); va_end(va); XDrawString(display,pix,gc,x,y,buff,strlen(buff)); } static void XRedraw() { #ifdef USE_SHAPE if (shape_window) { XShapeCombineMask (display, win, ShapeBounding, 0, 0, pix, ShapeSet); } else #endif { XCopyArea(display,pix,win,gc,0,0,width,height,0,0); } XSync(display,False); } static void XCopy(int x,int y,int w,int h,int dx,int dy) { #ifdef USE_SHAPE if (shape_window) { XShapeCombineMask (display, win, ShapeBounding, 0, 0, pix, ShapeSet); } #endif else { XCopyArea(display,pix,win,gc,x,y,width,height,dx,dy); } XSync(display,False); } static void DrawByte(int b, int x, int y) { int f; for(f=0;f<8;f++) { if (b & (1<=0;cy--) { for(cx=0;cx<8;cx++) { if (font[ch]&(1<1) { mode=atoi(argv[1]); } else { mode=0; } if (argc > 3) { pthread_t t; args.type = eIC_InboxHack; args.ic_hack.host = argv[2]; args.ic_hack.port = argv[3]; pthread_create(&t, NULL, ThreadCode, &args); } if (mode < 0) { #ifdef USE_SHAPE shape_window = 1; #endif mode = -mode; } screen=DefaultScreen(display); depth=DefaultDepth(display,screen); /* Find a visual for us to use... */ if (!XMatchVisualInfo(display,DefaultScreen(display),depth, depth==8 ? PseudoColor:TrueColor,&vinfo)) { fprintf(stderr,"no visual to match the root window!\n"); exit(1); } if (shape_window) { char *name[]={"rootclock"}; XTextProperty prop; XClassHint class; XSizeHints size; width = 200; if (mode==2) { height = ANASIZE + 20; } else { height = 60; } size.flags = PSize|PPosition|PMinSize|PMaxSize; size.x = 0; size.y = 0; size.max_width = size.min_width = size.width = width; size.max_height = size.min_height = size.height = height; win = XCreateWindow(display, RootWindow(display,screen), 0, 0, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL); if (1) /* (argc < 3) */ { XSetWindowBackground(display, win, WhitePixel(display,screen)); } else { XWindowAttributes attr; XColor col; col.pixel = WhitePixel(display,screen); XGetWindowAttributes(display, win, &attr); XParseColor(display, attr.colormap, argv[2], &col); XSetWindowBackground(display, win, col.pixel); } pix = XCreatePixmap(display, win, width, height, 1); XSelectInput(display, win, 0); XStoreName(display, win, name[0]); XStringListToTextProperty(name, 1, &prop); XSetWMName(display, win, &prop); class.res_name = name[0]; class.res_class = name[0]; XSetClassHint(display, win, &class); XSetWMNormalHints(display, win, &size); bg = 0; fg = 1; } else { win=RootWindow(display,screen); width=DisplayWidth(display,screen); height=DisplayHeight(display,screen); pix=XCreatePixmap(display,win,width,height,vinfo.depth); bg = BlackPixel(display,screen); fg = WhitePixel(display,screen); } gc=XCreateGC(display,pix,0,NULL); XSetForeground(display,gc,fg); XSetBackground(display,gc,bg); XSetPlaneMask(display,gc,AllPlanes); XMapWindow (display,win); if (!shape_window) { XSetWindowBackgroundPixmap(display,win,pix); } XSync(display,False); XCls(); XRedraw(); /* putenv("TZ=GMT0BST"); */ while(1) { static time_t start_time=0; time_t diff; time_t t; struct tm *tm; int mbox; Subject subject; int f; if (start_time==0) { start_time=time(NULL); } t=time(NULL); diff=t-start_time; tm=localtime(&t); while(XPending(display)) { XEvent e; XNextEvent(display, &e); } mbox = GetCountAndSubject(subject); switch(mode) { case 1: XClear(0,0,64,24); DrawByte(tm->tm_sec,0,0); DrawByte(tm->tm_min,0,10); DrawByte(tm->tm_hour,0,20); XCopy(0,0,64,28,0,0); break; case 2: DrawAnalogue(tm->tm_hour,tm->tm_min,tm->tm_sec); break; case 3: XClear(0,0,600,100); XPrintSinclair(0,0,2,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); XCopy(0,0,600,100,0,0); break; case 34: XClear(0,0,600,100); XPrintSinclair(0,0,2,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); XPrintSinclair(2,2,1,"%2.2d %s %4.4d",tm->tm_mday, mon[tm->tm_mon], 1900+tm->tm_year); if (mbox) { for(f = 0; f < mbox; f++) { XPrintSinclair(f,3,1,"\177"); } XPrintSinclair(0,4,1, "%s", subject); } XCopy(0,0,600,100,0,0); break; case 35: XClear(0,0,600,100); XPrintSinclair(0,0,2,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); XPrintSinclair(2,2,1,"%2.2d %s %4.4d",tm->tm_mday, mon[tm->tm_mon], 1900+tm->tm_year); for(f = 0; f < mbox; f++) { XPrintSinclair(f,3,1,"\177"); } XCopy(0,0,600,100,0,0); break; case 36: XClear(0,0,600,100); XPrintSinclairShaded(0,0,2,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); XPrintSinclairShaded(2,3,1,"%2.2d %s %4.4d",tm->tm_mday, mon[tm->tm_mon], 1900+tm->tm_year); XCopy(0,0,600,100,0,0); break; case 37: XClear(0,0,600,100); XPrintSinclair(0,0,2,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); XPrintSinclair(2,2,1,"%2.2d %s %4.4d",tm->tm_mday, mon[tm->tm_mon], 1900+tm->tm_year); XPrintSinclair(0,3,1,"\177 %d", mbox); XCopy(0,0,600,100,0,0); break; case 4: XClear(0,0,600,100); XPrintSinclair(0,0,2,"%2.2X:%2.2X:%2.2X",tm->tm_hour, tm->tm_min, tm->tm_sec); XCopy(0,0,600,100,0,0); break; default: XClear(0,0,600,100); XPrintf(0,10,"%2.2d:%2.2d:%2.2d",tm->tm_hour, tm->tm_min, tm->tm_sec); /* XPrintf(0,30,"+%1.1d:%2.2d:%2.2d",diff/3600, (diff%3600)/60, diff%60); */ XCopy(0,0,600,100,0,0); break; } sleep(1); } } /* END OF FILE */