1 /*
2 * wmslib/src/but/timer.c, part of wmslib (Library functions)
3 * Copyright (C) 1994 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #ifdef X11_DISP
10
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/cursorfont.h>
14 #include <X11/Xatom.h>
15 #include <X11/keysym.h>
16 #include <sys/time.h>
17 #include <wms.h>
18 #include <but/but.h>
19 #include <but/timer.h>
20
21
butTimer_create(void * packet,But * but,struct timeval delay,struct timeval period,bool winOnly,ButOut (* timerFunc)(ButTimer * timer))22 ButTimer *butTimer_create(void *packet, But *but, struct timeval delay,
23 struct timeval period, bool winOnly,
24 ButOut (*timerFunc)(ButTimer *timer)) {
25 ButTimer *bt;
26 struct timeval now;
27 struct timezone tzone;
28
29 bt = wms_malloc(sizeof(ButTimer));
30 MAGIC_SET(bt);
31 bt->packet = packet;
32 bt->eventNum = 0;
33 bt->period = period;
34 bt->state = butTimer_on;
35 gettimeofday(&now, &tzone);
36 bt->nextFiring = but_timerAdd(now, delay);
37 if (but)
38 bt->win = but->win;
39 else
40 bt->win = NULL;
41 bt->but = but;
42 bt->timerFunc = timerFunc;
43 bt->winOnly = winOnly;
44 bt->next = but_timerList;
45 bt->freqCounter = FALSE;
46 bt->ticksLeft = 0;
47 but_timerList = bt;
48 return(bt);
49 }
50
51
butTimer_fCreate(void * packet,But * but,struct timeval delay,int frequency,bool winOnly,ButOut (* timerFunc)(ButTimer * timer))52 ButTimer *butTimer_fCreate(void *packet, But *but, struct timeval delay,
53 int frequency, bool winOnly,
54 ButOut (*timerFunc)(ButTimer *timer)) {
55 ButTimer *bt;
56 struct timeval now;
57 struct timezone tzone;
58 int i;
59
60 bt = wms_malloc(sizeof(ButTimer));
61 MAGIC_SET(bt);
62 bt->packet = packet;
63 bt->eventNum = 0;
64 bt->period.tv_sec = 0;
65 bt->winOnly = winOnly;
66 if (frequency < BUTTIMER_MAXFREQ) {
67 bt->period.tv_usec = 1000000 / frequency;
68 bt->ticksPerPeriod = 1;
69 } else {
70 bt->period.tv_usec = 1000000 / BUTTIMER_STDFREQ;
71 bt->ticksPerPeriod = (frequency + BUTTIMER_STDFREQ/2) /
72 BUTTIMER_STDFREQ;
73 }
74 bt->state = butTimer_on;
75 gettimeofday(&now, &tzone);
76 bt->nextFiring = but_timerAdd(now, delay);
77 if (but)
78 bt->win = but->win;
79 else
80 bt->win = NULL;
81 bt->but = but;
82 bt->timerFunc = timerFunc;
83 bt->next = but_timerList;
84 bt->freqCounter = TRUE;
85 for (i = 0; i < BUTTIMER_HIST; ++i)
86 bt->lastRes[i] = 1;
87 bt->resnum = 0;
88 bt->ticksLeft = 0;
89 but_timerList = bt;
90 return(bt);
91 }
92
93
butTimer_destroy(ButTimer * timer)94 void butTimer_destroy(ButTimer *timer) {
95 assert(MAGIC(timer));
96 timer->state = butTimer_dead;
97 }
98
99
butTimer_reset(ButTimer * timer)100 void butTimer_reset(ButTimer *timer) {
101 struct timeval now;
102 struct timezone tzone;
103
104 assert(MAGIC(timer));
105 timer->eventNum = 0;
106 gettimeofday(&now, &tzone);
107 timer->nextFiring = but_timerAdd(now, timer->period);
108 }
109
110
but_timerAdd(struct timeval t1,struct timeval t2)111 struct timeval but_timerAdd(struct timeval t1, struct timeval t2) {
112 struct timeval r;
113
114 r.tv_sec = t1.tv_sec + t2.tv_sec;
115 if ((r.tv_usec = t1.tv_usec + t2.tv_usec) > 1000000) {
116 r.tv_usec -= 1000000;
117 ++r.tv_sec;
118 }
119 return(r);
120 }
121
122
but_timerSub(struct timeval t1,struct timeval t2)123 struct timeval but_timerSub(struct timeval t1, struct timeval t2) {
124 struct timeval r;
125
126 r.tv_sec = t1.tv_sec - t2.tv_sec;
127 if ((r.tv_usec = t1.tv_usec - t2.tv_usec) < 0) {
128 r.tv_usec += 1000000;
129 --r.tv_sec;
130 }
131 if (r.tv_sec < 0)
132 r.tv_sec += 60*60*24;
133 return(r);
134 }
135
136
but_timerDiv(struct timeval t1,struct timeval t2,struct timeval * remainder)137 int but_timerDiv(struct timeval t1, struct timeval t2,
138 struct timeval *remainder) {
139 int result;
140 long it1, it2, irem;
141
142 it1 = (t1.tv_sec*1000000L) + t1.tv_usec;
143 it2 = (t2.tv_sec*1000000L) + t2.tv_usec;
144 result = it1 / it2;
145 if (remainder != NULL) {
146 irem = it1 % it2;
147 remainder->tv_usec = irem % 1000000;
148 remainder->tv_sec = irem / 1000000;
149 }
150 return(result);
151 }
152
153
butEnv_checkTimers(ButEnv * env,struct timeval * timeout)154 int butEnv_checkTimers(ButEnv *env, struct timeval *timeout) {
155 struct timeval current_time, next_timer, timerem;
156 struct timezone tzone;
157 bool take_timer, timer_set = FALSE;
158 ButTimer *bt, *bt2;
159 int ticks, i, orig_ticks;
160 int result = 0;
161
162 /* First, kill off all the dead timers. */
163 for (bt = but_timerList; bt != NULL;) {
164 if (bt->state == butTimer_dead) {
165 if (bt == but_timerList)
166 but_timerList = bt->next;
167 else {
168 for (bt2 = but_timerList; bt2->next != bt; bt2 = bt2->next);
169 bt2->next = bt->next;
170 }
171 bt2 = bt->next;
172 MAGIC_UNSET(bt);
173 wms_free(bt);
174 bt = bt2;
175 } else {
176 bt = bt->next;
177 }
178 }
179 gettimeofday(¤t_time, &tzone);
180 for (bt = but_timerList; bt != NULL; bt = bt->next) {
181 if (bt->state == butTimer_on) {
182 if (timercmp(&bt->nextFiring, ¤t_time, <)) {
183 take_timer = TRUE;
184 ticks = but_timerDiv(but_timerSub(current_time, bt->nextFiring),
185 bt->period, &timerem) + 1 + bt->ticksLeft;
186 take_timer = TRUE;
187 orig_ticks = ticks;
188 if (bt->freqCounter) {
189 for (i = 0; i < BUTTIMER_HIST; ++i) {
190 if (bt->lastRes[i] > ticks) {
191 take_timer = FALSE;
192 }
193 }
194 if (!bt->ticksLeft) {
195 bt->lastRes[bt->resnum] = ticks;
196 bt->resnum = (bt->resnum + 1) & (BUTTIMER_HIST - 1);
197 }
198 ticks *= bt->ticksPerPeriod;
199 }
200 bt->nextFiring = but_timerSub(but_timerAdd(current_time, bt->period),
201 timerem);
202 if (take_timer) {
203 bt->eventNum += ticks;
204 result |= bt->timerFunc(bt);
205 XSync(env->dpy, False);
206 bt->ticksLeft = 0;
207 } else
208 bt->ticksLeft += orig_ticks;
209 }
210 if (!timer_set || timercmp(&bt->nextFiring, &next_timer, <)) {
211 timer_set = TRUE;
212 next_timer = bt->nextFiring;
213 }
214 }
215 }
216 if (timer_set)
217 *timeout = but_timerSub(next_timer, current_time);
218 else {
219 timeout->tv_usec = 0;
220 timeout->tv_sec = 365*24*60*60; /* 1 spurious interrupt per year. */
221 }
222 return(result);
223 }
224
225 #endif /* X11_DISP */
226