Help_View: Improve target line management

This commit is contained in:
Matthias Melcher
2025-07-02 17:54:32 +02:00
parent a05ae33e20
commit e4d43a3951
2 changed files with 29 additions and 71 deletions
+8 -13
View File
@@ -32,6 +32,10 @@
#include "fl_draw.H"
#include "filename.H"
#include <map>
#include <vector>
#include <string>
class Fl_Shared_Image;
//
// Fl_Help_Func type - link callback function for files...
@@ -122,12 +126,6 @@ protected:
Fl_Help_Font_Style elts_[MAX_FL_HELP_FS_ELTS]; ///< font elements
};
/** Fl_Help_Target structure */
struct Fl_Help_Target {
char name[32]; ///< Target name
int y; ///< Y offset of target
};
/**
The Fl_Help_View widget displays HTML text. Most HTML 2.0
@@ -221,9 +219,7 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
alinks_; ///< Allocated links
Fl_Help_Link *links_; ///< Links
int ntargets_, ///< Number of targets
atargets_; ///< Allocated targets
Fl_Help_Target *targets_; ///< Targets
std::map<std::string, int> target_line_map_; ///< Map of targets for fast access
// FIXME: do we really need this size?
char directory_[2 * FL_PATH_MAX + 15]; ///< Directory for current file
@@ -261,10 +257,9 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
Fl_Help_Block *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0);
void add_link(const char *n, int xx, int yy, int ww, int hh);
void add_target(const char *n, int yy);
static int compare_targets(const Fl_Help_Target *t0, const Fl_Help_Target *t1);
int do_align(Fl_Help_Block *block, int line, int xx, int a, int &l);
protected:
void draw() FL_OVERRIDE;
void draw() override;
private:
void format();
void format_table(int *table_width, int *columns, const char *table);
@@ -275,7 +270,7 @@ private:
Fl_Shared_Image *get_image(const char *name, int W, int H);
int get_length(const char *l);
public:
int handle(int) FL_OVERRIDE;
int handle(int) override;
private:
void hv_draw(const char *t, int x, int y, int entity_extra_length = 0);
@@ -323,7 +318,7 @@ public:
*/
void link(Fl_Help_Func *fn) { link_ = fn; }
int load(const char *f);
void resize(int,int,int,int) FL_OVERRIDE;
void resize(int,int,int,int) override;
/** Gets the size of the help view. */
int size() const { return (size_); }
void size(int W, int H) { Fl_Widget::size(W, H); }
+21 -58
View File
@@ -84,6 +84,15 @@ static int quote_char(const char *);
static void scrollbar_callback(Fl_Widget *s, void *);
static void hscrollbar_callback(Fl_Widget *s, void *);
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);
}
return lower_str;
}
// This function skips 'n' bytes *within* a string, i.e. it checks
// for a NUL byte as string terminator.
// If a NUL byte is found before 'n' bytes have been scanned it returns
@@ -451,34 +460,10 @@ void Fl_Help_View::add_link(const char *n, // I - Name of link
void Fl_Help_View::add_target(const char *n, // I - Name of target
int yy) // I - Y position of target
{
Fl_Help_Target *temp; // New target
if (ntargets_ >= atargets_)
{
atargets_ += 16;
if (atargets_ == 16)
targets_ = (Fl_Help_Target *)malloc(sizeof(Fl_Help_Target) * atargets_);
else
targets_ = (Fl_Help_Target *)realloc(targets_, sizeof(Fl_Help_Target) * atargets_);
}
temp = targets_ + ntargets_;
temp->y = yy;
strlcpy(temp->name, n, sizeof(temp->name));
ntargets_ ++;
std::string target = to_lower(n); // Convert target name to lower case
target_line_map_[target] = yy; // Store the target line in the map
}
/** Compares two targets.*/
int // O - Result of comparison
Fl_Help_View::compare_targets(const Fl_Help_Target *t0, // I - First target
const Fl_Help_Target *t1) // I - Second target
{
return (strcasecmp(t0->name, t1->name));
}
/** Computes the alignment for a line in a block.*/
int // O - New line
@@ -1261,7 +1246,7 @@ void Fl_Help_View::format() {
done = 1;
nblocks_ = 0;
nlinks_ = 0;
ntargets_ = 0;
target_line_map_.clear();
size_ = 0;
bgcolor_ = color();
textcolor_ = textcolor();
@@ -1992,10 +1977,6 @@ void Fl_Help_View::format() {
// printf("margins.depth_=%d\n", margins.depth_);
if (ntargets_ > 1)
qsort(targets_, ntargets_, sizeof(Fl_Help_Target),
(compare_func_t)compare_targets);
int dx = Fl::box_dw(b) - Fl::box_dx(b);
int dy = Fl::box_dh(b) - Fl::box_dy(b);
int ss = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
@@ -2556,14 +2537,7 @@ Fl_Help_View::free_data() {
nlinks_ = 0;
links_ = 0;
}
if (ntargets_) {
free(targets_);
atargets_ = 0;
ntargets_ = 0;
targets_ = 0;
}
target_line_map_.clear();
} // free_data()
/** Gets an alignment attribute. */
@@ -3275,10 +3249,6 @@ Fl_Help_View::Fl_Help_View(int xx, // I - Left position
nlinks_ = 0;
links_ = (Fl_Help_Link *)0;
atargets_ = 0;
ntargets_ = 0;
targets_ = (Fl_Help_Target *)0;
directory_[0] = '\0';
filename_[0] = '\0';
@@ -3492,23 +3462,16 @@ Fl_Help_View::resize(int xx, // I - New left position
void
Fl_Help_View::topline(const char *n) // I - Target name
{
Fl_Help_Target key, // Target name key
*target; // Pointer to matching target
if (ntargets_ == 0)
return;
strlcpy(key.name, n, sizeof(key.name));
target = (Fl_Help_Target *)bsearch(&key, targets_, ntargets_, sizeof(Fl_Help_Target),
(compare_func_t)compare_targets);
if (target != NULL)
topline(target->y);
std::string target_name = to_lower(n); // Convert to lower case
auto tl = target_line_map_.find(target_name);
if (tl != target_line_map_.end()) {
// Found the target name, scroll to the line
topline(tl->second);
} else {
topline(0);
}
}
/** Scrolls the text to the indicated position, given a pixel line.
If the given pixel value \p top is out of range, then the text is