chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / misc.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2008 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "eobj.h"
26 #include "xwin.h"
27 #include <sys/time.h>
28 #include <time.h>
29
30 /* This is a general quicksort algorithm, using median-of-three strategy.
31  * 
32  * Parameters:
33  * ===========
34  * a:            array of items to be sorted (list of void pointers).
35  * l:            left edge of sub-array to be sorted. Toplevel call has 0 here.
36  * r:            right edge of sub-array to be sorted. Toplevel call has |a| - 1 here.
37  * CompareFunc:  Pointer to a function that accepts two general items d1 and d2
38  * and returns values as follows:
39  * 
40  * < 0  --> d1 "smaller" than d2
41  * > 0  --> d1 "larger"  than d2
42  * 0    --> d1 "==" d2.
43  * 
44  * See sample application in ipc.c's IPC_Help.
45  */
46 void
47 Quicksort(void **a, int l, int r, int (*CompareFunc) (void *d1, void *d2))
48 {
49
50    int                 i, j, m;
51    void               *v, *t;
52
53    if (r > l)
54      {
55
56         m = (r + l) / 2 + 1;
57         if (CompareFunc(a[l], a[r]) > 0)
58           {
59              t = a[l];
60              a[l] = a[r];
61              a[r] = t;
62           }
63         if (CompareFunc(a[l], a[m]) > 0)
64           {
65              t = a[l];
66              a[l] = a[m];
67              a[m] = t;
68           }
69         if (CompareFunc(a[r], a[m]) > 0)
70           {
71              t = a[r];
72              a[r] = a[m];
73              a[m] = t;
74           }
75
76         v = a[r];
77         i = l - 1;
78         j = r;
79
80         for (;;)
81           {
82              while (CompareFunc(a[++i], v) < 0)
83                 ;
84              while (CompareFunc(a[--j], v) > 0)
85                 ;
86              if (i >= j)
87                 break;
88              t = a[i];
89              a[i] = a[j];
90              a[j] = t;
91           }
92         t = a[i];
93         a[i] = a[r];
94         a[r] = t;
95         Quicksort(a, l, i - 1, CompareFunc);
96         Quicksort(a, i + 1, r, CompareFunc);
97      }
98 }
99
100 /*
101  * Stuff to make loops for animated effects.
102  */
103 struct timeval      etl_tv_start;
104 static int          etl_k1, etl_k2;
105 static double       etl_k, etl_fac;
106
107 /*
108  * Return elapsed time in seconds since t0
109  */
110 static double
111 ETimeElapsed(struct timeval *t0)
112 {
113    struct timeval      tv;
114    int                 sec, usec;
115
116    gettimeofday(&tv, NULL);
117    sec = tv.tv_sec - t0->tv_sec;
118    usec = tv.tv_usec - t0->tv_usec;
119    return (double)sec + (((double)usec) / 1000000);
120 }
121
122 #include <math.h>
123
124 static float
125 ETimeCurve(int k1, int k2, float k, int mode)
126 {
127    float               x, l;
128
129    if (k >= k2 || mode == 0)
130       return k;
131
132    l = k2 - k1;
133    x = k - k1;
134
135    switch (mode)
136      {
137      case 1:                    /* Sinuoidal - half cycle */
138         x = x / l - 0.5;        /* x: -0.5 -> 0.5 */
139         x = (float)(0.5 * (1. + sin(x * M_PI)));
140         break;
141      case 2:                    /* Sinuoidal - quarter cycle */
142         x = x / l;              /* x: 0 -> 1 */
143         x = (float)sin(x * M_PI / 2);
144         break;
145      }
146
147    return k1 + x * l;
148 }
149
150 void
151 ETimedLoopInit(int k1, int k2, int speed)
152 {
153    etl_k1 = k1;
154    etl_k2 = k2;
155    if (speed < 500)
156       speed = 500;
157    /* When speed is 1000 the loop will take one sec. */
158    etl_fac = (k2 - k1) * (double)speed / 1000.;
159
160    gettimeofday(&etl_tv_start, NULL);
161    ESync(ESYNC_TLOOP);
162 }
163
164 int
165 ETimedLoopNext(void)
166 {
167    double              tm, y;
168
169    /* Is this portable? */
170    usleep(5000);
171
172    /* Find elapsed time since loop start */
173    tm = ETimeElapsed(&etl_tv_start);
174    etl_k = etl_k1 + tm * etl_fac;
175 #if 0
176    Eprintf("ETimedLoopNext k=%4f tm=%.3f\n", etl_k, tm);
177 #endif
178    y = ETimeCurve(etl_k1, etl_k2, (float)etl_k, 2);
179
180    EobjsRepaint();
181
182    return (int)y;
183 }
184
185 /*
186  * Debug/error message printing.
187  */
188 static struct timeval tv0 = { 0, 0 };
189
190 static void
191 _tvdiff(struct timeval *tvd, const struct timeval *tv1,
192         const struct timeval *tv2)
193 {
194    long                tsec, tus;
195
196    tsec = tv2->tv_sec - tv1->tv_sec;
197    tus = tv2->tv_usec - tv1->tv_usec;
198    if (tus < 0)
199      {
200         tus += 1000000;
201         tsec -= 1;
202      }
203    tvd->tv_sec = tsec;
204    tvd->tv_usec = tus;
205 }
206
207 void
208 Eprintf(const char *fmt, ...)
209 {
210    va_list             args;
211    struct timeval      tv;
212
213    if (tv0.tv_sec == 0)
214       gettimeofday(&tv0, NULL);
215
216    gettimeofday(&tv, NULL);
217    _tvdiff(&tv, &tv0, &tv);
218
219    if (Conf.difftime)
220      {
221         static struct timeval tv1 = { 0, 0 };
222         struct timeval      tvd;
223         unsigned long       nreq;
224
225         _tvdiff(&tvd, &tv1, &tv);
226         tv1 = tv;
227
228         nreq = (disp) ? NextRequest(disp) : 0;
229         fprintf(stdout, "[%d] %#8lx %4ld.%06ld [%3ld.%06ld]: ", getpid(), nreq,
230                 (long)tv1.tv_sec, tv1.tv_usec, (long)tvd.tv_sec, tvd.tv_usec);
231      }
232    else
233      {
234         fprintf(stdout, "[%d] %4ld.%06ld: ", getpid(),
235                 (long)tv.tv_sec, tv.tv_usec);
236      }
237
238    va_start(args, fmt);
239    vfprintf(stdout, fmt, args);
240    va_end(args);
241 }
242
243 #if ENABLE_DEBUG_EVENTS
244 /*
245  * Event debug stuff
246  */
247 #define N_DEBUG_FLAGS 256
248 static char         ev_debug;
249 static char         ev_debug_flags[N_DEBUG_FLAGS];
250
251 /*
252  * param is <ItemNumber>[:<ItemNumber> ... ]
253  *
254  * ItemNumber:
255  * 0            : Verbose flag
256  * 1            : X11 errors
257  * [   2;  35 [ : X11 event codes, see /usr/include/X11/X.h
258  * [  64; ... [ : Remapped X11 events, see events.h
259  * [ 128; 256 [ : E events, see E.h
260  */
261 void
262 EDebugInit(const char *param)
263 {
264    const char         *s;
265    int                 ix, onoff;
266
267    if (!param)
268       return;
269
270    for (;;)
271      {
272         s = strchr(param, ':');
273         if (!param[0])
274            break;
275         ev_debug = 1;
276         ix = strtol(param, NULL, 0);
277         onoff = (ix >= 0);
278         if (ix < 0)
279            ix = -ix;
280         if (ix < N_DEBUG_FLAGS)
281           {
282              if (onoff)
283                 ev_debug_flags[ix]++;
284              else
285                 ev_debug_flags[ix] = 0;
286           }
287         if (!s)
288            break;
289         param = s + 1;
290      }
291 }
292
293 int
294 EDebug(unsigned int type)
295 {
296    return (ev_debug &&
297            (type < sizeof(ev_debug_flags))) ? ev_debug_flags[type] : 0;
298 }
299
300 void
301 EDebugSet(unsigned int type, int value)
302 {
303    if (type >= sizeof(ev_debug_flags))
304       return;
305
306    ev_debug = 1;
307    ev_debug_flags[type] += value;
308 }
309
310 #endif
311
312 #if USE_MODULES
313 /*
314  * Dynamic module loading
315  */
316 #include <dlfcn.h>
317
318 const void         *
319 ModLoadSym(const char *lib, const char *sym, const char *name)
320 {
321    char                buf[1024];
322    void               *h;
323
324    Esnprintf(buf, sizeof(buf), "%s/lib%s_%s.so", ENLIGHTENMENT_LIB, lib, name);
325    if (EDebug(1))
326       Eprintf("ModLoad %s\n", buf);
327    h = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
328    if (!h)
329       Eprintf("*** ModLoad %s: %s\n", buf, dlerror());
330    if (!h)
331       return NULL;
332
333    Esnprintf(buf, sizeof(buf), "%s_%s", sym, name);
334    h = dlsym(h, buf);
335    if (!h)
336       Eprintf("*** ModLoad %s: %s\n", buf, dlerror());
337
338    return h;
339 }
340
341 #endif /* USE_MODULES */