From 79832b679f2d195eb3b0f30ca920a857cc133b2b Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Wed, 11 Jan 2023 20:20:56 +0100 Subject: Add the initial version of class Fl_Scheme This basic version of class Fl_Scheme contains only static methods that are needed for Fl_Scheme_Choice and further extensions. --- FL/Fl_Scheme.H | 64 +++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/Fl_Scheme.cxx | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Makefile | 1 + 4 files changed, 215 insertions(+) create mode 100644 FL/Fl_Scheme.H create mode 100644 src/Fl_Scheme.cxx diff --git a/FL/Fl_Scheme.H b/FL/Fl_Scheme.H new file mode 100644 index 000000000..9a0f3cbf4 --- /dev/null +++ b/FL/Fl_Scheme.H @@ -0,0 +1,64 @@ +// +// Scheme header for the Fast Light Tool Kit (FLTK). +// +// Copyright 2022-2023 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#ifndef FL_Fl_Scheme_H_ +#define FL_Fl_Scheme_H_ + +#include + +class Fl_Scheme { + +private: + + static const char **names_; // registered scheme names + static int num_schemes_; // number of registered schemes + static int alloc_size_; // number of allocated scheme name entries + +protected: + + // const char *name_; // the scheme's name + + // protected constructor - not yet implemented + // Fl_Scheme(const char *name); + +public: + + // Static methods. + + // Some of these methods will replace the scheme related methods of class Fl, + // for instance Fl::scheme() and Fl::is_scheme(). + // Backwards compatibility must be kept though. + + static const char **names(); + + /** + Return the number of currently registered schemes. + + \return Number of registered schemes. + */ + static int num_schemes() { + if (!names_) names(); // force initialization + return num_schemes_; + } + + // Adding a scheme name must be a public static method in FLTK 1.4.0. + // This will later be protected or replaced by another method name. + + static int add_scheme_name(const char *name); + +}; // class Fl_Scheme + +#endif // FL_Fl_Scheme_H_ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c26363972..2b37a146f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ set (CPPFILES Fl_Return_Button.cxx Fl_Roller.cxx Fl_Round_Button.cxx + Fl_Scheme.cxx Fl_Screen_Driver.cxx Fl_Scroll.cxx Fl_Scrollbar.cxx diff --git a/src/Fl_Scheme.cxx b/src/Fl_Scheme.cxx new file mode 100644 index 000000000..0eab7a178 --- /dev/null +++ b/src/Fl_Scheme.cxx @@ -0,0 +1,149 @@ +// +// Scheme implementation for the Fast Light Tool Kit (FLTK). +// +// Copyright 2022-2023 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include +#include +#include +#include // fl_strdup + +#include // malloc, realloc + +const char **Fl_Scheme::names_ = NULL; +int Fl_Scheme::num_schemes_ = 0; +int Fl_Scheme::alloc_size_ = 0; + +/** + Return a list of all known scheme names. + + This list is only valid until a new scheme is added or one is removed. + It is possible that scheme names are appended to the list during the + runtime of the program but schemes can't be removed. + + Getting the list of known schemes can be useful to populate a menu of + scheme choices to let the user select a scheme. You should process the + names immediately and you should never store a pointer to the list or + any individual name for later reference because the location of the + list can be changed (reallocated) when schemes are added. + + The list of scheme names is nul-terminated. + + \note + Currently (in FLTK 1.4.0) schemes can only be added to the list and + not removed from the list. This may change in a later version. + + \return List of currently known scheme names. +*/ + +const char **Fl_Scheme::names() { + if (names_) + return names_; + + alloc_size_ = 8; + names_ = (const char **)malloc(alloc_size_ * sizeof(const char *)); + + // FIXME: register "known" scheme names ... + + add_scheme_name("base"); + add_scheme_name("plastic"); + add_scheme_name("gtk+"); + add_scheme_name("gleam"); + add_scheme_name("oxy"); + + return names_; +} + +/** + Add a scheme name to the list of known schemes. + + This method is public in FLTK 1.4.0 because derived classes of Fl_Scheme + are not yet implemented. Thus, users implementing their own schemes can + use this method to add the scheme name to the list of known schemes + which is for instance used in Fl_Scheme::names(). + + \note \b Attention! + In a future version, when subclasses of Fl_Scheme will be implemented, + this method will either be replaced by another \p protected method or + it will no longer do anything (kept only for ABI reasons). + + The new scheme name must consist of valid ASCII characters as described + below: + - lowercase letters \p 'a' - \p 'z' + - numbers \p '0' - \p '9' + - any character in \p "$+_." (w/o the quotes). + + The name must not be longer than 12 ASCII characters (bytes). + The new scheme name is added to the \b end of the \b unordered list. + + \note Call this method only once for each scheme name. If the returned + value is \<= 0 you should check the scheme name. + + The given scheme \p name is copied and may be freed directly after the + call to add_scheme_name(). + + \param[in] name New scheme name + + \returns The new number of schemes if the name was successfully added. + This is the same as the index of the scheme + 1. + \retval 0 Scheme \p name already exists + \retval -1 Invalid character(s) in \p name + \retval -2 The \p name is too long + + \since 1.4.0 +*/ +int Fl_Scheme::add_scheme_name(const char *name) { + + static const char valid_chars[] = "$+_."; + + // test if the scheme name is valid + + int nlen = static_cast(strlen(name)); + + if (nlen > 12) + return (-2); + + for (int i = 0; i < nlen; i++) { + if ((name[i] >= 'a' && name[i] <= 'z') || + (name[i] >= '0' && name[i] <= '9')) + continue; + if (!strchr(valid_chars, name[i])) + return (-1); + } + + // Test if the scheme name already exists. + // We know already that it consists only of valid characters, + // hence we can use the faster strcmp() for comparison. + + const char **s = names(); + for (int i = 0; i < num_schemes_; i++) { + if (strcmp(name, s[i]) == 0) + return 0; + } + + // The scheme name is OK, we can add it. Take care that we need + // a null pointer at the end of the list. + + num_schemes_++; + + if (num_schemes_ + 1 > alloc_size_) { // overflow, extend the list + alloc_size_ += 8; + names_ = (const char **)realloc(names_, alloc_size_ * sizeof(const char *)); + } + + names_[num_schemes_-1] = fl_strdup(name); + names_[num_schemes_] = NULL; + + return num_schemes_; +} diff --git a/src/Makefile b/src/Makefile index dddb7fcb4..c6a6cec63 100644 --- a/src/Makefile +++ b/src/Makefile @@ -76,6 +76,7 @@ CPPFILES = \ Fl_Roller.cxx \ Fl_Round_Button.cxx \ Fl_Screen_Driver.cxx \ + Fl_Scheme.cxx \ Fl_Scroll.cxx \ Fl_Scrollbar.cxx \ Fl_Shared_Image.cxx \ -- cgit v1.2.3