summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 21:32:25 +0500
committermaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 21:32:25 +0500
commitdc39575fb3ef90e5a2689babe7fb335cd88f6727 (patch)
tree24f6cef8f2b558ae6f1f812c75be0c09a53fe417 /src
parent7d3793ce1d8cb26e7608bf859beca21359cec6e9 (diff)
wip
Diffstat (limited to 'src')
-rw-r--r--src/Fl.cxx9
-rw-r--r--src/Fl_Color_Chooser.cxx8
-rw-r--r--src/Fl_Counter.cxx5
-rw-r--r--src/Fl_Help_View.cxx568
-rw-r--r--src/Fl_Native_File_Chooser_Kdialog.H5
-rw-r--r--src/Fl_Native_File_Chooser_Kdialog.cxx62
-rw-r--r--src/Fl_Native_File_Chooser_Zenity.H4
-rw-r--r--src/Fl_Native_File_Chooser_Zenity.cxx58
-rw-r--r--src/Fl_Preferences.cxx67
-rw-r--r--src/Fl_Terminal.cxx37
-rw-r--r--src/Fl_Text_Buffer.cxx15
-rw-r--r--src/Fl_Timeout.cxx11
-rw-r--r--src/Fl_Timeout.h3
-rw-r--r--src/Fl_Valuator.cxx12
-rw-r--r--src/Fl_Value_Input.cxx5
-rw-r--r--src/Fl_Value_Output.cxx5
-rw-r--r--src/Fl_Value_Slider.cxx5
-rw-r--r--src/Fl_grab.cxx3
-rw-r--r--src/drivers/Base/Fl_Base_Pen_Events.H85
-rw-r--r--src/drivers/Base/Fl_Base_Pen_Events.cxx188
-rw-r--r--src/drivers/Posix/Fl_Posix_System_Driver.cxx11
-rw-r--r--src/drivers/Unix/Fl_Unix_System_Driver.cxx89
-rw-r--r--src/filename_absolute.cxx124
-rw-r--r--src/fl_ask.cxx115
24 files changed, 717 insertions, 777 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx
index 368e330a6..029235dee 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -448,15 +448,6 @@ int Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_retur
return Fl_Timeout::remove_next_timeout(cb, data, data_return);
}
-/**
- Return a list of all currently running timeouts.
- \return a vector with all relevant timeout data
-*/
-std::vector<Fl::TimeoutData> Fl::timeout_list() {
- return Fl_Timeout::timeout_list();
-}
-
-
////////////////////////////////////////////////////////////////
// Checks are just stored in a list. They are called in the reverse
// order that they were added (this may change in the future).
diff --git a/src/Fl_Color_Chooser.cxx b/src/Fl_Color_Chooser.cxx
index 341a51347..f219906f1 100644
--- a/src/Fl_Color_Chooser.cxx
+++ b/src/Fl_Color_Chooser.cxx
@@ -106,14 +106,6 @@ int Flcc_Value_Input::format(char* buf) {
else return Fl_Valuator::format(buf);
}
-// Note: although Flcc_Value_Input is marked private in the header files,
-// it nevertheless is publicly accessible, so implement this here just in case.
-std::string Flcc_Value_Input::format_str() {
- char buffer[129];
- int size = format(buffer);
- return std::string(buffer, size);
-}
-
#endif // !FL_DOXYGEN
void Fl_Color_Chooser::set_valuators() {
diff --git a/src/Fl_Counter.cxx b/src/Fl_Counter.cxx
index 3536a2213..d086f0229 100644
--- a/src/Fl_Counter.cxx
+++ b/src/Fl_Counter.cxx
@@ -102,8 +102,9 @@ void Fl_Counter::draw() {
draw_box(tbt, tx, y(), tw, h(), FL_BACKGROUND2_COLOR);
fl_font(textfont(), textsize());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
- std::string str = format_str();
- fl_draw(str.c_str(), tx, y(), tw, h(), FL_ALIGN_CENTER);
+ char buf[129];
+ format(buf);
+ fl_draw(buf, tx, y(), tw, h(), FL_ALIGN_CENTER);
if (Fl::focus() == this) draw_focus(tbt, tx, y(), tw, h());
if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text
diff --git a/src/Fl_Help_View.cxx b/src/Fl_Help_View.cxx
index 0b55393ee..3f0c38bba 100644
--- a/src/Fl_Help_View.cxx
+++ b/src/Fl_Help_View.cxx
@@ -35,7 +35,7 @@
#include "flstring.h"
//
-// System and C++ header files
+// System header files
//
#include <stdio.h>
@@ -44,9 +44,7 @@
#include <ctype.h>
#include <errno.h>
#include <math.h>
-#include <map>
-#include <vector>
-#include <string>
+#include <string.h>
//
// Debugging
@@ -88,14 +86,22 @@ public:
textsize_ = 12;
value_ = 0;
- blocks_.clear();
+ blocks_ = 0;
+ blocks_count_ = 0;
+ blocks_alloc_ = 0;
link_ = (Fl_Help_Func *)0;
- link_list_.clear();
+ link_list_ = 0;
+ link_list_count_ = 0;
+ link_list_alloc_ = 0;
- directory_.clear();
- filename_.clear();
+ targets_ = 0;
+ targets_count_ = 0;
+ targets_alloc_ = 0;
+
+ directory_ = 0;
+ filename_ = 0;
topline_ = 0;
leftline_ = 0;
@@ -120,9 +126,11 @@ public:
/** Helper class to manage margins in Fl_Help_View. */
class Margin_Stack
{
- std::vector<int> margins_;
+ enum { MAX_MARGINS = 64 };
+ int margins_[MAX_MARGINS];
+ int count_;
public:
- Margin_Stack() = default;
+ Margin_Stack() : count_(0) {}
void clear();
int current() const;
int pop();
@@ -134,11 +142,23 @@ public:
allow buffer management to avoid buffer overflows in stack variables
used to edit strings for formatting and drawing (STR #3275).
*/
- class Edit_Buffer : public std::string {
+ class Edit_Buffer {
+ char *buf_;
+ int len_;
+ int alloc_;
+ void ensure(int needed);
public:
+ Edit_Buffer();
+ ~Edit_Buffer();
void add(int ucs);
int cmp(const char *str);
int width() const;
+ void clear();
+ void append(const char *s, int n);
+ Edit_Buffer &operator+=(char c);
+ char operator[](int i) const { return (buf_ && i >= 0 && i < len_) ? buf_[i] : '\0'; }
+ const char *c_str() const { return buf_ ? buf_ : ""; }
+ int size() const { return len_; }
};
/** Private struct to describe blocks of text. */
@@ -158,9 +178,11 @@ public:
/** Private class to hold a link with target and its position on screen. */
struct Link {
- std::string filename_; // Filename part of a link
- std::string target; // Target part of a link
+ char *filename_; // Filename part of a link (malloc'd)
+ char *target; // Target part of a link (malloc'd)
Fl_Rect box; // Clickable rectangle that defines the link area
+ Link() : filename_(0), target(0) {}
+ ~Link() { if (filename_) free(filename_); if (target) free(target); }
};
/** Private font stack element definition. */
@@ -176,13 +198,15 @@ public:
/** Private class to hold font information on a stack. */
struct Font_Stack {
+ enum { MAX_FONTS = 100 };
void init(Fl_Font f, Fl_Fontsize s, Fl_Color c);
void top(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c);
void push(Fl_Font f, Fl_Fontsize s, Fl_Color c);
void pop(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c);
- size_t count() const;
+ int count() const;
private:
- std::vector<Font_Style> elts_; ///< font elements
+ Font_Style elts_[MAX_FONTS]; ///< font elements
+ int count_; ///< number of elements on stack
};
enum { ALIGN_RIGHT = -1, ALIGN_CENTER, ALIGN_LEFT }; ///< Alignments
@@ -193,16 +217,24 @@ public:
// HTML source and raw data
const char *value_; ///< Copy of raw HTML text, as set by `value()` or `load()`
- std::string directory_; ///< Directory for current document
- std::string filename_; ///< Original file name from `load()`
+ char *directory_; ///< Directory for current document (malloc'd)
+ char *filename_; ///< Original file name from `load()` (malloc'd)
// HTML document data
- std::string title_; ///< Title string from <title> tag
+ char title_[256]; ///< Title string from <title> tag
Font_Stack fstack_; ///< Font and style stack
- std::vector<Text_Block> blocks_; ///< List of all text blocks on screen
- std::vector<std::shared_ptr<Link> > link_list_; ///< List of all clickable links and their position on screen
- std::map<std::string, int> target_line_map_; ///< List of vertical position of all HTML Targets in a document
+ Text_Block *blocks_; ///< Array of all text blocks on screen
+ int blocks_count_; ///< Number of blocks
+ int blocks_alloc_; ///< Allocated size of blocks array
+ Link **link_list_; ///< Array of pointers to links
+ int link_list_count_; ///< Number of links
+ int link_list_alloc_; ///< Allocated size of link_list array
+ // Target name to line mapping (simple linear search)
+ struct Target { char *name; int line; };
+ Target *targets_; ///< Array of target names and their line positions
+ int targets_count_; ///< Number of targets
+ int targets_alloc_; ///< Allocated size of targets array
int topline_; ///< Vertical offset of document, measure in pixels
int leftline_; ///< Horizontal offset of document, measure in pixels
@@ -247,14 +279,15 @@ public:
// HTML source and raw data, getter
void free_data();
- std::shared_ptr<Link> find_link(int, int);
- void follow_link(std::shared_ptr<Link>);
+ Link *find_link(int, int);
+ void follow_link(Link *linkp);
// HTML interpretation and formatting
Text_Block *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0);
- void add_link(const std::string &link, int xx, int yy, int ww, int hh);
- void add_target(const std::string &n, int yy);
+ void add_link(const char *link, int xx, int yy, int ww, int hh);
+ void add_target(const char *n, int yy);
+ int find_target(const char *name);
int do_align(Text_Block *block, int line, int xx, int a, int &l);
void format();
void format_table(int *table_width, int *columns, const char *table);
@@ -369,8 +402,8 @@ int Fl_Help_View::Impl::current_pos_ = 0;
//
static int quote_char(const char *);
-static std::string to_lower(const std::string &str);
-static size_t url_scheme(const std::string &url, bool skip_slashes=false);
+static char *to_lower(const char *str); // caller must free()
+static size_t url_scheme(const char *url, bool skip_slashes=false);
static const char *vanilla(const char *p, const char *end);
static uint32_t command(const char *cmd);
@@ -434,30 +467,71 @@ static Fl_Menu_Item rmb_menu[] = {
// ---- Helper class to manage margins in Fl_Help_View
void Fl_Help_View::Impl::Margin_Stack::clear() {
- margins_.clear();
- margins_.push_back(4); // default margin
+ count_ = 1;
+ margins_[0] = 4; // default margin
}
int Fl_Help_View::Impl::Margin_Stack::current() const {
- return margins_.back();
+ return margins_[count_ - 1];
}
int Fl_Help_View::Impl::Margin_Stack::pop() {
- if (margins_.size() > 1) {
- margins_.pop_back();
+ if (count_ > 1) {
+ count_--;
}
- return margins_.back();
+ return margins_[count_ - 1];
}
int Fl_Help_View::Impl::Margin_Stack::push(int indent) {
int xx = current() + indent;
- margins_.push_back(xx);
+ if (count_ < MAX_MARGINS) {
+ margins_[count_++] = xx;
+ }
return xx;
}
// ---- Helper class HV_Edit_Buffer to ease buffer management
+Fl_Help_View::Impl::Edit_Buffer::Edit_Buffer() {
+ buf_ = 0;
+ len_ = 0;
+ alloc_ = 0;
+}
+
+Fl_Help_View::Impl::Edit_Buffer::~Edit_Buffer() {
+ if (buf_) free(buf_);
+}
+
+void Fl_Help_View::Impl::Edit_Buffer::ensure(int needed) {
+ int total = len_ + needed + 1;
+ if (total > alloc_) {
+ int newalloc = alloc_ ? alloc_ * 2 : 64;
+ while (newalloc < total) newalloc *= 2;
+ buf_ = (char *)realloc(buf_, newalloc);
+ alloc_ = newalloc;
+ }
+}
+
+void Fl_Help_View::Impl::Edit_Buffer::clear() {
+ len_ = 0;
+ if (buf_) buf_[0] = '\0';
+}
+
+void Fl_Help_View::Impl::Edit_Buffer::append(const char *s, int n) {
+ ensure(n);
+ memcpy(buf_ + len_, s, n);
+ len_ += n;
+ buf_[len_] = '\0';
+}
+
+Fl_Help_View::Impl::Edit_Buffer &Fl_Help_View::Impl::Edit_Buffer::operator+=(char c) {
+ ensure(1);
+ buf_[len_++] = c;
+ buf_[len_] = '\0';
+ return *this;
+}
+
// Append one Unicode character (code point) to the buffer.
// The Unicode character \p ucs is converted to UTF-8 and appended to
// the buffer.
@@ -527,7 +601,7 @@ void Fl_Help_View::Impl::Font_Style::set(Fl_Font afont, Fl_Fontsize asize, Fl_Co
\param[in] c color to apply
*/
void Fl_Help_View::Impl::Font_Stack::init(Fl_Font f, Fl_Fontsize s, Fl_Color c) {
- elts_.clear();
+ count_ = 0;
push(f, s, c);
}
@@ -540,7 +614,7 @@ void Fl_Help_View::Impl::Font_Stack::init(Fl_Font f, Fl_Fontsize s, Fl_Color c)
\note This function does not pop the stack, it just returns the top element.
*/
void Fl_Help_View::Impl::Font_Stack::top(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c) {
- elts_.back().get(f, s, c);
+ elts_[count_ - 1].get(f, s, c);
}
@@ -552,7 +626,9 @@ void Fl_Help_View::Impl::Font_Stack::top(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c
\param[in] c color to apply
*/
void Fl_Help_View::Impl::Font_Stack::push(Fl_Font f, Fl_Fontsize s, Fl_Color c) {
- elts_.push_back(Font_Style(f, s, c));
+ if (count_ < MAX_FONTS) {
+ elts_[count_++].set(f, s, c);
+ }
fl_font(f, s);
fl_color(c);
}
@@ -569,8 +645,8 @@ void Fl_Help_View::Impl::Font_Stack::push(Fl_Font f, Fl_Fontsize s, Fl_Color c)
but the top element will be applied again.
*/
void Fl_Help_View::Impl::Font_Stack::pop(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c) {
- if (elts_.size() > 1)
- elts_.pop_back();
+ if (count_ > 1)
+ count_--;
top(f, s, c);
fl_font(f, s);
fl_color(c);
@@ -581,8 +657,8 @@ void Fl_Help_View::Impl::Font_Stack::pop(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c
\brief Gets the current count of font style elements in the stack.
\return stack size in number of elements
*/
-size_t Fl_Help_View::Impl::Font_Stack::count() const {
- return elts_.size();
+int Fl_Help_View::Impl::Font_Stack::count() const {
+ return count_;
}
@@ -664,22 +740,55 @@ void Fl_Help_View::Impl::free_data() {
value_ = 0;
}
- blocks_ .clear();
- link_list_.clear();
- target_line_map_.clear();
+ // Free blocks array
+ if (blocks_) {
+ free(blocks_);
+ blocks_ = 0;
+ }
+ blocks_count_ = 0;
+ blocks_alloc_ = 0;
+
+ // Free link list
+ if (link_list_) {
+ int i;
+ for (i = 0; i < link_list_count_; i++) {
+ delete link_list_[i];
+ }
+ free(link_list_);
+ link_list_ = 0;
+ }
+ link_list_count_ = 0;
+ link_list_alloc_ = 0;
+
+ // Free targets
+ if (targets_) {
+ int i;
+ for (i = 0; i < targets_count_; i++) {
+ if (targets_[i].name) free(targets_[i].name);
+ }
+ free(targets_);
+ targets_ = 0;
+ }
+ targets_count_ = 0;
+ targets_alloc_ = 0;
+
+ // Free directory and filename
+ if (directory_) { free(directory_); directory_ = 0; }
+ if (filename_) { free(filename_); filename_ = 0; }
}
/**
\brief Find out if the mouse is over a hyperlink and return the link data.
\parm[in] xx, yy Pixel coordinates inside the widget.
- \return Shared pointer to the link if found, 0 otherwise.
+ \return Pointer to the link if found, 0 otherwise.
*/
-std::shared_ptr<Fl_Help_View::Impl::Link> Fl_Help_View::Impl::find_link(int xx, int yy)
+Fl_Help_View::Impl::Link *Fl_Help_View::Impl::find_link(int xx, int yy)
{
- for (auto &link : link_list_) {
- if (link->box.contains(xx, yy)) {
- return link;
+ int i;
+ for (i = 0; i < link_list_count_; i++) {
+ if (link_list_[i]->box.contains(xx, yy)) {
+ return link_list_[i];
}
}
return 0;
@@ -690,54 +799,65 @@ std::shared_ptr<Fl_Help_View::Impl::Link> Fl_Help_View::Impl::find_link(int xx,
\brief Follow a link and load the target document or scroll to the target.
This function clears the current selection and loads a new document or
scrolls to a target line in the current document.
- \param linkp Shared pointer to the link to follow.
+ \param linkp Pointer to the link to follow.
*/
-void Fl_Help_View::Impl::follow_link(std::shared_ptr<Link> linkp)
+void Fl_Help_View::Impl::follow_link(Link *linkp)
{
clear_selection();
view.set_changed();
- std::string target = linkp->target;; // Current target
- if ( (linkp->filename_ != filename_) && !linkp->filename_.empty() ) {
+ // Helper to check if filename differs from current
+ int filename_differs = 0;
+ if (linkp->filename_ && linkp->filename_[0]) {
+ if (!filename_ || strcmp(linkp->filename_, filename_) != 0) {
+ filename_differs = 1;
+ }
+ }
+
+ if (filename_differs) {
// Load the new document, if the filename is different
- std::string url;
+ char url[FL_PATH_MAX * 2];
+ url[0] = '\0';
+
size_t directory_scheme_length = url_scheme(directory_);
size_t filename_scheme_length = url_scheme(linkp->filename_);
+
if ( (directory_scheme_length > 0) && (filename_scheme_length == 0) ) {
// If directory_ starts with a scheme (e.g.ftp:), but linkp->filename_ does not:
if (linkp->filename_[0] == '/') {
// If linkp->filename_ is absolute...
- url = directory_.substr(0, directory_scheme_length) + linkp->filename_;;
+ snprintf(url, sizeof(url), "%.*s%s", (int)directory_scheme_length, directory_, linkp->filename_);
} else {
// If linkp->filename_ is relative, the URL is the directory_ plus the filename
- url = directory_ + "/" + linkp->filename_;
+ snprintf(url, sizeof(url), "%s/%s", directory_ ? directory_ : "", linkp->filename_);
}
} else if (linkp->filename_[0] != '/' && (filename_scheme_length == 0)) {
// If the filename is relative and does not start with a scheme (ftp: , etc.)...
- if (!directory_.empty()) {
+ if (directory_ && directory_[0]) {
// If we have a current directory, use that as the base for the URL
- url = directory_ + "/" + linkp->filename_;
+ snprintf(url, sizeof(url), "%s/%s", directory_, linkp->filename_);
} else {
// If we do not have a current directory, use the application's current working directory
- char dir[FL_PATH_MAX]; // Current directory (static size ok until we have fl_getcwd_std()
+ char dir[FL_PATH_MAX];
fl_getcwd(dir, sizeof(dir));
- url = "file:" + std::string(dir) + "/" + linkp->filename_;
+ snprintf(url, sizeof(url), "file:%s/%s", dir, linkp->filename_);
}
} else {
// If the filename is absolute or starts with a protocol (e.g.ftp:), use it as is
- url = linkp->filename_;
+ snprintf(url, sizeof(url), "%s", linkp->filename_);
}
// If a target is specified, append it to the URL
- if (!linkp->target.empty()) {
- url += "#" + linkp->target;
+ if (linkp->target && linkp->target[0]) {
+ size_t len = strlen(url);
+ snprintf(url + len, sizeof(url) - len, "#%s", linkp->target);
}
- load(url.c_str());
+ load(url);
- } else if (!target.empty()) {
+ } else if (linkp->target && linkp->target[0]) {
// Keep the same document, scroll to the target line
- topline(target.c_str());
+ topline(linkp->target);
} else {
// No target, no filename, just scroll to the top of the document
topline(0);
@@ -769,8 +889,14 @@ Fl_Help_View::Impl::Text_Block *Fl_Help_View::Impl::add_block(
// printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n",
// s, xx, yy, ww, hh, border);
- blocks_.push_back(Text_Block()); // Add a new block to the vector
- temp = &blocks_.back();
+ // Grow the array if needed
+ if (blocks_count_ >= blocks_alloc_) {
+ int newalloc = blocks_alloc_ ? blocks_alloc_ * 2 : 64;
+ blocks_ = (Text_Block *)realloc(blocks_, newalloc * sizeof(Text_Block));
+ blocks_alloc_ = newalloc;
+ }
+
+ temp = &blocks_[blocks_count_++];
memset(temp, 0, sizeof(Text_Block));
temp->start = s;
@@ -791,24 +917,33 @@ Fl_Help_View::Impl::Text_Block *Fl_Help_View::Impl::add_block(
\param[in] link a filename, followed by a hash and a target. All parts are optional.
\param[in] xx, yy, ww, hh bounding box of the link text on screen
*/
-void Fl_Help_View::Impl::add_link(const std::string &link, int xx, int yy, int ww, int hh)
+void Fl_Help_View::Impl::add_link(const char *link, int xx, int yy, int ww, int hh)
{
- auto new_link = std::make_shared<Link>(); // Create a new link storage object.
+ Link *new_link = new Link(); // Create a new link storage object.
- new_link->box = { xx, yy, ww, hh };
+ new_link->box = Fl_Rect(xx, yy, ww, hh);
- size_t hash_pos = link.find('#'); // Find the hash character
- if (hash_pos != std::string::npos) {
+ const char *hash = link ? strchr(link, '#') : 0;
+ if (hash) {
// If a '#' is found, split the link into filename and target
- new_link->filename_ = link.substr(0, hash_pos);
- new_link->target = link.substr(hash_pos + 1);
+ int flen = (int)(hash - link);
+ new_link->filename_ = (char *)malloc(flen + 1);
+ memcpy(new_link->filename_, link, flen);
+ new_link->filename_[flen] = '\0';
+ new_link->target = fl_strdup(hash + 1);
} else {
// No '#' found, use the whole link as filename
- new_link->filename_ = link;
- new_link->target.clear();
+ new_link->filename_ = link ? fl_strdup(link) : 0;
+ new_link->target = 0;
}
- link_list_.push_back(new_link); // Add the link to the list.
+ // Grow the array if needed
+ if (link_list_count_ >= link_list_alloc_) {
+ int newalloc = link_list_alloc_ ? link_list_alloc_ * 2 : 32;
+ link_list_ = (Link **)realloc(link_list_, newalloc * sizeof(Link *));
+ link_list_alloc_ = newalloc;
+ }
+ link_list_[link_list_count_++] = new_link;
}
@@ -817,10 +952,39 @@ void Fl_Help_View::Impl::add_link(const std::string &link, int xx, int yy, int w
\param[in] n Name of target (string)
\param[in] yy line number of target position
*/
-void Fl_Help_View::Impl::add_target(const std::string &n, int yy)
+void Fl_Help_View::Impl::add_target(const char *n, int yy)
{
- std::string target = to_lower(n); // Convert target name to lower case
- target_line_map_[target] = yy; // Store the target line in the map
+ char *target = to_lower(n); // Convert target name to lower case
+
+ // Grow the array if needed
+ if (targets_count_ >= targets_alloc_) {
+ int newalloc = targets_alloc_ ? targets_alloc_ * 2 : 32;
+ targets_ = (Target *)realloc(targets_, newalloc * sizeof(Target));
+ targets_alloc_ = newalloc;
+ }
+
+ targets_[targets_count_].name = target;
+ targets_[targets_count_].line = yy;
+ targets_count_++;
+}
+
+/**
+ \brief Finds a target by name and returns its line position.
+ \param[in] name Name of target (string)
+ \return line number, or -1 if not found
+ */
+int Fl_Help_View::Impl::find_target(const char *name)
+{
+ char *lower = to_lower(name);
+ int i;
+ for (i = 0; i < targets_count_; i++) {
+ if (targets_[i].name && strcmp(targets_[i].name, lower) == 0) {
+ free(lower);
+ return targets_[i].line;
+ }
+ }
+ free(lower);
+ return -1;
}
@@ -860,7 +1024,7 @@ int Fl_Help_View::Impl::do_align(
if (line < 31)
line ++;
- while (l < (int)link_list_.size()) {
+ while (l < link_list_count_) {
link_list_[l]->box.x( link_list_[l]->box.x() + offset);
l++;
}
@@ -917,9 +1081,12 @@ void Fl_Help_View::Impl::format() {
Fl_Boxtype b = view.box() ? view.box() : FL_DOWN_BOX;
// Box to draw...
Margin_Stack margins; // Left margin stack...
- std::vector<int> OL_num; // if nonnegative, in OL mode and this is the item number
+ // Simple OL_num stack using fixed-size array
+ enum { MAX_OL_DEPTH = 64 };
+ int OL_num[MAX_OL_DEPTH];
+ int OL_num_count = 0;
- OL_num.push_back(-1);
+ OL_num[OL_num_count++] = -1;
DEBUG_FUNCTION(__LINE__,__FUNCTION__);
@@ -932,9 +1099,20 @@ void Fl_Help_View::Impl::format() {
{
// Reset state variables...
done = 1;
- blocks_.clear();
- link_list_.clear();
- target_line_map_.clear();
+ // Clear blocks
+ blocks_count_ = 0;
+ // Clear links
+ {
+ int li;
+ for (li = 0; li < link_list_count_; li++) delete link_list_[li];
+ link_list_count_ = 0;
+ }
+ // Clear targets
+ {
+ int ti;
+ for (ti = 0; ti < targets_count_; ti++) if (targets_[ti].name) free(targets_[ti].name);
+ targets_count_ = 0;
+ }
size_ = 0;
bgcolor_ = view.color();
textcolor_ = textcolor();
@@ -942,7 +1120,7 @@ void Fl_Help_View::Impl::format() {
tc = rc = bgcolor_;
- title_ = "Untitled";
+ strcpy(title_, "Untitled");
if (!value_)
return;
@@ -1097,10 +1275,13 @@ void Fl_Help_View::Impl::format() {
else if (buf.cmp("TITLE"))
{
// Copy the title in the document...
- title_.clear();
- for ( ; *ptr != '<' && *ptr; ptr++) {
- title_.push_back(*ptr);
+ int title_len = 0;
+ for ( ; *ptr != '<' && *ptr && title_len < (int)sizeof(title_) - 1; ptr++) {
+ title_[title_len++] = *ptr;
}
+ title_[title_len] = '\0';
+ // Skip any remaining title content
+ while (*ptr && *ptr != '<') ptr++;
buf.clear();
}
else if (buf.cmp("A"))
@@ -1163,10 +1344,10 @@ void Fl_Help_View::Impl::format() {
if (errno || endptr == attr || ol_num < 0)
ol_num = 1;
}
- OL_num.push_back(ol_num);
+ if (OL_num_count < MAX_OL_DEPTH) OL_num[OL_num_count++] = ol_num;
}
else if (buf.cmp("UL"))
- OL_num.push_back(-1);
+ if (OL_num_count < MAX_OL_DEPTH) OL_num[OL_num_count++] = -1;
if (buf.cmp("UL") ||
buf.cmp("OL") ||
@@ -1261,10 +1442,10 @@ void Fl_Help_View::Impl::format() {
if (buf.cmp("LI")) {
block->ol = 0;
- if (OL_num.size() && (OL_num.back() >= 0)) {
+ if (OL_num_count > 0 && OL_num[OL_num_count - 1] >= 0) {
block->ol = 1;
- block->ol_num = OL_num.back();
- OL_num.back()++;
+ block->ol_num = OL_num[OL_num_count - 1];
+ OL_num[OL_num_count - 1]++;
}
}
@@ -1296,7 +1477,7 @@ void Fl_Help_View::Impl::format() {
if (buf.cmp("/OL") ||
buf.cmp("/UL")) {
- if (OL_num.size()) OL_num.pop_back();
+ if (OL_num_count > 0) OL_num_count--;
}
if (buf.cmp("/UL") ||
@@ -1444,9 +1625,9 @@ void Fl_Help_View::Impl::format() {
for (i = 0, ww = -6; i < colspan; i ++)
ww += columns[column + i] + 6;
- if (block->end == block->start && blocks_.size() > 1)
+ if (block->end == block->start && blocks_count_ > 1)
{
- blocks_.pop_back();
+ blocks_count_--;
block --;
}
@@ -2350,62 +2531,64 @@ Fl_Color Fl_Help_View::Impl::get_color(const char *n, Fl_Color c)
*/
Fl_Shared_Image *Fl_Help_View::Impl::get_image(const char *name, int W, int H)
{
- std::string url;
+ char url[FL_PATH_MAX * 2];
Fl_Shared_Image *ip; // Image pointer...
if (!name || !name[0]) {
// No image name given, return broken image
return (Fl_Shared_Image *)&broken_image;
}
- std::string imagename = name;
+ const char *imagename = name;
size_t directory_scheme_length = url_scheme(directory_);
size_t imagename_scheme_length = url_scheme(imagename);
+ url[0] = '\0';
+
// See if the image can be found...
if ( (directory_scheme_length > 0) && (imagename_scheme_length == 0) ) {
// If directory_ starts with a scheme (e.g.ftp:), but linkp->filename_ does not:
if (imagename[0] == '/') {
// If linkp->filename_ is absolute...
- url = directory_.substr(0, directory_scheme_length) + imagename;;
+ snprintf(url, sizeof(url), "%.*s%s", (int)directory_scheme_length, directory_, imagename);
} else {
// If linkp->filename_ is relative, the URL is the directory_ plus the filename
- url = directory_ + "/" + imagename;
+ snprintf(url, sizeof(url), "%s/%s", directory_ ? directory_ : "", imagename);
}
} else if (imagename[0] != '/' && (imagename_scheme_length == 0)) {
// If the filename is relative and does not start with a scheme (ftp: , etc.)...
- if (!directory_.empty()) {
+ if (directory_ && directory_[0]) {
// If we have a current directory, use that as the base for the URL
- url = directory_ + "/" + imagename;
+ snprintf(url, sizeof(url), "%s/%s", directory_, imagename);
} else {
// If we do not have a current directory, use the application's current working directory
- char dir[FL_PATH_MAX]; // Current directory (static size ok until we have fl_getcwd_std()
+ char dir[FL_PATH_MAX];
fl_getcwd(dir, sizeof(dir));
- url = "file:" + std::string(dir) + "/" + imagename;
+ snprintf(url, sizeof(url), "file:%s/%s", dir, imagename);
}
} else {
// If the filename is absolute or starts with a protocol (e.g.ftp:), use it as is
- url = imagename;
+ snprintf(url, sizeof(url), "%s", imagename);
}
if (link_) {
- const char *n = (*link_)(&view, url.c_str());
+ const char *n = (*link_)(&view, url);
if (n == 0)
return 0;
- url = n;
+ snprintf(url, sizeof(url), "%s", n);
}
- if (url.empty()) return 0;
+ if (!url[0]) return 0;
// If the URL starts with "file:", remove it
- if (url.find("file:") == 0) {
- url = url.substr(5);
+ if (strncmp(url, "file:", 5) == 0) {
+ memmove(url, url + 5, strlen(url + 5) + 1);
}
if (initial_load) {
- if ((ip = Fl_Shared_Image::get(url.c_str(), W, H)) == 0) {
+ if ((ip = Fl_Shared_Image::get(url, W, H)) == 0) {
ip = (Fl_Shared_Image *)&broken_image;
}
} else { // draw or resize
- if ((ip = Fl_Shared_Image::find(url.c_str(), W, H)) == 0) {
+ if ((ip = Fl_Shared_Image::find(url, W, H)) == 0) {
ip = (Fl_Shared_Image *)&broken_image;
} else {
ip->release();
@@ -2697,7 +2880,7 @@ void Fl_Help_View::Impl::draw()
fl_color(textcolor_);
// Draw all visible blocks...
- for (i = 0, block = &blocks_[0]; i < (int)blocks_.size(); i ++, block ++)
+ for (i = 0, block = &blocks_[0]; i < (int)blocks_count_; i ++, block ++)
if ((block->y + block->h) >= topline_ && block->y < (topline_ + view.h()))
{
line = 0;
@@ -3215,6 +3398,7 @@ Fl_Help_View::Fl_Help_View(int xx, int yy, int ww, int hh, const char *l)
*/
Fl_Help_View::~Fl_Help_View()
{
+ delete impl_;
}
@@ -3234,7 +3418,7 @@ int Fl_Help_View::handle(int event)
*/
int Fl_Help_View::Impl::handle(int event)
{
- static std::shared_ptr<Link> linkp = 0; // currently clicked link
+ static Link *linkp = 0; // currently clicked link
int xx = Fl::event_x() - view.x() + leftline_;
int yy = Fl::event_y() - view.y() + topline_;
@@ -3454,10 +3638,14 @@ int Fl_Help_View::Impl::load(const char *f)
{
FILE *fp; // File to read from
long len; // Length of file
- std::string target; // Target in file
- std::string localname; // Local filename
- std::string error; // Error buffer
- std::string newname; // New filename buffer
+ char target[FL_PATH_MAX]; // Target in file
+ char localname[FL_PATH_MAX]; // Local filename
+ char error[FL_PATH_MAX * 2]; // Error buffer
+ char newname[FL_PATH_MAX]; // New filename buffer
+
+ target[0] = '\0';
+ localname[0] = '\0';
+ newname[0] = '\0';
// printf("load(%s)\n",f); fflush(stdout);
@@ -3472,41 +3660,43 @@ int Fl_Help_View::Impl::load(const char *f)
if ( fl_open_uri(f, urimsg, sizeof(urimsg)) == 0 ) {
clear_selection();
- newname = f;
- size_t hash_pos = newname.rfind('#');
- if (hash_pos != std::string::npos) {
- target = newname.substr(hash_pos + 1);
- newname.resize(hash_pos);
+ strlcpy(newname, f, sizeof(newname));
+ char *hash = strrchr(newname, '#');
+ if (hash) {
+ strlcpy(target, hash + 1, sizeof(target));
+ *hash = '\0';
}
if (link_) {
- const char *n = (*link_)(&view, newname.c_str());
+ const char *n = (*link_)(&view, newname);
if (n == 0)
return 0;
- localname = n;
+ strlcpy(localname, n, sizeof(localname));
} else {
- localname = newname;
+ strlcpy(localname, newname, sizeof(localname));
}
free_data();
- filename_ = newname;
+ filename_ = fl_strdup(newname);
// Note: We do not support Windows backslashes, since they are illegal
// in URLs...
- directory_ = newname;
- size_t slash_pos = directory_.rfind('/');
- if (slash_pos == std::string::npos) {
- directory_.clear();
- } else if ((slash_pos > 0) && (directory_[slash_pos-1] != '/')) {
- directory_.resize(slash_pos);
+ directory_ = fl_strdup(newname);
+ char *slash = strrchr(directory_, '/');
+ if (!slash) {
+ free(directory_);
+ directory_ = 0;
+ } else if ((slash > directory_) && (*(slash-1) != '/')) {
+ *slash = '\0';
}
- error = "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
- "<BODY><H1>Error</H1>"
- "<P>Unable to follow the link \""
- + std::string(f) + "\" - " + std::string(urimsg) + ".</P></BODY>";
- value(error.c_str());
+ snprintf(error, sizeof(error),
+ "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
+ "<BODY><H1>Error</H1>"
+ "<P>Unable to follow the link \"%s\" - %s.</P></BODY>",
+ f, urimsg);
+ value(error);
return -1;
} else {
return 0;
@@ -3515,42 +3705,43 @@ int Fl_Help_View::Impl::load(const char *f)
clear_selection();
- newname = f;
- size_t hash_pos = newname.rfind('#');
- if (hash_pos != std::string::npos) {
- target = newname.substr(hash_pos + 1);
- newname.resize(hash_pos);
+ strlcpy(newname, f, sizeof(newname));
+ char *hash = strrchr(newname, '#');
+ if (hash) {
+ strlcpy(target, hash + 1, sizeof(target));
+ *hash = '\0';
}
if (link_) {
- const char *n = (*link_)(&view, newname.c_str());
+ const char *n = (*link_)(&view, newname);
if (n == 0)
return -1;
- localname = n;
+ strlcpy(localname, n, sizeof(localname));
} else {
- localname = newname;
+ strlcpy(localname, newname, sizeof(localname));
}
free_data();
- filename_ = newname;
- directory_ = newname;
+ filename_ = fl_strdup(newname);
+ directory_ = fl_strdup(newname);
// Note: We do not support Windows backslashes, since they are illegal
// in URLs...
- size_t slash_pos = directory_.rfind('/');
- if (slash_pos == std::string::npos) {
- directory_.clear();
- } else if ((slash_pos > 0) && (directory_[slash_pos-1] != '/')) {
- directory_.resize(slash_pos);
+ char *slash = strrchr(directory_, '/');
+ if (!slash) {
+ free(directory_);
+ directory_ = 0;
+ } else if ((slash > directory_) && (*(slash-1) != '/')) {
+ *slash = '\0';
}
- if (localname.find("file:") == 0) {
- localname.erase(0, 5); // Adjust for local filename...
+ if (strncmp(localname, "file:", 5) == 0) {
+ memmove(localname, localname + 5, strlen(localname + 5) + 1);
}
int ret = 0;
- if ((fp = fl_fopen(localname.c_str(), "rb")) != 0)
+ if ((fp = fl_fopen(localname, "rb")) != 0)
{
fseek(fp, 0, SEEK_END);
len = ftell(fp);
@@ -3562,11 +3753,12 @@ int Fl_Help_View::Impl::load(const char *f)
}
else
{
- error = "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
- "<BODY><H1>Error</H1>"
- "<P>Unable to follow the link \"" +localname + "\" - "
- + strerror(errno) + ".</P></BODY>";
- value_ = fl_strdup(error.c_str());
+ snprintf(error, sizeof(error),
+ "<HTML><HEAD><TITLE>Error</TITLE></HEAD>"
+ "<BODY><H1>Error</H1>"
+ "<P>Unable to follow the link \"%s\" - %s.</P></BODY>",
+ localname, strerror(errno));
+ value_ = fl_strdup(error);
ret = -1;
}
@@ -3574,8 +3766,8 @@ int Fl_Help_View::Impl::load(const char *f)
format();
initial_load = 0;
- if (!target.empty())
- topline(target.c_str());
+ if (target[0])
+ topline(target);
else
topline(0);
@@ -3626,7 +3818,7 @@ int Fl_Help_View::Impl::find(const char *s, int p)
if (p < 0 || p >= (int)strlen(value_)) p = 0;
// Look for the string...
- for (i = (int)blocks_.size(), b = &blocks_[0]; i > 0; i--, b++) {
+ for (i = (int)blocks_count_, b = &blocks_[0]; i > 0; i--, b++) {
if (b->end < (value_ + p))
continue;
@@ -3761,10 +3953,10 @@ const char *Fl_Help_View::filename() const {
\see Fl_Help_View::filename() const
*/
const char *Fl_Help_View::Impl::filename() const {
- if (filename_.empty())
+ if (!filename_ || !filename_[0])
return 0;
else
- return filename_.c_str();
+ return filename_;
}
@@ -3785,10 +3977,10 @@ const char *Fl_Help_View::directory() const {
\see Fl_Help_View::directory() const
*/
const char *Fl_Help_View::Impl::directory() const {
- if (directory_.empty())
+ if (!directory_ || !directory_[0])
return 0;
else
- return directory_.c_str();
+ return directory_;
}
@@ -3810,7 +4002,7 @@ const char *Fl_Help_View::title() const {
*/
const char *Fl_Help_View::Impl::title() const
{
- return title_.c_str();
+ return title_;
}
@@ -3830,11 +4022,10 @@ void Fl_Help_View::topline(const char *anchor) {
*/
void Fl_Help_View::Impl::topline(const char *anchor)
{
- std::string target_name = to_lower(anchor); // Convert to lower case
- auto tl = target_line_map_.find(target_name);
- if (tl != target_line_map_.end()) {
+ int line = find_target(anchor);
+ if (line >= 0) {
// Found the target name, scroll to the line
- topline(tl->second);
+ topline(line);
} else {
// Scroll to the top.
topline(0);
@@ -4361,12 +4552,15 @@ static int quote_char(const char *p) {
// But as with everything in HTML, nobody cares and everybody does what they
// want anyway ;-) .
-static std::string to_lower(const std::string &str) {
- std::string lower_str;
- lower_str.reserve(str.size());
- for (char c : str) {
- lower_str += fl_tolower(c);
+static char *to_lower(const char *str) {
+ if (!str) return 0;
+ int len = (int)strlen(str);
+ char *lower_str = (char *)malloc(len + 1);
+ int i;
+ for (i = 0; i < len; i++) {
+ lower_str[i] = fl_tolower(str[i]);
}
+ lower_str[len] = '\0';
return lower_str;
}
@@ -4377,21 +4571,23 @@ static std::string to_lower(const std::string &str) {
\return 0 if not found, otherwise the length of the scheme string including
the following '/' characters.
*/
-static size_t url_scheme(const std::string &url, bool skip_slashes)
+static size_t url_scheme(const char *url, bool skip_slashes)
{
+ if (!url) return 0;
+ size_t len = strlen(url);
// First skip all ascii letters and digits
size_t pos = 0;
- while ( (pos < url.size()) && ( isalnum(url[pos]) || (url[pos] == '+') || (url[pos] == '-') || (url[pos] == '.') )) {
+ while ( (pos < len) && ( isalnum(url[pos]) || (url[pos] == '+') || (url[pos] == '-') || (url[pos] == '.') )) {
pos++;
}
// Next, check for the ':' character
- if ( (pos < url.size()) && (url[pos] == ':') ) {
+ if ( (pos < len) && (url[pos] == ':') ) {
pos++; // Skip the ':' character
if (skip_slashes) {
// If found, skip up to two '/' characters as well
- if ( (pos < url.size()) && (url[pos] == '/') ) {
+ if ( (pos < len) && (url[pos] == '/') ) {
pos++; // Skip the first '/' character
- if ( (pos < url.size()) && (url[pos] == '/') ) {
+ if ( (pos < len) && (url[pos] == '/') ) {
pos++; // Skip the second '/' character
}
}
diff --git a/src/Fl_Native_File_Chooser_Kdialog.H b/src/Fl_Native_File_Chooser_Kdialog.H
index b90f77ca4..6500f563e 100644
--- a/src/Fl_Native_File_Chooser_Kdialog.H
+++ b/src/Fl_Native_File_Chooser_Kdialog.H
@@ -24,7 +24,6 @@
*/
#include <FL/Fl_Native_File_Chooser.H>
-#include <string>
class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK_Driver {
friend class Fl_Native_File_Chooser;
@@ -46,7 +45,7 @@ class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK
int count() const FL_OVERRIDE;
const char *filename() const FL_OVERRIDE;
const char *filename(int i) const FL_OVERRIDE;
- virtual void build_command(std::string& command);
+ virtual void build_command(char *command, int maxlen);
int show() FL_OVERRIDE;
char *parse_filter(const char *f);
const char *filter() const FL_OVERRIDE;
@@ -58,7 +57,7 @@ class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK
const char *directory() const FL_OVERRIDE;
void title(const char *val) FL_OVERRIDE;
const char *title() const FL_OVERRIDE;
- void shell_quote(std::string& s);
+ void shell_quote(const char *in, char *out, int maxlen);
};
/**
diff --git a/src/Fl_Native_File_Chooser_Kdialog.cxx b/src/Fl_Native_File_Chooser_Kdialog.cxx
index d0580162d..68cb4729e 100644
--- a/src/Fl_Native_File_Chooser_Kdialog.cxx
+++ b/src/Fl_Native_File_Chooser_Kdialog.cxx
@@ -73,7 +73,7 @@ static int fnfc_dispatch(int /*event*/, Fl_Window* /*win*/) {
}
-void Fl_Kdialog_Native_File_Chooser_Driver::build_command(std::string& command) {
+void Fl_Kdialog_Native_File_Chooser_Driver::build_command(char *command, int maxlen) {
const char *option;
switch (_btype) {
case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
@@ -103,23 +103,21 @@ void Fl_Kdialog_Native_File_Chooser_Driver::build_command(std::string& command)
}
// Build command
- command = "kdialog";
+ int pos = 0;
+ pos += snprintf(command + pos, maxlen - pos, "kdialog");
if (_title) {
- std::string quoted_title = _title; shell_quote(quoted_title);
- command += " --title ";
- command += quoted_title;
+ char quoted_title[FL_PATH_MAX];
+ shell_quote(_title, quoted_title, sizeof(quoted_title));
+ pos += snprintf(command + pos, maxlen - pos, " --title %s", quoted_title);
}
- command += " ";
- command += option;
- command += " ";
- command += preset;
+ pos += snprintf(command + pos, maxlen - pos, " %s %s", option, preset);
if (_parsedfilt) {
- std::string quoted_filt = _parsedfilt; shell_quote(quoted_filt); // NOTE: orig code used double quoting -erco 1/10/24
- command += " ";
- command += quoted_filt;
+ char quoted_filt[FL_PATH_MAX * 2];
+ shell_quote(_parsedfilt, quoted_filt, sizeof(quoted_filt));
+ pos += snprintf(command + pos, maxlen - pos, " %s", quoted_filt);
}
- command += " 2> /dev/null"; // get rid of stderr
- // printf("command = %s\n", command.c_str());
+ snprintf(command + pos, maxlen - pos, " 2> /dev/null");
+ // printf("command = %s\n", command);
}
@@ -146,10 +144,10 @@ int Fl_Kdialog_Native_File_Chooser_Driver::show() {
return retval;
}
- std::string command;
- build_command(command);
- //fprintf(stderr, "DEBUG: POPEN: %s\n", command.c_str());
- FILE *pipe = popen(command.c_str(), "r");
+ char command[FL_PATH_MAX * 4];
+ build_command(command, sizeof(command));
+ //fprintf(stderr, "DEBUG: POPEN: %s\n", command);
+ FILE *pipe = popen(command, "r");
fnfc_pipe_struct data;
data.all_files = NULL;
if (pipe) {
@@ -307,17 +305,29 @@ const char *Fl_Kdialog_Native_File_Chooser_Driver::title() const {
return _title;
}
-// Add shell quotes around string 's'.
+// Add shell quotes around string 'in', store result in 'out'.
// Handles quoting embedded quotes.
//
-void Fl_Kdialog_Native_File_Chooser_Driver::shell_quote(std::string& s) {
- std::string out = "'"; // leading quote
- for (int t=0; t<(int)s.size(); t++) {
- if (s[t] == '\'') out += "'\"'\"'"; // quote any quotes
- else out += s[t];
+void Fl_Kdialog_Native_File_Chooser_Driver::shell_quote(const char *in, char *out, int maxlen) {
+ int pos = 0;
+ out[pos++] = '\''; // leading quote
+ while (*in && pos < maxlen - 6) { // leave room for closing quote + null
+ if (*in == '\'') {
+ // quote any quotes: replace ' with '"'"'
+ if (pos + 5 < maxlen) {
+ out[pos++] = '\'';
+ out[pos++] = '"';
+ out[pos++] = '\'';
+ out[pos++] = '"';
+ out[pos++] = '\'';
+ }
+ } else {
+ out[pos++] = *in;
+ }
+ in++;
}
- out += "'"; // trailing quote
- s = out;
+ out[pos++] = '\''; // trailing quote
+ out[pos] = '\0';
}
/**
diff --git a/src/Fl_Native_File_Chooser_Zenity.H b/src/Fl_Native_File_Chooser_Zenity.H
index 6d9804341..708ab51fe 100644
--- a/src/Fl_Native_File_Chooser_Zenity.H
+++ b/src/Fl_Native_File_Chooser_Zenity.H
@@ -30,8 +30,8 @@ class Fl_Zenity_Native_File_Chooser_Driver : public Fl_Kdialog_Native_File_Choos
static bool did_find_zenity;
static bool have_looked_for_zenity;
Fl_Zenity_Native_File_Chooser_Driver(int val);
- void append_filter(std::string& command);
- void build_command(std::string& command) FL_OVERRIDE;
+ void append_filter(char *command, int *pos, int maxlen);
+ void build_command(char *command, int maxlen);
};
/**
diff --git a/src/Fl_Native_File_Chooser_Zenity.cxx b/src/Fl_Native_File_Chooser_Zenity.cxx
index c765b8827..b4a75b62e 100644
--- a/src/Fl_Native_File_Chooser_Zenity.cxx
+++ b/src/Fl_Native_File_Chooser_Zenity.cxx
@@ -36,8 +36,7 @@ bool Fl_Zenity_Native_File_Chooser_Driver::have_looked_for_zenity = false;
Fl_Zenity_Native_File_Chooser_Driver::Fl_Zenity_Native_File_Chooser_Driver(int val) : Fl_Kdialog_Native_File_Chooser_Driver(val) {
}
-void Fl_Zenity_Native_File_Chooser_Driver::append_filter(std::string& ret_command) {
- // TODO: This could probably be simplified + toughened with std::string -erco 1/10/24
+void Fl_Zenity_Native_File_Chooser_Driver::append_filter(char *ret_command, int *pos, int maxlen) {
int l;
int lcommand = 10000;
char *command = new char[lcommand];
@@ -46,7 +45,7 @@ void Fl_Zenity_Native_File_Chooser_Driver::append_filter(std::string& ret_comman
char *p = strtok(parsed_filter_copy, "\n");
while (p) {
char *op = strchr(p, '(');
- l = strlen(command);
+ l = (int)strlen(command);
snprintf(command+l, lcommand-l, " --file-filter='%s|", p);
char *cp = strchr(p, ')');
*cp = 0;
@@ -55,28 +54,30 @@ void Fl_Zenity_Native_File_Chooser_Driver::append_filter(std::string& ret_comman
*ob = 0;
char *cb = strchr(ob+1, ']');
char aux[100];
- for (char *q = ob+1; q < cb; q++) {
+ char *q;
+ for (q = ob+1; q < cb; q++) {
strcpy(aux, op+1);
- int la = strlen(aux);
+ int la = (int)strlen(aux);
aux[la++] = *q;
- if (cb < cp-1) { strcpy(aux+la, cb+1); la += strlen(cb+1); }
+ if (cb < cp-1) { strcpy(aux+la, cb+1); la += (int)strlen(cb+1); }
aux[la] = 0;
- l = strlen(command);
+ l = (int)strlen(command);
snprintf(command+l, lcommand-l, " %s", aux);
}
strcat(command, "'");
} else {
- l = strlen(command);
+ l = (int)strlen(command);
snprintf(command+l, lcommand-l, "%s'", op+1);
}
p = strtok(NULL, "\n");
}
free(parsed_filter_copy);
- ret_command += command; // append to parent's std::string
+ // append to ret_command
+ *pos += snprintf(ret_command + *pos, maxlen - *pos, "%s", command);
delete [] command;
}
-void Fl_Zenity_Native_File_Chooser_Driver::build_command(std::string& command) {
+void Fl_Zenity_Native_File_Chooser_Driver::build_command(char *command, int maxlen) {
const char *option;
switch (_btype) {
case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
@@ -100,34 +101,33 @@ void Fl_Zenity_Native_File_Chooser_Driver::build_command(std::string& command) {
}
// Build preset
- std::string preset;
+ char preset[FL_PATH_MAX * 2] = "";
if (_preset_file) {
- std::string quoted_filename = _preset_file; shell_quote(quoted_filename);
- preset = "--filename=";
- preset += quoted_filename;
+ char quoted_filename[FL_PATH_MAX];
+ shell_quote(_preset_file, quoted_filename, sizeof(quoted_filename));
+ snprintf(preset, sizeof(preset), "--filename=%s", quoted_filename);
} else if (_directory) {
// This doesn't actually seem to do anything, but supply it anyway.
- std::string quoted_dir = _directory; shell_quote(quoted_dir);
- preset = "--filename=";
- preset += quoted_dir;
+ char quoted_dir[FL_PATH_MAX];
+ shell_quote(_directory, quoted_dir, sizeof(quoted_dir));
+ snprintf(preset, sizeof(preset), "--filename=%s", quoted_dir);
}
// Build command
- command = "zenity";
+ int pos = 0;
+ pos += snprintf(command + pos, maxlen - pos, "zenity");
if (_title) {
- std::string quoted_title = _title; shell_quote(quoted_title);
- command += " --title ";
- command += quoted_title;
+ char quoted_title[FL_PATH_MAX];
+ shell_quote(_title, quoted_title, sizeof(quoted_title));
+ pos += snprintf(command + pos, maxlen - pos, " --title %s", quoted_title);
}
- command += " ";
- command += option;
- if (preset != "") {
- command += " ";
- command += preset;
+ pos += snprintf(command + pos, maxlen - pos, " %s", option);
+ if (preset[0]) {
+ pos += snprintf(command + pos, maxlen - pos, " %s", preset);
}
- if (_parsedfilt) append_filter(command);
- command += " 2> /dev/null"; // get rid of stderr
- //printf("command = %s\n", command.c_str());
+ if (_parsedfilt) append_filter(command, &pos, maxlen);
+ snprintf(command + pos, maxlen - pos, " 2> /dev/null");
+ //printf("command = %s\n", command);
}
/**
diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx
index aa77a4e61..ca0b17916 100644
--- a/src/Fl_Preferences.cxx
+++ b/src/Fl_Preferences.cxx
@@ -28,8 +28,6 @@
#include <stdlib.h>
#include <stdarg.h>
-#include <string>
-
/*
The format of preferences files is not part of the FLTK specification
and intentionally undocumented in Doxygen. The following documentation is FOR
@@ -965,35 +963,6 @@ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue
}
/**
- 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). NUL characters in std::string
- are treated as the end of the text.
-
- \param[in] key name of entry
- \param[out] value returned from preferences or default value if none was set
- \param[in] defaultValue default value to be used if no preference was set
- \return 0 if the default value was used
- */
-char Fl_Preferences::get( const char *key, std::string &value, const std::string &defaultValue ) {
- const char *v = node->get( key );
- if (v) {
- if ( strchr( v, '\\' ) ) {
- char *text = decodeText( v );
- value = text;
- ::free(text);
- } else {
- value = v;
- }
- return 1;
- } else {
- value = defaultValue;
- return 0;
- }
-}
-
-/**
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 preference file.
@@ -1164,21 +1133,6 @@ char Fl_Preferences::set( const char *key, const void *data, int dsize ) {
}
/**
- 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 preference
- file. NUL characters in std::string are treated as the end of the text.
-
- \param[in] entry name of entry
- \param[in] value set this entry to value (stops at the first nul character).
- \return 0 if setting the value failed
- */
-char Fl_Preferences::set( const char *entry, const std::string &value ) {
- return set(entry, value.c_str());
-}
-
-/**
Returns the size of the value part of an entry.
\param[in] key name of entry
@@ -2119,24 +2073,3 @@ int Fl_Plugin_Manager::loadAll(const char *dirpath, const char *pattern) {
return 0;
}
-/**
- Return a list of all plugin klasses that have been registered so far.
- The returned strings can be used to crate a manager for the klass of
- plugins, which in turn can be used to list plugins for that klass.
- ```
- auto kl = Fl_Plugin_Manager::klass_list();
- for (auto &k: kl) {
- Fl_Plugin_Manager m { k.c_str() };
- std::cout << m.plugins() << "plugins have registered for klass" << k << std::endl;
- }
- ```
- \return a copy of a vector of strings
- */
-std::vector<std::string> Fl_Plugin_Manager::klass_list() {
- Fl_Preferences p(0, "plugins");
- std::vector<std::string> pm;
- for (int i = 0; i < p.groups(); i++) {
- pm.push_back(p.group(i));
- }
- return pm;
-}
diff --git a/src/Fl_Terminal.cxx b/src/Fl_Terminal.cxx
index fea9f4121..150cb6641 100644
--- a/src/Fl_Terminal.cxx
+++ b/src/Fl_Terminal.cxx
@@ -29,7 +29,6 @@
#include <string.h> // strlen
#include <stdarg.h> // vprintf, va_list
#include <assert.h>
-#include <string>
#include <FL/Fl.H>
#include <FL/Fl_Terminal.H>
@@ -3988,28 +3987,46 @@ int Fl_Terminal::handle(int e) {
\return A string allocated with strdup(3) which must be free'd, text is UTF-8.
*/
const char* Fl_Terminal::text(bool lines_below_cursor) const {
- std::string lines; // lines of text we'll return
+ // Dynamic buffer for lines of text we'll return
+ int buf_alloc = 4096;
+ int buf_len = 0;
+ char *lines = (char*)malloc(buf_alloc);
+ if (!lines) return 0;
+ lines[0] = '\0';
+
// See how many display rows we need to include
int disprows = lines_below_cursor ? disp_rows() - 1 // all display lines
: cursor_row(); // only lines up to cursor
// Start at top of 'in use' history, and walk to end of display
int srow = hist_use_srow(); // start row of text to return
int erow = srow + hist_use() + disprows; // end row of text to return
- for (int row=srow; row<=erow; row++) { // walk rows
+ int row;
+ for (row=srow; row<=erow; row++) { // walk rows
const Utf8Char *u8c = u8c_ring_row(row); // start of row
int trim = 0;
- for (int col=0; col<ring_cols(); col++,u8c++) { // walk cols in row
+ int col;
+ for (col=0; col<ring_cols(); col++,u8c++) { // walk cols in row
const char *s = u8c->text_utf8(); // first byte of char
- for (int i=0; i<u8c->length(); i++) lines += *s++; // append all bytes in multibyte char
+ int charlen = u8c->length();
+ // Ensure buffer has space
+ if (buf_len + charlen + 2 > buf_alloc) {
+ buf_alloc *= 2;
+ char *newbuf = (char*)realloc(lines, buf_alloc);
+ if (!newbuf) { free(lines); return 0; }
+ lines = newbuf;
+ }
+ int i;
+ for (i=0; i<charlen; i++) lines[buf_len++] = *s++; // append all bytes in multibyte char
// Count any trailing whitespace to trim
- if (u8c->length()==1 && s[-1]==' ') trim++; // trailing whitespace? trim
- else trim = 0; // non-whitespace? don't trim
+ if (charlen==1 && s[-1]==' ') trim++; // trailing whitespace? trim
+ else trim = 0; // non-whitespace? don't trim
}
// trim trailing whitespace from each line, if any
- if (trim) lines.resize(lines.size() - trim);
- lines += "\n";
+ if (trim) buf_len -= trim;
+ lines[buf_len++] = '\n';
}
- return fl_strdup(lines.c_str());
+ lines[buf_len] = '\0';
+ return lines; // caller must free()
}
/**
diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx
index 93bc2e42f..9aa099208 100644
--- a/src/Fl_Text_Buffer.cxx
+++ b/src/Fl_Text_Buffer.cxx
@@ -268,21 +268,6 @@ char *Fl_Text_Buffer::text() const {
/*
- This function copies verbose whatever is in front and after the gap into a
- single buffer.
- */
-std::string Fl_Text_Buffer::text_str() const {
- std::string t;
- if (mLength) {
- t.reserve(mLength);
- t.insert(0, mBuf, mGapStart);
- t.insert(mGapStart, mBuf+mGapEnd, mLength - mGapStart);
- }
- return t;
-}
-
-
-/*
Set the text buffer to a new string.
*/
void Fl_Text_Buffer::text(const char *t)
diff --git a/src/Fl_Timeout.cxx b/src/Fl_Timeout.cxx
index 4ba8a0f63..9aa89b839 100644
--- a/src/Fl_Timeout.cxx
+++ b/src/Fl_Timeout.cxx
@@ -344,17 +344,6 @@ int Fl_Timeout::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **da
return ret;
}
-std::vector<Fl::TimeoutData> Fl_Timeout::timeout_list() {
- std::vector<Fl::TimeoutData> v;
- const Fl_Timeout *t = first_timeout;
- while (t) {
- v.push_back( { t->time, t->callback, t->data } );
- t = t->next;
- }
- return v;
-}
-
-
/**
Remove the timeout from the active timer queue and push it onto
the stack of currently running callbacks.
diff --git a/src/Fl_Timeout.h b/src/Fl_Timeout.h
index 279935a71..8f2cc7a12 100644
--- a/src/Fl_Timeout.h
+++ b/src/Fl_Timeout.h
@@ -108,8 +108,7 @@ public:
static void add_timeout(double time, Fl_Timeout_Handler cb, void *data);
static void repeat_timeout(double time, Fl_Timeout_Handler cb, void *data);
static void remove_timeout(Fl_Timeout_Handler cb, void *data);
- static int remove_next_timeout(Fl_Timeout_Handler cb, void *data = NULL, void **data_return = NULL);
- static std::vector<Fl::TimeoutData> timeout_list();
+ static int remove_next_timeout(Fl_Timeout_Handler cb, void *data = 0, void **data_return = 0);
// Elapse timeouts, i.e. calculate new delay time of all timers.
// This does not call the timer callbacks.
diff --git a/src/Fl_Valuator.cxx b/src/Fl_Valuator.cxx
index 90fa23325..cb1f9dea9 100644
--- a/src/Fl_Valuator.cxx
+++ b/src/Fl_Valuator.cxx
@@ -191,15 +191,3 @@ int Fl_Valuator::format(char* buffer) {
return snprintf(buffer, 128, "%.*f", c, v);
}
-/**
- \brief C++11 API for Fl_Valuator::format(char* buffer).
- Users can override either version to change the format of the text output
- in the valuator.
- \return the formatted text of the current value
- \see Fl_Valuator::format(char* buffer)
- */
-std::string Fl_Valuator::format_str() {
- char buffer[129];
- int size = format(buffer);
- return std::string(buffer, size);
-}
diff --git a/src/Fl_Value_Input.cxx b/src/Fl_Value_Input.cxx
index c44386662..781d9fcdf 100644
--- a/src/Fl_Value_Input.cxx
+++ b/src/Fl_Value_Input.cxx
@@ -51,8 +51,9 @@ void Fl_Value_Input::resize(int X, int Y, int W, int H) {
}
void Fl_Value_Input::value_damage() {
- std::string buf = format_str();
- input.value(buf.c_str());
+ char buf[129];
+ format(buf);
+ input.value(buf);
input.mark(input.insert_position()); // turn off selection highlight
}
diff --git a/src/Fl_Value_Output.cxx b/src/Fl_Value_Output.cxx
index 924829937..cdea175ed 100644
--- a/src/Fl_Value_Output.cxx
+++ b/src/Fl_Value_Output.cxx
@@ -34,10 +34,11 @@ void Fl_Value_Output::draw() {
fl_color(color());
fl_rectf(X, Y, W, H);
}
- std::string buf = format_str();
+ char buf[129];
+ format(buf);
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
fl_font(textfont(), textsize());
- fl_draw(buf.c_str(),X,Y,W,H,FL_ALIGN_LEFT);
+ fl_draw(buf,X,Y,W,H,FL_ALIGN_LEFT);
}
int Fl_Value_Output::handle(int event) {
diff --git a/src/Fl_Value_Slider.cxx b/src/Fl_Value_Slider.cxx
index 776632751..9607dd2c6 100644
--- a/src/Fl_Value_Slider.cxx
+++ b/src/Fl_Value_Slider.cxx
@@ -53,10 +53,11 @@ void Fl_Value_Slider::draw() {
sww-Fl::box_dw(box()),
shh-Fl::box_dh(box()));
draw_box(box(),bxx,byy,bww,bhh,color());
- std::string buf = format_str();
+ char buf[129];
+ format(buf);
fl_font(textfont(), textsize());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
- fl_draw(buf.c_str(), bxx, byy, bww, bhh, FL_ALIGN_CLIP);
+ fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP);
}
int Fl_Value_Slider::handle(int event) {
diff --git a/src/Fl_grab.cxx b/src/Fl_grab.cxx
index 9def8ee4f..d7019c4f7 100644
--- a/src/Fl_grab.cxx
+++ b/src/Fl_grab.cxx
@@ -16,6 +16,7 @@
#include <config.h>
#include <FL/Fl.H>
+#include <FL/core/pen_events.H>
#include "Fl_Screen_Driver.H"
////////////////////////////////////////////////////////////////
@@ -29,7 +30,7 @@
void Fl::grab(Fl_Window *win)
{
#if defined(FLTK_HAVE_PEN_SUPPORT)
- Fl::Pen::release();
+ Fl_Pen_release();
#endif
screen_driver()->grab(win);
}
diff --git a/src/drivers/Base/Fl_Base_Pen_Events.H b/src/drivers/Base/Fl_Base_Pen_Events.H
index ba4882d0b..2259c51aa 100644
--- a/src/drivers/Base/Fl_Base_Pen_Events.H
+++ b/src/drivers/Base/Fl_Base_Pen_Events.H
@@ -22,37 +22,32 @@
#include <FL/core/pen_events.H>
#include <FL/Fl.H>
-#include <map>
-#include <memory>
-
class Fl_Widget;
-namespace Fl {
-
-namespace Pen {
-
/* Pen event data storage.
A second storage may be useful if the driver needs to collect pen data
from multiple events, or if one system event can send multiple FLTK events.
*/
-typedef struct EventData {
- double x { 0.0 };
- double y { 0.0 };
- double rx { 0.0 };
- double ry { 0.0 };
- double tilt_x { 0.0 };
- double tilt_y { 0.0 };
- double pressure { 1.0 };
- double proximity { 0.0 };
- double barrel_pressure { 0.0 };
- double twist { 0.0 };
- int pen_id { 0 };
- Fl::Pen::State state { (Fl::Pen::State)0 };
- Fl::Pen::State trigger { (Fl::Pen::State)0 };
-} EventData;
-
-extern EventData e;
+typedef struct Fl_Pen_EventData {
+ double x;
+ double y;
+ double rx;
+ double ry;
+ double tilt_x;
+ double tilt_y;
+ double pressure;
+ double proximity;
+ double barrel_pressure;
+ double twist;
+ int pen_id;
+ Fl_Pen_State state;
+ Fl_Pen_State trigger;
+} Fl_Pen_EventData;
+
+extern Fl_Pen_EventData fl_pen_event_data;
+
+void fl_pen_event_data_init(Fl_Pen_EventData *d);
/*
@@ -66,51 +61,55 @@ extern EventData e;
including during event handling, the driver will remove the subscription.
There is no need to explicitly unsubscribe.
*/
-class Subscriber : public Fl_Widget_Tracker {
+class Fl_Pen_Subscriber : public Fl_Widget_Tracker {
public:
- Subscriber(Fl_Widget *w) : Fl_Widget_Tracker(w) { }
+ Fl_Pen_Subscriber(Fl_Widget *w) : Fl_Widget_Tracker(w) { }
};
/*
- Manage a list of subscribers.
+ Manage a list of subscribers using a simple array.
*/
-class SubscriberList : public std::map<Fl_Widget*, std::shared_ptr<Subscriber>> {
+class Fl_Pen_SubscriberList {
+ Fl_Pen_Subscriber **items_;
+ Fl_Widget **widgets_;
+ int count_;
+ int alloc_;
public:
- SubscriberList() = default;
+ Fl_Pen_SubscriberList();
+ ~Fl_Pen_SubscriberList();
void cleanup();
- std::shared_ptr<Subscriber> add(Fl_Widget *w);
+ Fl_Pen_Subscriber *add(Fl_Widget *w);
void remove(Fl_Widget *w);
+ Fl_Pen_Subscriber *find(Fl_Widget *w);
+ int count() const { return count_; }
+ Fl_Pen_Subscriber *get(int i) const { return (i >= 0 && i < count_) ? items_[i] : 0; }
};
-extern SubscriberList subscriber_list_;
-extern std::shared_ptr<Subscriber> pushed_;
-extern std::shared_ptr<Subscriber> below_pen_;
+extern Fl_Pen_SubscriberList fl_pen_subscriber_list;
+extern Fl_Pen_Subscriber *fl_pen_pushed;
+extern Fl_Pen_Subscriber *fl_pen_below;
/* The base driver for calls by apps into the pen system.
Most traffic is generated by system events. The data is then converted
- for the FLTK API and stored in Fl::Pen::e. The Pen interface then sends
+ for the FLTK API and stored in fl_pen_event_data. The Pen interface then sends
the appropriate FLTK events to the subscribers.
This driver class manages calls from the app into FLTK, including subscriber
management and queries for driver an pen abilities.
*/
-class Driver {
+class Fl_Pen_Driver {
public:
- Driver() = default;
+ Fl_Pen_Driver() { }
virtual void subscribe(Fl_Widget* widget);
virtual void unsubscribe(Fl_Widget* widget);
virtual void release();
- virtual Trait traits();
- virtual Trait pen_traits(int pen_id);
+ virtual Fl_Pen_Trait traits();
+ virtual Fl_Pen_Trait pen_traits(int pen_id);
};
-extern Driver& driver;
-
-} // namespace Pen
-
-} // namespace Fl
+extern Fl_Pen_Driver *fl_pen_driver;
#endif // FL_BASE_PEN_EVENTS_H
diff --git a/src/drivers/Base/Fl_Base_Pen_Events.cxx b/src/drivers/Base/Fl_Base_Pen_Events.cxx
index 12f207731..2214a61f5 100644
--- a/src/drivers/Base/Fl_Base_Pen_Events.cxx
+++ b/src/drivers/Base/Fl_Base_Pen_Events.cxx
@@ -15,134 +15,186 @@
//
#include "src/drivers/Base/Fl_Base_Pen_Events.H"
+#include <stdlib.h>
class Fl_Widget;
-namespace Fl {
-
-namespace Pen {
-
-EventData e;
-SubscriberList subscriber_list_;
-std::shared_ptr<Subscriber> pushed_;
-std::shared_ptr<Subscriber> below_pen_;
-
-} // namespace Pen
-
-} // namespace Fl
+Fl_Pen_EventData fl_pen_event_data;
+Fl_Pen_SubscriberList fl_pen_subscriber_list;
+Fl_Pen_Subscriber *fl_pen_pushed = 0;
+Fl_Pen_Subscriber *fl_pen_below = 0;
+
+
+void fl_pen_event_data_init(Fl_Pen_EventData *d) {
+ d->x = 0.0;
+ d->y = 0.0;
+ d->rx = 0.0;
+ d->ry = 0.0;
+ d->tilt_x = 0.0;
+ d->tilt_y = 0.0;
+ d->pressure = 1.0;
+ d->proximity = 0.0;
+ d->barrel_pressure = 0.0;
+ d->twist = 0.0;
+ d->pen_id = 0;
+ d->state = (Fl_Pen_State)0;
+ d->trigger = (Fl_Pen_State)0;
+}
-using namespace Fl::Pen;
+// ---- Fl_Pen_SubscriberList implementation ------------------------------------
+Fl_Pen_SubscriberList::Fl_Pen_SubscriberList() {
+ items_ = 0;
+ widgets_ = 0;
+ count_ = 0;
+ alloc_ = 0;
+}
-// ---- SubscriberList implementation ------------------------------------------
+Fl_Pen_SubscriberList::~Fl_Pen_SubscriberList() {
+ int i;
+ for (i = 0; i < count_; i++) {
+ delete items_[i];
+ }
+ if (items_) free(items_);
+ if (widgets_) free(widgets_);
+}
/* Remove subscribers that have a 0 as a widget */
-void Fl::Pen::SubscriberList::cleanup() {
- for (auto it = begin(); it != end(); ) {
- if (!it->second->widget()) {
- it = erase(it);
+void Fl_Pen_SubscriberList::cleanup() {
+ int i, j;
+ for (i = 0, j = 0; i < count_; i++) {
+ if (items_[i]->widget()) {
+ if (i != j) {
+ items_[j] = items_[i];
+ widgets_[j] = widgets_[i];
+ }
+ j++;
} else {
- ++it;
+ delete items_[i];
}
}
+ count_ = j;
+}
+
+Fl_Pen_Subscriber *Fl_Pen_SubscriberList::find(Fl_Widget *w) {
+ int i;
+ for (i = 0; i < count_; i++) {
+ if (widgets_[i] == w) return items_[i];
+ }
+ return 0;
}
/* Add a new subscriber, or return an existing one. */
-std::shared_ptr<Subscriber> Fl::Pen::SubscriberList::add(Fl_Widget *w) {
+Fl_Pen_Subscriber *Fl_Pen_SubscriberList::add(Fl_Widget *w) {
+ Fl_Pen_Subscriber *existing;
cleanup();
- auto it = find(w);
- if (it == end()) {
- auto sub = std::make_shared<Subscriber>(w);
- insert(std::make_pair(w, sub));
- return sub;
- } else {
- return it->second;
+ existing = find(w);
+ if (existing) return existing;
+
+ if (count_ >= alloc_) {
+ int new_alloc = alloc_ ? alloc_ * 2 : 8;
+ items_ = (Fl_Pen_Subscriber **)realloc(items_, new_alloc * sizeof(Fl_Pen_Subscriber *));
+ widgets_ = (Fl_Widget **)realloc(widgets_, new_alloc * sizeof(Fl_Widget *));
+ alloc_ = new_alloc;
}
+ Fl_Pen_Subscriber *sub = new Fl_Pen_Subscriber(w);
+ items_[count_] = sub;
+ widgets_[count_] = w;
+ count_++;
+ return sub;
}
/* Remove a subscriber from the list. */
-void Fl::Pen::SubscriberList::remove(Fl_Widget *w) {
- auto it = find(w);
- if (it != end()) {
- it->second->clear();
- erase(it);
+void Fl_Pen_SubscriberList::remove(Fl_Widget *w) {
+ int i;
+ for (i = 0; i < count_; i++) {
+ if (widgets_[i] == w) {
+ items_[i]->clear();
+ delete items_[i];
+ count_--;
+ if (i < count_) {
+ items_[i] = items_[count_];
+ widgets_[i] = widgets_[count_];
+ }
+ return;
+ }
}
}
-// ---- Driver implementation --------------------------------------------------
+// ---- Fl_Pen_Driver implementation --------------------------------------------
// Override the methods below to handle subscriptions and queries by user apps.
-void Fl::Pen::Driver::subscribe(Fl_Widget* widget) {
+void Fl_Pen_Driver::subscribe(Fl_Widget* widget) {
if (widget == 0) return;
- subscriber_list_.add(widget);
+ fl_pen_subscriber_list.add(widget);
}
-void Fl::Pen::Driver::unsubscribe(Fl_Widget* widget) {
+void Fl_Pen_Driver::unsubscribe(Fl_Widget* widget) {
if (widget == 0) return;
- subscriber_list_.remove(widget);
+ fl_pen_subscriber_list.remove(widget);
}
-void Fl::Pen::Driver::release() {
- pushed_ = 0;
- below_pen_ = 0;
+void Fl_Pen_Driver::release() {
+ fl_pen_pushed = 0;
+ fl_pen_below = 0;
}
-Trait Fl::Pen::Driver::traits() {
- return Trait::NONE;
+Fl_Pen_Trait Fl_Pen_Driver::traits() {
+ return FL_PEN_TRAIT_NONE;
}
-Trait Fl::Pen::Driver::pen_traits(int pen_id) {
+Fl_Pen_Trait Fl_Pen_Driver::pen_traits(int pen_id) {
(void)pen_id;
- return Trait::NONE;
+ return FL_PEN_TRAIT_NONE;
}
-// ---- Fl::Pen API ------------------------------------------------------------
+// ---- Fl_Pen API --------------------------------------------------------------
-void Fl::Pen::subscribe(Fl_Widget* widget) {
- driver.subscribe(widget);
+void Fl_Pen_subscribe(Fl_Widget* widget) {
+ fl_pen_driver->subscribe(widget);
}
-void Fl::Pen::unsubscribe(Fl_Widget* widget) {
- driver.unsubscribe(widget);
+void Fl_Pen_unsubscribe(Fl_Widget* widget) {
+ fl_pen_driver->unsubscribe(widget);
}
-void Fl::Pen::release() {
- driver.release();
+void Fl_Pen_release(void) {
+ fl_pen_driver->release();
}
-Trait Fl::Pen::driver_traits() {
- return driver.traits();
+Fl_Pen_Trait Fl_Pen_driver_traits(void) {
+ return fl_pen_driver->traits();
}
-Trait Fl::Pen::pen_traits(int pen_id) {
- return driver.pen_traits(pen_id);
+Fl_Pen_Trait Fl_Pen_pen_traits(int pen_id) {
+ return fl_pen_driver->pen_traits(pen_id);
}
-double Fl::Pen::event_x() { return e.x; }
+double Fl_Pen_event_x(void) { return fl_pen_event_data.x; }
-double Fl::Pen::event_y() { return e.y; }
+double Fl_Pen_event_y(void) { return fl_pen_event_data.y; }
-double Fl::Pen::event_x_root() { return e.rx; }
+double Fl_Pen_event_x_root(void) { return fl_pen_event_data.rx; }
-double Fl::Pen::event_y_root() { return e.ry; }
+double Fl_Pen_event_y_root(void) { return fl_pen_event_data.ry; }
-int Fl::Pen::event_pen_id() { return e.pen_id; }
+int Fl_Pen_event_pen_id(void) { return fl_pen_event_data.pen_id; }
-double Fl::Pen::event_pressure() { return e.pressure; }
+double Fl_Pen_event_pressure(void) { return fl_pen_event_data.pressure; }
-double Fl::Pen::event_barrel_pressure() { return e.barrel_pressure; }
+double Fl_Pen_event_barrel_pressure(void) { return fl_pen_event_data.barrel_pressure; }
-double Fl::Pen::event_tilt_x() { return e.tilt_x; }
+double Fl_Pen_event_tilt_x(void) { return fl_pen_event_data.tilt_x; }
-double Fl::Pen::event_tilt_y() { return e.tilt_y; }
+double Fl_Pen_event_tilt_y(void) { return fl_pen_event_data.tilt_y; }
-double Fl::Pen::event_twist() { return e.twist; }
+double Fl_Pen_event_twist(void) { return fl_pen_event_data.twist; }
-double Fl::Pen::event_proximity() { return e.proximity; }
+double Fl_Pen_event_proximity(void) { return fl_pen_event_data.proximity; }
-State Fl::Pen::event_state() { return e.state; }
+Fl_Pen_State Fl_Pen_event_state(void) { return fl_pen_event_data.state; }
-State Fl::Pen::event_trigger() { return e.trigger; }
+Fl_Pen_State Fl_Pen_event_trigger(void) { return fl_pen_event_data.trigger; }
diff --git a/src/drivers/Posix/Fl_Posix_System_Driver.cxx b/src/drivers/Posix/Fl_Posix_System_Driver.cxx
index 299a1b901..babcc758b 100644
--- a/src/drivers/Posix/Fl_Posix_System_Driver.cxx
+++ b/src/drivers/Posix/Fl_Posix_System_Driver.cxx
@@ -322,7 +322,6 @@ int Fl_Posix_System_Driver::close_fd(int fd) { return close(fd); }
# include <fcntl.h>
# include <pthread.h>
# include <sys/ioctl.h>
-# include <mutex> // for std::mutex (since C++11)
// Pipe for thread messaging via Fl::awake()...
static int thread_filedes[2];
@@ -372,12 +371,12 @@ static void unlock_function_rec() {
// -- Start of "awake" implementation --
static void* thread_message_ = 0;
-static std::mutex pipe_mutex;
+static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
void Fl_Posix_System_Driver::awake(void* msg) {
thread_message_ = msg;
if (thread_filedes[1]) {
- pipe_mutex.lock();
+ pthread_mutex_lock(&pipe_mutex);
int avail = 0;
ioctl(thread_filedes[0], FIONREAD, &avail);
if (avail == 0) {
@@ -385,7 +384,7 @@ void Fl_Posix_System_Driver::awake(void* msg) {
char dummy = 0;
if (write(thread_filedes[1], &dummy, 1)==0) { /* ignore */ }
}
- pipe_mutex.unlock();
+ pthread_mutex_unlock(&pipe_mutex);
}
}
@@ -397,10 +396,10 @@ void* Fl_Posix_System_Driver::thread_message() {
static void thread_awake_cb(int fd, void*) {
if (thread_filedes[1]) {
- pipe_mutex.lock();
+ pthread_mutex_lock(&pipe_mutex);
char dummy = 0;
if (read(fd, &dummy, 1)==0) { /* This should never happen */ }
- pipe_mutex.unlock();
+ pthread_mutex_unlock(&pipe_mutex);
}
Fl_Awake_Handler func;
void *data;
diff --git a/src/drivers/Unix/Fl_Unix_System_Driver.cxx b/src/drivers/Unix/Fl_Unix_System_Driver.cxx
index 443838c5d..ab6f678aa 100644
--- a/src/drivers/Unix/Fl_Unix_System_Driver.cxx
+++ b/src/drivers/Unix/Fl_Unix_System_Driver.cxx
@@ -30,7 +30,6 @@
#include <pwd.h>
#include <string.h> // strerror(errno)
#include <errno.h> // errno
-#include <string>
#if HAVE_DLSYM && HAVE_DLFCN_H
#include <dlfcn.h> // for dlsym
#endif
@@ -537,53 +536,79 @@ char *Fl_Unix_System_Driver::preference_user_rootnode(
const char *application,
char *buffer)
{
+ char home_path[FL_PATH_MAX];
+ char prefs_path_14[FL_PATH_MAX];
+ char prefs_path_13[FL_PATH_MAX];
+ char *p;
+ int len;
+
// Find the path to the user's home directory.
const char *home_path_c = getenv("HOME");
- std::string home_path = home_path_c ? home_path_c : "";
- if (home_path.empty()) {
+ if (home_path_c && home_path_c[0]) {
+ strlcpy(home_path, home_path_c, FL_PATH_MAX);
+ } else {
+ home_path[0] = '\0';
struct passwd *pw = getpwuid(getuid());
- if (pw)
- home_path = pw->pw_dir;
+ if (pw && pw->pw_dir)
+ strlcpy(home_path, pw->pw_dir, FL_PATH_MAX);
}
// 1: Generate the 1.4 path for this vendor and application.
const char *prefs_path_14_c = getenv("XDG_CONFIG_HOME");
- std::string prefs_path_14 = prefs_path_14_c ? prefs_path_14_c : "";
- if (prefs_path_14.empty()) {
- prefs_path_14 = home_path + "/.config";
+ if (!prefs_path_14_c || !prefs_path_14_c[0]) {
+ snprintf(prefs_path_14, FL_PATH_MAX, "%s/.config", home_path);
} else {
- if (prefs_path_14[prefs_path_14.size()-1]!='/')
- prefs_path_14.append("/");
- if (prefs_path_14.find("~/")==0) // starts with "~"
- prefs_path_14.replace(0, 1, home_path);
- int h_env = prefs_path_14.find("${HOME}");
- if (h_env!=(int)prefs_path_14.npos)
- prefs_path_14.replace(h_env, 7, home_path);
- h_env = prefs_path_14.find("$HOME/");
- if (h_env!=(int)prefs_path_14.npos)
- prefs_path_14.replace(h_env, 5, home_path);
+ strlcpy(prefs_path_14, prefs_path_14_c, FL_PATH_MAX);
+ len = (int)strlen(prefs_path_14);
+ if (len > 0 && prefs_path_14[len-1] != '/') {
+ strlcat(prefs_path_14, "/", FL_PATH_MAX);
+ len++;
+ }
+ // Handle ~/ at start
+ if (prefs_path_14[0] == '~' && prefs_path_14[1] == '/') {
+ char temp[FL_PATH_MAX];
+ snprintf(temp, FL_PATH_MAX, "%s%s", home_path, prefs_path_14 + 1);
+ strlcpy(prefs_path_14, temp, FL_PATH_MAX);
+ }
+ // Handle ${HOME}
+ p = strstr(prefs_path_14, "${HOME}");
+ if (p) {
+ char temp[FL_PATH_MAX];
+ *p = '\0';
+ snprintf(temp, FL_PATH_MAX, "%s%s%s", prefs_path_14, home_path, p + 7);
+ strlcpy(prefs_path_14, temp, FL_PATH_MAX);
+ }
+ // Handle $HOME/
+ p = strstr(prefs_path_14, "$HOME/");
+ if (p) {
+ char temp[FL_PATH_MAX];
+ *p = '\0';
+ snprintf(temp, FL_PATH_MAX, "%s%s%s", prefs_path_14, home_path, p + 5);
+ strlcpy(prefs_path_14, temp, FL_PATH_MAX);
+ }
}
- if (prefs_path_14[prefs_path_14.size()-1]!='/')
- prefs_path_14.append("/");
- prefs_path_14.append(vendor);
+ len = (int)strlen(prefs_path_14);
+ if (len > 0 && prefs_path_14[len-1] != '/')
+ strlcat(prefs_path_14, "/", FL_PATH_MAX);
+ strlcat(prefs_path_14, vendor, FL_PATH_MAX);
// 2: If this base path does not exist, try the 1.3 path
- if (::access(prefs_path_14.c_str(), F_OK) == -1) {
- std::string prefs_path_13 = home_path + "/.fltk/" + vendor;
- if (::access(prefs_path_13.c_str(), F_OK) == 0) {
- prefs_path_13.append("/");
- prefs_path_13.append(application);
- prefs_path_13.append(".prefs");
- strlcpy(buffer, prefs_path_13.c_str(), FL_PATH_MAX);
+ if (::access(prefs_path_14, F_OK) == -1) {
+ snprintf(prefs_path_13, FL_PATH_MAX, "%s/.fltk/%s", home_path, vendor);
+ if (::access(prefs_path_13, F_OK) == 0) {
+ strlcat(prefs_path_13, "/", FL_PATH_MAX);
+ strlcat(prefs_path_13, application, FL_PATH_MAX);
+ strlcat(prefs_path_13, ".prefs", FL_PATH_MAX);
+ strlcpy(buffer, prefs_path_13, FL_PATH_MAX);
return buffer;
}
}
// 3: neither path exists, return the 1.4 file path and name
- prefs_path_14.append("/");
- prefs_path_14.append(application);
- prefs_path_14.append(".prefs");
- strlcpy(buffer, prefs_path_14.c_str(), FL_PATH_MAX);
+ strlcat(prefs_path_14, "/", FL_PATH_MAX);
+ strlcat(prefs_path_14, application, FL_PATH_MAX);
+ strlcat(prefs_path_14, ".prefs", FL_PATH_MAX);
+ strlcpy(buffer, prefs_path_14, FL_PATH_MAX);
return buffer;
}
diff --git a/src/filename_absolute.cxx b/src/filename_absolute.cxx
index b134c48c0..4573a34c1 100644
--- a/src/filename_absolute.cxx
+++ b/src/filename_absolute.cxx
@@ -292,127 +292,3 @@ int Fl_System_Driver::filename_relative_(char *to, int tolen, const char *dest_d
*/
-/**
- Return a new string that contains the name part of the filename.
- \param[in] filename file path and name
- \return the name part of a filename
- \see fl_filename_name(const char *filename)
- */
-std::string fl_filename_name_str(const std::string &filename) {
- return std::string(fl_filename_name(filename.c_str()));
-}
-
-/**
- Return a new string that contains the path part of the filename.
- \param[in] filename file path and name
- \return the path part of a filename without the name
- \see fl_filename_name(const char *filename)
- */
-std::string fl_filename_path_str(const std::string &filename) {
- const char *base = filename.c_str();
- const char *name = fl_filename_name(base);
- if (name) {
- return std::string(base, (int)(name-base));
- } else {
- return std::string();
- }
-}
-
-/**
- Return a new string that contains the filename extension.
- \param[in] filename file path and name
- \return the filename extension including the prepending '.', or an empty
- string if the filename has no extension
- \see fl_filename_ext(const char *buf)
- */
-std::string fl_filename_ext_str(const std::string &filename) {
- return std::string(fl_filename_ext(filename.c_str()));
-}
-
-/**
- Return a copy of the old filename with the new extension.
- \param[in] filename file path and name
- \param[in] new_extension new filename extension, starts with a '.'
- \return the new filename
- \see fl_filename_setext(char *to, int tolen, const char *ext)
- */
-std::string fl_filename_setext_str(const std::string &filename, const std::string &new_extension) {
- char buffer[FL_PATH_MAX];
- fl_strlcpy(buffer, filename.c_str(), FL_PATH_MAX);
- fl_filename_setext(buffer, FL_PATH_MAX, new_extension.c_str());
- return std::string(buffer);
-}
-
-/**
- Expands a filename containing shell variables and tilde (~).
- \param[in] from file path and name
- \return the new, expanded filename
- \see fl_filename_expand(char *to, int tolen, const char *from)
-*/
-std::string fl_filename_expand_str(const std::string &from) {
- char buffer[FL_PATH_MAX];
- fl_filename_expand(buffer, FL_PATH_MAX, from.c_str());
- return std::string(buffer);
-}
-
-/**
- Makes a filename absolute from a filename relative to the current working directory.
- \param[in] from relative filename
- \return the new, absolute filename
- \see fl_filename_absolute(char *to, int tolen, const char *from)
- */
-std::string fl_filename_absolute_str(const std::string &from) {
- char buffer[FL_PATH_MAX];
- fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str());
- return std::string(buffer);
-}
-
-/**
- Append the relative filename `from` to the absolute filename `base` to form
- the new absolute path.
- \param[in] from relative filename
- \param[in] base `from` is relative to this absolute file path
- \return the new, absolute filename
- \see fl_filename_absolute(char *to, int tolen, const char *from, const char *base)
- */
-std::string fl_filename_absolute_str(const std::string &from, const std::string &base) {
- char buffer[FL_PATH_MAX];
- fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str(), base.c_str());
- return std::string(buffer);
-}
-
-/**
- Makes a filename relative to the current working directory.
- \param[in] from file path and name
- \return the new, relative filename
- \see fl_filename_relative(char *to, int tolen, const char *from)
- */
-std::string fl_filename_relative_str(const std::string &from) {
- char buffer[FL_PATH_MAX];
- fl_filename_relative(buffer, FL_PATH_MAX, from.c_str());
- return std::string(buffer);
-}
-
-/**
- Makes a filename relative to any directory.
- \param[in] from file path and name
- \param[in] base relative to this absolute path
- \return the new, relative filename
- \see fl_filename_relative(char *to, int tolen, const char *from, const char *base)
- */
-std::string fl_filename_relative_str(const std::string &from, const std::string &base) {
- char buffer[FL_PATH_MAX];
- fl_filename_relative(buffer, FL_PATH_MAX, from.c_str(), base.c_str());
- return std::string(buffer);
-}
-
-/** Cross-platform function to get the current working directory
- as a UTF-8 encoded value in an std::string.
- \return the CWD encoded as UTF-8
- */
-std::string fl_getcwd_str() {
- char buffer[FL_PATH_MAX];
- buffer[0] = 0;
- fl_getcwd(buffer, FL_PATH_MAX);
- return std::string(buffer);
-}
diff --git a/src/fl_ask.cxx b/src/fl_ask.cxx
index 205979d7e..b9c31fd43 100644
--- a/src/fl_ask.cxx
+++ b/src/fl_ask.cxx
@@ -32,9 +32,7 @@
- fl_ask() // deprecated since 1.1.7 (2006), see comment in FL/fl_ask.H
- fl_choice()
- fl_input()
- - fl_input_str()
- fl_password()
- - fl_password_str()
and some more functions to change their behavior (positioning,
window title, and more).
@@ -352,70 +350,6 @@ const char *fl_input(int maxchar, const char *fmt, const char *defstr, ...) {
/** Shows an input dialog displaying the \p fmt message with variable arguments.
- Like fl_input(), but this method has the additional argument \p maxchar
- that limits the number of \b characters that can be input. Since the
- string is encoded in UTF-8 it is possible that the number of bytes
- in the string is larger than \p maxchar.
-
- Other than the deprecated fl_input() method w/o the \p maxchar argument, this one
- returns the string in an std::string object that must be released after use. This
- can be a local/automatic variable.
-
- The \p ret variable is set to 0 if the user clicked OK, and to a negative
- value if the user canceled the dialog. If the dialog was canceled, the returned
- string will be empty.
-
- \code #include <FL/fl_ask.H> \endcode
-
- Example:
- \code
- { int ret;
- std::string str = fl_input_str(ret, 0, "Enter text:", "");
- if (ret < 0)
- printf("Text input was canceled.\n");
- else
- printf("Text is: '%s'\n", str.c_str());
- } // (str goes out of scope)
- \endcode
-
- \param[out] ret 0 if user clicked OK, negative if dialog was canceled
- \param[in] maxchar input size limit in characters (not bytes), use 0 for no limit
- \param[in] fmt can be used as an sprintf-like format and variables for the message text
- \param[in] defstr defines the default returned string if no text is entered
-
- \return the user string input if OK was clicked which can be empty
- \return an empty string and set \p ret to a negative value if the user canceled the dialog
-
- \since 1.4.0
-*/
-std::string fl_input_str(int &ret, int maxchar, const char *fmt, const char *defstr, ...) {
- Fl_Message msg("?");
- if (maxchar < 0) maxchar = 0;
- va_list ap;
- va_start(ap, defstr);
- const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar, true);
- va_end(ap);
- ret = (r == NULL) ? -1 : 0;
- return (r == NULL) ? std::string("") : std::string(r);
-}
-
-/** Shows an input dialog displaying the \p fmt message with variable arguments.
- \note No information is given if the user canceled the dialog or clicked OK.
- \see fl_input_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...)
- */
-std::string fl_input_str(int maxchar, const char *fmt, const char *defstr, ...) {
- Fl_Message msg("?");
- if (maxchar < 0) maxchar = 0;
- va_list ap;
- va_start(ap, defstr);
- const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar, true);
- va_end(ap);
- return (r == NULL) ? std::string("") : std::string(r);
-}
-
-
-/** Shows an input dialog displaying the \p fmt message with variable arguments.
-
Like fl_input() except the input text is not shown,
'*' or similar replacement characters are displayed instead.
@@ -461,55 +395,6 @@ const char *fl_password(int maxchar, const char *fmt, const char *defstr, ...) {
}
-/** Shows an input dialog displaying the \p fmt message with variable arguments.
-
- Like fl_input_str() except the input text is not shown,
- '*' or similar replacement characters are displayed instead.
-
- Other than the fl_password() method w/o the \p maxchar argument, this one
- returns the string in an std::string object that must be released after use.
- This can be a local/automatic variable.
-
- For an example see fl_input_str()
-
- \code #include <FL/fl_ask.H> \endcode
-
- \param[out] ret 0 if user clicked OK, negative if dialog was canceled
- \param[in] maxchar input size limit in characters (not bytes), use 0 for no limit
- \param[in] fmt can be used as an sprintf-like format and variables for the message text
- \param[in] defstr defines the default returned string if no text is entered
-
- \return the user string input if OK was clicked which can be empty
- \return an empty string and set \p ret to a negative value if the user canceled the dialog
-
- \since 1.4.0
-*/
-std::string fl_password_str(int &ret, int maxchar, const char *fmt, const char *defstr, ...) {
- Fl_Message msg("?");
- if (maxchar < 0) maxchar = 0;
- va_list ap;
- va_start(ap, defstr);
- const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar, true);
- va_end(ap);
- ret = (r == NULL) ? -1 : 0;
- return (r == NULL) ? std::string("") : std::string(r);
-}
-
-/** Shows an input dialog displaying the \p fmt message with variable arguments.
- \note No information is given if the user canceled the dialog or clicked OK.
- \see fl_password_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...)
- */
-std::string fl_password_str(int maxchar, const char *fmt, const char *defstr, ...) {
- Fl_Message msg("?");
- if (maxchar < 0) maxchar = 0;
- va_list ap;
- va_start(ap, defstr);
- const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar, true);
- va_end(ap);
- return (r == NULL) ? std::string("") : std::string(r);
-}
-
-
/** Sets the preferred position for the message box used in
many common dialogs like fl_message(), fl_alert(),
fl_ask(), fl_choice(), fl_input(), fl_password().