1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7 #include <control.h>
8
9 typedef struct Cache Cache;
10
11 struct Cache
12 {
13 char *name;
14 CCache **cache;
15 int ncache;
16 };
17
18 static struct Cache imagecache = {"image"};
19 static struct Cache fontcache = {"font"};
20
21 static CCache*
getcacheitem(Cache * c,char * name)22 getcacheitem(Cache *c, char *name)
23 {
24 int i;
25
26 for(i=0; i<c->ncache; i++)
27 if(c->cache[i]!=nil && strcmp(c->cache[i]->name, name)==0){
28 c->cache[i]->ref++;
29 return c->cache[i];
30 }
31 return nil;
32 }
33
34 static int
namecacheitem(Cache * c,void * image,char * name)35 namecacheitem(Cache *c, void *image, char *name)
36 {
37 int i, free;
38 CCache *cc;
39
40 free = -1;
41 for(i=0; i<c->ncache; i++){
42 if(c->cache[i] == nil){
43 free = i;
44 continue;
45 }
46 if(strcmp(c->cache[i]->name, name) == 0){
47 werrstr("%s name %q already in use", c->name, name);
48 return -1;
49 }
50 }
51 cc = ctlmalloc(sizeof(CCache));
52 cc->image = image;
53 cc->name = ctlstrdup(name);
54 if(free >= 0){
55 cc->index = free;
56 c->cache[free] = cc;
57 }else{
58 cc->index = c->ncache;
59 c->cache = ctlrealloc(c->cache, (c->ncache+1)*sizeof(CCache*));
60 c->cache[c->ncache++] = cc;
61 }
62 cc->ref = 1;
63 return 1;
64 }
65
66 static int
freecacheitem(Cache * c,char * name)67 freecacheitem(Cache *c, char *name)
68 {
69 CCache *cc;
70
71 cc = getcacheitem(c, name);
72 if(cc == nil){
73 werrstr("%s name %q not in use", c->name, name);
74 return -1;
75 }
76 cc->ref--; /* getcacheitem increments ref */
77 if(cc->ref-- == 1){
78 /* client must free object itself */
79 free(cc->name);
80 c->cache[cc->index] = nil;
81 free(cc);
82 }
83 return 0;
84 }
85
86 static void
putcacheitem(CCache * cc)87 putcacheitem(CCache *cc)
88 {
89 if(cc == nil)
90 return;
91 cc->ref--;
92 }
93
94 static void
setcacheitemptr(Cache * c,Control * ctl,CCache ** cp,char * s)95 setcacheitemptr(Cache *c, Control *ctl, CCache **cp, char *s)
96 {
97 CCache *ci;
98
99 ci = getcacheitem(c, s);
100 if(ci == nil)
101 ctlerror("%q: %s name %q not defined", ctl->name, c->name, s);
102 putcacheitem(*cp);
103 *cp = ci;
104 }
105
106 /* Images */
107
108 CImage*
_getctlimage(char * name)109 _getctlimage(char *name)
110 {
111 return getcacheitem(&imagecache, name);
112 }
113
114 void
_putctlimage(CImage * c)115 _putctlimage(CImage *c)
116 {
117 putcacheitem(c);
118 }
119
120 int
namectlimage(Image * image,char * name)121 namectlimage(Image *image, char *name)
122 {
123 return namecacheitem(&imagecache, image, name);
124 }
125
126 int
freectlimage(char * name)127 freectlimage(char *name)
128 {
129 return freecacheitem(&imagecache, name);
130 }
131
132 void
_setctlimage(Control * c,CImage ** cp,char * s)133 _setctlimage(Control *c, CImage **cp, char *s)
134 {
135 setcacheitemptr(&imagecache, c, cp, s);
136 }
137
138 /* Fonts */
139
140 CFont*
_getctlfont(char * name)141 _getctlfont(char *name)
142 {
143 return getcacheitem(&fontcache, name);
144 }
145
146 void
_putctlfont(CFont * c)147 _putctlfont(CFont *c)
148 {
149 putcacheitem(c);
150 }
151
152 int
namectlfont(Font * font,char * name)153 namectlfont(Font *font, char *name)
154 {
155 return namecacheitem(&fontcache, font, name);
156 }
157
158 int
freectlfont(char * name)159 freectlfont(char *name)
160 {
161 return freecacheitem(&fontcache, name);
162 }
163
164 void
_setctlfont(Control * c,CFont ** cp,char * s)165 _setctlfont(Control *c, CFont **cp, char *s)
166 {
167 setcacheitemptr(&fontcache, c, cp, s);
168 }
169