#include #include #include #include Point circlept(Point c, int r, int degrees) { double rad = (double)degrees * PI / 180.0; c.x += cos(rad) * r; c.y -= sin(rad) * r; return c; } void lineb(Image* dst, Point p0, Point p1, Image* src, Point sp) { int dx = abs(p1.x - p0.x), sx = p0.x < p1.x ? 1 : -1; int dy = -abs(p1.y - p0.y), sy = p0.y < p1.y ? 1 : -1; int err = dx + dy, e2; for(;;) { draw(dst, Rect(p0.x, p0.y, p0.x + 1, p0.y + 1), src, nil, ZP); if(p0.x == p1.x && p0.y == p1.y) break; e2 = 2 * err; if(e2 >= dy) { err += dy; p0.x += sx; } if(e2 <= dx) { err += dx; p0.y += sy; } } } void redraw(Image* dst) { Point size = subpt(screen->r.max, screen->r.min); Point center = divpt(size, 2); Rectangle frame = (Rectangle){Pt(0, 0), size}; int pad = 20; int rad = ((size.x < size.y ? size.x : size.y) / 2) - pad; int range = rad - pad; Image* view = allocimage(display, frame, screen->chan, 1, 0x000000FF); Image* secclr = allocimagemix(display, DRed, DRed); for(int i = 0; i < 60; i++) { int len = i % 15 == 0 ? range : i % 5 == 0 ? rad - pad / 2 : rad - pad / 3; lineb(view, circlept(center, len, i * 6), circlept(center, rad, i * 6), display->white, ZP); } Tm tms = *localtime(time(0)); int anghr = 90 - (tms.hour * 5 + tms.min / 12) * 6; int angmin = 90 - tms.min * 6; int angsec = 90 - tms.sec * 6; int angsecrev = 270 - tms.sec * 6; fillellipse(view, center, rad - pad, rad - pad, display->black, ZP); lineb(view, center, circlept(center, range * 0.7, anghr), display->white, ZP); lineb(view, center, circlept(center, range - 2, angmin), display->white, ZP); lineb(view, center, circlept(center, range - 2, angsec), secclr, ZP); lineb(view, center, circlept(center, range * 0.1, angsecrev), secclr, ZP); fillellipse(view, center, 2, 2, secclr, ZP); /* collapse when horizontal window */ if(size.y > size.x + 2 * pad) { /* time */ char timestr[9]; snprint(timestr, sizeof(timestr), "%02d:%02d:%02d", tms.hour, tms.min, tms.sec); Point timesize = stringsize(display->defaultfont, timestr); Point timept = Pt(pad, pad); /* date */ char datestr[30]; snprint(datestr, sizeof(datestr), "%s", ctime(time(0))); datestr[10] = '\0'; Point datesize = stringsize(display->defaultfont, datestr); Point datept = Pt(size.x - datesize.x - pad, pad); /* draw */ draw(view, (Rectangle){timept, addpt(timept, Pt(size.x - pad * 2, 0))}, display->black, nil, ZP); string(view, timept, display->white, ZP, display->defaultfont, timestr); if(timesize.x + datesize.x < size.x - pad - pad) string(view, datept, display->white, ZP, display->defaultfont, datestr); } draw(dst, screen->r, view, nil, ZP); flushimage(display, 1); freeimage(secclr); freeimage(view); } void eresized(int new) { if(new&& getwindow(display, Refnone) < 0) fprint(2, "can't reattach to window"); redraw(screen); } void main(int argc, char* argv[]) { USED(argc, argv); Event e; Mouse m; Menu menu; char* mstr[] = {"exit", 0}; int key, timer, t = 1000; if(initdraw(0, 0, "clock") < 0) sysfatal("initdraw failed"); eresized(0); einit(Emouse); timer = etimer(0, t); menu.item = mstr; menu.lasthit = 0; for(;;) { key = event(&e); if(key == Emouse) { m = e.mouse; if(m.buttons & 4) { if(emenuhit(3, &m, &menu) == 0) exits(0); } } else if(key == timer) { redraw(screen); } } }