-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path9clock.c
More file actions
169 lines (137 loc) · 4.98 KB
/
9clock.c
File metadata and controls
169 lines (137 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* 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 <u.h>
#include <libc.h>
#include <draw.h>
#include <cursor.h>
#include <event.h>
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);
}