rllib  1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
rlinifile.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlinifile.cpp - description
3  -------------------
4  begin : Tue Jan 02 2001
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rldefine.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #ifdef RLWIN32
22 #include <windows.h>
23 #endif
24 #include "rlinifile.h"
25 #include "rlcutil.h"
26 
27 static const char null_string[] = "";
28 
30 {
31  _firstSection = new rlSection; // first section holds names with section name = null_string
32  _firstSection->nextSection = NULL;
33  _firstSection->firstName = NULL;
34  _firstSection->name = new char[1];
35  _firstSection->name[0] = '\0';
37 }
38 
40 {
41  rlSection *section, *last_section;
42 
43  section = _firstSection;
44  while(section != NULL)
45  {
46  deleteSectionNames(section);
47  last_section = section;
48  section = section->nextSection;
49  delete last_section;
50  }
51 }
52 
54 {
55  rlSectionName *name, *last_name;
56 
57  if(section == NULL) return;
58  name = section->firstName;
59  while(name != NULL)
60  {
61  if(name->name != NULL) delete [] name->name;
62  if(name->param != NULL) delete [] name->param;
63  last_name = name;
64  name = name->nextName;
65  delete [] last_name;
66  }
67  if(section->name != NULL) delete [] section->name;
68 }
69 
70 void rlIniFile::copyIdentifier(char *buf, const char *line)
71 {
72  int i = 1;
73  buf[0] = '\0';
74  if(line[0] != '[') return;
75  while(line[i] != ']' && line[i] != '\0')
76  {
77  *buf++ = line[i++];
78  }
79  *buf = '\0';
80 }
81 
82 void rlIniFile::copyName(char *buf, const char *line)
83 {
84  int i = 0;
85  buf[0] = '\0';
86  //while(line[i] > ' ' && line[i] != '=')
87  while(line[i] != '\0' && (line[i] != '=' || (line[i] == '=' && line[i-1] == '\\')))
88  {
89  *buf++ = line[i++];
90  }
91  *buf = '\0';
92  i--; // eventually delete spaces
93  while(i>=0 && (buf[i] == ' ' || buf[i] == '\t'))
94  {
95  buf[i--] = '\0';
96  }
97 }
98 
99 void rlIniFile::copyParam(char *buf, const char *line)
100 {
101  const char *cptr = line;
102  buf[0] = '\0';
103  while(1)
104  {
105  cptr = strchr(cptr,'=');
106  if(cptr == NULL) return;
107  cptr++;
108  if(cptr[-2] != '\\') break;
109  }
110  while((*cptr == ' ' || *cptr == '\t') && *cptr != '\0') cptr++;
111  if(*cptr == '\0') return;
112  while(*cptr != '\0' && *cptr != '\n') *buf++ = *cptr++;
113  *buf = '\0';
114 }
115 
116 int rlIniFile::read(const char *filename)
117 {
118  FILE *fp;
119  char line[rl_PRINTF_LENGTH],
120  name_section[rl_PRINTF_LENGTH],
121  name_name[rl_PRINTF_LENGTH],
122  name_param[rl_PRINTF_LENGTH],
123  *cptr;
124  rlSection *s, *s_old;
125 
126  // delete old content
127  s = _firstSection;
128  while(s != NULL)
129  {
131  s_old = s;
132  s = s->nextSection;
133  delete s_old;
134  }
135 
136  // read the file
137  fname.setText(filename);
138  _firstSection = new rlSection; // first section holds names with section name = null_string
139  _firstSection->nextSection = NULL;
140  _firstSection->firstName = NULL;
141  _firstSection->name = new char[1];
142  _firstSection->name[0] = '\0';
143  fp = fopen(filename,"r");
144  if(fp == NULL) return -1;
145  name_section[0] = name_name[0] = name_param[0] = '\0';
146  while(fgets(line,sizeof(line)-1,fp) != NULL)
147  {
148  cptr = strchr(line,0x0d);
149  if(cptr != NULL) *cptr = '\0';
150  cptr = strchr(line,0x0a);
151  if(cptr != NULL) *cptr = '\0';
152  if(line[0] == '[') // section identifier
153  {
154  copyIdentifier(name_section,line);
155  setText(name_section, NULL, NULL);
156  }
157  else if(line[0] > ' ' && line[0] != '\t' && line[0] != '#') // name identifier
158  {
159  copyName(name_name,line);
160  copyParam(name_param,line);
161  setText(name_section, name_name, name_param);
162  }
163  else // it must be a comment line
164  {
165  setText(name_section, line, NULL);
166  }
167  }
168  fclose(fp);
169  return 0;
170 }
171 
172 int rlIniFile::write(const char *filename)
173 {
174  FILE *fp;
175  rlSection *s;
176  rlSectionName *n;
177 
178  fp = fopen(filename,"w");
179  if(fp == NULL) return -1;
180 
181  s = _firstSection;
182  while(s != NULL)
183  {
184  if (s->name[0] == '#') fprintf(fp,"%s\n",s->name);
185  else if(s->name[0] == '\0') ;
186  else fprintf(fp,"[%s]\n",s->name);
187  n = s->firstName;
188  while(n != NULL)
189  {
190  if (n->name[0] == '#') fprintf(fp,"%s\n",n->name);
191  else if(n->name[0] == '\0') fprintf(fp,"\n");
192  else if(n->param[0] == '\0') fprintf(fp,"\n");
193  else fprintf(fp,"%s=%s\n",n->name,n->param);
194  n = n->nextName;
195  }
196  s = s->nextSection;
197  }
198 
199  fclose(fp);
200  return 0;
201 }
202 
203 const char *rlIniFile::filename()
204 {
205  return fname.text();
206 }
207 
208 const char *rlIniFile::text(const char *section, const char *name)
209 {
210  rlSection *s;
211  rlSectionName *n;
212 
213  s = _firstSection;
214  while(s != NULL)
215  {
216  if(strcmp(section,s->name) == 0)
217  {
218  n = s->firstName;
219  while(n != NULL)
220  {
221  if(n->name != NULL && strcmp(name,n->name) == 0)
222  {
223  return n->param;
224  }
225  n = n->nextName;
226  }
227  return null_string;
228  }
229  s = s->nextSection;
230  }
231  return null_string;
232 }
233 
234 void rlIniFile::setText(const char *section, const char *name, const char *text)
235 {
236  rlSection *s, *last_section;
237  rlSectionName *n, *last_name;
238 
239  if(section == NULL) return;
240  last_section = NULL;
241  last_name = NULL;
242  s = _firstSection;
243  while(s != NULL)
244  {
245  if(strcmp(section,s->name) == 0)
246  {
247  last_name = NULL;
248  n = s->firstName;
249  while(n != NULL)
250  {
251  if(name != NULL && name[0] != '#' && name[0] != '\0' && strcmp(name,n->name) == 0)
252  {
253  if(n->param != NULL) delete [] n->param;
254  if(text == NULL)
255  {
256  n->param = new char[1];
257  n->param[0] = '\0';
258  }
259  else
260  {
261  n->param = new char[strlen(text)+1];
262  strcpy(n->param,text);
263  }
264  return;
265  }
266  last_name = n;
267  n = n->nextName;
268  }
269  if(last_name == NULL)
270  {
271  s->firstName = new rlSectionName;
272  n = s->firstName;
273  }
274  else
275  {
276  last_name->nextName = new rlSectionName;
277  n = last_name->nextName;
278  }
279  if(name == NULL)
280  {
281  n->name = new char[1];
282  n->name[0] = '\0';
283  }
284  else
285  {
286  n->name = new char[strlen(name)+1];
287  strcpy(n->name,name);
288  }
289  if(text == NULL)
290  {
291  n->param = new char[1];
292  n->param[0] = '\0';
293  }
294  else
295  {
296  n->param = new char[strlen(text)+1];
297  strcpy(n->param,text);
298  }
299  n->nextName = NULL;
300  return;
301  }
302  last_section = s;
303  s = s->nextSection;
304  }
305  if(last_section == NULL)
306  {
307  _firstSection = new rlSection;
308  last_section = _firstSection;
309  }
310  else
311  {
312  last_section->nextSection = new rlSection;
313  last_section = last_section->nextSection;
314  }
315  last_section->name = new char[strlen(section)+1];
316  strcpy(last_section->name,section);
317  last_section->nextSection = NULL;
318  if(name == NULL)
319  {
320  last_section->firstName = NULL;
321  }
322  else
323  {
324  last_section->firstName = new rlSectionName;
325  n = last_section->firstName;
326  n->name = new char[strlen(name)+1];
327  strcpy(n->name,name);
328  if(text == NULL)
329  {
330  n->param = new char[1];
331  n->param[0] = '\0';
332  }
333  else
334  {
335  n->param = new char[strlen(text)+1];
336  strcpy(n->param,text);
337  }
338  n->nextName = NULL;
339  }
340  return;
341 }
342 
343 int rlIniFile::printf(const char *section, const char *name, const char *format, ...)
344 {
345  int ret;
346  char buf[rl_PRINTF_LENGTH]; // should be big enough
347 
348  va_list ap;
349  va_start(ap,format);
350  ret = rlvsnprintf(buf, rl_PRINTF_LENGTH - 1, format, ap);
351  va_end(ap);
352  if(ret > 0) setText(section, name, buf);
353  return ret;
354 }
355 
356 void rlIniFile::remove(const char *section)
357 {
358  rlSection *s, *last;
359 
360  last = NULL;
361  s = _firstSection;
362  while(s != NULL)
363  {
364  if(strcmp(section,s->name) == 0)
365  {
367  if(last != NULL) last->nextSection = s->nextSection;
368  delete s;
369  return;
370  }
371  last = s;
372  s = s->nextSection;
373  }
374 }
375 
376 void rlIniFile::remove(const char *section, const char *name)
377 {
378  rlSection *s;
379  rlSectionName *n, *last;
380 
381  s = _firstSection;
382  while(s != NULL)
383  {
384  if(strcmp(section,s->name) == 0)
385  {
386  last = NULL;
387  n = s->firstName;
388  while(n != NULL)
389  {
390  if(strcmp(name,n->name) == 0)
391  {
392  if(n->name != NULL) delete [] n->name;
393  if(n->param != NULL) delete [] n->param;
394  if(last != NULL) last->nextName = n->nextName;
395  delete n;
396  return;
397  }
398  last = n;
399  n = n->nextName;
400  }
401  return;
402  }
403  s = s->nextSection;
404  }
405 }
406 
408 {
409  currentSection = 0;
410  return _firstSection->name;
411 }
412 
414 {
415  rlSection *s;
416  int i;
417 
418  if(currentSection < 0) return NULL;
419  currentSection++;
420  i = 0;
421  s = _firstSection;
422  while(s != NULL)
423  {
424  if(i == currentSection) return s->name;
425  s = s->nextSection;
426  i++;
427  }
428  currentSection = -1;
429  return NULL;
430 }
431 
432 const char *rlIniFile::firstName(const char *section)
433 {
434  rlSection *s;
435  rlSectionName *n;
436 
437  s = _firstSection;
438  while(s != NULL)
439  {
440  if(strcmp(section,s->name) == 0)
441  {
442  n = s->firstName;
443  currentName = 0;
444  return n->name;
445  }
446  s = s->nextSection;
447  }
448  return NULL;
449 }
450 
451 const char *rlIniFile::nextName(const char *section)
452 {
453  rlSection *s;
454  rlSectionName *n;
455  int i;
456 
457  if(currentName < 0) return NULL;
458  currentName++;
459  i = 0;
460  s = _firstSection;
461  while(s != NULL)
462  {
463  if(strcmp(section,s->name) == 0)
464  {
465  n = s->firstName;
466  while(n != NULL)
467  {
468  if(i == currentName) return n->name;
469  i++;
470  n = n->nextName;
471  }
472  return NULL;
473  }
474  s = s->nextSection;
475  }
476  return NULL;
477 }
478 
479 void rlIniFile::setDefaultSection(const char *section)
480 {
481  default_section.setText(section);
482 }
483 
485 {
486  return default_section.text();
487 }
488 
489 const char *rlIniFile::i18n(const char *tag, const char *default_text)
490 {
491  const char *cptr = text(default_section.text(), tag);
492  if(strcmp(cptr,null_string) == 0) return default_text;
493  else return cptr;
494 }
495 
496 const char *rlIniFile::tr(const char *txt)
497 {
498  if(txt == NULL) return "ERROR:txt=NULL";
499  char default_text[1024];
500  if(strlen(txt) < (sizeof(default_text) - 40)) sprintf(default_text,"tr_error:%s", txt);
501  else strcpy(default_text,"tr_error:text too long");
502  return i18n(txt,default_text);
503 }
504 
505 // Translator
506 static rlIniFile *trIniFile = NULL;
507 
508 int rlSetTranslator(const char *language, const char *inifile)
509 {
510  if(inifile != NULL)
511  {
512  if(trIniFile == NULL) trIniFile = new rlIniFile();
513  if(trIniFile->read(inifile) < 0) return -1;
514  }
515  trIniFile->setDefaultSection(language);
516  return 0;
517 }
518 
519 static const char *fixquote(const char *text, char **mytext)
520 {
521  if(strchr(text,'\\') == NULL) return text;
522  int len = strlen(text);
523  if(*mytext != NULL) delete [] *mytext;
524  *mytext = new char[len+1];
525  char *temp = *mytext;
526  int i2 = 0;
527  for(int i=0; i<len; i++)
528  {
529  if (text[i] == '\\' && text[i+1] == '=') { temp[i2] = '='; i++; }
530  else if(text[i] == '\\' && text[i+1] == 'n') { temp[i2] = '\n'; i++; }
531  else if(text[i] == '\\' && text[i+1] == 't') { temp[i2] = '\t'; i++; }
532  else if(text[i] == '\\' && text[i+1] == '\\') { temp[i2] = '\\'; i++; }
533  else { temp[i2] = text[i]; }
534  i2++;
535  }
536  temp[i2] = '\0';
537  //printf("fixquote(%s) return=%s\n", text, temp);
538  return temp;
539 }
540 
541 const char *rltranslate(const char *txt, char **mytext)
542 {
543  if(trIniFile == NULL) return fixquote(txt,mytext); // use original language because translator is not initalized
544  const char *text = trIniFile->i18n(txt,"@"); // translate
545  if(strcmp(text,"@") == 0) return fixquote(txt,mytext); // use original language because there is no tranlation available
546  return fixquote(text,mytext); // return the translated text
547 }
548 
549 const char *rltranslate2(const char *section, const char *txt, char **mytext)
550 {
551  //printf("rltranslate2(%s,%s) mytext=%s\n", section, txt, *mytext);
552  if(trIniFile == NULL) return fixquote(txt,mytext); // use original language because translator is not initalized
553  if(*section == '\0') return rltranslate(txt,mytext); // user did not call pvSelectLanguage()
554  const char *text = trIniFile->text(section,txt); // translate
555  if(text[0] == '\0') return fixquote(txt,mytext); // use original language because there is no tranlation available
556  return fixquote(text,mytext); // return the translated text
557 }
558 
559