/* * 9clock.c: a basic graphical clock for plan 9 * sean caron (scaron@umich.edu) */ /* * The paradigm here is that we must always include u.h * first and libc.h second, and anything else after that. */ #include #include #include #include #include int main(void); void eresized(int new); int main(void) { Point center, minend, hrend, o_minend, o_hrend; Tm *thetime; int xdim, ydim, fd; double mintheta, hrtheta; char *buttons[] = { "quit", 0 }; Menu menu = { buttons }; Mouse m; Event e; ulong timer, evtype; initdraw(nil, nil, "9clock"); /* * initialize event handler for mouse events only. we * must call this subsequent to initdraw(). */ einit(Emouse); /* we need to call this resize handler at least once */ eresized(0); /* * we need to set up this timer event because when you use * the event() system call, it basically blocks until some sort * of event occurs. we use the timer event in lieu of a real * event occurring or else the clock would not update until * the user moved the mouse or clicked a button. */ timer = etimer(0,10); /* * initdraw() sets up some global variables, * * Display *display * Image *screen * Screen *_screen * Font *font * * ZP is a constant point (0,0). */ /* resize the current window. */ fd = open("/dev/wctl", OWRITE); fprint(fd, "resize -dx 200 -dy 200"); close(fd); getwindow(display, Refnone); /* initialize some variables. */ xdim = (screen->r.max.x - screen->r.min.x) / 2; ydim = (screen->r.max.y - screen->r.min.y) / 2; center.x = screen->r.min.x + xdim; center.y = screen->r.min.y + ydim; /* main program loop */ while (1) { evtype = event(&e); /* look for mouse events */ if (evtype == Emouse) { m = e.mouse; /* if left mouse button is clicked, show the menu */ if (m.buttons == 4) { /* quit */ if (emenuhit(3, &m, &menu) == 0) { closedisplay(display); exits(0); } } } /* use the faux timer event to update the clock if there is no real input */ else if (event(&e) == timer) { /* draw outline of clock face. */ ellipse(screen, center, xdim, ydim, 2, display->black, center); thetime = localtime(time(nil)); /* correct 24 hour system time to 12 hour clock. */ if (thetime->hour > 12) { thetime->hour = thetime->hour - 12; } /* * 6 degrees = 0.104718 rads per minute on the clock face. * 30 degrees = 0.523590 rads per hour on the clock face. * * we subtract the value from PI/2 to correct between standard * form and clock form. */ mintheta = (PI/2.0) - (0.104718 * (double)thetime->min); hrtheta = (PI/2.0) - (0.523590 * (double)thetime->hour); /* * calculate the endpoints for the minute and hour hands. * we resize the window to be square so xdim and ydim are actually the same. * we scale down the hour hand to make it shorter than the minute hand. */ minend.x = center.x + (double)xdim*cos(mintheta); minend.y = center.y - (double)ydim*sin(mintheta); hrend.x = center.x + (double)xdim*cos(hrtheta); hrend.y = center.y - (double)ydim*sin(hrtheta); /* * if the time has changed since the last time we looped, get rid of the stale minute or * hour hands. */ if ((o_minend.x != minend.x) || (o_minend.y != minend.y)) { line(screen, center, o_minend, Endsquare, Endarrow, 1, display->white, center); } if ((o_hrend.x != hrend.x) || (o_hrend.y != hrend.y)) { line(screen, center, o_hrend, Endsquare, Endarrow, 2, display->white, center); } /* draw the current minute and hour hands. */ line(screen, center, minend, Endsquare, Endarrow, 1, display->black, center); line(screen, center, hrend, Endsquare, Endarrow, 2, display->black, center); /* save the minute and hour hand coordinates for comparison the next time around. */ o_minend = minend; o_hrend = hrend; /* let some other processes get a word in edgewise. */ sleep(1); /* * the draw (2) manpage suggests that this is not required, but the graphics will not * show up unless we use it. */ flushimage(display,1); } } } /* * by convention we must declare an eresized() function to * handle the window resizing event. */ void eresized(int new) { /* just refresh the window for now. */ getwindow(display, Refnone); }