summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2025-12-06 02:29:57 +0100
committerMatthias Melcher <github@matthiasm.com>2025-12-06 02:29:57 +0100
commit5e7ed2f6534bf8d99688e375c56f44f792bdf7bb (patch)
treebd59017682dad0a5887faf4b6cfe0bc8389ca9c6 /fluid
parentb2746ad28693d61cecaa1e9fb57ab93c0050e3d3 (diff)
Fluid: fix class prefix user input check.
Diffstat (limited to 'fluid')
-rw-r--r--fluid/io/Project_Reader.cxx7
-rw-r--r--fluid/nodes/Function_Node.cxx19
-rw-r--r--fluid/nodes/Function_Node.h10
-rw-r--r--fluid/nodes/Node.cxx6
-rw-r--r--fluid/panels/widget_panel.cxx40
-rw-r--r--fluid/panels/widget_panel.fl48
6 files changed, 86 insertions, 44 deletions
diff --git a/fluid/io/Project_Reader.cxx b/fluid/io/Project_Reader.cxx
index 0eeee8014..a4c3695d6 100644
--- a/fluid/io/Project_Reader.cxx
+++ b/fluid/io/Project_Reader.cxx
@@ -320,11 +320,10 @@ Node *Project_Reader::read_children(Node *p, int merge, Strategy strategy, char
c = read_word(1);
// There can actually be two keywords here. The first one used to be a
- // "prefix" in Fluid < 1.5.0, but is no longer supported. So if we still
- // find the prefix in files, it will simply be prefixed to the name.
+ // "prefix", i.e. class attributes.
if (strcmp(c,"{") && t->is_class()) { // <prefix> <name>
- std::string tmp = std::string {t->name() } + " " + c;
- t->name(tmp.c_str());
+ ((Class_Node*)t)->prefix( t->name() );
+ t->name( c );
c = read_word(1);
}
diff --git a/fluid/nodes/Function_Node.cxx b/fluid/nodes/Function_Node.cxx
index 095b3fc5f..3e98a898f 100644
--- a/fluid/nodes/Function_Node.cxx
+++ b/fluid/nodes/Function_Node.cxx
@@ -1514,8 +1514,7 @@ Class_Node Class_Node::prototype;
Class_Node::Class_Node() :
Node(),
subclass_of(nullptr),
- public_(1),
- class_prefix(nullptr)
+ public_(1)
{ }
/**
@@ -1524,8 +1523,6 @@ Class_Node::Class_Node() :
Class_Node::~Class_Node() {
if (subclass_of)
free((void*)subclass_of);
- if (class_prefix)
- free((void*)class_prefix);
}
/**
@@ -1536,14 +1533,6 @@ int Class_Node::is_public() const {
}
/**
- Set the prefixx string.
- */
-void Class_Node::prefix(const char*p) {
- free((void*) class_prefix);
- class_prefix=fl_strdup(p ? p : "" );
-}
-
-/**
Make a new class node.
\param[in] strategy add after current or as last child
\return new Class node
@@ -1559,7 +1548,7 @@ Node *Class_Node::make(Strategy strategy) {
}
Class_Node *o = new Class_Node();
o->name("UserInterface");
- o->class_prefix = nullptr;
+ o->prefix("");
o->subclass_of = nullptr;
o->public_ = 1;
o->add(anchor, strategy);
@@ -1615,8 +1604,8 @@ void Class_Node::write_code1(fld::io::Code_Writer& f) {
write_public_state = 0;
f.write_h("\n");
write_comment_h(f);
- if (prefix() && strlen(prefix()))
- f.write_h("class %s %s ", prefix(), name());
+ if (!prefix().empty())
+ f.write_h("class %s %s ", prefix().c_str(), name());
else
f.write_h("class %s ", name());
if (subclass_of) f.write_h(": %s ", subclass_of);
diff --git a/fluid/nodes/Function_Node.h b/fluid/nodes/Function_Node.h
index 56a0046e0..282f33312 100644
--- a/fluid/nodes/Function_Node.h
+++ b/fluid/nodes/Function_Node.h
@@ -34,6 +34,8 @@
#include <stdarg.h>
#include <stdlib.h>
+#include <string>
+
extern class Class_Node *current_class;
int has_toplevel_function(const char *rtype, const char *sig);
@@ -271,7 +273,7 @@ public:
private:
const char* subclass_of;
char public_;
- const char* class_prefix;
+ std::string prefix_;
public:
Class_Node();
~Class_Node();
@@ -298,8 +300,10 @@ public:
void visibility(char v) { public_ = v; }
// class prefix attribute access
- void prefix(const char* p);
- const char* prefix() const {return class_prefix;}
+ /** Set the text between `class` and the class name */
+ void prefix(const std::string& p) { prefix_ = p; }
+ /** Get the text between `class` and the class name */
+ std::string prefix() const { return prefix_; }
};
#endif // FLUID_NODES_FUNCTION_NODE_H
diff --git a/fluid/nodes/Node.cxx b/fluid/nodes/Node.cxx
index 0b1cb2d4d..7557e61f4 100644
--- a/fluid/nodes/Node.cxx
+++ b/fluid/nodes/Node.cxx
@@ -889,9 +889,9 @@ void Node::write(fld::io::Project_Writer &f) {
f.write_word(type_name());
if (is_class()) {
- const char * p = ((Class_Node*)this)->prefix();
- if (p && strlen(p))
- f.write_word(p);
+ auto p = ((Class_Node*)this)->prefix();
+ if (!p.empty())
+ f.write_word(p.c_str());
}
f.write_word(name());
diff --git a/fluid/panels/widget_panel.cxx b/fluid/panels/widget_panel.cxx
index 5bbde2fec..5556a19fa 100644
--- a/fluid/panels/widget_panel.cxx
+++ b/fluid/panels/widget_panel.cxx
@@ -31,6 +31,7 @@
#include <FL/fl_ask.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_File_Chooser.H>
+#include <ctype.h>
#define ZERO_ENTRY 1000
extern const char* when_symbol_name(int n);
extern void set_whenmenu(int n);
@@ -2636,11 +2637,10 @@ static void cb_Attribute(Fl_Input* o, void* v) {
Class_Node* nd = (Class_Node*)current_node;
if (v == LOAD) {
- o->value( nd->prefix() );
+ o->value( nd->prefix().c_str() );
} else {
- const char *nn = nd->prefix();
- if ( ( nn && (strcmp(nn, o->value()) != 0))
- || (!nn && (strcmp("", o->value()) != 0)) )
+ auto nn = nd->prefix();
+ if (nn != o->value())
{
nd->prefix( o->value() );
Fluid.proj.set_modflag(1);
@@ -2657,13 +2657,37 @@ static void cb_Class(Fl_Input* o, void* v) {
o->value( nd->name() );
} else {
const char *nn = nd->name();
- if ( ( nn && (strcmp(nn, o->value()) != 0))
- || (!nn && (strcmp("", o->value()) != 0)) )
+ char *nv = strdup( o->value() );
+ // There is an inconsistency in the project file reader, so this string
+ // must not coantain anything but alphanumeric and underscore characters.
+ char *s = (char*)nv;
+ char *d = (char*)nv;
+ while (*s) {
+ if (isalnum((unsigned char)*s) || *s == '_') {
+ *d++ = *s;
+ }
+ s++;
+ }
+ *d = 0;
+ // The class name must not be empty either
+ if (*nv == 0) {
+ free((void*)nv);
+ nv = strdup("MyClass");
+ }
+ // The class name may have changed, so update the widget
+ o->value( nv );
+ // Now copy the new name into the node if it changed
+ if ( ( nn && (strcmp(nn, nv) != 0))
+ || (!nn && (strcmp("", nv) != 0)) )
{
- nd->name( o->value() );
+ nd->name( nv );
Fluid.proj.set_modflag(1);
redraw_browser();
}
+ // Don't forget to clean up
+ if (nv) {
+ free((void*)nv);
+ }
}
}
@@ -3239,6 +3263,7 @@ Fl_Double_Window* make_widget_panel() {
widget_tabs->labelcolor(FL_BACKGROUND2_COLOR);
widget_tabs->callback((Fl_Callback*)cb_widget_tabs);
widget_tabs->when(FL_WHEN_NEVER);
+ widget_tabs->hide();
{ wp_gui_tab = new Fl_Group(10, 30, 400, 330, "GUI");
wp_gui_tab->labelsize(11);
wp_gui_tab->callback((Fl_Callback*)propagate_load);
@@ -4326,7 +4351,6 @@ Fl_Double_Window* make_widget_panel() {
class_tabs->labelsize(11);
class_tabs->labelcolor(FL_WHITE);
class_tabs->callback((Fl_Callback*)cb_class_tabs);
- class_tabs->hide();
{ class_tabs_main = new Fl_Group(10, 30, 400, 330, "Class");
class_tabs_main->labelsize(11);
class_tabs_main->callback((Fl_Callback*)propagate_load);
diff --git a/fluid/panels/widget_panel.fl b/fluid/panels/widget_panel.fl
index beba75690..17c545d15 100644
--- a/fluid/panels/widget_panel.fl
+++ b/fluid/panels/widget_panel.fl
@@ -80,6 +80,9 @@ decl {\#include <FL/Fl_Menu_Item.H>} {private global
decl {\#include <FL/Fl_File_Chooser.H>} {private global
}
+decl {\#include <ctype.h>} {selected private global
+}
+
decl {\#define ZERO_ENTRY 1000} {private global
}
@@ -486,8 +489,8 @@ Function {make_widget_panel()} {
} {
Fl_Tabs widget_tabs {
callback {if (current_widget)
- propagate_load((Fl_Group *)o,v);} selected
- xywh {10 10 400 350} selection_color 12 labelsize 11 labelcolor 7 when 0
+ propagate_load((Fl_Group *)o,v);}
+ xywh {10 10 400 350} selection_color 12 labelsize 11 labelcolor 7 when 0 hide
code0 {o->show();}
} {
Fl_Group wp_gui_tab {
@@ -2972,8 +2975,8 @@ if (v == LOAD) {
}
Fl_Tabs class_tabs {
callback {if (current_node && current_node->is_a(Type::Class))
- propagate_load((Fl_Group *)o,v);}
- xywh {10 10 400 350} selection_color 12 labelsize 11 labelcolor 255 hide
+ propagate_load((Fl_Group *)o,v);} open
+ xywh {10 10 400 350} selection_color 12 labelsize 11 labelcolor 255
} {
Fl_Group class_tabs_main {
label Class
@@ -3032,11 +3035,10 @@ if (v == LOAD) {
Class_Node* nd = (Class_Node*)current_node;
if (v == LOAD) {
- o->value( nd->prefix() );
+ o->value( nd->prefix().c_str() );
} else {
- const char *nn = nd->prefix();
- if ( ( nn && (strcmp(nn, o->value()) != 0))
- || (!nn && (strcmp("", o->value()) != 0)) )
+ auto nn = nd->prefix();
+ if (nn != o->value())
{
nd->prefix( o->value() );
Fluid.proj.set_modflag(1);
@@ -3054,13 +3056,37 @@ if (v == LOAD) {
o->value( nd->name() );
} else {
const char *nn = nd->name();
- if ( ( nn && (strcmp(nn, o->value()) != 0))
- || (!nn && (strcmp("", o->value()) != 0)) )
+ char *nv = strdup( o->value() );
+ // There is an inconsistency in the project file reader, so this string
+ // must not coantain anything but alphanumeric and underscore characters.
+ char *s = (char*)nv;
+ char *d = (char*)nv;
+ while (*s) {
+ if (isalnum((unsigned char)*s) || *s == '_') {
+ *d++ = *s;
+ }
+ s++;
+ }
+ *d = 0;
+ // The class name must not be empty either
+ if (*nv == 0) {
+ free((void*)nv);
+ nv = strdup("MyClass");
+ }
+ // The class name may have changed, so update the widget
+ o->value( nv );
+ // Now copy the new name into the node if it changed
+ if ( ( nn && (strcmp(nn, nv) != 0))
+ || (!nn && (strcmp("", nv) != 0)) )
{
- nd->name( o->value() );
+ nd->name( nv );
Fluid.proj.set_modflag(1);
redraw_browser();
}
+ // Don't forget to clean up
+ if (nv) {
+ free((void*)nv);
+ }
}}
tooltip {class name, must be a single C++ keyword} xywh {95 75 305 20} labelfont 1 labelsize 11 textfont 4 textsize 11
}