#include #include #include #include /* "Magic clock" * It's unfortunate that face[] and map[] aren't connected better. * init() and drawclock() are also very hard-coded to this specific face. */ Image *background; Image *inactive; Image *active; Font *font; char* fontname; Tm* now; int center, resize; char* face[31] = {"IT", "R", "IS", "O", "TWENTY", "QUARTER", "A", "HALF", "TEN", "FIVE", "L", "PAST", "TO", "U", "TWELVE", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "MSB", "ELEVEN", "ALM", "A", "O\'CLOCK", "COLS"}; int map[31][2][12]; void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void init(void) { if(initdraw(nil, nil, argv0) < 0) { fprint(2, "%s: initdraw failed: %r\n", argv0); exits("initdraw"); } background = allocimagemix(display, DBlack, 0x443344FF); if(background==nil) { fprint(2, "%s: can't create images: %r\n", argv0); exits("image"); } inactive = allocimagemix(display, DWhite, DBlack); if(inactive==nil) { fprint(2, "%s: can't create images: %r\n", argv0); exits("image"); } active = allocimagemix(display, DWhite, DWhite); if(active==nil) { fprint(2, "%s: can't create images: %r\n", argv0); exits("image"); } font = openfont(display, fontname); if(font == nil) { fprint(2, "%s: openfont failed for font: %r\n", argv0); exits("font"); } draw(screen, screen->r, background, nil, ZP); memset(map, 0, sizeof(map)); /* Hours; this is inherently 12-hour, 0=12. */ map[14][0][0] = 1; map[15][0][1] = 1; map[16][0][2] = 1; map[17][0][3] = 1; map[18][0][4] = 1; map[19][0][5] = 1; map[20][0][6] = 1; map[21][0][7] = 1; map[22][0][8] = 1; map[23][0][9] = 1; map[24][0][10] = 1; map[26][0][11] = 1; /* Minutes, divided by 5. */ map[29][1][0] = 1; map[9][1][1] = 1; map[8][1][2] = 1; map[5][1][3] = 1; map[4][1][4] = 1; map[4][1][5] = 1; /* For 25 past, light up "TWENTY"... */ map[9][1][5] = 1; /* ...and "FIVE". */ map[7][1][6] = 1; map[4][1][7] = 1; /* For 25 to, light up "TWENTY"... */ map[9][1][7] = 1; /* ...and "FIVE". */ map[4][1][8] = 1; map[5][1][9] = 1; map[8][1][10] = 1; map[9][1][11] = 1; } #define DISPLAY(f) if(map[f][0][hh] == 1 || map[f][1][mm] == 1) \ insert = string(screen, insert, active, ZP, font, face[f]); \ else insert = string(screen, insert, inactive, ZP, font, face[f]); void drawclock() { int hh, mm, until; Point insert; int margin[2] = {40, 40}; until = 0; if(center) { margin[0] = (screen->r.max.x-screen->r.min.x-stringsize(font, "XXXXXXXXXXXX").x)/2; margin[1] = (screen->r.max.y-screen->r.min.y-stringsize(font, "X").y*9)/2; } hh = now->hour%12; mm = now->min/5; if (mm >= 7) { until++; hh = (hh+1)%12; } draw(screen, screen->r, background, nil, ZP); insert = addpt(Pt(margin[0], margin[1]), screen->r.min); insert = string(screen, insert, active, ZP, font, face[0]); insert = string(screen, insert, inactive, ZP, font, face[1]); insert = string(screen, insert, active, ZP, font, face[2]); insert = string(screen, insert, inactive, ZP, font, face[3]); DISPLAY(4); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+stringsize(font, "X").y); DISPLAY(5); insert = string(screen, insert, inactive, ZP, font, face[6]); DISPLAY(7); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*2); DISPLAY(8); DISPLAY(9); insert = string(screen, insert, inactive, ZP, font, face[10]); if((!until) && mm) insert = string(screen, insert, active, ZP, font, face[11]); else insert = string(screen, insert, inactive, ZP, font, face[11]); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*3); if(!until) insert = string(screen, insert, inactive, ZP, font, face[12]); else insert = string(screen, insert, active, ZP, font, face[12]); insert = string(screen, insert, inactive, ZP, font, face[13]); DISPLAY(14); DISPLAY(15); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*4); DISPLAY(16); DISPLAY(17); DISPLAY(18); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*5); DISPLAY(19); DISPLAY(20); DISPLAY(21); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*6); DISPLAY(22); DISPLAY(23); DISPLAY(24); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*7); insert = string(screen, insert, inactive, ZP, font, face[25]); DISPLAY(26); insert = string(screen, insert, inactive, ZP, font, face[27]); insert = Pt(screen->r.min.x+margin[0], screen->r.min.y+margin[1]+(stringsize(font, "X").y)*8); insert = string(screen, insert, inactive, ZP, font, face[28]); DISPLAY(29); insert = string(screen, insert, inactive, ZP, font, face[30]); flushimage(display, 1); } void eresized(int new) { if(new && getwindow(display, Refmesg) < 0) fprint(2,"can't reattach to window"); draw(screen, screen->r, background, nil, ZP); drawclock(); flushimage(display, 1); } void main(int argc, char *argv[]) { Event e; int Etimer, tflag; center = resize = tflag = 0; /* We don't have great monospaced options on Plan 9 by default. */ fontname = "/lib/font/bit/pelm/ascii.16.font"; if ((strcmp(getenv("service"), "unix") == 0) || strcmp(getenv("service"), "") == 0) { fontname = "/mnt/font/Menlo-Regular/48a/font"; } ARGBEGIN { case 'c': center++; break; case 't': tflag = atol(EARGF(usage())); break; case 'f': fontname = EARGF(usage()); break; default: usage(); } ARGEND init(); /* We don't need mouse events, but resize events are sent over /dev/mouse, */ /* so we won't see them unless we ask for mouse events somehow. */ einit(Ekeyboard|Emouse); Etimer = etimer(0, 10000); /* This is a low-precision clock; redraw less. */ for (;;) { if (!tflag) now = localtime(time(0)); else now = localtime(tflag); drawclock(); switch(eread(Ekeyboard|Etimer, &e)) { case Ekeyboard: if(e.kbdc==0x7F || e.kbdc=='q') exits(0); break; default: break; } } }