From dc39575fb3ef90e5a2689babe7fb335cd88f6727 Mon Sep 17 00:00:00 2001 From: maxim nikonov Date: Thu, 5 Feb 2026 21:32:25 +0500 Subject: wip --- FL/Enumerations.H | 3 +- FL/Fl.H | 3 - FL/Fl_Color_Chooser.H | 3 - FL/Fl_Help_View.H | 7 +- FL/Fl_Plugin.H | 4 - FL/Fl_Preferences.H | 4 - FL/Fl_Table_Row.H | 2 +- FL/Fl_Text_Buffer.H | 7 - FL/Fl_Valuator.H | 3 - FL/core/pen_events.H | 284 +++++--------- FL/filename.H | 17 - FL/fl_ask.H | 20 - FL/names.h | 118 +++--- bin/fluid | Bin 2710072 -> 0 bytes lib/libfltk 2.a | Bin 2305568 -> 2237456 bytes lib/libfltk.a | Bin 2294696 -> 2237456 bytes lib/libfltk_forms 2.a | Bin 32896 -> 0 bytes lib/libfltk_forms.a | Bin 32896 -> 0 bytes lib/libfltk_gl 2.a | Bin 212456 -> 0 bytes lib/libfltk_gl.a | Bin 212456 -> 0 bytes lib/libfltk_images 2.a | Bin 268016 -> 0 bytes lib/libfltk_images.a | Bin 268016 -> 0 bytes lib/libfltk_jpeg 2.a | Bin 305416 -> 0 bytes lib/libfltk_jpeg.a | Bin 305416 -> 0 bytes lib/libfltk_png 2.a | Bin 287384 -> 0 bytes lib/libfltk_png.a | Bin 287384 -> 0 bytes lib/libfltk_z 2.a | Bin 103976 -> 0 bytes lib/libfltk_z.a | Bin 103976 -> 0 bytes src/Fl.cxx | 9 - src/Fl_Color_Chooser.cxx | 8 - src/Fl_Counter.cxx | 5 +- src/Fl_Help_View.cxx | 568 ++++++++++++++++++--------- src/Fl_Native_File_Chooser_Kdialog.H | 5 +- src/Fl_Native_File_Chooser_Kdialog.cxx | 62 +-- src/Fl_Native_File_Chooser_Zenity.H | 4 +- src/Fl_Native_File_Chooser_Zenity.cxx | 58 +-- src/Fl_Preferences.cxx | 67 ---- src/Fl_Terminal.cxx | 37 +- src/Fl_Text_Buffer.cxx | 15 - src/Fl_Timeout.cxx | 11 - src/Fl_Timeout.h | 3 +- src/Fl_Valuator.cxx | 12 - src/Fl_Value_Input.cxx | 5 +- src/Fl_Value_Output.cxx | 5 +- src/Fl_Value_Slider.cxx | 5 +- src/Fl_grab.cxx | 3 +- src/drivers/Base/Fl_Base_Pen_Events.H | 85 ++-- src/drivers/Base/Fl_Base_Pen_Events.cxx | 188 +++++---- src/drivers/Posix/Fl_Posix_System_Driver.cxx | 11 +- src/drivers/Unix/Fl_Unix_System_Driver.cxx | 89 +++-- src/filename_absolute.cxx | 124 ------ src/fl_ask.cxx | 115 ------ 52 files changed, 880 insertions(+), 1089 deletions(-) delete mode 100755 bin/fluid delete mode 100644 lib/libfltk_forms 2.a delete mode 100644 lib/libfltk_forms.a delete mode 100644 lib/libfltk_gl 2.a delete mode 100644 lib/libfltk_gl.a delete mode 100644 lib/libfltk_images 2.a delete mode 100644 lib/libfltk_images.a delete mode 100644 lib/libfltk_jpeg 2.a delete mode 100644 lib/libfltk_jpeg.a delete mode 100644 lib/libfltk_png 2.a delete mode 100644 lib/libfltk_png.a delete mode 100644 lib/libfltk_z 2.a delete mode 100644 lib/libfltk_z.a diff --git a/FL/Enumerations.H b/FL/Enumerations.H index 0557e6a75..e426d90c4 100644 --- a/FL/Enumerations.H +++ b/FL/Enumerations.H @@ -107,8 +107,7 @@ is ok to look at it outside of the handle() method. Event numbers can be converted to their actual names using the - fl_eventnames[] array (std::map since FLTK 1.5) defined - in \#include <FL/names.h> + fl_eventnames[] array defined in \#include <FL/names.h> \see Fl::event_text(), Fl::event_key(), class Fl:: */ diff --git a/FL/Fl.H b/FL/Fl.H index f84c85fac..dd5958750 100644 --- a/FL/Fl.H +++ b/FL/Fl.H @@ -50,7 +50,6 @@ #endif #include // FIXME: Fl::is_scheme(): strcmp needs string.h -#include class Fl_Widget; class Fl_Window; @@ -238,8 +237,6 @@ FL_EXPORT extern void repeat_timeout(double t, Fl_Timeout_Handler cb, void *data FL_EXPORT extern int has_timeout(Fl_Timeout_Handler cb, void *data = 0); FL_EXPORT extern void remove_timeout(Fl_Timeout_Handler cb, void *data = 0); FL_EXPORT extern int remove_next_timeout(Fl_Timeout_Handler cb, void *data = 0, void **data_return = 0); -typedef struct { double t; Fl_Timeout_Handler cb; void *data; } TimeoutData; -FL_EXPORT extern std::vector timeout_list(); FL_EXPORT extern void add_check(Fl_Timeout_Handler, void* = 0); FL_EXPORT extern int has_check(Fl_Timeout_Handler, void* = 0); diff --git a/FL/Fl_Color_Chooser.H b/FL/Fl_Color_Chooser.H index 5be4c2c71..2160a4fd4 100644 --- a/FL/Fl_Color_Chooser.H +++ b/FL/Fl_Color_Chooser.H @@ -30,8 +30,6 @@ #include #include -#include - #ifndef FL_DOXYGEN /** For internal use only */ @@ -62,7 +60,6 @@ public: class FL_EXPORT Flcc_Value_Input : public Fl_Value_Input { public: int format(char*); - std::string format_str(); Flcc_Value_Input(int X, int Y, int W, int H) : Fl_Value_Input(X,Y,W,H) {} }; diff --git a/FL/Fl_Help_View.H b/FL/Fl_Help_View.H index 079b6ef83..f636d0598 100644 --- a/FL/Fl_Help_View.H +++ b/FL/Fl_Help_View.H @@ -27,11 +27,6 @@ #include "Fl_Group.H" #include "Fl_Scrollbar.H" -// -// System and C++ header files -// - -#include // std::unique_ptr<> // // Forward declarations and typedefs @@ -119,7 +114,7 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { private: class Impl; - std::unique_ptr impl_; ///< Pointer to the implementation details + Impl *impl_; ///< Pointer to the implementation details Fl_Scrollbar scrollbar_; ///< Vertical scrollbar for document Fl_Scrollbar hscrollbar_; ///< Horizontal scrollbar diff --git a/FL/Fl_Plugin.H b/FL/Fl_Plugin.H index d2b1dd1bd..09daf6f97 100644 --- a/FL/Fl_Plugin.H +++ b/FL/Fl_Plugin.H @@ -22,9 +22,6 @@ #include "Fl_Preferences.H" -#include -#include - /** \brief Fl_Plugin allows link-time and run-time integration of binary modules. @@ -86,7 +83,6 @@ public: static void removePlugin(Fl_Preferences::ID id); static int load(const char *filename); static int loadAll(const char *dirpath, const char *pattern=0); - static std::vector klass_list(); }; diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H index 92cc966b3..d8fab7fc5 100644 --- a/FL/Fl_Preferences.H +++ b/FL/Fl_Preferences.H @@ -24,8 +24,6 @@ # include "Fl_Export.H" # include "fl_attr.h" -#include - /** \brief Fl_Preferences store user settings between application starts. @@ -242,7 +240,6 @@ public: char set( const char *entry, double value, int precision ); char set( const char *entry, const char *value ); char set( const char *entry, const void *value, int size ); - char set( const char *entry, const std::string &value ); char get( const char *entry, int &value, int defaultValue ); char get( const char *entry, float &value, float defaultValue ); @@ -252,7 +249,6 @@ public: char get( const char *entry, void *&value, const void *defaultValue, int defaultSize ); char get( const char *entry, void *value, const void *defaultValue, int defaultSize, int maxSize ); char get( const char *entry, void *value, const void *defaultValue, int defaultSize, int *size ); - char get( const char *entry, std::string &value, const std::string &defaultValue ); int size( const char *entry ); diff --git a/FL/Fl_Table_Row.H b/FL/Fl_Table_Row.H index ec5cd4512..6e17d356f 100644 --- a/FL/Fl_Table_Row.H +++ b/FL/Fl_Table_Row.H @@ -23,7 +23,7 @@ #include -#include +#include /** A table with row selection capabilities. diff --git a/FL/Fl_Text_Buffer.H b/FL/Fl_Text_Buffer.H index a9365d5c0..e27214a6c 100644 --- a/FL/Fl_Text_Buffer.H +++ b/FL/Fl_Text_Buffer.H @@ -23,7 +23,6 @@ #define FL_TEXT_BUFFER_H #include /* va_list */ -#include #include "fl_attr.h" /* Doxygen can't find */ #undef ASSERT_UTF8 @@ -231,12 +230,6 @@ public: */ char* text() const; - /** - \brief Get a copy of the entire contents of the text buffer. - \return text as a UTF-8 string - */ - std::string text_str() const; - /** Replaces the entire contents of the text buffer. \param text Text must be valid UTF-8. If null, an empty string is substituted. diff --git a/FL/Fl_Valuator.H b/FL/Fl_Valuator.H index 5855971fb..cca0495df 100644 --- a/FL/Fl_Valuator.H +++ b/FL/Fl_Valuator.H @@ -24,8 +24,6 @@ #include "Fl_Widget.H" #endif -#include - // shared type() values for classes that work in both directions: #define FL_VERTICAL 0 ///< The valuator can work vertically #define FL_HORIZONTAL 1 ///< The valuator can work horizontally @@ -128,7 +126,6 @@ public: int value(double); virtual int format(char*); - virtual std::string format_str(); double round(double); // round to nearest multiple of step double clamp(double); // keep in range double increment(double, int); // add n*step to value diff --git a/FL/core/pen_events.H b/FL/core/pen_events.H index 48ce47034..39310e4cb 100644 --- a/FL/core/pen_events.H +++ b/FL/core/pen_events.H @@ -26,31 +26,26 @@ #include // for FL_EXPORT #include // widget callbacks and services -#include +#include class Fl_Widget; -namespace Fl { - -/** FLTK Pen/Stylus/Tablet input driver API. */ -namespace Pen { - /** \defgroup fl_pen_events Pen and tablet event handling \ingroup fl_events - \brief This chapter documents the Fl::Pen namespace API, declared in + \brief This chapter documents the Fl_Pen API, declared in - The FL::Pen namespace contains everything needed to work with a pen type input + The Fl_Pen prefix contains everything needed to work with a pen type input device, either in connection with an external tablet, or as a stylus for drawing directly onto a screen. - To receive pen input, call Fl::Pen::subscribe() for one or more widgets. The - widget will receive a Fl::Pen::ENTER event when the stylus enters the widget - area. By returning 1 to Fl::Pen::ENTER, all further pen events are sent to - this widget, and no mouse events are generated until Fl::Pen::LEAVE. + To receive pen input, call Fl_Pen_subscribe() for one or more widgets. The + widget will receive a FL_PEN_ENTER event when the stylus enters the widget + area. By returning 1 to FL_PEN_ENTER, all further pen events are sent to + this widget, and no mouse events are generated until FL_PEN_LEAVE. - Returning 0 Fl::Pen::ENTER tells FLTK to suppress further pen events until - Fl::Pen::LEAVE, and convert them into mouse events instead. + Returning 0 to FL_PEN_ENTER tells FLTK to suppress further pen events until + FL_PEN_LEAVE, and convert them into mouse events instead. Pen events also set Fl::event_x(), Fl::event_y(), Fl::event_x_root(), Fl::event_y_root(), Fl::event_is_click(), and Fl::event_clicks(). @@ -60,137 +55,77 @@ namespace Pen { /** \brief Bitfield of traits. - This is used in Fl::Pen::driver_traits() and Fl::Pen::pen_traits(). + This is used in Fl_Pen_driver_traits() and Fl_Pen_pen_traits(). */ -enum class Trait : uint32_t { +typedef uint32_t Fl_Pen_Trait; +enum { /// No bits set - NONE = 0x0000, + FL_PEN_TRAIT_NONE = 0x0000, /// Set if FLTK supports tablets and pens on this platform - DRIVER_AVAILABLE = 0x0001, + FL_PEN_TRAIT_DRIVER_AVAILABLE = 0x0001, /// Set after the system detected a pen, stylus, or tablet. This bit may not be /// set until a pen is brought into proximity of the tablet. - DETECTED = 0x0002, + FL_PEN_TRAIT_DETECTED = 0x0002, /// If set, this is a digitizer for a display; if clear, this is a standalone tablet - DISPLAY = 0x0004, + FL_PEN_TRAIT_DISPLAY = 0x0004, /// Driver provides different device IDs for different pens - PEN_ID = 0x0008, + FL_PEN_TRAIT_PEN_ID = 0x0008, /// Pen may have an eraser tip - ERASER = 0x0010, + FL_PEN_TRAIT_ERASER = 0x0010, /// Pen returns a pressure value - PRESSURE = 0x0020, + FL_PEN_TRAIT_PRESSURE = 0x0020, /// Pen returns a barrel pressure value (tangential pressure) - BARREL_PRESSURE = 0x0040, + FL_PEN_TRAIT_BARREL_PRESSURE = 0x0040, /// Pen returns tilt in X direction - TILT_X = 0x0080, + FL_PEN_TRAIT_TILT_X = 0x0080, /// Pen returns tilt in Y direction - TILT_Y = 0x0100, + FL_PEN_TRAIT_TILT_Y = 0x0100, /// Pen returns a twist value - TWIST = 0x0200, + FL_PEN_TRAIT_TWIST = 0x0200, /// Pen returns a proximity value - PROXIMITY = 0x0400, + FL_PEN_TRAIT_PROXIMITY = 0x0400 }; -/** - \brief Bitwise OR operator for Trait enum. - \param lhs Left-hand side trait flags - \param rhs Right-hand side trait flags - \return Combined trait flags - */ -inline constexpr Trait operator|(Trait lhs, Trait rhs) { - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -/** - \brief Bitwise AND operator for Trait enum. - \param lhs Left-hand side trait flags - \param rhs Right-hand side trait flags - \return Intersection of trait flags - */ -inline constexpr Trait operator&(Trait lhs, Trait rhs) { - return static_cast(static_cast(lhs) & static_cast(rhs)); -} - -/** - \brief Bitwise OR assignment operator for Trait enum. - \param lhs Left-hand side trait flags (modified in place) - \param rhs Right-hand side trait flags - \return Reference to modified lhs - */ -inline Trait& operator|=(Trait& lhs, Trait rhs) { - lhs = lhs | rhs; - return lhs; -} - /** \brief Bitfield of pen state flags. - \see event_state(), event_trigger() + \see Fl_Pen_event_state(), Fl_Pen_event_trigger() */ -enum class State : uint32_t { +typedef uint32_t Fl_Pen_State; +enum { /// No button pressed - NONE = 0x0000, + FL_PEN_STATE_NONE = 0x0000, /// The tip hovers over the surface but does not touch it - TIP_HOVERS = 0x0001, + FL_PEN_STATE_TIP_HOVERS = 0x0001, /// The tip touches the surface - TIP_DOWN = 0x0002, + FL_PEN_STATE_TIP_DOWN = 0x0002, /// The eraser hovers over the surface but does not touch it - ERASER_HOVERS = 0x0004, + FL_PEN_STATE_ERASER_HOVERS = 0x0004, /// The eraser touches the surface - ERASER_DOWN = 0x0008, + FL_PEN_STATE_ERASER_DOWN = 0x0008, /// Barrel button 0, usually the lower button on a pen, is pressed - BUTTON0 = 0x0100, + FL_PEN_STATE_BUTTON0 = 0x0100, /// Barrel button 1, usually the upper button on a pen, is pressed - BUTTON1 = 0x0200, + FL_PEN_STATE_BUTTON1 = 0x0200, /// Barrel button 2 is pressed - BUTTON2 = 0x0400, + FL_PEN_STATE_BUTTON2 = 0x0400, /// Barrel button 3 is pressed - BUTTON3 = 0x0800, + FL_PEN_STATE_BUTTON3 = 0x0800, /// Mask for all buttons, tip, and eraser down - ANY_DOWN = BUTTON0 | BUTTON1 | BUTTON2 | BUTTON3 | TIP_DOWN | ERASER_DOWN, + FL_PEN_STATE_ANY_DOWN = 0x0100 | 0x0200 | 0x0400 | 0x0800 | 0x0002 | 0x0008 }; -/** - \brief Bitwise OR operator for State enum. - \param lhs Left-hand side state flags - \param rhs Right-hand side state flags - \return Combined state flags - */ -inline constexpr State operator|(State lhs, State rhs) { - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -/** - \brief Bitwise AND operator for State enum. - \param lhs Left-hand side state flags - \param rhs Right-hand side state flags - \return Intersection of state flags - */ -inline constexpr State operator&(State lhs, State rhs) { - return static_cast(static_cast(lhs) & static_cast(rhs)); -} - -/** - \brief Bitwise OR assignment operator for State enum. - \param lhs Left-hand side state flags (modified in place) - \param rhs Right-hand side state flags - \return Reference to modified lhs - */ -inline State& operator|=(State& lhs, State rhs) { - lhs = lhs | rhs; - return lhs; -} - /** \brief List of pen events. These events extend the standard Fl_Event enumeration. \see enum Fl_Event */ -enum Event { +enum { /** Pen entered the proximity of the tablet with a new pen. */ - DETECTED = 0x1000, + FL_PEN_DETECTED = 0x1000, /** Pen entered the proximity of the tablet with a known, but changed pen. @@ -198,63 +133,63 @@ enum Event { was disconnected (event_id() == -1). Pen IDs, if supported, are assigned by the tablet manufacturer. */ - CHANGED, + FL_PEN_CHANGED, /** Pen entered the proximity of the tablet with a known pen. */ - IN_RANGE, + FL_PEN_IN_RANGE, /** Pen left the proximity of the tablet. */ - OUT_OF_RANGE, + FL_PEN_OUT_OF_RANGE, /** Pen entered the widget area, either by moving in x/y, or by a proximity change (pen gets closer to the surface). - event_trigger() returns 0, TIP_HOVERS, or ERASER_HOVERS. + Fl_Pen_event_trigger() returns 0, FL_PEN_STATE_TIP_HOVERS, or FL_PEN_STATE_ERASER_HOVERS. */ - ENTER, + FL_PEN_ENTER, /** If no button is pressed, indicates that the pen left the widget area. While any pen button is held down, or the pen touches the surface, Fl::pushed() is set, and the pushed widgets receives DRAG events, even if the pen leaves the widget area. If all buttons are released outside the - widget area, a LEAVE event is sent as well as LIFT or BUTTON_RELEASE. + widget area, a LEAVE event is sent as well as FL_PEN_LIFT or FL_PEN_BUTTON_RELEASE. */ - LEAVE, + FL_PEN_LEAVE, /** Pen went from hovering to touching the surface. - event_trigger() returns TIP_DOWN or ERASER_DOWN. + Fl_Pen_event_trigger() returns FL_PEN_STATE_TIP_DOWN or FL_PEN_STATE_ERASER_DOWN. */ - TOUCH, + FL_PEN_TOUCH, /** Pen went from touching to hovering over the surface. - event_trigger() returns TIP_HOVERS or ERASER_HOVERS. + Fl_Pen_event_trigger() returns FL_PEN_STATE_TIP_HOVERS or FL_PEN_STATE_ERASER_HOVERS. */ - LIFT, + FL_PEN_LIFT, /** Pen moved without touching the surface and no button is pressed. */ - HOVER, + FL_PEN_HOVER, /** Pen moved while touching the surface, or any button is pressed. */ - DRAW, + FL_PEN_DRAW, /** A pen button was pushed. - event_trigger() returns BUTTON0, BUTTON1, BUTTON2, or BUTTON3. + Fl_Pen_event_trigger() returns FL_PEN_STATE_BUTTON0, FL_PEN_STATE_BUTTON1, FL_PEN_STATE_BUTTON2, or FL_PEN_STATE_BUTTON3. */ - BUTTON_PUSH, + FL_PEN_BUTTON_PUSH, /** A pen button was released. - event_trigger() returns BUTTON0, BUTTON1, BUTTON2, or BUTTON3. + Fl_Pen_event_trigger() returns FL_PEN_STATE_BUTTON0, FL_PEN_STATE_BUTTON1, FL_PEN_STATE_BUTTON2, or FL_PEN_STATE_BUTTON3. */ - BUTTON_RELEASE + FL_PEN_BUTTON_RELEASE }; @@ -264,67 +199,67 @@ enum Event { This function returns a bitfield of traits that are supported by the FLTK driver for this platform. If a trait is not supported, the corresponding event value will not return a useful value. Note that even if the FLTK driver support a - trait, the underlying pen device or driver may not. Fl::Pen will return a - known default for those event values. + trait, the underlying pen device or driver may not. The Fl_Pen API will return + a known default for those event values. The bitfield returned is static. \return a bitfield of supported traits - \see pen_traits() + \see Fl_Pen_pen_traits() */ -FL_EXPORT extern Trait driver_traits(); +FL_EXPORT Fl_Pen_Trait Fl_Pen_driver_traits(void); /** - \brief Return true if the corresponding bit is set in the driver traits. + \brief Return non-zero if the corresponding bit is set in the driver traits. \param[in] bits check for one or more trait bits - \return true if any bit is set + \return non-zero if any bit is set */ -inline bool driver_traits(Trait bits) { - return ((driver_traits() & bits) != Trait::NONE); +inline int Fl_Pen_driver_traits_check(Fl_Pen_Trait bits) { + return ((Fl_Pen_driver_traits() & bits) != FL_PEN_TRAIT_NONE); } /** \brief Query traits of the current pen or stylus. The value returned by this function may change when pens change or when more information becomes known about the currently used pen. - \param[in] pen_id a know pen ID as returned from event_pen_id(), + \param[in] pen_id a know pen ID as returned from Fl_Pen_event_pen_id(), or 0 for the current pen \return a bitfield of supported traits */ -FL_EXPORT extern Trait pen_traits(int pen_id = 0); +FL_EXPORT Fl_Pen_Trait Fl_Pen_pen_traits(int pen_id); /** - \brief Return true if the corresponding bit is set in the pen traits. + \brief Return non-zero if the corresponding bit is set in the pen traits. \param[in] bits check for one or more trait bits - \param[in] pen_id a know pen ID as returned from event_pen_id(), + \param[in] pen_id a know pen ID as returned from Fl_Pen_event_pen_id(), or 0 for the current pen - \return true if any bit is set + \return non-zero if any bit is set */ -inline bool pen_traits(Trait bits, int pen_id = 0) { - return ((pen_traits() & bits) != Trait::NONE); +inline int Fl_Pen_pen_traits_check(Fl_Pen_Trait bits, int pen_id) { + return ((Fl_Pen_pen_traits(pen_id) & bits) != FL_PEN_TRAIT_NONE); } /** - \brief Receives a Pen::ENTER event when the pen enters this widget. + \brief Receives a FL_PEN_ENTER event when the pen enters this widget. Multiple widgets may subscribe to pen events. Additional subscription requests for the same widget are ignored. \param widget The widget subscribing to pen events. */ -FL_EXPORT extern void subscribe(Fl_Widget* widget); +FL_EXPORT void Fl_Pen_subscribe(Fl_Widget* widget); /** - \brief Stop receiving Pen::ENTER for this widget. + \brief Stop receiving FL_PEN_ENTER for this widget. Deleting a widget will automatically unsubscribe it. \param widget Widget to unsubscribe from pen events */ -FL_EXPORT extern void unsubscribe(Fl_Widget* widget); +FL_EXPORT void Fl_Pen_unsubscribe(Fl_Widget* widget); /** Clear the "pushed" state and forward pen events as mouse events. Call this if another window is popped up during pen event handling, so mouse event handling can resume normal. */ -FL_EXPORT extern void release(); +FL_EXPORT void Fl_Pen_release(void); /// \name Query values during event handling /// @{ @@ -337,9 +272,9 @@ FL_EXPORT extern void release(); \return Pen position as floating-point coordinate, defaults to 0.0 \see Fl::event_x(), Fl::event_y() */ -FL_EXPORT extern double event_x(); -/** \brief Returns pen Y coordinate in widget space, see event_x(). */ -FL_EXPORT extern double event_y(); +FL_EXPORT double Fl_Pen_event_x(void); +/** \brief Returns pen Y coordinate in widget space, see Fl_Pen_event_x(). */ +FL_EXPORT double Fl_Pen_event_y(void); /** \brief Returns the pen x and y position in global coordinates as doubles. @@ -347,31 +282,31 @@ FL_EXPORT extern double event_y(); \return Pen position as floating-point coordinate in screen space, defaults to 0.0 \see Fl::event_x_root(), Fl::event_y_root() */ -FL_EXPORT extern double event_x_root(); -/** \brief Returns pen Y coordinate in screen space, see event_x_root(). */ -FL_EXPORT extern double event_y_root(); +FL_EXPORT double Fl_Pen_event_x_root(void); +/** \brief Returns pen Y coordinate in screen space, see Fl_Pen_event_x_root(). */ +FL_EXPORT double Fl_Pen_event_y_root(void); /** \brief Returns the ID of the pen used in the last event. \return Unique pen identifier, or -1 if pen was removed, defaults to 0 - \see Trait::PEN_ID + \see FL_PEN_TRAIT_PEN_ID */ -FL_EXPORT extern int event_pen_id(); +FL_EXPORT int Fl_Pen_event_pen_id(void); /** \brief Returns the pressure between the tip or eraser and the surface. \return pressure value from 0.0 (no pressure) to 1.0 (maximum pressure), defaults to 1.0. - \see Trait::PRESSURE + \see FL_PEN_TRAIT_PRESSURE */ -FL_EXPORT extern double event_pressure(); +FL_EXPORT double Fl_Pen_event_pressure(void); /** \brief Returns barrel pressure or tangential pressure. \return Pressure value from -1.0 to 1.0 , defaults to 0.0 . - \see Trait::BARREL_PRESSURE + \see FL_PEN_TRAIT_BARREL_PRESSURE */ -FL_EXPORT extern double event_barrel_pressure(); +FL_EXPORT double Fl_Pen_event_barrel_pressure(void); /** \brief Returns the tilt of the pen in the x and y directions between -1 and 1. @@ -384,61 +319,56 @@ FL_EXPORT extern double event_barrel_pressure(); it tilts toward the user. \return Tilt value from -1.0 to 1.0, defaults to 0.0 - \see Trait::TILT_X, Trait::TILT_Y + \see FL_PEN_TRAIT_TILT_X, FL_PEN_TRAIT_TILT_Y */ -FL_EXPORT extern double event_tilt_x(); -/** \brief Returns pen Y-axis tilt, see event_tilt_x() */ -FL_EXPORT extern double event_tilt_y(); +FL_EXPORT double Fl_Pen_event_tilt_x(void); +/** \brief Returns pen Y-axis tilt, see Fl_Pen_event_tilt_x() */ +FL_EXPORT double Fl_Pen_event_tilt_y(void); /** \brief Returns the pen's axial rotation in degrees. The twist angle is reported in degrees, with: - - 0° : pen’s “top” (the button side) facing upward - - +180° : twisted halfway clockwise, looking at the end of the pen toward the tip - - –180° → twisted half way counter clockwise - So the full range is usually –180° to +180°. + - 0 deg : pen's "top" (the button side) facing upward + - +180 deg : twisted halfway clockwise, looking at the end of the pen toward the tip + - -180 deg : twisted half way counter clockwise + So the full range is usually -180 to +180. \return Twist angle in degrees, defaults to 0.0. - \see Trait::TWIST + \see FL_PEN_TRAIT_TWIST */ -FL_EXPORT extern double event_twist(); +FL_EXPORT double Fl_Pen_event_twist(void); /** \brief Returns the proximity of the pen to the surface between 0 and 1. A proximity of 0 is closest to the surface, 1 is farthest away. \return Proximity value from 0.0 (touching) to 1.0 (far away), defaults to 0.0 . - \see Trait::PROXIMITY + \see FL_PEN_TRAIT_PROXIMITY */ -FL_EXPORT extern double event_proximity(); +FL_EXPORT double Fl_Pen_event_proximity(void); /** \brief Returns the state of the various buttons and tips. - \return Current state flags (combination of State values) + \return Current state flags (combination of Fl_Pen_State values) */ -FL_EXPORT extern State event_state(); +FL_EXPORT Fl_Pen_State Fl_Pen_event_state(void); /** - \brief Return true if any of the bits are set in the event state. + \brief Return non-zero if any of the bits are set in the event state. \param[in] bits check for one or more event state bits - \return true if any bit is set + \return non-zero if any bit is set */ -inline bool event_state(State bits) { - return ((event_state() & bits) != State::NONE); +inline int Fl_Pen_event_state_check(Fl_Pen_State bits) { + return ((Fl_Pen_event_state() & bits) != FL_PEN_STATE_NONE); } /** \brief Returns the state change that triggered the event. \return a state with one bit set for the action that triggered this event */ -FL_EXPORT extern State event_trigger(); +FL_EXPORT Fl_Pen_State Fl_Pen_event_trigger(void); /** @} */ // group fl_pen_events -} // namespace Pen - -} // namespace Fl - - /* Resources: diff --git a/FL/filename.H b/FL/filename.H index 74ef1c91c..4aae10275 100644 --- a/FL/filename.H +++ b/FL/filename.H @@ -31,11 +31,6 @@ #include #ifdef __cplusplus - -// The following include is not (yet) used in FLTK 1.4 -// In FLTK 1.5 or 4.0 using std::string would be default. -// #include - #endif /* __cplusplus */ /** \addtogroup filenames File names and URI utility functions @@ -72,18 +67,6 @@ FL_EXPORT int fl_filename_isdir(const char *name); FL_EXPORT int fl_filename_absolute(char *to, int tolen, const char *from, const char *cwd); FL_EXPORT int fl_filename_relative(char *to, int tolen, const char *from, const char *cwd); -#include - -FL_EXPORT std::string fl_filename_name_str(const std::string &filename); -FL_EXPORT std::string fl_filename_path_str(const std::string &filename); -FL_EXPORT std::string fl_filename_ext_str(const std::string &filename); -FL_EXPORT std::string fl_filename_setext_str(const std::string &filename, const std::string &new_extension); -FL_EXPORT std::string fl_filename_expand_str(const std::string &from); -FL_EXPORT std::string fl_filename_absolute_str(const std::string &from); -FL_EXPORT std::string fl_filename_absolute_str(const std::string &from, const std::string &base); -FL_EXPORT std::string fl_filename_relative_str(const std::string &from); -FL_EXPORT std::string fl_filename_relative_str(const std::string &from, const std::string &base); -FL_EXPORT std::string fl_getcwd_str(); # endif /* defined(__cplusplus) */ diff --git a/FL/fl_ask.H b/FL/fl_ask.H index d596e9347..9ff169521 100644 --- a/FL/fl_ask.H +++ b/FL/fl_ask.H @@ -24,8 +24,6 @@ #include #include -#include - // Note to FLTK developers: fl_ask() had been deprecated since FLTK 1.1.7 // (released Jan 17, 2006 !) but was still available in FLTK 1.4.x. // FLTK 1.5 disables it by using an *undocumented* preprocessor macro. @@ -95,24 +93,6 @@ FL_EXPORT const char *fl_input(int maxchar, const char *label, const char *deflt FL_EXPORT const char *fl_password(int maxchar, const char *label, const char *deflt = 0, ...) __fl_attr((__format__(__printf__, 2, 4))); -// since FLTK 1.4.0 -- optional -// since FLTK 1.5.0 -- always - -// - fl_input_str() with limited input size, returns std::string -// - fl_password_str() with limited input size, returns std::string - -FL_EXPORT std::string fl_input_str(int maxchar, const char *label, const char *deflt = 0, ...) - __fl_attr((__format__(__printf__, 2, 4))); - -FL_EXPORT std::string fl_input_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...) - __fl_attr((__format__(__printf__, 3, 5))); - -FL_EXPORT std::string fl_password_str(int maxchar, const char *label, const char *deflt = 0, ...) - __fl_attr((__format__(__printf__, 2, 4))); - -FL_EXPORT std::string fl_password_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...) - __fl_attr((__format__(__printf__, 3, 5))); - FL_EXPORT Fl_Widget *fl_message_icon(); extern FL_EXPORT Fl_Font fl_message_font_; extern FL_EXPORT Fl_Fontsize fl_message_size_; diff --git a/FL/names.h b/FL/names.h index 33bc6caa4..0cdc9edea 100644 --- a/FL/names.h +++ b/FL/names.h @@ -25,8 +25,6 @@ #define FL_NAMES_H #include // for event constants -#include -#include /** \defgroup fl_events Events handling functions @{ @@ -47,63 +45,53 @@ } \endcode */ -static std::map fl_eventnames = { - { FL_NO_EVENT, "FL_NO_EVENT" }, - { FL_PUSH, "FL_PUSH" }, - { FL_RELEASE, "FL_RELEASE" }, - { FL_ENTER, "FL_ENTER" }, - { FL_LEAVE, "FL_LEAVE" }, - { FL_DRAG, "FL_DRAG" }, - { FL_FOCUS, "FL_FOCUS" }, - { FL_UNFOCUS, "FL_UNFOCUS" }, - { FL_KEYDOWN, "FL_KEYDOWN" }, - { FL_KEYUP, "FL_KEYUP" }, - { FL_CLOSE, "FL_CLOSE" }, - { FL_MOVE, "FL_MOVE" }, - { FL_SHORTCUT, "FL_SHORTCUT" }, - { FL_DEACTIVATE, "FL_DEACTIVATE" }, - { FL_ACTIVATE, "FL_ACTIVATE" }, - { FL_HIDE, "FL_HIDE" }, - { FL_SHOW, "FL_SHOW" }, - { FL_PASTE, "FL_PASTE" }, - { FL_SELECTIONCLEAR, "FL_SELECTIONCLEAR" }, - { FL_MOUSEWHEEL, "FL_MOUSEWHEEL" }, - { FL_DND_ENTER, "FL_DND_ENTER" }, - { FL_DND_DRAG, "FL_DND_DRAG" }, - { FL_DND_LEAVE, "FL_DND_LEAVE" }, - { FL_DND_RELEASE, "FL_DND_RELEASE" }, - { FL_SCREEN_CONFIGURATION_CHANGED, "FL_SCREEN_CONFIGURATION_CHANGED" }, - { FL_FULLSCREEN, "FL_FULLSCREEN" }, - { FL_ZOOM_GESTURE, "FL_ZOOM_GESTURE" }, - { FL_ZOOM_EVENT, "FL_ZOOM_EVENT" }, - { FL_BEFORE_TOOLTIP, "FL_BEFORE_TOOLTIP" }, - { FL_BEFORE_MENU, "FL_BEFORE_MENU" }, - { FL_APP_ACTIVATE, "FL_APP_ACTIVATE" }, - { FL_APP_DEACTIVATE, "FL_APP_DEACTIVATE" }, - { Fl::Pen::DETECTED, "Fl::Pen::DETECTED" }, - { Fl::Pen::CHANGED, "Fl::Pen::CHANGED" }, - { Fl::Pen::ENTER, "Fl::Pen::ENTER" }, - { Fl::Pen::LEAVE, "Fl::Pen::LEAVE" }, - { Fl::Pen::TOUCH, "Fl::Pen::TOUCH" }, - { Fl::Pen::LIFT, "Fl::Pen::LIFT" }, - { Fl::Pen::HOVER, "Fl::Pen::HOVER" }, - { Fl::Pen::DRAW, "Fl::Pen::DRAW" }, - { Fl::Pen::BUTTON_PUSH, "Fl::Pen::BUTTON_PUSH" }, - { Fl::Pen::BUTTON_RELEASE, "Fl::Pen::BUTTON_RELEASE" } +static const char * const fl_eventnames[] = { + "FL_NO_EVENT", + "FL_PUSH", + "FL_RELEASE", + "FL_ENTER", + "FL_LEAVE", + "FL_DRAG", + "FL_FOCUS", + "FL_UNFOCUS", + "FL_KEYDOWN", + "FL_KEYUP", + "FL_CLOSE", + "FL_MOVE", + "FL_SHORTCUT", + "FL_DEACTIVATE", + "FL_ACTIVATE", + "FL_HIDE", + "FL_SHOW", + "FL_PASTE", + "FL_SELECTIONCLEAR", + "FL_MOUSEWHEEL", + "FL_DND_ENTER", + "FL_DND_DRAG", + "FL_DND_LEAVE", + "FL_DND_RELEASE", + "FL_SCREEN_CONFIGURATION_CHANGED", + "FL_FULLSCREEN", + "FL_ZOOM_GESTURE", + "FL_ZOOM_EVENT", + "FL_BEFORE_TOOLTIP", + "FL_BEFORE_MENU", + "FL_APP_ACTIVATE", + "FL_APP_DEACTIVATE" }; +#define FL_EVENTNAMES_MAX 32 + /** Return the C++ symbol of an Fl_Event as a string. \param[in] event index as an integer - \return C++ symbol of event index as a string + \return C++ symbol of event index as a string, or 0 if out of range */ -inline std::string fl_eventname_str(int event) { - auto it = fl_eventnames.find(event); - if (it == fl_eventnames.end()) { - return "FL_EVENT_" + std::to_string(event); - } else { - return it->second; +inline const char *fl_eventname(int event) { + if (event >= 0 && event < FL_EVENTNAMES_MAX) { + return fl_eventnames[event]; } + return 0; } @@ -147,14 +135,13 @@ const char * const fl_fontnames[] = /** Return the C++ symbol of an Fl_Font as a string. \param[in] font index as an integer - \return C++ symbol of font index as a string + \return C++ symbol of font index as a string, or 0 if out of range */ -inline std::string fl_fontname_str(int font) { - if ((font < 0) || (font >= FL_ZAPF_DINGBATS)) { - return "FL_FONT_" + std::to_string(font); - } else { +inline const char *fl_fontname(int font) { + if (font >= 0 && font <= FL_ZAPF_DINGBATS) { return fl_fontnames[font]; } + return 0; } @@ -178,23 +165,24 @@ const char * const fl_callback_reason_names[] = "FL_REASON_LOST_FOCUS", "FL_REASON_RELEASED", "FL_REASON_ENTER_KEY", - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, "FL_REASON_USER", "FL_REASON_USER+1", "FL_REASON_USER+2", "FL_REASON_USER+3", }; +#define FL_REASON_NAMES_MAX 36 + /** Return the C++ symbol of an Fl_Callback_Reason as a string. \param[in] reason as an integer - \return C++ symbol of reason as a string + \return C++ symbol of reason as a string, or 0 if out of range or invalid */ -inline std::string fl_callback_reason_str(int reason) { - if ((reason < 0) || (reason >= FL_REASON_USER+3) || (fl_callback_reason_names[reason] == 0)) { - return "FL_REASON_" + std::to_string(reason); - } else { +inline const char *fl_callback_reason_name(int reason) { + if (reason >= 0 && reason < FL_REASON_NAMES_MAX) { return fl_callback_reason_names[reason]; } + return 0; } /** @} */ diff --git a/bin/fluid b/bin/fluid deleted file mode 100755 index 3a0076317..000000000 Binary files a/bin/fluid and /dev/null differ diff --git a/lib/libfltk 2.a b/lib/libfltk 2.a index ba76187dc..b74f1b0fc 100644 Binary files a/lib/libfltk 2.a and b/lib/libfltk 2.a differ diff --git a/lib/libfltk.a b/lib/libfltk.a index dbf965448..856ab0207 100644 Binary files a/lib/libfltk.a and b/lib/libfltk.a differ diff --git a/lib/libfltk_forms 2.a b/lib/libfltk_forms 2.a deleted file mode 100644 index 1fa091713..000000000 Binary files a/lib/libfltk_forms 2.a and /dev/null differ diff --git a/lib/libfltk_forms.a b/lib/libfltk_forms.a deleted file mode 100644 index c4cc0703b..000000000 Binary files a/lib/libfltk_forms.a and /dev/null differ diff --git a/lib/libfltk_gl 2.a b/lib/libfltk_gl 2.a deleted file mode 100644 index bd4254c7e..000000000 Binary files a/lib/libfltk_gl 2.a and /dev/null differ diff --git a/lib/libfltk_gl.a b/lib/libfltk_gl.a deleted file mode 100644 index 5bbcbd06f..000000000 Binary files a/lib/libfltk_gl.a and /dev/null differ diff --git a/lib/libfltk_images 2.a b/lib/libfltk_images 2.a deleted file mode 100644 index 917d48dfc..000000000 Binary files a/lib/libfltk_images 2.a and /dev/null differ diff --git a/lib/libfltk_images.a b/lib/libfltk_images.a deleted file mode 100644 index b23c4094e..000000000 Binary files a/lib/libfltk_images.a and /dev/null differ diff --git a/lib/libfltk_jpeg 2.a b/lib/libfltk_jpeg 2.a deleted file mode 100644 index bcf7bf8d6..000000000 Binary files a/lib/libfltk_jpeg 2.a and /dev/null differ diff --git a/lib/libfltk_jpeg.a b/lib/libfltk_jpeg.a deleted file mode 100644 index 49f2ddfd9..000000000 Binary files a/lib/libfltk_jpeg.a and /dev/null differ diff --git a/lib/libfltk_png 2.a b/lib/libfltk_png 2.a deleted file mode 100644 index 87e370537..000000000 Binary files a/lib/libfltk_png 2.a and /dev/null differ diff --git a/lib/libfltk_png.a b/lib/libfltk_png.a deleted file mode 100644 index 90191e8f9..000000000 Binary files a/lib/libfltk_png.a and /dev/null differ diff --git a/lib/libfltk_z 2.a b/lib/libfltk_z 2.a deleted file mode 100644 index 06adfe745..000000000 Binary files a/lib/libfltk_z 2.a and /dev/null differ diff --git a/lib/libfltk_z.a b/lib/libfltk_z.a deleted file mode 100644 index 7039a61fa..000000000 Binary files a/lib/libfltk_z.a and /dev/null differ 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::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 @@ -44,9 +44,7 @@ #include #include #include -#include -#include -#include +#include // // 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 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 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 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" - "

Error

" - "

Unable to follow the link \"" - + std::string(f) + "\" - " + std::string(urimsg) + ".

"; - value(error.c_str()); + snprintf(error, sizeof(error), + "Error" + "

Error

" + "

Unable to follow the link \"%s\" - %s.

", + 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 = "Error" - "

Error

" - "

Unable to follow the link \"" +localname + "\" - " - + strerror(errno) + ".

"; - value_ = fl_strdup(error.c_str()); + snprintf(error, sizeof(error), + "Error" + "

Error

" + "

Unable to follow the link \"%s\" - %s.

", + 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 -#include 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 #include -#include - /* The format of preferences files is not part of the FLTK specification and intentionally undocumented in Doxygen. The following documentation is FOR @@ -964,35 +962,6 @@ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue return ( v != 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 @@ -1163,21 +1132,6 @@ char Fl_Preferences::set( const char *key, const void *data, int dsize ) { return 1; } -/** - 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. @@ -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 Fl_Plugin_Manager::klass_list() { - Fl_Preferences p(0, "plugins"); - std::vector 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 // strlen #include // vprintf, va_list #include -#include #include #include @@ -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; coltext_utf8(); // first byte of char - for (int i=0; ilength(); 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; ilength()==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 @@ -267,21 +267,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. */ 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_Timeout::timeout_list() { - std::vector 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 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 #include +#include #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 #include -#include -#include - 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> { +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 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 pushed_; -extern std::shared_ptr 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 class Fl_Widget; -namespace Fl { - -namespace Pen { - -EventData e; -SubscriberList subscriber_list_; -std::shared_ptr pushed_; -std::shared_ptr 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 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(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 # include # include -# include // 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 #include // strerror(errno) #include // errno -#include #if HAVE_DLSYM && HAVE_DLFCN_H #include // 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). @@ -350,70 +348,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 \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, @@ -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 \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(). -- cgit v1.2.3