From f72cc39e2b1a14dec72e4f0b88728dbe6b61587d Mon Sep 17 00:00:00 2001 From: Ian C Date: Fri, 3 Jun 2011 13:49:30 +0000 Subject: Initial import. --- Makefile | 2 + rootclock.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 891 insertions(+) create mode 100644 Makefile create mode 100644 rootclock.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..51e0ce1 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +rootclock: rootclock.c + cc -o rootclock rootclock.c -lX11 -lXext -lm -lpthread diff --git a/rootclock.c b/rootclock.c new file mode 100644 index 0000000..9074262 --- /dev/null +++ b/rootclock.c @@ -0,0 +1,889 @@ +#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 */ -- cgit v1.2.3