xref: /plan9/sys/src/libcontrol/cache.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
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