1 b330c942 2005-10-31 devnull #include <u.h>
2 b330c942 2005-10-31 devnull #include <libc.h>
3 b330c942 2005-10-31 devnull #include <draw.h>
4 b330c942 2005-10-31 devnull #include <plumb.h>
5 b330c942 2005-10-31 devnull #include <regexp.h>
6 b330c942 2005-10-31 devnull #include <bio.h>
7 b330c942 2005-10-31 devnull #include <9pclient.h>
8 b330c942 2005-10-31 devnull #include "faces.h"
10 b330c942 2005-10-31 devnull enum /* number of deleted faces to cache */
12 b330c942 2005-10-31 devnull Nsave = 20,
15 b330c942 2005-10-31 devnull static Facefile *facefiles;
16 b330c942 2005-10-31 devnull static int nsaved;
17 b330c942 2005-10-31 devnull static char *facedom;
20 b330c942 2005-10-31 devnull * Loading the files is slow enough on a dial-up line to be worth this trouble
22 b330c942 2005-10-31 devnull typedef struct Readcache Readcache;
23 b330c942 2005-10-31 devnull struct Readcache {
24 b330c942 2005-10-31 devnull char *file;
25 b330c942 2005-10-31 devnull char *data;
26 b330c942 2005-10-31 devnull long mtime;
27 b330c942 2005-10-31 devnull long rdtime;
28 b330c942 2005-10-31 devnull Readcache *next;
31 b330c942 2005-10-31 devnull static Readcache *rcache;
34 b330c942 2005-10-31 devnull dirlen(char *s)
37 b330c942 2005-10-31 devnull ulong len;
39 b330c942 2005-10-31 devnull d = dirstat(s);
40 b330c942 2005-10-31 devnull if(d == nil)
41 b330c942 2005-10-31 devnull return 0;
42 b330c942 2005-10-31 devnull len = d->length;
44 b330c942 2005-10-31 devnull return len;
48 b330c942 2005-10-31 devnull fsdirlen(CFsys *fs,char *s)
51 b330c942 2005-10-31 devnull ulong len;
53 b330c942 2005-10-31 devnull d = fsdirstat(fs,s);
54 b330c942 2005-10-31 devnull if(d == nil)
55 b330c942 2005-10-31 devnull return 0;
56 b330c942 2005-10-31 devnull len = d->length;
58 b330c942 2005-10-31 devnull return len;
62 b330c942 2005-10-31 devnull dirmtime(char *s)
67 b330c942 2005-10-31 devnull d = dirstat(s);
68 b330c942 2005-10-31 devnull if(d == nil)
69 b330c942 2005-10-31 devnull return 0;
70 b330c942 2005-10-31 devnull t = d->mtime;
72 b330c942 2005-10-31 devnull return t;
75 b330c942 2005-10-31 devnull static char*
76 b330c942 2005-10-31 devnull doreadfile(char *s)
79 b330c942 2005-10-31 devnull int fd, n;
80 b330c942 2005-10-31 devnull ulong len;
82 b330c942 2005-10-31 devnull len = dirlen(s);
83 b330c942 2005-10-31 devnull if(len == 0)
84 b330c942 2005-10-31 devnull return nil;
86 b330c942 2005-10-31 devnull p = malloc(len+1);
87 b330c942 2005-10-31 devnull if(p == nil)
88 b330c942 2005-10-31 devnull return nil;
90 b330c942 2005-10-31 devnull if((fd = open(s, OREAD)) < 0
91 b330c942 2005-10-31 devnull || (n = readn(fd, p, len)) < 0) {
92 b330c942 2005-10-31 devnull close(fd);
94 b330c942 2005-10-31 devnull return nil;
97 b330c942 2005-10-31 devnull p[n] = '\0';
98 b330c942 2005-10-31 devnull return p;
101 b330c942 2005-10-31 devnull static char*
102 b330c942 2005-10-31 devnull readfile(char *s)
104 b330c942 2005-10-31 devnull Readcache *r, **l;
105 b330c942 2005-10-31 devnull char *p;
106 b330c942 2005-10-31 devnull ulong mtime;
108 b330c942 2005-10-31 devnull for(l=&rcache, r=*l; r; l=&r->next, r=*l) {
109 b330c942 2005-10-31 devnull if(strcmp(r->file, s) != 0)
110 b330c942 2005-10-31 devnull continue;
113 b330c942 2005-10-31 devnull * if it's less than 30 seconds since we read it, or it
114 b330c942 2005-10-31 devnull * hasn't changed, send back our copy
116 b330c942 2005-10-31 devnull if(time(0) - r->rdtime < 30)
117 b330c942 2005-10-31 devnull return strdup(r->data);
118 b330c942 2005-10-31 devnull if(dirmtime(s) == r->mtime) {
119 b330c942 2005-10-31 devnull r->rdtime = time(0);
120 b330c942 2005-10-31 devnull return strdup(r->data);
123 b330c942 2005-10-31 devnull /* out of date, remove this and fall out of loop */
124 b330c942 2005-10-31 devnull *l = r->next;
125 b330c942 2005-10-31 devnull free(r->file);
126 b330c942 2005-10-31 devnull free(r->data);
127 b330c942 2005-10-31 devnull free(r);
131 b330c942 2005-10-31 devnull /* add to cache */
132 b330c942 2005-10-31 devnull mtime = dirmtime(s);
133 b330c942 2005-10-31 devnull if(mtime == 0)
134 b330c942 2005-10-31 devnull return nil;
136 b330c942 2005-10-31 devnull if((p = doreadfile(s)) == nil)
137 b330c942 2005-10-31 devnull return nil;
139 b330c942 2005-10-31 devnull r = malloc(sizeof(*r));
140 b330c942 2005-10-31 devnull if(r == nil)
141 b330c942 2005-10-31 devnull return nil;
142 b330c942 2005-10-31 devnull r->mtime = mtime;
143 b330c942 2005-10-31 devnull r->file = estrdup(s);
144 b330c942 2005-10-31 devnull r->data = p;
145 b330c942 2005-10-31 devnull r->rdtime = time(0);
146 b330c942 2005-10-31 devnull r->next = rcache;
147 b330c942 2005-10-31 devnull rcache = r;
148 b330c942 2005-10-31 devnull return strdup(r->data);
152 b330c942 2005-10-31 devnull static char*
153 b330c942 2005-10-31 devnull translatedomain(char *dom)
155 b330c942 2005-10-31 devnull static char buf[200];
156 b330c942 2005-10-31 devnull char *p, *ep, *q, *nextp, *file;
157 b330c942 2005-10-31 devnull char *bbuf, *ebuf;
158 b330c942 2005-10-31 devnull Reprog *exp;
160 b330c942 2005-10-31 devnull if(dom == nil || *dom == 0)
161 b330c942 2005-10-31 devnull return nil;
163 a5ba8a59 2005-11-12 devnull if((file = readfile(unsharp("#9/face/.machinelist"))) == nil)
164 b330c942 2005-10-31 devnull return dom;
166 b330c942 2005-10-31 devnull for(p=file; p; p=nextp) {
167 b330c942 2005-10-31 devnull if(nextp = strchr(p, '\n'))
168 b330c942 2005-10-31 devnull *nextp++ = '\0';
170 b330c942 2005-10-31 devnull if(*p == '#' || (q = strpbrk(p, " \t")) == nil || q-p > sizeof(buf)-2)
171 b330c942 2005-10-31 devnull continue;
173 b330c942 2005-10-31 devnull bbuf = buf+1;
174 b330c942 2005-10-31 devnull ebuf = buf+(1+(q-p));
175 b330c942 2005-10-31 devnull strncpy(bbuf, p, ebuf-bbuf);
176 b330c942 2005-10-31 devnull *ebuf = 0;
177 b330c942 2005-10-31 devnull if(*bbuf != '^')
178 b330c942 2005-10-31 devnull *--bbuf = '^';
179 b330c942 2005-10-31 devnull if(ebuf[-1] != '$') {
180 b330c942 2005-10-31 devnull *ebuf++ = '$';
181 b330c942 2005-10-31 devnull *ebuf = 0;
184 b330c942 2005-10-31 devnull if((exp = regcomp(bbuf)) == nil){
185 b330c942 2005-10-31 devnull fprint(2, "bad regexp in machinelist: %s\n", bbuf);
186 b330c942 2005-10-31 devnull killall("regexp");
189 b330c942 2005-10-31 devnull if(regexec(exp, dom, 0, 0)){
190 b330c942 2005-10-31 devnull free(exp);
191 b330c942 2005-10-31 devnull ep = p+strlen(p);
192 b330c942 2005-10-31 devnull q += strspn(q, " \t");
193 b330c942 2005-10-31 devnull if(ep-q+2 > sizeof buf) {
194 b330c942 2005-10-31 devnull fprint(2, "huge replacement in machinelist: %.*s\n", utfnlen(q, ep-q), q);
195 b330c942 2005-10-31 devnull exits("bad big replacement");
197 b330c942 2005-10-31 devnull strncpy(buf, q, ep-q);
198 b330c942 2005-10-31 devnull ebuf = buf+(ep-q);
199 b330c942 2005-10-31 devnull *ebuf = 0;
200 b330c942 2005-10-31 devnull while(ebuf > buf && (ebuf[-1] == ' ' || ebuf[-1] == '\t'))
201 b330c942 2005-10-31 devnull *--ebuf = 0;
202 b330c942 2005-10-31 devnull free(file);
203 b330c942 2005-10-31 devnull return buf;
205 b330c942 2005-10-31 devnull free(exp);
207 b330c942 2005-10-31 devnull free(file);
209 b330c942 2005-10-31 devnull return dom;
212 b330c942 2005-10-31 devnull static char*
213 b330c942 2005-10-31 devnull tryfindpicture_user(char *dom, char *user, int depth)
215 b330c942 2005-10-31 devnull static char buf[200];
216 a5ba8a59 2005-11-12 devnull char *p, *q, *nextp, *file;
217 a5ba8a59 2005-11-12 devnull static char *home;
219 a5ba8a59 2005-11-12 devnull if(home == nil)
220 a5ba8a59 2005-11-12 devnull home = getenv("home");
221 a5ba8a59 2005-11-12 devnull if(home == nil)
222 a5ba8a59 2005-11-12 devnull home = getenv("HOME");
223 a5ba8a59 2005-11-12 devnull if(home == nil)
224 a5ba8a59 2005-11-12 devnull return nil;
226 a5ba8a59 2005-11-12 devnull sprint(buf, "%s/lib/face/48x48x%d/.dict", home, depth);
227 b330c942 2005-10-31 devnull if((file = readfile(buf)) == nil)
228 b330c942 2005-10-31 devnull return nil;
230 b330c942 2005-10-31 devnull snprint(buf, sizeof buf, "%s/%s", dom, user);
232 b330c942 2005-10-31 devnull for(p=file; p; p=nextp) {
233 b330c942 2005-10-31 devnull if(nextp = strchr(p, '\n'))
234 b330c942 2005-10-31 devnull *nextp++ = '\0';
236 b330c942 2005-10-31 devnull if(*p == '#' || (q = strpbrk(p, " \t")) == nil)
237 b330c942 2005-10-31 devnull continue;
238 b330c942 2005-10-31 devnull *q++ = 0;
240 b330c942 2005-10-31 devnull if(strcmp(buf, p) == 0) {
241 b330c942 2005-10-31 devnull q += strspn(q, " \t");
242 a5ba8a59 2005-11-12 devnull q = buf+snprint(buf, sizeof buf, "%s/lib/face/48x48x%d/%s", home, depth, q);
243 b330c942 2005-10-31 devnull while(q > buf && (q[-1] == ' ' || q[-1] == '\t'))
244 b330c942 2005-10-31 devnull *--q = 0;
245 b330c942 2005-10-31 devnull free(file);
246 b330c942 2005-10-31 devnull return buf;
249 b330c942 2005-10-31 devnull free(file);
250 b330c942 2005-10-31 devnull return nil;
253 b330c942 2005-10-31 devnull static char*
254 b330c942 2005-10-31 devnull tryfindpicture_global(char *dom, char *user, int depth)
256 b330c942 2005-10-31 devnull static char buf[200];
257 b330c942 2005-10-31 devnull char *p, *q, *nextp, *file;
259 a5ba8a59 2005-11-12 devnull sprint(buf, "#9/face/48x48x%d/.dict", depth);
260 b330c942 2005-10-31 devnull if((file = readfile(unsharp(buf))) == nil)
261 b330c942 2005-10-31 devnull return nil;
263 b330c942 2005-10-31 devnull snprint(buf, sizeof buf, "%s/%s", dom, user);
265 b330c942 2005-10-31 devnull for(p=file; p; p=nextp) {
266 b330c942 2005-10-31 devnull if(nextp = strchr(p, '\n'))
267 b330c942 2005-10-31 devnull *nextp++ = '\0';
269 b330c942 2005-10-31 devnull if(*p == '#' || (q = strpbrk(p, " \t")) == nil)
270 b330c942 2005-10-31 devnull continue;
271 b330c942 2005-10-31 devnull *q++ = 0;
273 b330c942 2005-10-31 devnull if(strcmp(buf, p) == 0) {
274 b330c942 2005-10-31 devnull q += strspn(q, " \t");
275 a5ba8a59 2005-11-12 devnull q = buf+snprint(buf, sizeof buf, "#9/face/48x48x%d/%s", depth, q);
276 b330c942 2005-10-31 devnull while(q > buf && (q[-1] == ' ' || q[-1] == '\t'))
277 b330c942 2005-10-31 devnull *--q = 0;
278 b330c942 2005-10-31 devnull free(file);
279 b330c942 2005-10-31 devnull return unsharp(buf);
282 b330c942 2005-10-31 devnull free(file);
283 b330c942 2005-10-31 devnull return nil;
286 b330c942 2005-10-31 devnull static char*
287 b330c942 2005-10-31 devnull tryfindpicture(char *dom, char *user, int depth)
289 b330c942 2005-10-31 devnull char* result;
291 b330c942 2005-10-31 devnull if((result = tryfindpicture_user(dom, user, depth)) != nil)
292 b330c942 2005-10-31 devnull return result;
294 b330c942 2005-10-31 devnull return tryfindpicture_global(dom, user, depth);
297 b330c942 2005-10-31 devnull static char*
298 b330c942 2005-10-31 devnull tryfindfile(char *dom, char *user, int depth)
300 b330c942 2005-10-31 devnull char *p, *q;
302 b330c942 2005-10-31 devnull for(;;){
303 b330c942 2005-10-31 devnull for(p=dom; p; (p=strchr(p, '.')) && p++)
304 b330c942 2005-10-31 devnull if(q = tryfindpicture(p, user, depth))
305 b330c942 2005-10-31 devnull return q;
306 b330c942 2005-10-31 devnull depth >>= 1;
307 b330c942 2005-10-31 devnull if(depth == 0)
310 b330c942 2005-10-31 devnull return nil;
314 b330c942 2005-10-31 devnull findfile(Face *f, char *dom, char *user)
316 b330c942 2005-10-31 devnull char *p;
317 b330c942 2005-10-31 devnull int depth;
319 b330c942 2005-10-31 devnull if(facedom == nil){
320 b330c942 2005-10-31 devnull facedom = getenv("facedom");
321 b330c942 2005-10-31 devnull if(facedom == nil)
322 b330c942 2005-10-31 devnull facedom = DEFAULT;
325 b330c942 2005-10-31 devnull dom = translatedomain(dom);
326 b330c942 2005-10-31 devnull if(dom == nil)
327 b330c942 2005-10-31 devnull dom = facedom;
329 b330c942 2005-10-31 devnull if(screen == nil)
330 b330c942 2005-10-31 devnull depth = 8;
332 b330c942 2005-10-31 devnull depth = screen->depth;
334 b330c942 2005-10-31 devnull if(depth > 8)
335 b330c942 2005-10-31 devnull depth = 8;
337 b330c942 2005-10-31 devnull f->unknown = 0;
338 b330c942 2005-10-31 devnull if(p = tryfindfile(dom, user, depth))
339 b330c942 2005-10-31 devnull return p;
340 b330c942 2005-10-31 devnull f->unknown = 1;
341 b330c942 2005-10-31 devnull p = tryfindfile(dom, "unknown", depth);
342 b330c942 2005-10-31 devnull if(p != nil || strcmp(dom, facedom)==0)
343 b330c942 2005-10-31 devnull return p;
344 b330c942 2005-10-31 devnull return tryfindfile("unknown", "unknown", depth);
349 b330c942 2005-10-31 devnull clearsaved(void)
351 b330c942 2005-10-31 devnull Facefile *f, *next, **lf;
353 b330c942 2005-10-31 devnull lf = &facefiles;
354 b330c942 2005-10-31 devnull for(f=facefiles; f!=nil; f=next){
355 b330c942 2005-10-31 devnull next = f->next;
356 b330c942 2005-10-31 devnull if(f->ref > 0){
357 b330c942 2005-10-31 devnull *lf = f;
358 b330c942 2005-10-31 devnull lf = &(f->next);
359 b330c942 2005-10-31 devnull continue;
361 b330c942 2005-10-31 devnull if(f->image != display->black && f->image != display->white)
362 b330c942 2005-10-31 devnull freeimage(f->image);
363 b330c942 2005-10-31 devnull free(f->file);
364 b330c942 2005-10-31 devnull free(f);
366 b330c942 2005-10-31 devnull *lf = nil;
367 b330c942 2005-10-31 devnull nsaved = 0;
371 b330c942 2005-10-31 devnull freefacefile(Facefile *f)
373 b330c942 2005-10-31 devnull if(f==nil || f->ref-->1)
375 b330c942 2005-10-31 devnull if(++nsaved > Nsave)
376 b330c942 2005-10-31 devnull clearsaved();
379 b330c942 2005-10-31 devnull static Image*
380 b330c942 2005-10-31 devnull myallocimage(ulong chan)
382 b330c942 2005-10-31 devnull Image *img;
383 b330c942 2005-10-31 devnull img = allocimage(display, Rect(0,0,Facesize,Facesize), chan, 0, DNofill);
384 b330c942 2005-10-31 devnull if(img == nil){
385 b330c942 2005-10-31 devnull clearsaved();
386 b330c942 2005-10-31 devnull img = allocimage(display, Rect(0,0,Facesize,Facesize), chan, 0, DNofill);
387 b330c942 2005-10-31 devnull if(img == nil)
388 b330c942 2005-10-31 devnull return nil;
390 b330c942 2005-10-31 devnull return img;
394 b330c942 2005-10-31 devnull static Image*
395 b330c942 2005-10-31 devnull readbit(int fd, ulong chan)
397 b330c942 2005-10-31 devnull char buf[4096], hx[4], *p;
398 b330c942 2005-10-31 devnull uchar data[Facesize*Facesize]; /* more than enough */
399 b330c942 2005-10-31 devnull int nhx, i, n, ndata, nbit;
400 b330c942 2005-10-31 devnull Image *img;
402 b330c942 2005-10-31 devnull n = readn(fd, buf, sizeof buf);
403 b330c942 2005-10-31 devnull if(n <= 0)
404 b330c942 2005-10-31 devnull return nil;
405 b330c942 2005-10-31 devnull if(n >= sizeof buf)
406 b330c942 2005-10-31 devnull n = sizeof(buf)-1;
407 b330c942 2005-10-31 devnull buf[n] = '\0';
410 b330c942 2005-10-31 devnull nhx = 0;
411 b330c942 2005-10-31 devnull nbit = chantodepth(chan);
412 b330c942 2005-10-31 devnull ndata = (Facesize*Facesize*nbit)/8;
413 b330c942 2005-10-31 devnull p = buf;
414 b330c942 2005-10-31 devnull while(n < ndata) {
415 b330c942 2005-10-31 devnull p = strpbrk(p+1, "0123456789abcdefABCDEF");
416 b330c942 2005-10-31 devnull if(p == nil)
418 b330c942 2005-10-31 devnull if(p[0] == '0' && p[1] == 'x')
419 b330c942 2005-10-31 devnull continue;
421 b330c942 2005-10-31 devnull hx[nhx] = *p;
422 b330c942 2005-10-31 devnull if(++nhx == 2) {
423 b330c942 2005-10-31 devnull hx[nhx] = 0;
424 b330c942 2005-10-31 devnull i = strtoul(hx, 0, 16);
425 b330c942 2005-10-31 devnull data[n++] = i;
426 b330c942 2005-10-31 devnull nhx = 0;
429 b330c942 2005-10-31 devnull if(n < ndata)
430 b330c942 2005-10-31 devnull return allocimage(display, Rect(0,0,Facesize,Facesize), CMAP8, 0, 0x88888888);
432 b330c942 2005-10-31 devnull img = myallocimage(chan);
433 b330c942 2005-10-31 devnull if(img == nil)
434 b330c942 2005-10-31 devnull return nil;
435 b330c942 2005-10-31 devnull loadimage(img, img->r, data, ndata);
436 b330c942 2005-10-31 devnull return img;
439 b330c942 2005-10-31 devnull static Facefile*
440 b330c942 2005-10-31 devnull readface(char *fn)
442 b330c942 2005-10-31 devnull int x, y, fd;
443 b330c942 2005-10-31 devnull uchar bits;
444 b330c942 2005-10-31 devnull uchar *p;
445 b330c942 2005-10-31 devnull Image *mask;
446 b330c942 2005-10-31 devnull Image *face;
447 b330c942 2005-10-31 devnull char buf[16];
448 b330c942 2005-10-31 devnull uchar data[Facesize*Facesize];
449 b330c942 2005-10-31 devnull uchar mdata[(Facesize*Facesize)/8];
450 b330c942 2005-10-31 devnull Facefile *f;
453 b330c942 2005-10-31 devnull for(f=facefiles; f!=nil; f=f->next){
454 b330c942 2005-10-31 devnull if(strcmp(fn, f->file) == 0){
455 b330c942 2005-10-31 devnull if(f->image == nil)
457 b330c942 2005-10-31 devnull if(time(0) - f->rdtime >= 30) {
458 b330c942 2005-10-31 devnull if(dirmtime(fn) != f->mtime){
459 b330c942 2005-10-31 devnull f = nil;
462 b330c942 2005-10-31 devnull f->rdtime = time(0);
464 b330c942 2005-10-31 devnull f->ref++;
465 b330c942 2005-10-31 devnull return f;
469 b330c942 2005-10-31 devnull if((fd = open(fn, OREAD)) < 0)
470 b330c942 2005-10-31 devnull return nil;
472 b330c942 2005-10-31 devnull if(readn(fd, buf, sizeof buf) != sizeof buf){
473 b330c942 2005-10-31 devnull close(fd);
474 b330c942 2005-10-31 devnull return nil;
477 b330c942 2005-10-31 devnull seek(fd, 0, 0);
479 b330c942 2005-10-31 devnull mask = nil;
480 b330c942 2005-10-31 devnull if(buf[0] == '0' && buf[1] == 'x'){
481 b330c942 2005-10-31 devnull /* greyscale faces are just masks that we draw black through! */
482 b330c942 2005-10-31 devnull if(buf[2+8] == ',') /* ldepth 1 */
483 b330c942 2005-10-31 devnull mask = readbit(fd, GREY2);
485 b330c942 2005-10-31 devnull mask = readbit(fd, GREY1);
486 b330c942 2005-10-31 devnull face = display->black;
488 b330c942 2005-10-31 devnull face = readimage(display, fd, 0);
489 b330c942 2005-10-31 devnull if(face == nil)
490 b330c942 2005-10-31 devnull goto Done;
491 b330c942 2005-10-31 devnull else if(face->chan == GREY4 || face->chan == GREY8){ /* greyscale: use inversion as mask */
492 b330c942 2005-10-31 devnull mask = myallocimage(face->chan);
493 b330c942 2005-10-31 devnull /* okay if mask is nil: that will copy the image white background and all */
494 b330c942 2005-10-31 devnull if(mask == nil)
495 b330c942 2005-10-31 devnull goto Done;
497 b330c942 2005-10-31 devnull /* invert greyscale image */
498 b330c942 2005-10-31 devnull draw(mask, mask->r, display->white, nil, ZP);
499 b330c942 2005-10-31 devnull gendraw(mask, mask->r, display->black, ZP, face, face->r.min);
500 b330c942 2005-10-31 devnull freeimage(face);
501 b330c942 2005-10-31 devnull face = display->black;
502 b330c942 2005-10-31 devnull }else if(face->depth == 8){ /* snarf the bytes back and do a fill. */
503 b330c942 2005-10-31 devnull mask = myallocimage(GREY1);
504 b330c942 2005-10-31 devnull if(mask == nil)
505 b330c942 2005-10-31 devnull goto Done;
506 b330c942 2005-10-31 devnull if(unloadimage(face, face->r, data, Facesize*Facesize) != Facesize*Facesize){
507 b330c942 2005-10-31 devnull freeimage(mask);
508 b330c942 2005-10-31 devnull goto Done;
510 b330c942 2005-10-31 devnull bits = 0;
511 b330c942 2005-10-31 devnull p = mdata;
512 b330c942 2005-10-31 devnull for(y=0; y<Facesize; y++){
513 b330c942 2005-10-31 devnull for(x=0; x<Facesize; x++){
514 b330c942 2005-10-31 devnull bits <<= 1;
515 b330c942 2005-10-31 devnull if(data[Facesize*y+x] != 0xFF)
516 b330c942 2005-10-31 devnull bits |= 1;
517 b330c942 2005-10-31 devnull if((x&7) == 7)
518 b330c942 2005-10-31 devnull *p++ = bits&0xFF;
521 b330c942 2005-10-31 devnull if(loadimage(mask, mask->r, mdata, sizeof mdata) != sizeof mdata){
522 b330c942 2005-10-31 devnull freeimage(mask);
523 b330c942 2005-10-31 devnull goto Done;
529 b330c942 2005-10-31 devnull /* always add at beginning of list, so updated files don't collide in cache */
530 b330c942 2005-10-31 devnull if(f == nil){
531 b330c942 2005-10-31 devnull f = emalloc(sizeof(Facefile));
532 b330c942 2005-10-31 devnull f->file = estrdup(fn);
533 b330c942 2005-10-31 devnull d = dirfstat(fd);
534 b330c942 2005-10-31 devnull if(d != nil){
535 b330c942 2005-10-31 devnull f->mtime = d->mtime;
536 b330c942 2005-10-31 devnull free(d);
538 b330c942 2005-10-31 devnull f->next = facefiles;
539 b330c942 2005-10-31 devnull facefiles = f;
541 b330c942 2005-10-31 devnull f->ref++;
542 b330c942 2005-10-31 devnull f->image = face;
543 b330c942 2005-10-31 devnull f->mask = mask;
544 b330c942 2005-10-31 devnull f->rdtime = time(0);
545 b330c942 2005-10-31 devnull close(fd);
546 b330c942 2005-10-31 devnull return f;
550 b330c942 2005-10-31 devnull findbit(Face *f)
552 b330c942 2005-10-31 devnull char *fn;
554 b330c942 2005-10-31 devnull fn = findfile(f, f->str[Sdomain], f->str[Suser]);
555 b330c942 2005-10-31 devnull if(fn) {
556 b330c942 2005-10-31 devnull if(strstr(fn, "unknown"))
557 b330c942 2005-10-31 devnull f->unknown = 1;
558 b330c942 2005-10-31 devnull f->file = readface(fn);
560 b330c942 2005-10-31 devnull if(f->file){
561 b330c942 2005-10-31 devnull f->bit = f->file->image;
562 b330c942 2005-10-31 devnull f->mask = f->file->mask;
564 b330c942 2005-10-31 devnull /* if returns nil, this is still ok: draw(nil) works */
565 b330c942 2005-10-31 devnull f->bit = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DYellow);
566 b330c942 2005-10-31 devnull replclipr(f->bit, 1, Rect(0, 0, Facesize, Facesize));
567 b330c942 2005-10-31 devnull f->mask = nil;