prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / guicast / bchash.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "filesystem.h"
29 #include "format.inc"
30
31 BC_Hash::BC_Hash()
32 {
33         this->filename[0] = 0;
34         total = 0;
35         allocated = 0;
36         names = 0;
37         values = 0;
38 }
39
40 BC_Hash::BC_Hash(const char *filename)
41 {
42         strcpy(this->filename, filename);
43         total = 0;
44         allocated = 0;
45         names = 0;
46         values = 0;
47
48         FileSystem directory;
49
50         directory.parse_tildas(this->filename);
51 }
52
53 void BC_Hash::clear()
54 {
55         for(int i = 0; i < total; i++)
56         {
57                 delete [] names[i];
58                 delete [] values[i];
59         }
60         total = 0;
61 }
62
63 BC_Hash::~BC_Hash()
64 {
65         clear();
66         delete [] names;
67         delete [] values;
68 }
69
70 void BC_Hash::reallocate_table(int new_total)
71 {
72         if(allocated < new_total)
73         {
74                 int new_allocated = new_total * 2;
75                 char **new_names = new char*[new_allocated];
76                 char **new_values = new char*[new_allocated];
77
78                 for(int i = 0; i < total; i++)
79                 {
80                         new_names[i] = names[i];
81                         new_values[i] = values[i];
82                 }
83
84                 delete [] names;
85                 delete [] values;
86
87                 names = new_names;
88                 values = new_values;
89                 allocated = new_allocated;
90         }
91 }
92
93 int BC_Hash::load_file(FILE *fp)
94 {
95         char line[4096];
96         int done = 0, ch = -1;
97         total = 0;
98
99         while( !done ) {
100                 char *bp = line, *ep = bp + sizeof(line);
101                 if( !fgets(bp, ep-bp, fp) ) break;
102                 // skip ws (indent)
103                 while( bp < ep && *bp == ' ' ) ++bp;
104                 if( bp >= ep || !*bp || *bp == '\n' ) continue;
105                 char *title = bp;
106                 // span to ws
107                 while( bp < ep && *bp && *bp != ' ' && *bp != '\n' ) ++bp;
108                 if( bp >= ep || title == bp ) continue;
109                 int title_len = bp - title;
110                 // skip blank seperator
111                 if( *bp++ != ' ' ) continue;
112                 reallocate_table(total + 1);
113                 char *tp = new char[title_len + 1];
114                 names[total] = tp;
115                 while( --title_len >= 0 ) *tp++ = *title++;
116                 *tp = 0;
117                 // accumulate value (+ continued lines)
118                 char *value = bp;
119                 while( bp < ep && !done ) {
120                         while( bp < ep && *bp && *bp != '\n' ) ++bp;
121                         if( bp >= ep || !*bp ) break;
122                         if( (ch=fgetc(fp)) < 0 ) break;
123                         if( ch != '+' ) { ungetc(ch, fp); break; }
124                         *bp++ = '\n';
125                         done = !fgets(bp, ep-bp, fp);
126                 }
127                 int value_len = bp - value;
128                 char *vp = new char[value_len + 1];
129                 values[total] = vp;
130                 while( --value_len >= 0 ) *vp++ = *value++;
131                 *vp = 0;
132                 total++;
133         }
134         return 0;
135 }
136
137 int BC_Hash::load()
138 {
139         FILE *fp = fopen(filename, "r");
140         if( !fp ) return 1;
141         int ret = load_file(fp);
142         fclose(fp);
143         return ret;
144 }
145
146 int BC_Hash::save_file(FILE *fp)
147 {
148         for(int i = 0; i < total; i++) {
149                 fputs(names[i], fp);
150                 char *vp = values[i];
151                 char *bp = vp;
152                 fputc(' ',fp);
153                 while( (vp=strchr(vp, '\n')) ) {
154                         while( bp < vp ) fputc(*bp++,fp);
155                         fputc('\n',fp);  fputc('+',fp);
156                         ++bp;  ++vp;
157                 }
158                 while( *bp ) fputc(*bp++,fp);
159                 fputc('\n', fp);
160         }
161         return 0;
162 }
163
164 int BC_Hash::save()
165 {
166         FILE *fp = fopen(filename,"w");
167         if( !fp ) return 1;
168         int ret = save_file(fp);
169         fclose(fp);
170         return ret;
171 }
172
173 int BC_Hash::load_string(const char *bfr)
174 {
175         FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r");
176         if( !fp ) return 1;
177         int ret = load_file(fp);
178         fclose(fp);
179         return ret;
180 }
181
182 int BC_Hash::save_string(char *&bfr)
183 {
184         size_t bsz = 0;
185         FILE *fp = open_memstream(&bfr, &bsz);
186         if( !fp ) return 1;
187         int ret = save_file(fp);
188         fclose(fp);
189         return ret;
190 }
191
192
193
194 int32_t BC_Hash::get(const char *name, int32_t default_)
195 {
196         for(int i = 0; i < total; i++)
197         {
198                 if(!strcmp(names[i], name))
199                 {
200                         return (int32_t)atol(values[i]);
201                 }
202         }
203         return default_;  // failed
204 }
205
206 int64_t BC_Hash::get(const char *name, int64_t default_)
207 {
208         int64_t result = default_;
209         for(int i = 0; i < total; i++)
210         {
211                 if(!strcmp(names[i], name))
212                 {
213                         sscanf(values[i], "%jd", &result);
214                         return result;
215                 }
216         }
217         return result;
218 }
219
220 double BC_Hash::get(const char *name, double default_)
221 {
222         for(int i = 0; i < total; i++)
223         {
224                 if(!strcmp(names[i], name))
225                 {
226                         return atof(values[i]);
227                 }
228         }
229         return default_;  // failed
230 }
231
232 float BC_Hash::get(const char *name, float default_)
233 {
234         for(int i = 0; i < total; i++)
235         {
236                 if(!strcmp(names[i], name))
237                 {
238                         return atof(values[i]);
239                 }
240         }
241         return default_;  // failed
242 }
243
244 char* BC_Hash::get(const char *name, char *default_)
245 {
246         for(int i = 0; i < total; i++)
247         {
248                 if(!strcmp(names[i], name))
249                 {
250                         strcpy(default_, values[i]);
251                         return values[i];
252                 }
253         }
254         return default_;  // failed
255 }
256
257 int BC_Hash::update(const char *name, double value) // update a value if it exists
258 {
259         char string[BCSTRLEN];
260         sprintf(string, "%.16e", value);
261         return update(name, string);
262 }
263
264 int BC_Hash::update(const char *name, float value) // update a value if it exists
265 {
266         char string[BCSTRLEN];
267         sprintf(string, "%.6e", value);
268         return update(name, string);
269 }
270
271 int BC_Hash::update(const char *name, int32_t value) // update a value if it exists
272 {
273         char string[BCSTRLEN];
274         sprintf(string, "%d", value);
275         return update(name, string);
276 }
277
278 int BC_Hash::update(const char *name, int64_t value) // update a value if it exists
279 {
280         char string[BCSTRLEN];
281         sprintf(string, "%jd", value);
282         return update(name, string);
283 }
284
285 int BC_Hash::update(const char *name, const char *value)
286 {
287         for(int i = 0; i < total; i++)
288         {
289                 if(!strcmp(names[i], name))
290                 {
291                         delete [] values[i];
292                         values[i] = new char[strlen(value) + 1];
293                         strcpy(values[i], value);
294                         return 0;
295                 }
296         }
297
298 // didn't find so create new entry
299         reallocate_table(total + 1);
300         names[total] = new char[strlen(name) + 1];
301         strcpy(names[total], name);
302         values[total] = new char[strlen(value) + 1];
303         strcpy(values[total], value);
304         total++;
305         return 1;
306 }
307
308 #define varFn(rtyp, fn, typ) \
309 rtyp BC_Hash::fn##f(typ value, const char *fmt, ...) { \
310   char string[BCTEXTLEN];  va_list ap; va_start(ap, fmt); \
311   vsnprintf(string, BCTEXTLEN, fmt, ap); \
312   va_end(ap);  return fn(string, value); \
313 }
314
315 varFn(int,update,double)        varFn(double,get,double)
316 varFn(int,update,float)         varFn(float,get,float)
317 varFn(int,update,int32_t)       varFn(int32_t,get,int32_t)
318 varFn(int,update,int64_t)       varFn(int64_t,get,int64_t)
319 varFn(int,update,const char *)  varFn(char *,get,char *)
320
321
322 void BC_Hash::copy_from(BC_Hash *src)
323 {
324 // Can't delete because this is used by file decoders after plugins
325 // request data.  use explicit destructor to clear/clean
326 //      this->~BC_Hash();
327
328 SET_TRACE
329         reallocate_table(src->total);
330 //      total = src->total;
331 SET_TRACE
332         for(int i = 0; i < src->total; i++)
333         {
334                 update(src->names[i], src->values[i]);
335 //              names[i] = new char[strlen(src->names[i]) + 1];
336 //              values[i] = new char[strlen(src->values[i]) + 1];
337 //              strcpy(names[i], src->names[i]);
338 //              strcpy(values[i], src->values[i]);
339         }
340 SET_TRACE
341 }
342
343 int BC_Hash::equivalent(BC_Hash *src)
344 {
345         for(int i = 0; i < total && i < src->total; i++)
346         {
347                 if(strcmp(names[i], src->names[i]) ||
348                         strcmp(values[i], src->values[i])) return 0;
349         }
350         return 1;
351 }
352
353 int BC_Hash::size()
354 {
355         return total;
356 }
357
358 char* BC_Hash::get_key(int number)
359 {
360         return names[number];
361 }
362
363 char* BC_Hash::get_value(int number)
364 {
365         return values[number];
366 }
367
368
369 void BC_Hash::dump()
370 {
371         printf("BC_Hash::dump\n");
372         for(int i = 0; i < total; i++)
373                 printf("        key=%s value=%s\n", names[i], values[i]);
374 }