Add Fl_Preferences class to base library.

Add FLTK_DATADIR definition to config.h for system-wide configuration
data.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@2126 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Michael R Sweet 2002-04-28 16:41:17 +00:00
parent 081d369c11
commit 44bb5f60de
14 changed files with 1365 additions and 119 deletions

View File

@ -1,5 +1,8 @@
CHANGES IN FLTK 1.1.0rc1
- Added Fl_Preferences class from Matthias Melcher.
- FLUID now recognizes the "using" keyword in
declarations.
- fl_file_chooser() didn't highlight the requested file
the second time the file chooser dialog was shown.
- Fixed rendering of Fl_Light_Button with the plastic

148
FL/Fl_Preferences.H Normal file
View File

@ -0,0 +1,148 @@
//
// "$Id: Fl_Preferences.H,v 1.1.2.1 2002/04/28 16:41:16 easysw Exp $"
//
// Preferences header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 2002 by Matthias Melcher.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to "fltk-bugs@matthiasm.com".
//
#ifndef Fl_Preferences_H
#define Fl_Preferences_H
# include <stdio.h>
/* missing functions:
Fl_Preferences should return functions to create and access User Data directories
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
*/
class Fl_Preferences
{
public:
typedef enum { SYSTEM=0, USER } Root;
// typedef enum { win32, macos, fltk } Type;
FL_EXPORT Fl_Preferences( enum Root root, const char *vendor, const char *application );
FL_EXPORT Fl_Preferences( Fl_Preferences&, const char *group );
FL_EXPORT Fl_Preferences( Fl_Preferences*, const char *group );
FL_EXPORT ~Fl_Preferences();
FL_EXPORT int groups();
FL_EXPORT const char *group( int );
FL_EXPORT int groupExists( const char *group );
FL_EXPORT int deleteGroup( const char *group );
FL_EXPORT int entries();
FL_EXPORT const char *entry( int );
FL_EXPORT int entryExists( const char *entry );
FL_EXPORT int deleteEntry( const char *entry );
FL_EXPORT int set( const char *entry, int value );
FL_EXPORT int set( const char *entry, float value );
FL_EXPORT int set( const char *entry, double value );
FL_EXPORT int set( const char *entry, const char *value );
// FL_EXPORT int set( const char *entry, const void *value, int size );
FL_EXPORT int get( const char *entry, int &value, int defaultValue );
FL_EXPORT int get( const char *entry, float &value, float defaultValue );
FL_EXPORT int get( const char *entry, double &value, double defaultValue );
FL_EXPORT int get( const char *entry, char *&value, const char *defaultValue );
FL_EXPORT int get( const char *entry, char *value, const char *defaultValue, int maxSize );
// FL_EXPORT int get( const char *entry, void *&value, const char *defaultValue );
// FL_EXPORT int get( const char *entry, void *value, const char *defaultValue, int maxSize );
FL_EXPORT int size( const char *entry );
FL_EXPORT int getUserdataPath( char *path );
FL_EXPORT void flush();
// FL_EXPORT int export( const char *filename, enum Type fileFormat );
// FL_EXPORT int import( const char *filename );
// FL_EXPORT const char *namef( const char *, ... );
private:
static char nameBuffer[128];
struct Entry
{
char *name, *value;
};
class Node
{
Node *child_, *next_, *parent_;
char *path_;
int dirty_;
public:
Node( const char *path );
~Node();
Node *find( const char *path );
Node *search( const char *path );
int write( FILE *f );
void setParent( Node *parent );
Node *addChild( const char *path );
void set( const char *name, const char *value );
void set( const char *line );
void add( const char *line );
const char *get( const char *name );
int getEntry( const char *name );
int deleteEntry( const char *name );
int remove();
int dirty();
int nChildren();
const char *child( int ix );
Entry *entry;
int nEntry, NEntry;
static int lastEntrySet;
};
friend class Node;
class RootNode
{
Fl_Preferences *prefs_; //++ maybe we should hold a reference to the first node
char *filename_;
char *vendor_, *application_;
public:
RootNode( Fl_Preferences *, enum Root root, const char *vendor, const char *application );
~RootNode();
int read();
int write();
int getPath( char *path );
};
friend class RootNode;
Node *node;
RootNode *rootNode;
};
#endif
//
// End of "$Id: Fl_Preferences.H,v 1.1.2.1 2002/04/28 16:41:16 easysw Exp $".
//

View File

@ -1,5 +1,5 @@
/*
* "$Id: configh.in,v 1.11.2.11.2.10 2002/04/24 18:29:05 easysw Exp $"
* "$Id: configh.in,v 1.11.2.11.2.11 2002/04/28 16:41:15 easysw Exp $"
*
* Configuration file for the Fast Light Tool Kit (FLTK).
* @configure_input@
@ -25,9 +25,10 @@
*/
/*
* Where to find the documentation files...
* Where to find files...
*/
#define FLTK_DATADIR ""
#define FLTK_DOCDIR ""
/*
@ -219,5 +220,5 @@
/*
* End of "$Id: configh.in,v 1.11.2.11.2.10 2002/04/24 18:29:05 easysw Exp $".
* End of "$Id: configh.in,v 1.11.2.11.2.11 2002/04/28 16:41:15 easysw Exp $".
*/

View File

@ -1,7 +1,7 @@
dnl -*- sh -*-
dnl the "configure" script is made from this by running GNU "autoconf"
dnl
dnl "$Id: configure.in,v 1.33.2.31.2.63 2002/04/26 12:39:32 easysw Exp $"
dnl "$Id: configure.in,v 1.33.2.31.2.64 2002/04/28 16:41:15 easysw Exp $"
dnl
dnl Configuration script for the Fast Light Tool Kit (FLTK).
dnl
@ -720,6 +720,13 @@ else
AC_DEFINE_UNQUOTED(FLTK_DOCDIR, "$prefix/share/doc/fltk")
fi
dnl Define the FLTK data directory...
if test x$prefix = xNONE; then
AC_DEFINE_UNQUOTED(FLTK_DATADIR, "/usr/local/share/fltk")
else
AC_DEFINE_UNQUOTED(FLTK_DATADIR, "$prefix/share/fltk")
fi
dnl Write all of the files...
AC_CONFIG_HEADER(config.h:configh.in)
AC_OUTPUT(makeinclude fltk.list fltk-config FL/Makefile)
@ -728,5 +735,5 @@ dnl Make sure the fltk-config script is executable...
chmod +x fltk-config
dnl
dnl End of "$Id: configure.in,v 1.33.2.31.2.63 2002/04/26 12:39:32 easysw Exp $".
dnl End of "$Id: configure.in,v 1.33.2.31.2.64 2002/04/28 16:41:15 easysw Exp $".
dnl

View File

@ -0,0 +1,184 @@
<html>
<body>
<!-- NEW PAGE -->
<h2>class Fl_Preferences</h2>
<hr>
<h3>Class Hierarchy</h3>
<ul><pre>
<b>Fl_Preferences</a></H4>&nbsp;
</pre></ul>
<h3>Include Files</h3>
<ul><pre>
#include &lt;FL/Fl_Preferences.H&gt;
</pre></ul>
<h3>Description</h3>
<P><tt>Fl_Preferences </tt>provides methods to store user
setting between application starts. It is similar to the
Registry on WIN32 and Preferences on MacOS, and provides a
simple configuration mechanism for UNIX.
<P><tt>Fl_Preferences </tt>uses a hierarchy to store data. It
bundles similar data into groups and manages entries into those
groups as name/value pairs.
<P>Preferences are stored in text files that can be edited
manually. The file format is easy to read and relatively
forgiving. Preferences files are the same on all platforms. User
comments in preference files are preserved. Filenames are unique
for each application by using a vendor/application naming
scheme. The user must provide default values for all entries to
ensure proper operation should preferences be corrupted or not
yet exist.
<P>Entries can be of any length. However, the size of each
preferences file should be kept under 100k for performance
reasons. One application can have multiple preferences files.
Extensive binary data however should be stored in seperate
files; see the <A
href="#Fl_Preferences.getUserdataPath"><tt>getUserdataPath()</tt></A>
method.
<h3>Methods</h3>
<ul>
<li><a href="#Fl_Preferences.Fl_Preferences">Fl_Preferences</a></li>
<li><a href="#Fl_Preferences.~Fl_Preferences">~Fl_Preferences</a></li>
<li><a href="#Fl_Preferences.deleteEntry">deleteEntry</a></li>
<li><a href="#Fl_Preferences.deleteGroup">deleteGroup</a></li>
<li><a href="#Fl_Preferences.entries">entries</a></li>
<li><a href="#Fl_Preferences.entry">entry</a></li>
<li><a href="#Fl_Preferences.entryExists">entryExists</a></li>
<li><a href="#Fl_Preferences.get">get</a></li>
<li><a href="#Fl_Preferences.getUserdataPath">getUserdataPath</a></li>
<li><a href="#Fl_Preferences.group">group</a></li>
<li><a href="#Fl_Preferences.groupExists">groupExists</a></li>
<li><a href="#Fl_Preferences.groups">groups</a></li>
<li><a href="#Fl_Preferences.set">set</a></li>
<li><a href="#Fl_Preferences.size">size</a></li>
</ul>
<H4><a name="Fl_Preferences.Fl_Preferences">Fl_Preferences(enum Root root,
const char *vendor, const char *application)<BR>
Fl_Preferences(Fl_Preferences &amp;p, const char *groupname)</a></H4>
<P>The constructor creates a group that manages name/value pairs and
child groups. Groups are ready for reading and writing at any time.
The <tt>root</tt> argument is either <tt>Fl_Preferences::USER</tt>
or <tt>Fl_Preferences::SYSTEM</tt>.
<P>The first format creates the <i>base</i> instance for all
following entries and reads existing databases into memory. The
<tt>vendor</tt> argument is a unique text string identifying the
development team or vendor of an application. A domain name or
an EMail address are great unique names, e.g.
"researchATmatthiasm.com" or "fltk.org". The
<tt>application</tt> argument can be the working title or final
name of your application. Both <tt>vendor</tt> and
<tt>application</tt> must be valid relative UNIX pathnames and
may contain '/'s to create deeper file structures.
<P>The <tt>groupname</tt> argument identifies a group of
entries. It can contain '/'s to get quick access to individual
elements inside the hierarchy.
<H4><a name="Fl_Preferences.~Fl_Preferences">~Fl_Preferences()</a></H4>
<P>The destructor removes allocated resources. When used on the
<i>base</i> preferences group, the destructor flushes all
changes to the preferences file and deletes all internal
databases.
<H4><a name="Fl_Preferences.deleteEntry">int Fl_Preferences::deleteEntry(const char *entry)</a></H4>
<P>Removes a single entry (name/value pair).
<H4><a name="Fl_Preferences.deleteGroup">int Fl_Preferences::deleteGroup(const char *groupname)</a></H4>
<P>Deletes a group.
<H4><a name="Fl_Preferences.entries">int Fl_Preferences::entries()</a></H4>
<P>Returns the number of entries (name/value) pairs in a group.
<H4><a name="Fl_Preferences.entry">const char *Fl_Preferences::entry(int ix)</a></H4>
<P>Returns the name of an entry. There is no guaranteed order of
entry names. The index must be within the range given by
<tt>entries()</tt>.
<H4><a name="Fl_Preferences.entryExists">int Fl_Preferences::entryExists(const char *entry)</a></H4>
<P>Returns non-zero if an entry with this name exists.
<H4><a name="Fl_Preferences.flush">void Fl_Preferences::flush()</a></H4>
<P>Write all preferences to disk. This function works only with
the base preference group. This function is rarely used as
deleting the base preferences flushes automatically.
<H4><a name="Fl_Preferences.getUserdataPath">int Fl_Preferences::getUserdataPath(char *path)</a></H4>
<P>Creates a path that is related to the preferences file and
that is usable for application data beyond what is covered by
<tt>Fl_Preferences</tt>.
<H4><a name="Fl_Preferences.get">int get(const char *entry, int &amp;value,&nbsp;&nbsp; int defaultValue)<BR>
int get(const char *entry, int &amp;value,&nbsp;&nbsp;&nbsp; int defaultValue)<BR>
int get(const char *entry, float &amp;value,&nbsp; float defaultValue)<BR>
int get(const char *entry, double &amp;value, double defaultValue )
int get(const char *entry, char *&amp;value,&nbsp; const char *defaultValue)<BR>
int get(const char *entry, char *value,&nbsp;&nbsp; const char *defaultValue,
int maxSize)</a></H4>
<P>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 '<tt>char
*&amp;value</tt>' form is used, the resulting text must be freed
with '<tt>free(value)</tt>'.
<H4><a name="Fl_Preferences.group">const char
*Fl_Preferences::group(int ix)</a></H4>
<P>Returns the name of the Nth group. There is no guaranteed
order of group names. The index must be within the range given
by <tt>groups()</tt>.
<H4><a name="Fl_Preferences.groupExists">int Fl_Preferences::groupExists(const char *groupname)</a></H4>
<P>Returns non-zero if a group with this name exists.
<H4><a name="Fl_Preferences.groups">int Fl_Preferences::groups()</a></H4>
<P>Returns the number of groups that are contained within a
group.
<H4><a name="Fl_Preferences.set">int set(const char *entry, int value)<BR>
int set(const char *entry, int value)<BR>
int set(const char *entry, float value)<BR>
int set(const char *entry, double value)<BR>
int set(const char *entry, const char *value)</a></H4>
<P>Sets an entry (name/value pair). Text data must not contain
any '\n' or '\r' characters. 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.
<H4><a name="Fl_Preferences.size">int Fl_Preferences::size(const char *key)</a></H4>
<P>Returns the size of the value part of an entry.
</body>
</html>

View File

@ -1,5 +1,5 @@
#
# "$Id: Makefile,v 1.9.2.10.2.13 2002/04/20 21:07:18 easysw Exp $"
# "$Id: Makefile,v 1.9.2.10.2.14 2002/04/28 16:41:16 easysw Exp $"
#
# Documentation makefile for the Fast Light Tool Kit (FLTK).
#
@ -42,102 +42,163 @@ MEDIA = --size universal
# These are the HTML "source" files...
HTMLFILES = \
basics.html \
common.html \
drawing.html \
editor.html \
enumerations.html \
events.html \
Fl.html \
Fl_Adjuster.html \
Fl_Bitmap.html \
Fl_BMP_Image.html \
Fl_Box.html \
Fl_Browser_.html \
Fl_Browser.html \
Fl_Button.html \
Fl_Chart.html \
Fl_Check_Button.html \
Fl_Choice.html \
Fl_Clock.html \
Fl_Color_Chooser.html \
Fl_Counter.html \
Fl_Dial.html \
Fl_Double_Window.html \
Fl_End.html \
Fl_File_Browser.html \
Fl_File_Chooser.html \
Fl_File_Icon.html \
Fl_Float_Input.html \
Fl_Free.html \
Fl_GIF_Image.html \
Fl_Gl_Window.html \
Fl_Group.html \
Fl_Help_Dialog.html \
Fl_Help_View.html \
Fl_Hold_Browser.html \
Fl_Image.html \
Fl_Input_.html \
Fl_Input.html \
Fl_Int_Input.html \
Fl_JPEG_Image.html \
Fl_Light_Button.html \
Fl_Menu_Bar.html \
Fl_Menu_Button.html \
Fl_Menu_.html \
Fl_Menu_Item.html \
Fl_Menu_Window.html \
Fl_Multi_Browser.html \
Fl_Multiline_Input.html \
Fl_Multiline_Output.html \
Fl_Output.html \
Fl_Overlay_Window.html \
Fl_Pack.html \
Fl_Pixmap.html \
Fl_PNG_Image.html \
Fl_PNM_Image.html \
Fl_Positioner.html \
Fl_Repeat_Button.html \
Fl_Return_Button.html \
Fl_RGB_Image.html \
Fl_Roller.html \
Fl_Round_Button.html \
Fl_Scrollbar.html \
Fl_Scroll.html \
Fl_Secret_Input.html \
Fl_Select_Browser.html \
Fl_Shared_Image.html \
Fl_Single_Window.html \
Fl_Slider.html \
Fl_Tabs.html \
Fl_Text_Buffer.html \
Fl_Text_Display.html \
Fl_Text_Editor.html \
Fl_Tiled_Image.html \
Fl_Tile.html \
Fl_Timer.html \
Fl_Tooltip.html \
fluid.html \
Fl_Valuator.html \
Fl_Value_Input.html \
Fl_Value_Output.html \
Fl_Value_Slider.html \
Fl_Widget.html \
Fl_Window.html \
Fl_Wizard.html \
Fl_XBM_Image.html \
Fl_XPM_Image.html \
forms.html \
functions.html \
glut.html \
intro.html \
license.html \
migration.html \
opengl.html \
osissues.html \
preface.html \
subclassing.html \
widgets.html
preface.html \
intro.html \
basics.html \
common.html \
editor.html \
drawing.html \
events.html \
subclassing.html \
opengl.html \
fluid.html \
widgets.html \
Fl.html \
Fl_Adjuster.html \
Fl_Bitmap.html \
Fl_BMP_Image.html \
Fl_Box.html \
Fl_Browser_.html \
Fl_Browser.html \
Fl_Button.html \
Fl_Chart.html \
Fl_Check_Button.html \
Fl_Choice.html \
Fl_Clock.html \
Fl_Color_Chooser.html \
Fl_Counter.html \
Fl_Dial.html \
Fl_Double_Window.html \
Fl_End.html \
Fl_File_Browser.html \
Fl_File_Chooser.html \
Fl_File_Icon.html \
Fl_Float_Input.html \
Fl_Free.html \
Fl_GIF_Image.html \
Fl_Gl_Window.html \
Fl_Group.html \
Fl_Help_Dialog.html \
Fl_Help_View.html \
Fl_Hold_Browser.html \
Fl_Image.html \
Fl_Input.html \
Fl_Input_.html \
Fl_Int_Input.html \
Fl_JPEG_Image.html \
Fl_Light_Button.html \
Fl_Menu_.html \
Fl_Menu_Bar.html \
Fl_Menu_Button.html \
Fl_Menu_Item.html \
Fl_Menu_Window.html \
Fl_Multi_Browser.html \
Fl_Multiline_Input.html \
Fl_Multiline_Output.html \
Fl_Output.html \
Fl_Overlay_Window.html \
Fl_Pack.html \
Fl_Pixmap.html \
Fl_PNG_Image.html \
Fl_PNM_Image.html \
Fl_Positioner.html \
Fl_Progress.html \
Fl_Repeat_Button.html \
Fl_RGB_Image.html \
Fl_Return_Button.html \
Fl_Roller.html \
Fl_Round_Button.html \
Fl_Scroll.html \
Fl_Scrollbar.html \
Fl_Secret_Input.html \
Fl_Select_Browser.html \
Fl_Single_Window.html \
Fl_Slider.html \
Fl_Tabs.html \
Fl_Text_Buffer.html \
Fl_Text_Display.html \
Fl_Text_Editor.html \
Fl_Tile.html \
Fl_Tiled_Image.html \
Fl_Timer.html \
Fl_Tooltip.html \
Fl_Valuator.html \
Fl_Value_Input.html \
Fl_Value_Output.html \
Fl_Value_Slider.html \
Fl_Widget.html \
Fl_Window.html \
Fl_Wizard.html \
Fl_XBM_Image.html \
Fl_XPM_Image.html \
functions.html \
enumerations.html \
glut.html \
forms.html \
osissues.html \
migration.html \
license.html
IMAGEFILES = \
adjuster1.gif \
boxtypes.gif \
buttons.gif \
charts.gif \
choice.gif \
clock.gif \
counter.gif \
cubeview.gif \
dial.gif \
editor.gif \
editor-replace.gif \
filechooser.gif \
fl_alert.gif \
fl_ask.gif \
Fl_Check_Button.gif \
fl_choice.gif \
fl_color_chooser.jpg \
FL.gif \
Fl_Help_Dialog.gif \
fl_input.gif \
Fl_Light_Button.gif \
fl_message.gif \
fl_password.gif \
Fl_Return_Button.gif \
Fl_Roller.gif \
Fl_Round_Button.gif \
Fl_Scroll.gif \
fl_show_colormap.gif \
Fl_Tile.gif \
fluid1.gif \
fluid2.gif \
fluid3-cxx.gif \
fluid3-gui.gif \
fluid3-style.gif \
fluid4.gif \
fluid-catgets.gif \
fluid-gettext.gif \
fluid-org.gif \
fluid_prefs.gif \
fluid_widget_cxx.gif \
fluid_widget_gui.gif \
fluid_widget_style.gif \
Fl_Value_Input.gif \
Fl_Value_Output.gif \
hello.C.gif \
menubar.gif \
menu_button.gif \
menu.gif \
positioner.gif \
resizebox1.gif \
resizebox2.gif \
round_clock.gif \
scrollbar.gif \
slider.gif \
symbols.gif \
tabs.gif \
text.gif \
valuators.gif \
value_slider.gif
MANPAGES = fltk.$(CAT3EXT) fltk-config.$(CAT1EXT) fluid.$(CAT1EXT)
@ -192,22 +253,22 @@ uninstall:
# Base html files are now the readable ones, so this target is not make by
# default...
fltk.d/index.html: $(HTMLFILES)
fltk.d/index.html: $(HTMLFILES) $(IMAGEFILES)
echo "Generating HTML documentation..."
-mkdir fltk.d
-rm -f fltk.d/*
$(HTMLDOC) --verbose --batch fltk.book -d fltk.d -t html
fltk.ps: $(HTMLFILES)
fltk.ps: $(HTMLFILES) $(IMAGEFILES)
echo "Generating PostScript documentation..."
rm -f fltk.ps
$(HTMLDOC) --verbose --batch fltk.book $(MEDIA) -f fltk.ps
fltk.pdf: $(HTMLFILES)
fltk.pdf: $(HTMLFILES) $(IMAGEFILES)
echo "Generating PDF documentation..."
rm -f fltk.pdf
$(HTMLDOC) --verbose --batch fltk.book $(MEDIA) -f fltk.pdf
#
# End of "$Id: Makefile,v 1.9.2.10.2.13 2002/04/20 21:07:18 easysw Exp $".
# End of "$Id: Makefile,v 1.9.2.10.2.14 2002/04/28 16:41:16 easysw Exp $".
#

View File

@ -1,5 +1,5 @@
/*
* "$Id: config.mingw,v 1.1.2.3.2.3 2002/04/24 18:29:05 easysw Exp $"
* "$Id: config.mingw,v 1.1.2.3.2.4 2002/04/28 16:41:16 easysw Exp $"
*
* Configuration file for the Fast Light Tool Kit (FLTK).
*
@ -24,9 +24,10 @@
*/
/*
* Where to find the documentation files...
* Where to find files...
*/
#define FLTK_DATADIR "C:/FLTK"
#define FLTK_DOCDIR "C:/FLTK/DOC"
/*
@ -189,5 +190,5 @@
/*
* End of "$Id: config.mingw,v 1.1.2.3.2.3 2002/04/24 18:29:05 easysw Exp $".
* End of "$Id: config.mingw,v 1.1.2.3.2.4 2002/04/28 16:41:16 easysw Exp $".
*/

View File

@ -1,6 +1,6 @@
/* config.h. Generated automatically by configure. */
/*
* "$Id: config.os2x,v 1.1.2.4.2.5 2002/04/24 18:29:05 easysw Exp $"
* "$Id: config.os2x,v 1.1.2.4.2.6 2002/04/28 16:41:16 easysw Exp $"
*
* Configuration file for the Fast Light Tool Kit (FLTK).
* @configure_input@
@ -26,9 +26,10 @@
*/
/*
* Where to find the documentation files...
* Where to find files...
*/
#define FLTK_DATADIR "/usr/local/share/fltk"
#define FLTK_DOCDIR "/usr/local/share/doc/fltk"
/*
@ -220,5 +221,5 @@
/*
* End of "$Id: config.os2x,v 1.1.2.4.2.5 2002/04/24 18:29:05 easysw Exp $".
* End of "$Id: config.os2x,v 1.1.2.4.2.6 2002/04/28 16:41:16 easysw Exp $".
*/

828
src/Fl_Preferences.cxx Normal file
View File

@ -0,0 +1,828 @@
//
// "$Id: Fl_Preferences.cxx,v 1.1.2.1 2002/04/28 16:41:16 easysw Exp $"
//
// Preferences file for the Fast Light Tool Kit (FLTK).
//
// Copyright 2002 by Matthias Melcher.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to "fltk-bugs@fltk.org".
//
#include <FL/Fl.H>
#include <FL/Fl_Preferences.H>
#include <stdio.h>
#include <stdlib.h>
#include "flstring.h"
#include <sys/stat.h>
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
* Must be a valid directory name.
* i 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, "matthiasm.com", "test01");
*/
Fl_Preferences::Fl_Preferences( enum Root root, const char *vendor, const char *application )
{
node = new Node( "." );
rootNode = new RootNode( this, root, vendor, application );
}
/**
* 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)
* example: Fl_Preferences colors( base, "setup/colors" );
*/
Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *key )
{
rootNode = 0;
node = parent.node->addChild( 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)
* example: Fl_Preferences colors( base, "setup/colors" );
*/
Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *key )
{
rootNode = 0;
node = parent->node->addChild( key );
}
/**
* destroy individual keys
* - destroying the base preferences will flush changes to the prefs file
* - after destroying the base, none of the depending preferences must be read or written
*/
Fl_Preferences::~Fl_Preferences()
{
delete rootNode;
// DO NOT delete nodes! The root node will do that after writing the preferences
}
/**
* return the number of groups that are contained within a group
* example: int n = base.groups();
*/
int Fl_Preferences::groups()
{
return node->nChildren();
}
/**
* return the group name of the n'th group
* - there is no guaranteed order of group names
* - the index must be within the range given by groups()
* example: printf( "Group(%d)='%s'\n", ix, base.group(ix) );
*/
const char *Fl_Preferences::group( int ix )
{
return node->child( ix );
}
/**
* return 1, if a group with this name exists
* example: if ( base.groupExists( "setup/colors" ) ) ...
*/
int Fl_Preferences::groupExists( const char *key )
{
return node->search( key ) ? 1 : 0 ;
}
/**
* delete a group
* example: setup.deleteGroup( "colors/buttons" );
*/
int Fl_Preferences::deleteGroup( const char *key )
{
Node *nd = node->search( key );
if ( nd ) return nd->remove();
return 0;
}
/**
* return the number of entries (name/value) pairs for a group
* example: int n = buttonColor.entries();
*/
int Fl_Preferences::entries()
{
return node->nEntry;
}
/**
* return the name of an entry
* - there is no guaranteed order of entry names
* - the index must be within the range given by entries()
* example: printf( "Entry(%d)='%s'\n", ix, buttonColor.entry(ix) );
*/
const char *Fl_Preferences::entry( int ix )
{
return node->entry[ix].name;
}
/**
* return 1, if a group with this name exists
* example: if ( buttonColor.entryExists( "red" ) ) ...
*/
int Fl_Preferences::entryExists( const char *key )
{
return node->getEntry( key ) ? 1 : 0 ;
}
/**
* remove a single entry (name/value pair)
* example: buttonColor.deleteEntry( "red" );
*/
int Fl_Preferences::deleteEntry( const char *key )
{
return node->deleteEntry( key );
}
/**
* read an entry from the group
* - a default value must be supplied
* - the return value indicates, if the value was not available and the default was used (0)
* example: button.get( "visible", b.visible, 1 );
*/
int Fl_Preferences::get( const char *key, int &value, int defaultValue )
{
const char *v = node->get( key );
value = v ? atoi( v ) : defaultValue;
return 0;
}
/**
* set an entry (name/value pair)
*/
int Fl_Preferences::set( const char *key, int value )
{
sprintf( nameBuffer, "%d", value );
node->set( key, nameBuffer );
return 1;
}
/**
* read an entry from the group
*/
int Fl_Preferences::get( const char *key, float &value, float defaultValue )
{
const char *v = node->get( key );
value = v ? (float)atof( v ) : defaultValue;
return 0;
}
/**
* set an entry (name/value pair)
*/
int Fl_Preferences::set( const char *key, float value )
{
sprintf( nameBuffer, "%g", value );
node->set( key, nameBuffer );
return 1;
}
/**
* read an entry from the group
*/
int Fl_Preferences::get( const char *key, double &value, double defaultValue )
{
const char *v = node->get( key );
value = v ? atof( v ) : defaultValue;
return 0;
}
/**
* set an entry (name/value pair)
*/
int Fl_Preferences::set( const char *key, double value )
{
sprintf( nameBuffer, "%g", value );
node->set( key, nameBuffer );
return 1;
}
/**
* 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
*/
int Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize )
{
maxSize --;
const char *v = node->get( key );
if ( !v ) v = defaultValue;
strncpy( text, v, maxSize );
if ( (int)strlen(v) >= maxSize ) text[maxSize] = 0;
return 0;
}
/**
* 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.
*/
int Fl_Preferences::get( const char *key, char *&text, const char *defaultValue )
{
const char *v = node->get( key );
if ( !v ) v = defaultValue;
text = strdup( v );
return 0;
}
/**
* set an entry (name/value pair)
*/
int Fl_Preferences::set( const char *key, const char *text )
{
node->set( key, text );
return 1;
}
/**
* return the size of the value part of an entry
*/
int Fl_Preferences::size( const char *key )
{
const char *v = node->get( key );
return v ? strlen( v ) : 0 ;
}
/**
* creates a path that is related to the preferences file
* and that is usable for application data beyond what is covered
* by Fl_Preferences.
* - 'getUserdataPath' actually creates the directory
* - 'path' must be large enough to receive a complete file path
* example:
* Fl_Preferences prefs( USER, "matthiasm.com", "test" );
* char path[MAX_PATH];
* prefs.getUserdataPath( path );
* sample returns:
* Win32: c:/Documents and Settings/matt/Application Data/matthiasm.com/test/
* prefs: c:/Documents and Settings/matt/Application Data/matthiasm.com/test.prefs
*/
int Fl_Preferences::getUserdataPath( char *path )
{
if ( rootNode )
return rootNode->getPath( path );
return 0;
}
/**
* 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
*/
void Fl_Preferences::flush()
{
if ( rootNode && node->dirty() )
rootNode->write();
}
/*
int Fl_Preferences::export( const char *filename, enum Type type )
{
//#pragma message ( "TODO: implement Fl_Preferences::export(filepath)" )
switch ( type )
{
case win32:
break;
case macos:
break;
case fltk:
break;
}
return 0;
}
int Fl_Preferences::import( const char *filename )
{
//#pragma message ( "TODO: implement Fl_Preferences::import(filepath)" )
return 0;
}
*/
//-----------------------------------------------------------------------------
// internal methods, do not change or use as they will change without notice
//
int Fl_Preferences::Node::lastEntrySet = -1;
static int makePath( const char *path )
{
struct stat stats;
int ret = stat( path, &stats );
if ( ret )
{
char *s = strrchr( path, '/' );
if ( !s ) return 0;
int len = s-path;
char *p = (char*)malloc( len+1 );
memcpy( p, path, len );
p[len] = 0;
makePath( p );
free( p );
return ( mkdir( path, 0777 ) == 0 );
}
return 1;
}
static void makePathForFile( const char *path )
{
char *s = strrchr( path, '/' );
if ( !s ) return;
int len = s-path;
char *p = (char*)malloc( len+1 );
memcpy( p, path, len );
p[len] = 0;
makePath( p );
free( p );
}
// create the root node
// - construct the name of the file that will hold our preferences
Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, enum Root root, const char *vendor, const char *application )
{
const char *home; // Home directory
char filename[1024]; // Filename
#ifdef WIN32
HKEY key; // Registry key
DWORD size; // Size of string
char data[1024]; // Home (profile) directory
#endif // WIN32
// Find the home directory...
#ifdef WIN32
// Open the registry...
if (RegOpenKeyEx(HKEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0,
KEY_READ, &key)) {
data[0] = '\0';
} else {
// Grab the current user's AppData directory...
size = sizeof(data);
if (RegQueryValueEx(key, "AppData", NULL, NULL, (unsigned char *)data, &size))
data[0] = '\0';
RegCloseKey(key);
}
if (data[0])
home = data;
else
home = NULL;
#else
home = getenv("HOME");
#endif // WIN32
// Choose the appropriate path...
if (root == SYSTEM || !home) {
// Locate the preferences in the system data directory...
snprintf(filename, sizeof(filename),
FLTK_DATADIR "/%s/%s.prefs", vendor, application);
} else {
// Locate the preferences in the user data directory...
snprintf(filename, sizeof(filename),
"%s/.fltk/%s/%s.prefs", home, vendor, application);
}
makePathForFile( filename );
prefs_ = prefs;
filename_ = strdup( filename );
vendor_ = strdup( vendor );
application_ = strdup( application );
read();
}
// destroy the root node and all depending nodes
Fl_Preferences::RootNode::~RootNode()
{
if ( prefs_->node->dirty() )
write();
if ( filename_ )
free( filename_ );
delete vendor_;
delete application_;
delete prefs_->node;
}
// read a preferences file and construct the group tree and with all entry leafs
int Fl_Preferences::RootNode::read()
{
char buf[1024];
FILE *f = fopen( filename_, "rb" );
if ( !f ) return 0;
fgets( buf, 1024, f );
fgets( buf, 1024, f );
fgets( buf, 1024, f );
Node *nd = prefs_->node;
for (;;)
{
if ( !fgets( buf, 1024, f ) ) break; // EOF or Error
if ( buf[0]=='[' ) // read a new group
{
int end = strcspn( buf+1, "]\n\r" );
buf[ end+1 ] = 0;
nd = prefs_->node->find( buf+1 );
}
else if ( buf[0]=='+' ) //
{ // value of previous name/value pair spans multiple lines
int end = strcspn( buf+1, "\n\r" );
if ( end != 0 ) // if entry is not empty
{
buf[ end+1 ] = 0;
nd->add( buf+1 );
}
}
else // read a name/value pair
{
int end = strcspn( buf, "\n\r" );
if ( end != 0 ) // if entry is not empty
{
buf[ end ] = 0;
nd->set( buf );
}
}
}
fclose( f );
return 0;
}
// write the group tree and all entry leafs
int Fl_Preferences::RootNode::write()
{
FILE *f = fopen( filename_, "wb" );
if ( !f ) return 1;
fprintf( f, "; FLTK preferences file format 1.0\n" );
fprintf( f, "; vendor: %s\n", vendor_ );
fprintf( f, "; application: %s\n", application_ );
prefs_->node->write( f );
fclose( f );
return 0;
}
// get the path to the preferences directory
int Fl_Preferences::RootNode::getPath( char *path )
{
char *s;
strcpy( path, filename_ );
for ( s = path; *s; s++ ) if ( *s == '\\' ) *s = '/';
s = strrchr( path, '.' );
if ( !s ) return 0;
*s = 0;
int ret = makePath( path );
strcpy( s, "/" );
return ret;
}
// create a node that represents a group
// - path must be a single word, prferable alnum(), dot and underscore only. Space is ok.
Fl_Preferences::Node::Node( const char *path )
{
if ( path ) path_ = strdup( path ); else path_ = 0;
child_ = 0; next_ = 0; parent_ = 0;
entry = 0;
nEntry = NEntry = 0;
dirty_ = 0;
}
// delete this and all depending nodes
Fl_Preferences::Node::~Node()
{
Node *nx;
for ( Node *nd = child_; nd; nd = nx )
{
nx = nd->next_;
delete nd;
}
for ( int i = 0; i < nEntry; i++ )
{
delete entry[i].name;
delete entry[i].value;
}
delete[] entry;
if ( path_ ) free( path_ );
}
// recursively check if any entry is dirty (was changed after loading a fresh prefs file)
int Fl_Preferences::Node::dirty()
{
if ( dirty_ ) return 1;
if ( next_ && next_->dirty() ) return 1;
if ( child_ && child_->dirty() ) return 1;
return 0;
}
// write this node (recursively from the last neighbor back to this)
// write all entries
// write all children
int Fl_Preferences::Node::write( FILE *f )
{
if ( next_ ) next_->write( f );
fprintf( f, "\n[%s]\n\n", path_ );
for ( int i = 0; i < nEntry; i++ )
{
char *src = entry[i].value;
if ( src )
{ // hack it into smaller pieces if needed
fprintf( f, "%s:", entry[i].name );
int cnt;
for ( cnt = 0; cnt < 60; cnt++ )
if ( src[cnt]==0 ) break;
fwrite( src, cnt, 1, f );
fprintf( f, "\n" );
src += cnt;
for (;*src;)
{
for ( cnt = 0; cnt < 80; cnt++ )
if ( src[cnt]==0 ) break;
fputc( '+', f );
fwrite( src, cnt, 1, f );
fputc( '\n', f );
src += cnt;
}
}
else
fprintf( f, "%s\n", entry[i].name );
}
if ( child_ ) child_->write( f );
dirty_ = 0;
return 0;
}
// set the parent node and create the full path
void Fl_Preferences::Node::setParent( Node *pn )
{
parent_ = pn;
next_ = pn->child_;
pn->child_ = this;
sprintf( nameBuffer, "%s/%s", pn->path_, path_ );
free( path_ );
path_ = strdup( nameBuffer );
}
// add a child to this node and set its path (try to find it first...)
Fl_Preferences::Node *Fl_Preferences::Node::addChild( const char *path )
{
sprintf( nameBuffer, "%s/%s", path_, path );
char *name = strdup( nameBuffer );
Node *nd = find( nameBuffer );
free( name );
return nd;
}
// create and set, or change an entry within this node
void Fl_Preferences::Node::set( const char *name, const char *value )
{
for ( int i=0; i<nEntry; i++ )
{
if ( strcmp( name, entry[i].name ) == 0 )
{
if ( !value ) return; // annotation
if ( strcmp( value, entry[i].value ) != 0 )
{
delete entry[i].value;
entry[i].value = strdup( value );
dirty_ = 1;
}
lastEntrySet = i;
return;
}
}
if ( NEntry==nEntry )
{
NEntry = NEntry ? NEntry*2 : 10;
entry = (Entry*)realloc( entry, NEntry * sizeof(Entry) );
}
entry[ nEntry ].name = strdup( name );
entry[ nEntry ].value = value?strdup( value ):0;
lastEntrySet = nEntry;
nEntry++;
dirty_ = 1;
}
// create or set a value (or annotation) from a single line in the file buffer
void Fl_Preferences::Node::set( const char *line )
{
int dirty = dirty_; // hmm. If we assume that we always read yhis file in the beginning, we can handle the dirty flag 'quick and dirty'
if ( line[0]==';' || line[0]==0 || line[0]=='#' )
{
set( line, 0 );
}
else
{
char *c = strchr( line, ':' );
if ( c )
{
strncpy( nameBuffer, line, c-line );
nameBuffer[ c-line ] = 0;
set( nameBuffer, c+1 );
}
else
set( line, "" );
}
dirty_ = dirty;
}
// add more data to an existing entry
void Fl_Preferences::Node::add( const char *line )
{
if ( lastEntrySet<0 || lastEntrySet>=nEntry ) return;
char *&dst = entry[ lastEntrySet ].value;
int a = strlen( dst );
int b = strlen( line );
dst = (char*)realloc( dst, a+b+1 );
memcpy( dst+a, line, b+1 );
dirty_ = 1;
}
// get the value for a name, returns 0 if no such name
const char *Fl_Preferences::Node::get( const char *name )
{
int i = getEntry( name );
return i>=0 ? entry[i].value : 0 ;
}
// find the index of an entry, returns -1 if no such entry
int Fl_Preferences::Node::getEntry( const char *name )
{
for ( int i=0; i<nEntry; i++ )
{
if ( strcmp( name, entry[i].name ) == 0 )
{
return i;
}
}
return -1;
}
// remove one entry form this group
int Fl_Preferences::Node::deleteEntry( const char *name )
{
int ix = getEntry( name );
if ( ix == -1 ) return 0;
memmove( entry+ix, entry+ix+1, (nEntry-ix-1) * sizeof(Entry) );
nEntry--;
return 1;
}
// find a group somewhere in the tree starting here
// - this method will always return a valid node (except for memory allocation problems)
// - if the node was not found, 'find' will create the required branch
Fl_Preferences::Node *Fl_Preferences::Node::find( const char *path )
{
int len = strlen( path_ );
if ( strncmp( path, path_, len ) == 0 )
{
if ( path[ len ] == 0 )
return this;
if ( path[ len ] == '/' )
{
Node *nd;
for ( nd = child_; nd; nd = nd->next_ )
{
Node *nn = nd->find( path );
if ( nn ) return nn;
}
const char *s = path+len+1;
const char *e = strchr( s, '/' );
if ( e ) { strncpy( nameBuffer, s, e-s ); nameBuffer[ e-s ] = 0; } else strcpy( nameBuffer, s );
nd = new Node( nameBuffer );
nd->setParent( this );
return nd->find( path );
}
}
return 0;
}
// find a group somewhere in the tree starting here
// - if the node does not exist, 'search' returns NULL
Fl_Preferences::Node *Fl_Preferences::Node::search( const char *path )
{
int len = strlen( path_ );
if ( strncmp( path, path_, len ) == 0 )
{
if ( path[ len ] == 0 )
return this;
if ( path[ len ] == '/' )
{
Node *nd;
for ( nd = child_; nd; nd = nd->next_ )
{
Node *nn = nd->find( path );
if ( nn ) return nn;
}
return 0;
}
}
return 0;
}
// return the number of child nodes (groups)
int Fl_Preferences::Node::nChildren()
{
int cnt = 0;
for ( Node *nd = child_; nd; nd = nd->next_ )
cnt++;
return cnt;
}
// return the n'th child node
const char *Fl_Preferences::Node::child( int ix )
{
Node *nd;
for ( nd = child_; nd; nd = nd->next_ )
{
if ( !ix-- ) break;
}
if ( nd && nd->path_ )
{
char *r = strrchr( nd->path_, '/' );
return r ? r+1 : nd->path_ ;
}
return 0L ;
}
// remove myself from the list and delete me (and all children)
int Fl_Preferences::Node::remove()
{
Node *nd, *np;
if ( parent_ )
{
nd = parent_->child_; np = 0L;
for ( ; nd; nd = nd->next_ )
{
if ( nd == this )
{
if ( np )
np->next_ = nd->next_;
else
parent_->child_ = nd->next_;
break;
}
}
}
delete this;
return ( nd != 0 );
}
//
// End of "$Id: Fl_Preferences.cxx,v 1.1.2.1 2002/04/28 16:41:16 easysw Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_Window.cxx,v 1.6.2.3.2.3 2002/01/01 15:11:31 easysw Exp $"
// "$Id: Fl_Window.cxx,v 1.6.2.3.2.4 2002/04/28 16:41:16 easysw Exp $"
//
// Window widget class for the Fast Light Tool Kit (FLTK).
//
@ -84,6 +84,7 @@ int Fl_Window::y_root() const {
void Fl_Window::draw() {
int savex = x(); x(0);
int savey = y(); y(0);
Fl_Widget::label(0);
Fl_Group::draw();
y(savey);
x(savex);
@ -108,5 +109,5 @@ void Fl_Window::default_callback(Fl_Window* window, void* v) {
}
//
// End of "$Id: Fl_Window.cxx,v 1.6.2.3.2.3 2002/01/01 15:11:31 easysw Exp $".
// End of "$Id: Fl_Window.cxx,v 1.6.2.3.2.4 2002/04/28 16:41:16 easysw Exp $".
//

View File

@ -1,5 +1,5 @@
#
# "$Id: Makefile,v 1.18.2.14.2.39 2002/04/11 11:52:42 easysw Exp $"
# "$Id: Makefile,v 1.18.2.14.2.40 2002/04/28 16:41:16 easysw Exp $"
#
# Library makefile for the Fast Light Tool Kit (FLTK).
#
@ -70,6 +70,7 @@ CPPFILES = \
Fl_PNG_Image.cxx \
Fl_PNM_Image.cxx \
Fl_Positioner.cxx \
Fl_Preferences.cxx \
Fl_Progress.cxx \
Fl_Repeat_Button.cxx \
Fl_Return_Button.cxx \
@ -427,5 +428,5 @@ uninstall:
#
# End of "$Id: Makefile,v 1.18.2.14.2.39 2002/04/11 11:52:42 easysw Exp $".
# End of "$Id: Makefile,v 1.18.2.14.2.40 2002/04/28 16:41:16 easysw Exp $".
#

View File

@ -1,5 +1,5 @@
/*
* "$Id: config.h,v 1.5.2.5.2.6 2002/04/24 18:29:06 easysw Exp $"
* "$Id: config.h,v 1.5.2.5.2.7 2002/04/28 16:41:17 easysw Exp $"
*
* Configuration file for the Fast Light Tool Kit (FLTK) for Visual C++.
*
@ -24,9 +24,10 @@
*/
/*
* Where to find the documentation files...
* Where to find files...
*/
#define FLTK_DATADIR "C:/FLTK"
#define FLTK_DOCDIR "C:/FLTK/DOC"
/*
@ -182,5 +183,5 @@
/*
* End of "$Id: config.h,v 1.5.2.5.2.6 2002/04/24 18:29:06 easysw Exp $".
* End of "$Id: config.h,v 1.5.2.5.2.7 2002/04/28 16:41:17 easysw Exp $".
*/

View File

@ -601,5 +601,9 @@ SOURCE=..\src\scandir.c
SOURCE=..\src\vsnprintf.c
# End Source File
# Begin Source File
SOURCE=..\src\Fl_Preferences.cxx
# End Source File
# End Target
# End Project

View File

@ -2406,6 +2406,11 @@ SOURCE=..\src\vsnprintf.c
DEP_CPP_VSNPR=\
".\config.h"\
# End Source File
# Begin Source File
SOURCE=..\src\Fl_Preferences.cxx
# End Source File
# End Target
# End Project