From adb6fc4eeb0d73481a1368531f8593c485fd5c91 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Tue, 30 Apr 2002 22:25:18 +0000 Subject: added binary support and procedural names to Fl_Preferences, updated FLUID, update documentation. Attempted to strip all Win32 CR. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@2146 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Preferences.H | 23 ++--- documentation/Fl_Preferences.html | 39 +++++--- fluid/fluid.cxx | 12 +-- src/Fl_Preferences.cxx | 183 ++++++++++++++++++++++++++++++++++---- test/preferences.cxx | 24 ++++- 5 files changed, 232 insertions(+), 49 deletions(-) diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H index 8f2dfdfaf..d42e9a72d 100644 --- a/FL/Fl_Preferences.H +++ b/FL/Fl_Preferences.H @@ -1,5 +1,5 @@ // -// "$Id: Fl_Preferences.H,v 1.1.2.4 2002/04/30 18:11:49 easysw Exp $" +// "$Id: Fl_Preferences.H,v 1.1.2.5 2002/04/30 22:25:18 matthiaswm Exp $" // // Preferences definitions for the Fast Light Tool Kit (FLTK). // @@ -33,10 +33,6 @@ #include -// missing features: -// - get and set binary data -// - Fl_Preferences could offer functions that return the value instead off an error code to write directly into widgets - /** * Preferences are a data tree containing a root, branches and leafs @@ -69,7 +65,7 @@ public: FL_EXPORT char set( const char *entry, float value ); FL_EXPORT char set( const char *entry, double value ); FL_EXPORT char set( const char *entry, const char *value ); - // FL_EXPORT char set( const char *entry, const void *value, int size ); + FL_EXPORT char set( const char *entry, const void *value, int size ); FL_EXPORT char get( const char *entry, char &value, char defaultValue ); FL_EXPORT char get( const char *entry, int &value, int defaultValue ); @@ -77,8 +73,8 @@ public: FL_EXPORT char get( const char *entry, double &value, double defaultValue ); FL_EXPORT char get( const char *entry, char *&value, const char *defaultValue ); FL_EXPORT char get( const char *entry, char *value, const char *defaultValue, int maxSize ); - // FL_EXPORT char get( const char *entry, void *&value, const char *defaultValue ); - // FL_EXPORT char get( const char *entry, void *value, const char *defaultValue, int maxSize ); + FL_EXPORT char get( const char *entry, void *&value, const void *defaultValue, int defaultSize ); + FL_EXPORT char get( const char *entry, void *value, const void *defaultValue, int defaultSize, int maxSize ); FL_EXPORT int size( const char *entry ); FL_EXPORT char getUserdataPath( char *path, int pathlen ); @@ -88,7 +84,14 @@ public: // FL_EXPORT char export( const char *filename, enum Type fileFormat ); // FL_EXPORT char import( const char *filename ); - // FL_EXPORT const char *namef( const char *, ... ); + class Name { + char *data_; + public: + FL_EXPORT Name( unsigned int n ); + FL_EXPORT Name( const char *format, ... ); + FL_EXPORT operator const char *() { return data_; } + FL_EXPORT ~Name(); + }; private: @@ -154,5 +157,5 @@ private: #endif // !Fl_Preferences_H // -// End of "$Id: Fl_Preferences.H,v 1.1.2.4 2002/04/30 18:11:49 easysw Exp $". +// End of "$Id: Fl_Preferences.H,v 1.1.2.5 2002/04/30 22:25:18 matthiaswm Exp $". // diff --git a/documentation/Fl_Preferences.html b/documentation/Fl_Preferences.html index 966cf08e2..b5a30623c 100644 --- a/documentation/Fl_Preferences.html +++ b/documentation/Fl_Preferences.html @@ -10,7 +10,7 @@

Class Hierarchy

Include Files

@@ -65,6 +65,7 @@ method.
  • groups
  • set
  • size
  • +
  • Name
  • @@ -133,19 +134,21 @@ deleting the base preferences flushes automatically. that is usable for application data beyond what is covered by Fl_Preferences. -

    int get(const char *entry, int &value,   int defaultValue)
    -int get(const char *entry, int &value,    int defaultValue)
    -int get(const char *entry, float &value,  float defaultValue)
    -int get(const char *entry, double &value, double defaultValue ) -int get(const char *entry, char *&value,  const char *defaultValue)
    -int get(const char *entry, char *value,   const char *defaultValue, +

    int get(const char *entry, int &value, int defaultValue)
    +int get(const char *entry, int &value, int defaultValue)
    +int get(const char *entry, float &value, float defaultValue)
    +int get(const char *entry, double &value, double defaultValue )
    +int get(const char *entry, char *&text, const char *defaultValue)
    +int get(const char *entry, char *text, const char *defaultValue, int maxSize)
    +int get(const char *entry, void *&data, const void *defaultValue, int defaultSize)
    +int get(const char *entry, void *data, const void *defaultValue, int defaultSize, int maxSize)

    Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). If the 'char -*&value' form is used, the resulting text must be freed -with 'free(value)'. +*&text' or 'void *&data' form is used, +the resulting data must be freed with 'free(value)'.

    const char *Fl_Preferences::group(int ix)

    @@ -167,10 +170,10 @@ group. int set(const char *entry, int value)
    int set(const char *entry, float value)
    int set(const char *entry, double value)
    -int set(const char *entry, const char *value) +int set(const char *entry, const char *text)
    +int set(const char *entry, const void *data, int size) -

    Sets an entry (name/value pair). Text data must not contain -any '\n' or '\r' characters. The return value indicates if there +

    Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preferences file. @@ -179,6 +182,18 @@ file.

    Returns the size of the value part of an entry. +

    +Fl_Preferences::Name( unsigned int numericName )
    +Fl_Preferences::Name( const char *format, ... ) +

    + +

    'Name' provides a simple method to create numerical or more complex +procedural names for entries and groups on the fly, +i.e. prefs.set(Fl_Preferences::Name("File%d",i),file[i]);. +See test/preferences.cxx as a sample for writing arrays into preferences.

    +'Name' is actually implemented as a class inside Fl_Preferences. It casts +into const char* and gets automatically destroyed after the enclosing call. + diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index 1184a5d24..c66d07d24 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -1,5 +1,5 @@ // -// "$Id: fluid.cxx,v 1.15.2.13.2.15 2002/04/30 18:11:49 easysw Exp $" +// "$Id: fluid.cxx,v 1.15.2.13.2.16 2002/04/30 22:25:18 matthiaswm Exp $" // // FLUID main entry for the Fast Light Tool Kit (FLTK). // @@ -468,11 +468,9 @@ void make_main_window() { // Load file history from preferences... void load_history() { int i; // Looping var - char name[32]; // Variable name for (i = 0; i < 10; i ++) { - sprintf(name, "file%d", i); - fluid_prefs.get(name, absolute_history[i], "", sizeof(absolute_history[i])); + fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); if (absolute_history[i][0]) { // Make a relative version of the filename for the menu... fl_filename_relative(relative_history[i], sizeof(relative_history[i]), @@ -488,7 +486,6 @@ void load_history() { // Update file history from preferences... void update_history(const char *filename) { int i; // Looping var - char name[32]; // Variable name char absolute[1024]; fl_filename_absolute(absolute, sizeof(absolute), filename); @@ -519,8 +516,7 @@ void update_history(const char *filename) { // Update the menu items as needed... for (i = 0; i < 10; i ++) { - sprintf(name, "file%d", i); - fluid_prefs.set(name, absolute_history[i]); + fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); if (absolute_history[i][0]) Main_Menu[i + 4].flags = 0; else Main_Menu[i + 4].flags = FL_MENU_INVISIBLE; } @@ -618,5 +614,5 @@ int main(int argc,char **argv) { } // -// End of "$Id: fluid.cxx,v 1.15.2.13.2.15 2002/04/30 18:11:49 easysw Exp $". +// End of "$Id: fluid.cxx,v 1.15.2.13.2.16 2002/04/30 22:25:18 matthiaswm Exp $". // diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index 8d1ded130..d12c3cb69 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Preferences.cxx,v 1.1.2.7 2002/04/30 18:11:49 easysw Exp $" +// "$Id: Fl_Preferences.cxx,v 1.1.2.8 2002/04/30 22:25:18 matthiaswm Exp $" // // Preferences methods for the Fast Light Tool Kit (FLTK). // @@ -48,10 +48,10 @@ char Fl_Preferences::nameBuffer[]; /** * create the initial preferences base - * i root: machine or user preferences - * i vendor: unique identification of author or vendor of application + * - root: machine or user preferences + * - vendor: unique identification of author or vendor of application * Must be a valid directory name. - * i application: vendor unique application name, i.e. "PreferencesTest" + * - application: vendor unique application name, i.e. "PreferencesTest" * multiple preferences files can be created per application. * Must be a valid file name. * example: Fl_Preferences base( Fl_Preferences::USER, "fltk.org", "test01"); @@ -65,8 +65,8 @@ Fl_Preferences::Fl_Preferences( enum Root root, const char *vendor, const char * /** * create a Preferences node in relation to a parent node for reading and writing - * i parent: base name for group - * i group: group name (can contain '/' seperated group names) + * - parent: base name for group + * - group: group name (can contain '/' seperated group names) * example: Fl_Preferences colors( base, "setup/colors" ); */ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *key ) @@ -78,8 +78,8 @@ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *key ) /** * create a Preferences node in relation to a parent node for reading and writing - * i parent: base name for group - * i group: group name (can contain '/' seperated group names) + * - parent: base name for group + * - group: group name (can contain '/' seperated group names) * example: Fl_Preferences colors( base, "setup/colors" ); */ Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *key ) @@ -311,9 +311,8 @@ static char *decodeText( const char *src ) /** * read a text entry from the group - * - the maximum size for text plus entry name is 2046 bytes plus the trailling 0 - * - the text must not contain special characters - * the text will be movet into the given text buffer + * the text will be moved into the given text buffer + * text will be clipped to the buffer size */ char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize ) { @@ -327,16 +326,25 @@ char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, return 1; } if ( !v ) v = defaultValue; - strncpy( text, v, maxSize ); - if ( (int)strlen(v) >= maxSize ) text[maxSize] = 0; + if ( v ) + { + int vLen = strlen( v ); + if ( vLen >= maxSize ) + { + strncpy( text, v, maxSize ); + text[maxSize] = 0; + } + else + strcpy( text, v ); + } + else + text = 0; return ( v != defaultValue ); } /** * read a text entry from the group - * - the maximum size for text plus entry name is 2046 bytes plus the trailling 0 - * - the text must not contain special characters (no \n or \r, "quotes" are OK) * 'text' will be changed to point to a new text buffer * the text buffer must be deleted with 'free(text)' by the user. */ @@ -349,7 +357,10 @@ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue return 1; } if ( !v ) v = defaultValue; - text = strdup( v ); + if ( v ) + text = strdup( v ); + else + text = 0; return ( v != defaultValue ); } @@ -385,6 +396,97 @@ char Fl_Preferences::set( const char *key, const char *text ) } +// convert a hex string to binary data +static void *decodeHex( const char *src, int &size ) +{ + size = strlen( src )/2; + unsigned char *data = (unsigned char*)malloc( size ), *d = data; + const char *s = src; + int i; + + for ( i=size; i>0; i-- ) + { + unsigned char v = 0; + char x = tolower(*s++); + if ( x >= 'a' ) v = x-'a'+10; else v = x-'0'; + v = v<<4; + x = tolower(*s++); + if ( x >= 'a' ) v += x-'a'+10; else v += x-'0'; + *d++ = v; + } + + return (void*)data; +} + + +/** + * read a binary entry from the group + * the data will be moved into the given destination buffer + * data will be clipped to the buffer size + */ +char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize ) +{ + const char *v = node->get( key ); + if ( v ) + { + int size; + void *w = decodeHex( v, size ); + memmove( data, w, size>maxSize?maxSize:size ); + free( w ); + return 1; + } + if ( defaultValue ) + memmove( data, defaultValue, defaultSize>maxSize?maxSize:defaultSize ); + return 0; +} + + +/** + * read a binary entry from the group + * 'data' will be changed to point to a new data buffer + * the data buffer must be deleted with 'free(data)' by the user. + */ +char Fl_Preferences::get( const char *key, void *&data, const void *defaultValue, int defaultSize ) +{ + const char *v = node->get( key ); + if ( v ) + { + int size; + data = decodeHex( v, size ); + return 1; + } + if ( defaultValue ) + { + data = (void*)malloc( defaultSize ); + memmove( data, defaultValue, defaultSize ); + } + else + data = 0; + return 0; +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, const void *data, int size ) +{ + char *buffer = (char*)malloc( size*2+1 ), *d = buffer;; + unsigned char *s = (unsigned char*)data; + for ( ; size>0; size-- ) + { + static char lu[] = "0123456789abcdef"; + unsigned char v = *s++; + *d++ = lu[v>>4]; + *d++ = lu[v&0xf]; + } + *d = 0; + node->set( key, buffer ); + free( buffer ); + return 1; +} + + /** * return the size of the value part of an entry */ @@ -418,7 +520,7 @@ char Fl_Preferences::getUserdataPath( char *path, int pathlen ) /** * write all preferences to disk * - this function works only with the base preference group - * - this function is rarely used as deleting the base preferences does that automatically + * - this function is rarely used as deleting the base preferences flushes automatically */ void Fl_Preferences::flush() { @@ -426,6 +528,51 @@ void Fl_Preferences::flush() rootNode->write(); } +//----------------------------------------------------------------------------- +// helper class to create dynamic group and entry names on the fly +// + +/** + * create a group name or entry name on the fly + * - this version creates a simple unsigned integer as an entry name + * example: + * int n, i; + * Fl_Preferences prev( appPrefs, "PreviousFiles" ); + * prev.get( "n", 0 ); + * for ( i=0; i