fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Preferences.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Preferences methods for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 2002-2010 by Matthias Melcher.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 #include <FL/Fl.H>
20 #include <FL/Fl_Preferences.H>
21 #include <FL/Fl_Plugin.H>
22 #include <FL/filename.H>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <FL/fl_utf8.h>
28 #include "flstring.h"
29 #include <sys/stat.h>
30 #include <time.h>
31 
32 #if defined(WIN32) && !defined(__CYGWIN__)
33 # include <windows.h>
34 # include <direct.h>
35 # include <io.h>
36 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
37 // on Windows, which is supposed to be POSIX compliant...
38 # define access _access
39 # define mkdir _mkdir
40 #elif defined (__APPLE__)
41 # include <ApplicationServices/ApplicationServices.h>
42 # include <unistd.h>
43 # include <config.h>
44 # include <dlfcn.h>
45 #else
46 # include <unistd.h>
47 # include <config.h>
48 # if HAVE_DLFCN_H
49 # include <dlfcn.h>
50 # endif
51 #endif
52 
53 #ifdef WIN32
54 # include <windows.h>
55 # include <rpc.h>
56 // function pointer for the UuidCreate Function
57 // RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid);
58 typedef RPC_STATUS (WINAPI* uuid_func)(UUID __RPC_FAR *Uuid);
59 #else
60 # include <sys/time.h>
61 #endif // WIN32
62 
63 #ifdef __CYGWIN__
64 # include <wchar.h>
65 #endif
66 
70 
82 const char *Fl_Preferences::newUUID() {
83 #ifdef __APPLE__
84  CFUUIDRef theUUID = CFUUIDCreate(NULL);
85  CFUUIDBytes b = CFUUIDGetUUIDBytes(theUUID);
86  sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
87  b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7,
88  b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15);
89  CFRelease(theUUID);
90 #elif defined (WIN32)
91  // First try and use the win API function UuidCreate(), but if that is not
92  // available, fall back to making something up from scratch.
93  // We do not want to link against the Rpcrt4.dll, as we will rarely use it,
94  // so we load the DLL dynamically, if it is available, and work from there.
95  static HMODULE hMod = NULL;
96  UUID ud;
97  UUID *pu = &ud;
98  int got_uuid = 0;
99 
100  if (!hMod) { // first time in?
101  hMod = LoadLibrary("Rpcrt4.dll");
102  }
103 
104  if (hMod) { // do we have a usable handle to Rpcrt4.dll?
105  uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate");
106  if (uuid_crt != NULL) {
107  RPC_STATUS rpc_res = uuid_crt(pu);
108  if ( // is the return status OK for our needs?
109  (rpc_res == RPC_S_OK) || // all is well
110  (rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine
111  (rpc_res == RPC_S_UUID_NO_ADDRESS) // probably only locally unique
112  ) {
113  got_uuid = -1;
114  sprintf(uuidBuffer, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
115  pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1],
116  pu->Data4[2], pu->Data4[3], pu->Data4[4],
117  pu->Data4[5], pu->Data4[6], pu->Data4[7]);
118  }
119  }
120  }
121  if (got_uuid == 0) { // did not make a UUID - use fallback logic
122  unsigned char b[16];
123  time_t t = time(0); // first 4 byte
124  b[0] = (unsigned char)t;
125  b[1] = (unsigned char)(t>>8);
126  b[2] = (unsigned char)(t>>16);
127  b[3] = (unsigned char)(t>>24);
128  int r = rand(); // four more bytes
129  b[4] = (unsigned char)r;
130  b[5] = (unsigned char)(r>>8);
131  b[6] = (unsigned char)(r>>16);
132  b[7] = (unsigned char)(r>>24);
133  // Now we try to find 4 more "random" bytes. We extract the
134  // lower 4 bytes from the address of t - it is created on the
135  // stack so *might* be in a different place each time...
136  // This is now done via a union to make it compile OK on 64-bit systems.
137  union { void *pv; unsigned char a[sizeof(void*)]; } v;
138  v.pv = (void *)(&t);
139  // NOTE: This assume that all WinXX systems are little-endian
140  b[8] = v.a[0];
141  b[9] = v.a[1];
142  b[10] = v.a[2];
143  b[11] = v.a[3];
144  TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes
145  DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
146  // GetComputerName() does not depend on any extra libs, and returns something
147  // analogous to gethostname()
148  GetComputerName(name, &nSize);
149  // use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID
150  for (int ii = 0; ii < 4; ii++) {
151  b[12 + ii] = (unsigned char)name[ii];
152  }
153  sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
154  b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
155  b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
156  }
157 #else
158  // warning Unix implementation of Fl_Preferences::newUUID() incomplete!
159  // #include <uuid/uuid.h>
160  // void uuid_generate(uuid_t out);
161  unsigned char b[16];
162  time_t t = time(0); // first 4 byte
163  b[0] = (unsigned char)t;
164  b[1] = (unsigned char)(t>>8);
165  b[2] = (unsigned char)(t>>16);
166  b[3] = (unsigned char)(t>>24);
167  int r = rand(); // four more bytes
168  b[4] = (unsigned char)r;
169  b[5] = (unsigned char)(r>>8);
170  b[6] = (unsigned char)(r>>16);
171  b[7] = (unsigned char)(r>>24);
172  unsigned long a = (unsigned long)&t; // four more bytes
173  b[8] = (unsigned char)a;
174  b[9] = (unsigned char)(a>>8);
175  b[10] = (unsigned char)(a>>16);
176  b[11] = (unsigned char)(a>>24);
177  // Now we try to find 4 more "random" bytes. We extract the
178  // lower 4 bytes from the address of t - it is created on the
179  // stack so *might* be in a different place each time...
180  // This is now done via a union to make it compile OK on 64-bit systems.
181  union { void *pv; unsigned char a[sizeof(void*)]; } v;
182  v.pv = (void *)(&t);
183  // NOTE: May need to handle big- or little-endian systems here
184 # if WORDS_BIGENDIAN
185  b[8] = v.a[sizeof(void*) - 1];
186  b[9] = v.a[sizeof(void*) - 2];
187  b[10] = v.a[sizeof(void*) - 3];
188  b[11] = v.a[sizeof(void*) - 4];
189 # else /* data ordered for a little-endian system */
190  b[8] = v.a[0];
191  b[9] = v.a[1];
192  b[10] = v.a[2];
193  b[11] = v.a[3];
194 # endif
195  char name[80]; // last four bytes
196  gethostname(name, 79);
197  memcpy(b+12, name, 4);
198  sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
199  b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
200  b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
201 #endif
202 
203  return uuidBuffer;
204 }
205 
232 Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *application ) {
233  node = new Node( "." );
234  rootNode = new RootNode( this, root, vendor, application );
236 }
237 
250 Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application ) {
251  node = new Node( "." );
252  rootNode = new RootNode( this, path, vendor, application );
254 }
255 
266 Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *group ) {
267  rootNode = parent.rootNode;
268  node = parent.node->addChild( group );
269 }
270 
281 Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *group ) {
282  if (parent==0) {
283  if (!runtimePrefs) {
285  runtimePrefs->node = new Node( "." );
288  }
289  parent = runtimePrefs;
290  }
291  rootNode = parent->rootNode;
292  node = parent->node->addChild( group );
293 }
294 
308 Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, int groupIndex ) {
309  rootNode = parent.rootNode;
310  if (groupIndex<0 || groupIndex>=parent.groups()) {
311  node = parent.node->addChild( newUUID() );
312  } else {
313  node = parent.node->childNode( groupIndex );
314  }
315 }
316 
320 Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, int groupIndex ) {
321  rootNode = parent->rootNode;
322  if (groupIndex<0 || groupIndex>=parent->groups()) {
323  node = parent->node->addChild( newUUID() );
324  } else {
325  node = parent->node->childNode( groupIndex );
326  }
327 }
328 
341  node = (Node*)id;
342  rootNode = node->findRoot();
343 }
344 
349 : node(rhs.node),
350  rootNode(rhs.rootNode)
351 { }
352 
357  if (&rhs != this) {
358  node = rhs.node;
359  rootNode = rhs.rootNode;
360  }
361  return *this;
362 }
363 
374  if (node && !node->parent()) delete rootNode;
375  // DO NOT delete nodes! The root node will do that after writing the preferences
376  // zero all pointer to avoid memory errors, even though
377  // Valgrind does not complain (Cygwin does though)
378  node = 0L;
379  rootNode = 0L;
380 }
381 
388  return node->nChildren();
389 }
390 
399 const char *Fl_Preferences::group( int num_group ) {
400  return node->child( num_group );
401 }
402 
412 char Fl_Preferences::groupExists( const char *key ) {
413  return node->search( key ) ? 1 : 0 ;
414 }
415 
425 char Fl_Preferences::deleteGroup( const char *group ) {
426  Node *nd = node->search( group );
427  if ( nd ) return nd->remove();
428  return 0;
429 }
430 
436  return 1;
437 }
438 
445  return node->nEntry();
446 }
447 
456 const char *Fl_Preferences::entry( int index ) {
457  return node->entry(index).name;
458 }
459 
466 char Fl_Preferences::entryExists( const char *key ) {
467  return node->getEntry( key )>=0 ? 1 : 0 ;
468 }
469 
478 char Fl_Preferences::deleteEntry( const char *key ) {
479  return node->deleteEntry( key );
480 }
481 
487  return 1;
488 }
489 
494  char ret1 = deleteAllGroups();
495  char ret2 = deleteAllEntries();
496  return ret1 & ret2;
497 }
498 
509 char Fl_Preferences::get( const char *key, int &value, int defaultValue ) {
510  const char *v = node->get( key );
511  value = v ? atoi( v ) : defaultValue;
512  return ( v != 0 );
513 }
514 
525 char Fl_Preferences::set( const char *key, int value ) {
526  sprintf( nameBuffer, "%d", value );
527  node->set( key, nameBuffer );
528  return 1;
529 }
530 
541 char Fl_Preferences::get( const char *key, float &value, float defaultValue ) {
542  const char *v = node->get( key );
543  value = v ? (float)atof( v ) : defaultValue;
544  return ( v != 0 );
545 }
546 
557 char Fl_Preferences::set( const char *key, float value ) {
558  sprintf( nameBuffer, "%g", value );
559  node->set( key, nameBuffer );
560  return 1;
561 }
562 
574 char Fl_Preferences::set( const char *key, float value, int precision ) {
575  sprintf( nameBuffer, "%.*g", precision, value );
576  node->set( key, nameBuffer );
577  return 1;
578 }
579 
590 char Fl_Preferences::get( const char *key, double &value, double defaultValue ) {
591  const char *v = node->get( key );
592  value = v ? atof( v ) : defaultValue;
593  return ( v != 0 );
594 }
595 
606 char Fl_Preferences::set( const char *key, double value ) {
607  sprintf( nameBuffer, "%g", value );
608  node->set( key, nameBuffer );
609  return 1;
610 }
611 
623 char Fl_Preferences::set( const char *key, double value, int precision ) {
624  sprintf( nameBuffer, "%.*g", precision, value );
625  node->set( key, nameBuffer );
626  return 1;
627 }
628 
629 // remove control sequences from a string
630 static char *decodeText( const char *src ) {
631  int len = 0;
632  const char *s = src;
633  for ( ; *s; s++, len++ ) {
634  if ( *s == '\\' ) {
635  if ( isdigit( s[1] ) ) {
636  s+=3;
637  } else {
638  s+=1;
639  }
640  }
641  }
642  char *dst = (char*)malloc( len+1 ), *d = dst;
643  for ( s = src; *s; s++ ) {
644  char c = *s;
645  if ( c == '\\' ) {
646  if ( s[1] == '\\' ) { *d++ = c; s++; }
647  else if ( s[1] == 'n' ) { *d++ = '\n'; s++; }
648  else if ( s[1] == 'r' ) { *d++ = '\r'; s++; }
649  else if ( isdigit( s[1] ) ) { *d++ = ((s[1]-'0')<<6) + ((s[2]-'0')<<3) + (s[3]-'0'); s+=3; }
650  else s++; // error
651  }
652  else
653  *d++ = c;
654  }
655  *d = 0;
656  return dst;
657 }
658 
672 char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize ) {
673  const char *v = node->get( key );
674  if ( v && strchr( v, '\\' ) ) {
675  char *w = decodeText( v );
676  strlcpy(text, w, maxSize);
677  free( w );
678  return 1;
679  }
680  if ( !v ) v = defaultValue;
681  if ( v ) strlcpy(text, v, maxSize);
682  else *text = 0;
683  return ( v != defaultValue );
684 }
685 
698 char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue ) {
699  const char *v = node->get( key );
700  if ( v && strchr( v, '\\' ) ) {
701  text = decodeText( v );
702  return 1;
703  }
704  if ( !v ) v = defaultValue;
705  if ( v )
706  text = strdup( v );
707  else
708  text = 0;
709  return ( v != defaultValue );
710 }
711 
722 char Fl_Preferences::set( const char *key, const char *text ) {
723  const char *s = text ? text : "";
724  int n=0, ns=0;
725  for ( ; *s; s++ ) { n++; if ( *s<32 || *s=='\\' || *s==0x7f ) ns+=4; }
726  if ( ns ) {
727  char *buffer = (char*)malloc( n+ns+1 ), *d = buffer;
728  for ( s=text; *s; ) {
729  char c = *s;
730  if ( c=='\\' ) { *d++ = '\\'; *d++ = '\\'; s++; }
731  else if ( c=='\n' ) { *d++ = '\\'; *d++ = 'n'; s++; }
732  else if ( c=='\r' ) { *d++ = '\\'; *d++ = 'r'; s++; }
733  else if ( c<32 || c==0x7f )
734  { *d++ = '\\'; *d++ = '0'+((c>>6)&3); *d++ = '0'+((c>>3)&7); *d++ = '0'+(c&7); s++; }
735  else *d++ = *s++;
736  }
737  *d = 0;
738  node->set( key, buffer );
739  free( buffer );
740  }
741  else
742  node->set( key, text );
743  return 1;
744 }
745 
746 // convert a hex string to binary data
747 static void *decodeHex( const char *src, int &size ) {
748  size = (int) strlen( src )/2;
749  unsigned char *data = (unsigned char*)malloc( size ), *d = data;
750  const char *s = src;
751  for ( int i=size; i>0; i-- ) {
752  int v;
753  char x = tolower(*s++);
754  if ( x >= 'a' ) v = x-'a'+10; else v = x-'0';
755  v = v<<4;
756  x = tolower(*s++);
757  if ( x >= 'a' ) v += x-'a'+10; else v += x-'0';
758  *d++ = (uchar)v;
759  }
760  return (void*)data;
761 }
762 
778 char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize ) {
779  const char *v = node->get( key );
780  if ( v ) {
781  int dsize;
782  void *w = decodeHex( v, dsize );
783  memmove( data, w, dsize>maxSize?maxSize:dsize );
784  free( w );
785  return 1;
786  }
787  if ( defaultValue )
788  memmove( data, defaultValue, defaultSize>maxSize?maxSize:defaultSize );
789  return 0;
790 }
791 
805 char Fl_Preferences::get( const char *key, void *&data, const void *defaultValue, int defaultSize ) {
806  const char *v = node->get( key );
807  if ( v ) {
808  int dsize;
809  data = decodeHex( v, dsize );
810  return 1;
811  }
812  if ( defaultValue ) {
813  data = (void*)malloc( defaultSize );
814  memmove( data, defaultValue, defaultSize );
815  }
816  else
817  data = 0;
818  return 0;
819 }
820 
832 char Fl_Preferences::set( const char *key, const void *data, int dsize ) {
833  char *buffer = (char*)malloc( dsize*2+1 ), *d = buffer;;
834  unsigned char *s = (unsigned char*)data;
835  for ( ; dsize>0; dsize-- ) {
836  static char lu[] = "0123456789abcdef";
837  unsigned char v = *s++;
838  *d++ = lu[v>>4];
839  *d++ = lu[v&0xf];
840  }
841  *d = 0;
842  node->set( key, buffer );
843  free( buffer );
844  return 1;
845 }
846 
853 int Fl_Preferences::size( const char *key ) {
854  const char *v = node->get( key );
855  return (int) (v ? strlen( v ) : 0);
856 }
857 
885 char Fl_Preferences::getUserdataPath( char *path, int pathlen ) {
886  if ( rootNode )
887  return rootNode->getPath( path, pathlen );
888  return 0;
889 }
890 
897  if ( rootNode && node->dirty() )
898  rootNode->write();
899 }
900 
901 //-----------------------------------------------------------------------------
902 // helper class to create dynamic group and entry names on the fly
903 //
904 
918 Fl_Preferences::Name::Name( unsigned int n ) {
919  data_ = (char*)malloc(20);
920  sprintf(data_, "%u", n);
921 }
922 
936 Fl_Preferences::Name::Name( const char *format, ... ) {
937  data_ = (char*)malloc(1024);
938  va_list args;
939  va_start(args, format);
940  vsnprintf(data_, 1024, format, args);
941  va_end(args);
942 }
943 
944 // delete the name
946  if (data_) {
947  free(data_);
948  data_ = 0L;
949  }
950 }
951 
952 //-----------------------------------------------------------------------------
953 // internal methods, do not modify or use as they will change without notice
954 //
955 
957 
958 // create the root node
959 // - construct the name of the file that will hold our preferences
960 Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char *vendor, const char *application )
961 : prefs_(prefs),
962  filename_(0L),
963  vendor_(0L),
964  application_(0L) {
965 
966  char filename[ FL_PATH_MAX ]; filename[0] = 0;
967 #ifdef WIN32
968 # define FLPREFS_RESOURCE "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
969 # define FLPREFS_RESOURCEW L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
970  size_t appDataLen = strlen(vendor) + strlen(application) + 8;
971  DWORD type, nn;
972  LONG err;
973  HKEY key;
974 
975  switch (root) {
976  case SYSTEM:
977  err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key );
978  if (err == ERROR_SUCCESS) {
979  nn = (DWORD) (FL_PATH_MAX - appDataLen);
980  err = RegQueryValueExW( key, L"Common AppData", 0L, &type,
981  (BYTE*)filename, &nn );
982  if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
983  filename[0] = 0;
984  filename[1] = 0;
985  }
986  RegCloseKey(key);
987  }
988  break;
989  case USER:
990  err = RegOpenKeyW( HKEY_CURRENT_USER, FLPREFS_RESOURCEW, &key );
991  if (err == ERROR_SUCCESS) {
992  nn = (DWORD) (FL_PATH_MAX - appDataLen);
993  err = RegQueryValueExW( key, L"AppData", 0L, &type,
994  (BYTE*)filename, &nn );
995  if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
996  filename[0] = 0;
997  filename[1] = 0;
998  }
999  RegCloseKey(key);
1000  }
1001  break;
1002  }
1003  if (!filename[1] && !filename[0]) {
1004  strcpy(filename, "C:\\FLTK");
1005  } else {
1006 #if 0
1007  xchar *b = (xchar*)_wcsdup((xchar *)filename);
1008 #else
1009  // cygwin does not come with _wcsdup. Use malloc + wcscpy.
1010  // For implementation of wcsdup functionality See
1011  // - http://linenum.info/p/glibc/2.7/wcsmbs/wcsdup.c
1012  xchar *b = (xchar*) malloc((wcslen((xchar *) filename) + 1) * sizeof(xchar));
1013  wcscpy(b, (xchar *) filename);
1014 #endif
1015  // filename[fl_unicode2utf(b, wcslen((xchar*)b), filename)] = 0;
1016  unsigned len = fl_utf8fromwc(filename, (FL_PATH_MAX-1), b, (unsigned) wcslen(b));
1017  filename[len] = 0;
1018  free(b);
1019  }
1020  snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
1021  "/%s/%s.prefs", vendor, application);
1022  for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
1023 #elif defined ( __APPLE__ )
1024  // TODO: verify that this is the Apple sanctioned way of finding these folders
1025  // (On MSWindows, this frequently leads to issues with internationalized systems)
1026  // Carbon: err = FindFolder( kLocalDomain, kPreferencesFolderType, 1, &spec.vRefNum, &spec.parID );
1027  switch (root) {
1028  case SYSTEM:
1029  strcpy(filename, "/Library/Preferences");
1030  break;
1031  case USER:
1032  sprintf(filename, "%s/Library/Preferences", fl_getenv("HOME"));
1033  break;
1034  }
1035  snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
1036  "/%s/%s.prefs", vendor, application );
1037 #else
1038  const char *e;
1039  switch (root) {
1040  case USER:
1041  if ((e = fl_getenv("HOME")) != NULL) {
1042  strlcpy(filename, e, sizeof(filename));
1043 
1044  if (filename[strlen(filename)-1] != '/') {
1045  strlcat(filename, "/.fltk/", sizeof(filename));
1046  } else {
1047  strlcat(filename, ".fltk/", sizeof(filename));
1048  }
1049  break;
1050  }
1051  case SYSTEM:
1052  strcpy(filename, "/etc/fltk/");
1053  break;
1054  }
1055  snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
1056  "%s/%s.prefs", vendor, application);
1057 #endif
1058  filename_ = strdup(filename);
1059  vendor_ = strdup(vendor);
1060  application_ = strdup(application);
1061  read();
1062 }
1063 
1064 // create the root node
1065 // - construct the name of the file that will hold our preferences
1066 Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application )
1067 : prefs_(prefs),
1068  filename_(0L),
1069  vendor_(0L),
1070  application_(0L) {
1071 
1072  if (!vendor)
1073  vendor = "unknown";
1074  if (!application) {
1075  application = "unknown";
1076  filename_ = strdup(path);
1077  } else {
1078  char filename[ FL_PATH_MAX ]; filename[0] = 0;
1079  snprintf(filename, sizeof(filename), "%s/%s.prefs", path, application);
1080  filename_ = strdup(filename);
1081  }
1082  vendor_ = strdup(vendor);
1083  application_ = strdup(application);
1084  read();
1085 }
1086 
1087 // create a root node that exists only on RAM and can not be read or written to
1088 // a file
1090 : prefs_(prefs),
1091  filename_(0L),
1092  vendor_(0L),
1093  application_(0L) {
1094 }
1095 
1096 // destroy the root node and all depending nodes
1098  if ( prefs_->node->dirty() )
1099  write();
1100  if ( filename_ ) {
1101  free( filename_ );
1102  filename_ = 0L;
1103  }
1104  if ( vendor_ ) {
1105  free( vendor_ );
1106  vendor_ = 0L;
1107  }
1108  if ( application_ ) {
1109  free( application_ );
1110  application_ = 0L;
1111  }
1112  delete prefs_->node;
1113  prefs_->node = 0L;
1114 }
1115 
1116 // read a preferences file and construct the group tree and with all entry leafs
1118  if (!filename_) // RUNTIME preferences
1119  return -1;
1120  char buf[1024];
1121  FILE *f = fl_fopen( filename_, "rb" );
1122  if ( !f )
1123  return -1;
1124  if (fgets( buf, 1024, f )==0) { /* ignore */ }
1125  if (fgets( buf, 1024, f )==0) { /* ignore */ }
1126  if (fgets( buf, 1024, f )==0) { /* ignore */ }
1127  Node *nd = prefs_->node;
1128  for (;;) {
1129  if ( !fgets( buf, 1024, f ) ) break; // EOF or Error
1130  if ( buf[0]=='[' ) { // read a new group
1131  size_t end = strcspn( buf+1, "]\n\r" );
1132  buf[ end+1 ] = 0;
1133  nd = prefs_->node->find( buf+1 );
1134  } else if ( buf[0]=='+' ) { // value of previous name/value pair spans multiple lines
1135  size_t end = strcspn( buf+1, "\n\r" );
1136  if ( end != 0 ) { // if entry is not empty
1137  buf[ end+1 ] = 0;
1138  nd->add( buf+1 );
1139  }
1140  } else { // read a name/value pair
1141  size_t end = strcspn( buf, "\n\r" );
1142  if ( end != 0 ) { // if entry is not empty
1143  buf[ end ] = 0;
1144  nd->set( buf );
1145  }
1146  }
1147  }
1148  fclose( f );
1149  return 0;
1150 }
1151 
1152 // write the group tree and all entry leafs
1154  if (!filename_) // RUNTIME preferences
1155  return -1;
1156  fl_make_path_for_file(filename_);
1157  FILE *f = fl_fopen( filename_, "wb" );
1158  if ( !f )
1159  return -1;
1160  fprintf( f, "; FLTK preferences file format 1.0\n" );
1161  fprintf( f, "; vendor: %s\n", vendor_ );
1162  fprintf( f, "; application: %s\n", application_ );
1163  prefs_->node->write( f );
1164  fclose( f );
1165 #if !(defined(__APPLE__) || defined(WIN32))
1166  // unix: make sure that system prefs are user-readable
1167  if (strncmp(filename_, "/etc/fltk/", 10) == 0) {
1168  char *p;
1169  p = filename_ + 9;
1170  do { // for each directory to the pref file
1171  *p = 0;
1172  fl_chmod(filename_, 0755); // rwxr-xr-x
1173  *p = '/';
1174  p = strchr(p+1, '/');
1175  } while (p);
1176  fl_chmod(filename_, 0644); // rw-r--r--
1177  }
1178 #endif
1179  return 0;
1180 }
1181 
1182 // get the path to the preferences directory
1183 char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) {
1184  if (!filename_) // RUNTIME preferences
1185  return 1; // return 1 (not -1) to be consistent with fl_make_path()
1186  strlcpy( path, filename_, pathlen);
1187 
1188  char *s;
1189  for ( s = path; *s; s++ ) if ( *s == '\\' ) *s = '/';
1190  s = strrchr( path, '.' );
1191  if ( !s ) return 0;
1192  *s = 0;
1193  char ret = fl_make_path( path );
1194 #if !(defined(__APPLE__) || defined(WIN32))
1195  // unix: make sure that system prefs dir. is user-readable
1196  if (strncmp(path, "/etc/fltk/", 10) == 0) {
1197  fl_chmod(path, 0755); // rwxr-xr-x
1198  }
1199 #endif
1200  strcpy( s, "/" );
1201  return ret;
1202 }
1203 
1204 // create a node that represents a group
1205 // - path must be a single word, prferable alnum(), dot and underscore only. Space is ok.
1207  if ( path ) path_ = strdup( path ); else path_ = 0;
1208  child_ = 0; next_ = 0; parent_ = 0;
1209  entry_ = 0;
1210  nEntry_ = NEntry_ = 0;
1211  dirty_ = 0;
1212  top_ = 0;
1213  indexed_ = 0;
1214  index_ = 0;
1215  nIndex_ = NIndex_ = 0;
1216 }
1217 
1219  Node *nx;
1220  for ( Node *nd = child_; nd; nd = nx ) {
1221  nx = nd->next_;
1222  delete nd;
1223  }
1224  child_ = 0L;
1225  dirty_ = 1;
1226  updateIndex();
1227 }
1228 
1230  if ( entry_ ) {
1231  for ( int i = 0; i < nEntry_; i++ ) {
1232  if ( entry_[i].name ) {
1233  free( entry_[i].name );
1234  entry_[i].name = 0L;
1235  }
1236  if ( entry_[i].value ) {
1237  free( entry_[i].value );
1238  entry_[i].value = 0L;
1239  }
1240  }
1241  free( entry_ );
1242  entry_ = 0L;
1243  nEntry_ = 0;
1244  NEntry_ = 0;
1245  }
1246  dirty_ = 1;
1247 }
1248 
1249 // delete this and all depending nodes
1251  deleteAllChildren();
1252  deleteAllEntries();
1253  deleteIndex();
1254  if ( path_ ) {
1255  free( path_ );
1256  path_ = 0L;
1257  }
1258  next_ = 0L;
1259  parent_ = 0L;
1260 }
1261 
1262 // recursively check if any entry is dirty (was changed after loading a fresh prefs file)
1264  if ( dirty_ ) return 1;
1265  if ( next_ && next_->dirty() ) return 1;
1266  if ( child_ && child_->dirty() ) return 1;
1267  return 0;
1268 }
1269 
1270 // write this node (recursively from the last neighbor back to this)
1271 // write all entries
1272 // write all children
1274  if ( next_ ) next_->write( f );
1275  fprintf( f, "\n[%s]\n\n", path_ );
1276  for ( int i = 0; i < nEntry_; i++ ) {
1277  char *src = entry_[i].value;
1278  if ( src ) { // hack it into smaller pieces if needed
1279  fprintf( f, "%s:", entry_[i].name );
1280  size_t cnt, written = 0;
1281  for ( cnt = 0; cnt < 60; cnt++ )
1282  if ( src[cnt]==0 ) break;
1283  written += fwrite( src, cnt, 1, f );
1284  fprintf( f, "\n" );
1285  src += cnt;
1286  for (;*src;) {
1287  for ( cnt = 0; cnt < 80; cnt++ )
1288  if ( src[cnt]==0 ) break;
1289  fputc( '+', f );
1290  written += fwrite( src, cnt, 1, f );
1291  fputc( '\n', f );
1292  src += cnt;
1293  }
1294  }
1295  else
1296  fprintf( f, "%s\n", entry_[i].name );
1297  }
1298  if ( child_ ) child_->write( f );
1299  dirty_ = 0;
1300  return 0;
1301 }
1302 
1303 // set the parent node and create the full path
1305  parent_ = pn;
1306  next_ = pn->child_;
1307  pn->child_ = this;
1308  sprintf( nameBuffer, "%s/%s", pn->path_, path_ );
1309  free( path_ );
1310  path_ = strdup( nameBuffer );
1311 }
1312 
1313 // find the corresponding root node
1315  Node *n = this;
1316  do {
1317  if (n->top_)
1318  return n->root_;
1319  n = n->parent();
1320  } while (n);
1321  return 0L;
1322 }
1323 
1324 // add a child to this node and set its path (try to find it first...)
1326  sprintf( nameBuffer, "%s/%s", path_, path );
1327  char *name = strdup( nameBuffer );
1328  Node *nd = find( name );
1329  free( name );
1330  dirty_ = 1;
1331  updateIndex();
1332  return nd;
1333 }
1334 
1335 // create and set, or change an entry within this node
1336 void Fl_Preferences::Node::set( const char *name, const char *value )
1337 {
1338  for ( int i=0; i<nEntry_; i++ ) {
1339  if ( strcmp( name, entry_[i].name ) == 0 ) {
1340  if ( !value ) return; // annotation
1341  if ( strcmp( value, entry_[i].value ) != 0 ) {
1342  if ( entry_[i].value )
1343  free( entry_[i].value );
1344  entry_[i].value = strdup( value );
1345  dirty_ = 1;
1346  }
1347  lastEntrySet = i;
1348  return;
1349  }
1350  }
1351  if ( NEntry_==nEntry_ ) {
1352  NEntry_ = NEntry_ ? NEntry_*2 : 10;
1353  entry_ = (Entry*)realloc( entry_, NEntry_ * sizeof(Entry) );
1354  }
1355  entry_[ nEntry_ ].name = strdup( name );
1356  entry_[ nEntry_ ].value = value?strdup( value ):0;
1357  lastEntrySet = nEntry_;
1358  nEntry_++;
1359  dirty_ = 1;
1360 }
1361 
1362 // create or set a value (or annotation) from a single line in the file buffer
1363 void Fl_Preferences::Node::set( const char *line ) {
1364  // hmm. If we assume that we always read this file in the beginning,
1365  // we can handle the dirty flag 'quick and dirty'
1366  char dirt = dirty_;
1367  if ( line[0]==';' || line[0]==0 || line[0]=='#' ) {
1368  set( line, 0 );
1369  } else {
1370  const char *c = strchr( line, ':' );
1371  if ( c ) {
1372  size_t len = c-line+1;
1373  if ( len >= sizeof( nameBuffer ) )
1374  len = sizeof( nameBuffer );
1375  strlcpy( nameBuffer, line, len );
1376  set( nameBuffer, c+1 );
1377  } else {
1378  set( line, "" );
1379  }
1380  }
1381  dirty_ = dirt;
1382 }
1383 
1384 // add more data to an existing entry
1385 void Fl_Preferences::Node::add( const char *line ) {
1386  if ( lastEntrySet<0 || lastEntrySet>=nEntry_ ) return;
1387  char *&dst = entry_[ lastEntrySet ].value;
1388  size_t a = strlen( dst );
1389  size_t b = strlen( line );
1390  dst = (char*)realloc( dst, a+b+1 );
1391  memcpy( dst+a, line, b+1 );
1392  dirty_ = 1;
1393 }
1394 
1395 // get the value for a name, returns 0 if no such name
1396 const char *Fl_Preferences::Node::get( const char *name ) {
1397  int i = getEntry( name );
1398  return i>=0 ? entry_[i].value : 0 ;
1399 }
1400 
1401 // find the index of an entry, returns -1 if no such entry
1403  for ( int i=0; i<nEntry_; i++ ) {
1404  if ( strcmp( name, entry_[i].name ) == 0 ) {
1405  return i;
1406  }
1407  }
1408  return -1;
1409 }
1410 
1411 // remove one entry form this group
1413  int ix = getEntry( name );
1414  if ( ix == -1 ) return 0;
1415  memmove( entry_+ix, entry_+ix+1, (nEntry_-ix-1) * sizeof(Entry) );
1416  nEntry_--;
1417  dirty_ = 1;
1418  return 1;
1419 }
1420 
1421 // find a group somewhere in the tree starting here
1422 // - this method will always return a valid node (except for memory allocation problems)
1423 // - if the node was not found, 'find' will create the required branch
1425  int len = (int) strlen( path_ );
1426  if ( strncmp( path, path_, len ) == 0 ) {
1427  if ( path[ len ] == 0 )
1428  return this;
1429  if ( path[ len ] == '/' ) {
1430  Node *nd;
1431  for ( nd = child_; nd; nd = nd->next_ ) {
1432  Node *nn = nd->find( path );
1433  if ( nn ) return nn;
1434  }
1435  const char *s = path+len+1;
1436  const char *e = strchr( s, '/' );
1437  if (e) strlcpy( nameBuffer, s, e-s+1 );
1438  else strlcpy( nameBuffer, s, sizeof(nameBuffer));
1439  nd = new Node( nameBuffer );
1440  nd->setParent( this );
1441  return nd->find( path );
1442  }
1443  }
1444  return 0;
1445 }
1446 
1447 // find a group somewhere in the tree starting here
1448 // caller must not set 'offset' argument
1449 // - if the node does not exist, 'search' returns NULL
1450 // - if the pathname is "." (current node) return this node
1451 // - if the pathname is "./" (root node) return the topmost node
1452 // - if the pathname starts with "./", start the search at the root node instead
1454  if ( offset == 0 ) {
1455  if ( path[0] == '.' ) {
1456  if ( path[1] == 0 ) {
1457  return this; // user was searching for current node
1458  } else if ( path[1] == '/' ) {
1459  Node *nn = this;
1460  while ( nn->parent() ) nn = nn->parent();
1461  if ( path[2]==0 ) { // user is searching for root ( "./" )
1462  return nn;
1463  }
1464  return nn->search( path+2, 2 ); // do a relative search on the root node
1465  }
1466  }
1467  offset = (int) strlen( path_ ) + 1;
1468  }
1469  int len = (int) strlen( path_ );
1470  if ( len < offset-1 ) return 0;
1471  len -= offset;
1472  if ( ( len <= 0 ) || ( strncmp( path, path_+offset, len ) == 0 ) ) {
1473  if ( len > 0 && path[ len ] == 0 )
1474  return this;
1475  if ( len <= 0 || path[ len ] == '/' ) {
1476  for ( Node *nd = child_; nd; nd = nd->next_ ) {
1477  Node *nn = nd->search( path, offset );
1478  if ( nn ) return nn;
1479  }
1480  return 0;
1481  }
1482  }
1483  return 0;
1484 }
1485 
1486 // return the number of child nodes (groups)
1488  if (indexed_) {
1489  return nIndex_;
1490  } else {
1491  int cnt = 0;
1492  for ( Node *nd = child_; nd; nd = nd->next_ )
1493  cnt++;
1494  return cnt;
1495  }
1496 }
1497 
1498 // return the node name
1500  if ( path_ ) {
1501  char *r = strrchr( path_, '/' );
1502  return r ? r+1 : path_ ;
1503  } else {
1504  return 0L ;
1505  }
1506 }
1507 
1508 // return the n'th child node's name
1509 const char *Fl_Preferences::Node::child( int ix ) {
1510  Node *nd = childNode( ix );
1511  if ( nd )
1512  return nd->name();
1513  else
1514  return 0L ;
1515 }
1516 
1517 // return the n'th child node
1519  createIndex();
1520  if (indexed_) {
1521  // usually faster access in correct order, but needing more memory
1522  return index_[ix];
1523  } else {
1524  // slow access and reverse order
1525  int n = nChildren();
1526  ix = n - ix -1;
1527  Node *nd;
1528  for ( nd = child_; nd; nd = nd->next_ ) {
1529  if ( !ix-- ) break;
1530  if ( !nd ) break;
1531  }
1532  return nd;
1533  }
1534 }
1535 
1536 // remove myself from the list and delete me (and all children)
1538  Node *nd = 0, *np;
1539  if ( parent() ) {
1540  nd = parent()->child_; np = 0L;
1541  for ( ; nd; np = nd, nd = nd->next_ ) {
1542  if ( nd == this ) {
1543  if ( np )
1544  np->next_ = nd->next_;
1545  else
1546  parent()->child_ = nd->next_;
1547  break;
1548  }
1549  }
1550  parent()->dirty_ = 1;
1551  parent()->updateIndex();
1552  }
1553  delete this;
1554  return ( nd != 0 );
1555 }
1556 
1558  if (indexed_) return;
1559  int n = nChildren();
1560  if (n>NIndex_) {
1561  NIndex_ = n + 16;
1562  index_ = (Node**)realloc(index_, NIndex_*sizeof(Node**));
1563  }
1564  Node *nd;
1565  int i = 0;
1566  for (nd = child_; nd; nd = nd->next_, i++) {
1567  index_[n-i-1] = nd;
1568  }
1569  nIndex_ = n;
1570  indexed_ = 1;
1571 }
1572 
1574  indexed_ = 0;
1575 }
1576 
1578  if (index_) free(index_);
1579  NIndex_ = nIndex_ = 0;
1580  index_ = 0;
1581  indexed_ = 0;
1582 }
1583 
1590 Fl_Plugin::Fl_Plugin(const char *klass, const char *name)
1591 : id(0) {
1592 #ifdef FL_PLUGIN_VERBOSE
1593  printf("Fl_Plugin: creating a plugin, class \"%s\", name \"%s\"\n",
1594  klass, name);
1595 #endif
1596  Fl_Plugin_Manager pm(klass);
1597  id = pm.addPlugin(name, this);
1598 }
1599 
1604 #ifdef FL_PLUGIN_VERBOSE
1605  printf("Fl_Plugin: deleting a plugin\n");
1606 #endif
1607  if (id)
1609 }
1610 
1615 : Fl_Preferences(0, Fl_Preferences::Name("%s/%s", "plugins", klass)) {
1616 #ifdef FL_PLUGIN_VERBOSE
1617  printf("Fl_Plugin: creating a plugin manager for class \"%s\"\n", klass);
1618 #endif
1619 }
1620 
1628 #ifdef FL_PLUGIN_VERBOSE
1629  printf("Fl_Plugin: deleting a plugin manager\n");
1630 #endif
1631 }
1632 
1633 static unsigned char x2i(char hi, char lo) {
1634  return ((hi-'A')<<4) | (lo-'A');
1635 }
1636 
1637 static void i2x(unsigned char v, char *d) {
1638  d[0] = ((v>>4)&0x0f)+'A'; d[1] = (v&0x0f)+'A';
1639 }
1640 
1641 static void *a2p(const char *s) {
1642  union { void *ret; unsigned char d[sizeof(void*)]; } v;
1643  v.ret = 0L;
1644  int i=0, n=sizeof(void*);
1645  for (i=0; i<n; i++) {
1646  v.d[i] = x2i(s[2*i], s[2*i+1]);
1647  }
1648  return v.ret;
1649 }
1650 
1651 static void p2a(void *vp, char *d) {
1652  union { void *vp; unsigned char s[sizeof(void*)]; } v;
1653  v.vp = vp;
1654  int i=0, n=sizeof(void*);
1655  for (i=0; i<n; i++) {
1656  i2x(v.s[i], d+i*2);
1657  }
1658  d[2*i] = 0;
1659 }
1660 
1665  char buf[34];
1666  Fl_Plugin *ret = 0;
1667  Fl_Preferences pin(this, index);
1668  pin.get("address", buf, "", 34);
1669  if (buf[0]=='@') ret = (Fl_Plugin*)a2p(buf+1);
1670 #ifdef FL_PLUGIN_VERBOSE
1671  printf("Fl_Plugin: returning plugin at index %d: (%s) %p\n", index, buf, ret);
1672 #endif
1673  return ret;
1674 }
1675 
1680  char buf[34];
1681  Fl_Plugin *ret = 0;
1682  if (groupExists(name)) {
1683  Fl_Preferences pin(this, name);
1684  pin.get("address", buf, "", 34);
1685  if (buf[0]=='@') ret = (Fl_Plugin*)a2p(buf+1);
1686 #ifdef FL_PLUGIN_VERBOSE
1687  printf("Fl_Plugin: returning plugin named \"%s\": (%s) %p\n", name, buf, ret);
1688 #endif
1689  return ret;
1690  } else {
1691 #ifdef FL_PLUGIN_VERBOSE
1692  printf("Fl_Plugin: no plugin found named \"%s\"\n", name);
1693 #endif
1694  return 0L;
1695  }
1696 }
1697 
1705  char buf[34];
1706 #ifdef FL_PLUGIN_VERBOSE
1707  printf("Fl_Plugin: adding plugin named \"%s\" at 0x%p\n", name, plugin);
1708 #endif
1709  Fl_Preferences pin(this, name);
1710  buf[0] = '@'; p2a(plugin, buf+1);
1711  pin.set("address", buf);
1712  return pin.id();
1713 }
1714 
1723 }
1724 
1734  // the functions below will autmaticaly load plugins that are defined:
1735  // Fl_My_Plugin plugin();
1736 #if defined(WIN32) && !defined(__CYGWIN__)
1737  HMODULE dl = LoadLibrary(filename);
1738 #else
1739  void * dl = NULL;
1740 # if HAVE_DLSYM
1741  dl = dlopen(filename, RTLD_LAZY);
1742 # endif
1743 #endif
1744  // There is no way of unloading a plugin!
1745  return (dl!=0) ? 0 : -1;
1746 }
1747 
1751 int Fl_Plugin_Manager::loadAll(const char *filepath, const char *pattern) {
1752  struct dirent **dir;
1753  int i, n = fl_filename_list(filepath, &dir);
1754  for (i=0; i<n; i++) {
1755  struct dirent *e = dir[i];
1756  if (pattern==0 || fl_filename_match(e->d_name, pattern)) {
1757  load(Fl_Preferences::Name("%s%s", filepath, e->d_name));
1758  }
1759  free(e);
1760  }
1761  free(dir);
1762  return 0;
1763 }
1764 
1765 //
1766 // End of "$Id$".
1767 //
xchar
#define xchar
Definition: fl_utf8.h:68
Fl_Preferences::Node::name
const char * name()
Definition: Fl_Preferences.cxx:1499
Fl_Preferences::runtimePrefs
static Fl_Preferences * runtimePrefs
Definition: Fl_Preferences.H:186
Fl.H
buf
static char * buf
Definition: fl_encoding_mac_roman.cxx:76
Fl_Preferences::deleteAllEntries
char deleteAllEntries()
Definition: Fl_Preferences.cxx:485
Fl_Preferences::entry
const char * entry(int index)
Definition: Fl_Preferences.cxx:456
Fl_Preferences::Node::add
void add(const char *line)
Definition: Fl_Preferences.cxx:1385
Fl_Preferences::~Fl_Preferences
virtual ~Fl_Preferences()
Definition: Fl_Preferences.cxx:373
Fl_Preferences::Node::set
void set(const char *name, const char *value)
Definition: Fl_Preferences.cxx:1336
Fl_Preferences::Node::findRoot
RootNode * findRoot()
Definition: Fl_Preferences.cxx:1314
Fl_Plugin.H
Fl_Plugin_Manager::addPlugin
Fl_Preferences::ID addPlugin(const char *name, Fl_Plugin *plugin)
This function adds a new plugin to the database.
Definition: Fl_Preferences.cxx:1704
vsnprintf
#define vsnprintf
Definition: flstring.h:69
Fl_Preferences::Node::setParent
void setParent(Node *parent)
Definition: Fl_Preferences.cxx:1304
find
static Fl_Font_Descriptor * find(Fl_Font fnum, Fl_Fontsize size)
Definition: fl_font_mac.cxx:250
Fl_Preferences::USER
Preferences apply only to the current user.
Definition: Fl_Preferences.H:68
Fl_Plugin::~Fl_Plugin
virtual ~Fl_Plugin()
Clear the plugin and remove it from the database.
Definition: Fl_Preferences.cxx:1603
Fl_Preferences::Node::write
int write(FILE *f)
Definition: Fl_Preferences.cxx:1273
a2p
static void * a2p(const char *s)
Definition: Fl_Preferences.cxx:1641
Fl_Preferences::Node::remove
char remove()
Definition: Fl_Preferences.cxx:1537
Fl_Preferences::Node::entry
Entry & entry(int i)
Definition: Fl_Preferences.H:241
filename.H
Fl_Preferences::deleteAllGroups
char deleteAllGroups()
Definition: Fl_Preferences.cxx:434
free
void free()
offset
static double offset[5]
Definition: fl_rounded_box.cxx:32
Fl_Preferences::Node::nChildren
int nChildren()
Definition: Fl_Preferences.cxx:1487
Fl_Preferences::groups
int groups()
Definition: Fl_Preferences.cxx:387
Fl_Plugin_Manager::load
static int load(const char *filename)
Load a module from disk.
Definition: Fl_Preferences.cxx:1733
Fl_Preferences::Node::find
Node * find(const char *path)
Definition: Fl_Preferences.cxx:1424
NULL
#define NULL
Definition: forms.H:34
Fl_Preferences::size
int size(const char *entry)
Definition: Fl_Preferences.cxx:853
fl_utf8fromwc
unsigned fl_utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen)
Definition: fl_utf.c:617
Fl_Preferences::getUserdataPath
char getUserdataPath(char *path, int pathlen)
Creates a path that is related to the preferences file and that is usable for additional application ...
Definition: Fl_Preferences.cxx:885
Fl_Preferences::Entry::name
char * name
Definition: Fl_Preferences.H:177
Fl_Preferences::rootNode
RootNode * rootNode
Definition: Fl_Preferences.H:262
decodeText
static char * decodeText(const char *src)
Definition: Fl_Preferences.cxx:630
Fl_Preferences::Node::createIndex
void createIndex()
Definition: Fl_Preferences.cxx:1557
Fl_Preferences::RootNode::RootNode
RootNode(Fl_Preferences *, Root root, const char *vendor, const char *application)
Definition: Fl_Preferences.cxx:960
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
b
long b
Definition: jpegint.h:397
key
int key
Definition: Fl_Text_Editor.cxx:91
snprintf
#define snprintf
Definition: flstring.h:64
Fl_Preferences::clear
char clear()
Definition: Fl_Preferences.cxx:493
Fl_Preferences::RootNode
friend class RootNode
Definition: Fl_Preferences.H:258
Fl_Preferences::Node::~Node
~Node()
Definition: Fl_Preferences.cxx:1250
Fl_Preferences::path
const char * path()
Definition: Fl_Preferences.H:106
Fl_Preferences::Node::child_
Node * child_
Definition: Fl_Preferences.H:193
Fl_Preferences::RootNode::~RootNode
~RootNode()
Definition: Fl_Preferences.cxx:1097
buffer
static char * buffer
Definition: file.cxx:215
Fl_Preferences::RootNode::application_
char * application_
Definition: Fl_Preferences.H:248
Fl_Preferences::Node::deleteEntry
char deleteEntry(const char *name)
Definition: Fl_Preferences.cxx:1412
p
static menustate * p
Definition: Fl_Menu.cxx:606
Fl_Preferences::Node::dirty
char dirty()
Definition: Fl_Preferences.cxx:1263
Fl_Preferences::deleteGroup
char deleteGroup(const char *group)
Definition: Fl_Preferences.cxx:425
dir
static int dir
Definition: fl_draw_image.cxx:67
Fl_Preferences::Node::parent
Node * parent()
Definition: Fl_Preferences.H:224
fl_utf8.h
header for Unicode and UTF-8 character handling
Fl_Preferences::Fl_Preferences
Fl_Preferences()
Definition: Fl_Preferences.H:181
FL_PATH_MAX
#define FL_PATH_MAX
Definition: filename.H:38
Fl_Preferences::nameBuffer
static char nameBuffer[128]
Definition: Fl_Preferences.H:184
fl_filename_match
int fl_filename_match(const char *name, const char *pattern)
Definition: filename_match.cxx:44
fl_filename_list
int fl_filename_list(const char *d, dirent ***list, Fl_File_Sort_F *sort)
Definition: filename_list.cxx:75
Fl_Preferences::Node
Definition: Fl_Preferences.H:191
filename
static const char * filename
Definition: fluid.cxx:119
Fl_Preferences::group
const char * group(int num_group)
Definition: Fl_Preferences.cxx:399
Fl_Preferences::RootNode::getPath
char getPath(char *path, int pathlen)
Definition: Fl_Preferences.cxx:1183
Fl_Preferences::Node::nEntry
int nEntry()
Definition: Fl_Preferences.H:240
Fl_Preferences::RootNode::write
int write()
Definition: Fl_Preferences.cxx:1153
fl_chmod
int fl_chmod(const char *f, int mode)
Definition: fl_utf8.cxx:609
strlcpy
#define strlcpy
Definition: flstring.h:84
id
Definition: code.cxx:47
Fl_Plugin_Manager::Fl_Plugin_Manager
Fl_Plugin_Manager(const char *klass)
Manage all plugins belonging to one class.
Definition: Fl_Preferences.cxx:1614
Fl_Preferences::get
char get(const char *entry, int &value, int defaultValue)
Definition: Fl_Preferences.cxx:509
Fl_Preferences::set
char set(const char *entry, int value)
Definition: Fl_Preferences.cxx:525
Fl_Preferences::remove
static char remove(ID id_)
Definition: Fl_Preferences.H:98
i2x
static void i2x(unsigned char v, char *d)
Definition: Fl_Preferences.cxx:1637
Fl_Preferences::Name::Name
Name(unsigned int n)
Definition: Fl_Preferences.cxx:918
Fl_Preferences::Node::setRoot
void setRoot(RootNode *r)
Definition: Fl_Preferences.H:225
Fl_Preferences::Node::childNode
Node * childNode(int ix)
Definition: Fl_Preferences.cxx:1518
Fl_Plugin
Fl_Plugin allows link-time and run-time integration of binary modules.
Definition: Fl_Plugin.H:61
fl_getenv
char * fl_getenv(const char *name)
Definition: fl_utf8.cxx:421
Fl_Preferences::Node
friend class Node
Definition: Fl_Preferences.H:243
Fl_Preferences::SYSTEM
Preferences are used system-wide.
Definition: Fl_Preferences.H:67
fl_make_path_for_file
void fl_make_path_for_file(const char *path)
Definition: fl_utf8.cxx:878
Fl_Preferences::Name
Definition: Fl_Preferences.H:159
Fl_Plugin_Manager::loadAll
static int loadAll(const char *filepath, const char *pattern=0)
Use this function to load a whole directory full of modules.
Definition: Fl_Preferences.cxx:1751
Fl_Preferences::Root
Root
Definition: Fl_Preferences.H:66
Fl_Preferences::newUUID
static const char * newUUID()
Definition: Fl_Preferences.cxx:82
Fl_Preferences::Node::deleteAllChildren
void deleteAllChildren()
Definition: Fl_Preferences.cxx:1218
Fl_Preferences::Node::getEntry
int getEntry(const char *name)
Definition: Fl_Preferences.cxx:1402
Fl_Preferences::RootNode::vendor_
char * vendor_
Definition: Fl_Preferences.H:248
Fl_Preferences::Node::dirty_
unsigned char dirty_
Definition: Fl_Preferences.H:201
Fl_Preferences::id
ID id()
Definition: Fl_Preferences.H:94
Fl_Plugin_Manager
Fl_Plugin_Manager manages link-time and run-time plugin binaries.
Definition: Fl_Plugin.H:73
Fl_Preferences::Node::addChild
Node * addChild(const char *path)
Definition: Fl_Preferences.cxx:1325
Fl_Preferences::Name::~Name
~Name()
Definition: Fl_Preferences.cxx:945
x
int x
Definition: test.c:73
Fl_Preferences::Node::path_
char * path_
Definition: Fl_Preferences.H:198
Fl_Preferences::Node::Node
Node(const char *path)
Definition: Fl_Preferences.cxx:1206
Fl_Preferences::Node::search
Node * search(const char *path, int offset=0)
Definition: Fl_Preferences.cxx:1453
x2i
static unsigned char x2i(char hi, char lo)
Definition: Fl_Preferences.cxx:1633
Fl_Preferences::Name::data_
char * data_
Definition: Fl_Preferences.H:161
Fl_Preferences::RootNode::read
int read()
Definition: Fl_Preferences.cxx:1117
Fl_Preferences::flush
void flush()
Definition: Fl_Preferences.cxx:896
Fl_Preferences::node
Node * node
Definition: Fl_Preferences.H:261
Fl_Plugin_Manager::plugin
Fl_Plugin * plugin(int index)
Return the address of a plugin by index.
Definition: Fl_Preferences.cxx:1664
Fl_Preferences
Fl_Preferences provides methods to store user settings between application starts.
Definition: Fl_Preferences.H:60
Fl_Plugin_Manager::removePlugin
static void removePlugin(Fl_Preferences::ID id)
Remove any plugin.
Definition: Fl_Preferences.cxx:1721
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
malloc
voidp malloc()
Fl_Plugin_Manager::~Fl_Plugin_Manager
~Fl_Plugin_Manager()
Remove the plugin manager.
Definition: Fl_Preferences.cxx:1627
Fl_Preferences::Node::root_
RootNode * root_
Definition: Fl_Preferences.H:196
flstring.h
Fl_Preferences::Node::next_
Node * next_
Definition: Fl_Preferences.H:193
Fl_Preferences::Node::get
const char * get(const char *name)
Definition: Fl_Preferences.cxx:1396
Fl_Preferences::deleteEntry
char deleteEntry(const char *entry)
Definition: Fl_Preferences.cxx:478
Fl_Preferences.H
Fl_Preferences::ID
void * ID
Definition: Fl_Preferences.H:78
Fl_Preferences::Node::top_
unsigned char top_
Definition: Fl_Preferences.H:202
Fl_Preferences::name
const char * name()
Definition: Fl_Preferences.H:102
Fl_Preferences::entryExists
char entryExists(const char *key)
Definition: Fl_Preferences.cxx:466
strlcat
#define strlcat
Definition: flstring.h:79
Fl_Preferences::groupExists
char groupExists(const char *key)
Definition: Fl_Preferences.cxx:412
Fl_Preferences::Node::deleteAllEntries
void deleteAllEntries()
Definition: Fl_Preferences.cxx:1229
Fl_Preferences::RootNode
Definition: Fl_Preferences.H:245
Fl_Preferences::operator=
Fl_Preferences & operator=(const Fl_Preferences &)
Definition: Fl_Preferences.cxx:356
Fl_Preferences::Node::updateIndex
void updateIndex()
Definition: Fl_Preferences.cxx:1573
uchar
unsigned char uchar
Definition: fl_types.h:30
name
static const char * name
Definition: Fl_arg.cxx:53
p2a
static void p2a(void *vp, char *d)
Definition: Fl_Preferences.cxx:1651
fl_make_path
char fl_make_path(const char *path)
Definition: fl_utf8.cxx:857
Fl_Plugin::Fl_Plugin
Fl_Plugin(const char *klass, const char *name)
Create a plugin.
Definition: Fl_Preferences.cxx:1590
Fl_Preferences::entries
int entries()
Definition: Fl_Preferences.cxx:444
Fl_Preferences::Node::lastEntrySet
static int lastEntrySet
Definition: Fl_Preferences.H:211
Fl_Preferences::RootNode::filename_
char * filename_
Definition: Fl_Preferences.H:247
Fl_Preferences::Node::deleteIndex
void deleteIndex()
Definition: Fl_Preferences.cxx:1577
Fl_Preferences::uuidBuffer
static char uuidBuffer[40]
Definition: Fl_Preferences.H:185
dirent
#define dirent
Definition: numericsort.c:31
Fl_Preferences::Entry
Definition: Fl_Preferences.H:176
Fl_Preferences::Node::child
const char * child(int ix)
Definition: Fl_Preferences.cxx:1509
decodeHex
static void * decodeHex(const char *src, int &size)
Definition: Fl_Preferences.cxx:747