summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>1998-10-06 18:21:25 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>1998-10-06 18:21:25 +0000
commitf9039b2ae21988783feae9b362818e7923e82d14 (patch)
tree6d6fe3679d73448758f9794e7d4d4f6b22a4adad /fluid
parent67e89232f9ba067825a158734a09e0fa21aacbe3 (diff)
Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'fluid')
-rw-r--r--fluid/Fl_Function_Type.cxx669
-rw-r--r--fluid/Fl_Group_Type.cxx245
-rw-r--r--fluid/Fl_Menu_Type.cxx487
-rw-r--r--fluid/Fl_Type.cxx617
-rw-r--r--fluid/Fl_Type.h142
-rw-r--r--fluid/Fl_Widget_Type.cxx1676
-rw-r--r--fluid/Fl_Widget_Type.h67
-rw-r--r--fluid/Fl_Window_Type.cxx666
-rw-r--r--fluid/Fluid_Image.cxx384
-rw-r--r--fluid/Fluid_Image.h28
-rw-r--r--fluid/Makefile83
-rw-r--r--fluid/README214
-rw-r--r--fluid/Shortcut_Button.h10
-rw-r--r--fluid/about_panel.cxx122
-rw-r--r--fluid/about_panel.fl71
-rw-r--r--fluid/about_panel.h12
-rw-r--r--fluid/alignment_panel.cxx73
-rw-r--r--fluid/alignment_panel.fl65
-rw-r--r--fluid/alignment_panel.h17
-rw-r--r--fluid/class.C123
-rw-r--r--fluid/class.H34
-rw-r--r--fluid/code.cxx263
-rw-r--r--fluid/factory.cxx651
-rw-r--r--fluid/file.cxx562
-rw-r--r--fluid/fluid.cxx387
-rw-r--r--fluid/function_panel.cxx262
-rw-r--r--fluid/function_panel.fl164
-rw-r--r--fluid/function_panel.h46
-rw-r--r--fluid/gif.cxx336
-rw-r--r--fluid/keyboard_ui.cxx536
-rw-r--r--fluid/keyboard_ui.h8
-rw-r--r--fluid/penne.C85
-rw-r--r--fluid/penne.H32
-rw-r--r--fluid/primes.fl22
-rw-r--r--fluid/widget_panel.cxx316
-rw-r--r--fluid/widget_panel.fl300
-rw-r--r--fluid/widget_panel.h61
37 files changed, 9836 insertions, 0 deletions
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx
new file mode 100644
index 000000000..21bdb5b37
--- /dev/null
+++ b/fluid/Fl_Function_Type.cxx
@@ -0,0 +1,669 @@
+/* Fl_Function_Type_Type.C
+
+ Type describing a C function output by Fluid.
+
+*/
+
+#include <FL/Fl.H>
+#include "Fl_Type.H"
+#include <FL/fl_show_input.H>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+////////////////////////////////////////////////////////////////
+// quick check of any C code for legality, returns an error message
+// these currently require comments to parse correctly!
+
+static char buffer[128]; // for error messages
+
+// check a quoted string ending in either " or ' or >:
+const char *_q_check(const char * & c, int type) {
+ for (;;) switch (*c++) {
+ case '\0':
+ sprintf(buffer,"missing %c",type);
+ return buffer;
+ case '\\':
+ if (*c) c++;
+ break;
+ default:
+ if (*(c-1) == type) return 0;
+ }
+}
+
+// check normal code, match braces and parenthesis:
+const char *_c_check(const char * & c, int type) {
+ const char *d;
+ for (;;) switch (*c++) {
+ case 0:
+ if (!type) return 0;
+ sprintf(buffer, "missing %c", type);
+ return buffer;
+ case '{':
+ if (type==')') goto UNEXPECTED;
+ d = _c_check(c,'}'); if (d) return d; break;
+ case '(':
+ d = _c_check(c,')'); if (d) return d; break;
+ case '\"':
+ d = _q_check(c,'\"'); if (d) return d; break;
+ case '\'':
+ d = _q_check(c,'\''); if (d) return d; break;
+ case '}':
+ case ')':
+ case '#':
+ UNEXPECTED:
+ if (type == *(c-1)) return 0;
+ sprintf(buffer, "unexpected %c", *(c-1));
+ return buffer;
+ }
+}
+
+const char *c_check(const char *c, int type) {
+ return _c_check(c,type);
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Function_Type : public Fl_Type {
+ const char* return_type;
+ char public_, constructor, havewidgets;
+public:
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ int ismain() {return name_ == 0;}
+ virtual const char *type_name() {return "Function";}
+ virtual const char *title() {
+ return name() ? name() : "main()";
+ }
+ int is_parent() const {return 1;}
+ int is_code_block() const {return 1;}
+ void write_properties();
+ void read_property(const char *);
+};
+
+Fl_Type *Fl_Function_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Function_Type *o = new Fl_Function_Type();
+ o->name("make_window()");
+ o->return_type = 0;
+ o->add(p);
+ o->factory = this;
+ o->public_ = 1;
+ return o;
+}
+
+void Fl_Function_Type::write_properties() {
+ Fl_Type::write_properties();
+ if (!public_) write_string("private");
+ if (return_type) {
+ write_string("return_type");
+ write_word(return_type);
+ }
+}
+
+void Fl_Function_Type::read_property(const char *c) {
+ if (!strcmp(c,"private")) {
+ public_ = 0;
+ } else if (!strcmp(c,"return_type")) {
+ storestring(read_word(),return_type);
+ } else {
+ Fl_Type::read_property(c);
+ }
+}
+
+#include "function_panel.H"
+#include <FL/fl_ask.H>
+
+void Fl_Function_Type::open() {
+ if (!function_panel) make_function_panel();
+ f_return_type_input->static_value(return_type);
+ f_name_input->static_value(name());
+ f_public_button->value(public_);
+ function_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == f_panel_cancel) goto BREAK2;
+ else if (w == f_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = f_name_input->value();
+ while (isspace(*c)) c++;
+ message = c_check(c); if (message) continue;
+ const char *d = c;
+ for (; *d != '('; d++) if (isspace(*d) || !*d) break;
+ if (*c && *d != '(') {
+ message = "must be name(arguments), try again:"; continue;
+ }
+ c = f_return_type_input->value();
+ message = c_check(c); if (message) continue;
+ name(f_name_input->value());
+ storestring(c, return_type);
+ public_ = f_public_button->value();
+ break;
+ }
+ BREAK2:
+ function_panel->hide();
+}
+
+Fl_Function_Type Fl_Function_type;
+
+void Fl_Function_Type::write_declare() {
+ ::write_declare("#include <FL/Fl.H>");
+}
+
+extern const char* subclassname(Fl_Type*);
+
+void Fl_Function_Type::write_code1() {
+ constructor=0;
+ havewidgets = 0;
+ Fl_Type *child;
+ const char* widget_type = 0;
+ for (child = next; child && child->level > level; child = child->next)
+ if (child->is_widget()) {
+ havewidgets = 1;
+ widget_type = subclassname(child);
+ break;
+ }
+ write_c("\n");
+ if (ismain())
+ write_c("int main(int argc, char **argv) {\n");
+ else {
+ const char* t = return_type;
+ const char* star = "";
+ if (!t) {
+ if (havewidgets) {t = widget_type; star = "*";}
+ else t = "void";
+ }
+ const char* k = class_name();
+ if (k) {
+ write_public(public_);
+ if (name()[0] == '~')
+ constructor = 1;
+ else {
+ size_t n; for (n=0; name()[n] && name()[n]!='('; n++);
+ if (n == strlen(k) && !strncmp(name(), k, n)) constructor = 1;
+ }
+ write_h(" ");
+ if (!constructor) {write_h("%s%s ", t, star); write_c("%s%s ", t,star);}
+ write_h("%s;\n", name());
+ write_c("%s::%s {\n", k, name());
+ } else {
+ if (public_) write_h("%s%s %s;\n", t, star, name());
+ else write_c("static ");
+ write_c("%s%s %s {\n", t, star, name());
+ }
+ }
+ if (havewidgets) write_c(" %s* w;\n", widget_type);
+ indentation += 2;
+}
+
+void Fl_Function_Type::write_code2() {
+ if (ismain()) {
+ if (havewidgets) write_c(" w->show(argc, argv);\n");
+ write_c(" return Fl::run();\n");
+ } else if (havewidgets && !constructor)
+ write_c(" return w;\n");
+ write_c("}\n");
+ indentation = 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Code_Type : public Fl_Type {
+public:
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "code";}
+ int is_code_block() const {return 0;}
+};
+
+Fl_Type *Fl_Code_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_code_block()) p = p->parent;
+ if (!p) {
+ fl_message("Please select a function");
+ return 0;
+ }
+ Fl_Code_Type *o = new Fl_Code_Type();
+ o->name("printf(\"Hello, World!\\n\");");
+ o->add(p);
+ o->factory = this;
+ return o;
+}
+
+void Fl_Code_Type::open() {
+ if (!code_panel) make_code_panel();
+ code_input->static_value(name());
+ code_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == code_panel_cancel) goto BREAK2;
+ else if (w == code_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = code_input->value();
+ message = c_check(c); if (message) continue;
+ name(c);
+ break;
+ }
+ BREAK2:
+ code_panel->hide();
+}
+
+Fl_Code_Type Fl_Code_type;
+
+void Fl_Code_Type::write_declare() {}
+
+void Fl_Code_Type::write_code1() {
+ const char* c = name();
+ if (!c) return;
+ write_c("%s%s\n", indent(), c);
+}
+
+void Fl_Code_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_CodeBlock_Type : public Fl_Type {
+ const char* after;
+public:
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "codeblock";}
+ int is_code_block() const {return 1;}
+ int is_parent() const {return 1;}
+ void write_properties();
+ void read_property(const char *);
+};
+
+Fl_Type *Fl_CodeBlock_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_code_block()) p = p->parent;
+ if (!p) {
+ fl_message("Please select a function");
+ return 0;
+ }
+ Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
+ o->name("if (test())");
+ o->after = 0;
+ o->add(p);
+ o->factory = this;
+ return o;
+}
+
+void Fl_CodeBlock_Type::write_properties() {
+ Fl_Type::write_properties();
+ if (after) {
+ write_string("after");
+ write_word(after);
+ }
+}
+
+void Fl_CodeBlock_Type::read_property(const char *c) {
+ if (!strcmp(c,"after")) {
+ storestring(read_word(),after);
+ } else {
+ Fl_Type::read_property(c);
+ }
+}
+
+void Fl_CodeBlock_Type::open() {
+ if (!codeblock_panel) make_codeblock_panel();
+ code_before_input->static_value(name());
+ code_after_input->static_value(after);
+ codeblock_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == codeblock_panel_cancel) goto BREAK2;
+ else if (w == codeblock_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = code_before_input->value();
+ message = c_check(c); if (message) continue;
+ name(c);
+ c = code_after_input->value();
+ message = c_check(c); if (message) continue;
+ storestring(c, after);
+ break;
+ }
+ BREAK2:
+ codeblock_panel->hide();
+}
+
+Fl_CodeBlock_Type Fl_CodeBlock_type;
+
+void Fl_CodeBlock_Type::write_declare() {}
+
+void Fl_CodeBlock_Type::write_code1() {
+ const char* c = name();
+ write_c("%s%s {\n", indent(), c ? c : "");
+ indentation += 2;
+}
+
+void Fl_CodeBlock_Type::write_code2() {
+ indentation += 2;
+ if (after) write_c("%s} %s\n", indent(), after);
+ else write_c("%s}\n", indent());
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Decl_Type : public Fl_Type {
+ char public_;
+public:
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "decl";}
+ void write_properties();
+ void read_property(const char *);
+};
+
+Fl_Type *Fl_Decl_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Decl_Type *o = new Fl_Decl_Type();
+ o->public_ = 0;
+ o->name("int x;");
+ o->add(p);
+ o->factory = this;
+ return o;
+}
+
+void Fl_Decl_Type::write_properties() {
+ Fl_Type::write_properties();
+ if (public_) write_string("public");
+}
+
+void Fl_Decl_Type::read_property(const char *c) {
+ if (!strcmp(c,"public")) {
+ public_ = 1;
+ } else {
+ Fl_Type::read_property(c);
+ }
+}
+
+void Fl_Decl_Type::open() {
+ if (!decl_panel) make_decl_panel();
+ decl_input->static_value(name());
+ decl_public_button->value(public_);
+ decl_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == decl_panel_cancel) goto BREAK2;
+ else if (w == decl_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = decl_input->value();
+ while (isspace(*c)) c++;
+ message = c_check(c&&c[0]=='#' ? c+1 : c);
+ if (message) continue;
+ name(c);
+ public_ = decl_public_button->value();
+ break;
+ }
+ BREAK2:
+ decl_panel->hide();
+}
+
+Fl_Decl_Type Fl_Decl_type;
+
+void Fl_Decl_Type::write_declare() {}
+
+void Fl_Decl_Type::write_code1() {
+ const char* c = name();
+ if (!c) return;
+ // handle putting #include or extern into decl:
+ if (!isalpha(*c) || !strncmp(c,"extern",6)) {
+ if (public_)
+ write_h("%s\n", c);
+ else
+ write_c("%s\n", c);
+ return;
+ }
+ // lose all trailing semicolons so I can add one:
+ const char* e = c+strlen(c);
+ while (e>c && e[-1]==';') e--;
+ if (class_name()) {
+ write_public(public_);
+ write_h(" %.*s;\n", e-c, c);
+ } else {
+ if (public_) {
+ write_h("extern %.*s;\n", e-c, c);
+ write_c("%.*s;\n", e-c, c);
+ } else {
+ write_c("static %.*s;\n", e-c, c);
+ }
+ }
+}
+
+void Fl_Decl_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_DeclBlock_Type : public Fl_Type {
+ const char* after;
+public:
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "declblock";}
+ void write_properties();
+ void read_property(const char *);
+ int is_parent() const {return 1;}
+ int is_decl_block() const {return 1;}
+};
+
+Fl_Type *Fl_DeclBlock_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_decl_block()) p = p->parent;
+ Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
+ o->name("#if 1");
+ o->after = strdup("#endif");
+ o->add(p);
+ o->factory = this;
+ return o;
+}
+
+void Fl_DeclBlock_Type::write_properties() {
+ Fl_Type::write_properties();
+ write_string("after");
+ write_word(after);
+}
+
+void Fl_DeclBlock_Type::read_property(const char *c) {
+ if (!strcmp(c,"after")) {
+ storestring(read_word(),after);
+ } else {
+ Fl_Type::read_property(c);
+ }
+}
+
+void Fl_DeclBlock_Type::open() {
+ if (!declblock_panel) make_declblock_panel();
+ decl_before_input->static_value(name());
+ decl_after_input->static_value(after);
+ declblock_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == declblock_panel_cancel) goto BREAK2;
+ else if (w == declblock_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = decl_before_input->value();
+ while (isspace(*c)) c++;
+ message = c_check(c&&c[0]=='#' ? c+1 : c);
+ if (message) continue;
+ name(c);
+ c = decl_after_input->value();
+ while (isspace(*c)) c++;
+ message = c_check(c&&c[0]=='#' ? c+1 : c);
+ if (message) continue;
+ storestring(c,after);
+ break;
+ }
+ BREAK2:
+ declblock_panel->hide();
+}
+
+Fl_DeclBlock_Type Fl_DeclBlock_type;
+
+void Fl_DeclBlock_Type::write_declare() {}
+
+void Fl_DeclBlock_Type::write_code1() {
+ const char* c = name();
+ if (c) write_c("%s\n", c);
+}
+
+void Fl_DeclBlock_Type::write_code2() {
+ const char* c = after;
+ if (c) write_c("%s\n", c);
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Class_Type : public Fl_Type {
+ const char* subclass_of;
+ char public_;
+public:
+ // state variables for output:
+ char write_public_state; // true when public: has been printed
+ Fl_Class_Type* parent_class; // save class if nested
+//
+ Fl_Type *make();
+ void write_declare();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "class";}
+ int is_parent() const {return 1;}
+ int is_decl_block() const {return 1;}
+ int is_class() const {return 1;}
+ void write_properties();
+ void read_property(const char *);
+};
+
+const char* Fl_Type::class_name() const {
+ Fl_Type* p = parent;
+ while (p) {if (p->is_class()) return p->name(); p = p->parent;}
+ return 0;
+}
+
+Fl_Type *Fl_Class_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Class_Type *o = new Fl_Class_Type();
+ o->name("UserInterface");
+ o->subclass_of = 0;
+ o->public_ = 1;
+ o->add(p);
+ o->factory = this;
+ return o;
+}
+
+void Fl_Class_Type::write_properties() {
+ Fl_Type::write_properties();
+ if (subclass_of) {
+ write_string(":");
+ write_word(subclass_of);
+ }
+ if (!public_) write_string("private");
+}
+
+void Fl_Class_Type::read_property(const char *c) {
+ if (!strcmp(c,"private")) {
+ public_ = 0;
+ } else if (!strcmp(c,":")) {
+ storestring(read_word(), subclass_of);
+ } else {
+ Fl_Type::read_property(c);
+ }
+}
+
+void Fl_Class_Type::open() {
+ if (!class_panel) make_class_panel();
+ c_name_input->static_value(name());
+ c_subclass_input->static_value(subclass_of);
+ c_public_button->value(public_);
+ class_panel->show();
+ const char* message = 0;
+ for (;;) { // repeat as long as there are errors
+ if (message) fl_alert(message);
+ for (;;) {
+ Fl_Widget* w = Fl::readqueue();
+ if (w == c_panel_cancel) goto BREAK2;
+ else if (w == c_panel_ok) break;
+ else if (!w) Fl::wait();
+ }
+ const char*c = c_name_input->value();
+ while (isspace(*c)) c++;
+ if (!*c) goto OOPS;
+ while (is_id(*c)) c++;
+ while (isspace(*c)) c++;
+ if (*c) {OOPS: message = "class name must be C++ identifier"; continue;}
+ c = c_subclass_input->value();
+ message = c_check(c); if (message) continue;
+ name(c_name_input->value());
+ storestring(c, subclass_of);
+ public_ = c_public_button->value();
+ break;
+ }
+ BREAK2:
+ class_panel->hide();
+}
+
+Fl_Class_Type Fl_Class_type;
+
+void Fl_Class_Type::write_declare() {}
+
+static Fl_Class_Type *current_class;
+extern int varused_test;
+void write_public(int state) {
+ if (!current_class || varused_test) return;
+ if (current_class->write_public_state == state) return;
+ current_class->write_public_state = state;
+ write_h(state ? "public:\n" : "private:\n");
+}
+
+void Fl_Class_Type::write_code1() {
+ parent_class = current_class;
+ current_class = this;
+ write_public_state = 0;
+ write_h("\nclass %s ", name());
+ if (subclass_of) write_h(": %s ", subclass_of);
+ write_h("{\n");
+}
+
+void Fl_Class_Type::write_code2() {
+ write_h("};\n");
+ current_class = parent_class;
+}
diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx
new file mode 100644
index 000000000..0e499339d
--- /dev/null
+++ b/fluid/Fl_Group_Type.cxx
@@ -0,0 +1,245 @@
+// Fl_Group_Type.C
+
+// Object describing an Fl_Group
+// Probably also links to Fl_Window_Type.C
+
+// Also the Fl_Tabs widget, with special stuff to select tab items
+// and insure that only one is visible.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/fl_message.H>
+#include "Fl_Widget_Type.H"
+
+class igroup : public Fl_Group {
+public:
+ void resize(int,int,int,int);
+ igroup(int x,int y,int w,int h) : Fl_Group(x,y,w,h) {Fl_Group::current(0);}
+};
+// Override group's resize behavior to do nothing to children:
+void igroup::resize(int X, int Y, int W, int H) {
+ Fl_Widget::resize(X,Y,W,H);
+ redraw();
+}
+
+class Fl_Group_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Group";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ igroup *g = new igroup(x,y,w,h); Fl_Group::current(0); return g;}
+ Fl_Widget_Type *_make() {return new Fl_Group_Type();}
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void add_child(Fl_Type*, Fl_Type*);
+ void move_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+ int is_parent() const {return 1;}
+ int is_group() const {return 1;}
+};
+Fl_Group_Type Fl_Group_type; // the "factory"
+
+Fl_Type *Fl_Group_Type::make() {
+ return Fl_Widget_Type::make();
+}
+
+void fix_group_size(Fl_Type *tt) {
+ if (!tt || !tt->is_group()) return;
+ Fl_Group_Type* t = (Fl_Group_Type*)tt;
+ int X = t->o->x();
+ int Y = t->o->y();
+ int R = X+t->o->w();
+ int B = Y+t->o->h();
+ for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) {
+ if (!nn->is_widget() || nn->is_menu_item()) continue;
+ Fl_Widget_Type* n = (Fl_Widget_Type*)nn;
+ int x = n->o->x(); if (x < X) X = x;
+ int y = n->o->y(); if (y < Y) Y = y;
+ int r = x+n->o->w();if (r > R) R = r;
+ int b = y+n->o->h();if (b > B) B = b;
+ }
+ t->o->resize(X,Y,R-X,B-Y);
+}
+
+extern int force_parent;
+
+void group_cb(Fl_Widget *, void *) {
+ // Find the current widget:
+ Fl_Type *qq = Fl_Type::current;
+ while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent;
+ if (!qq || qq->level <= 1) {
+ fl_message("Please select widgets to group");
+ return;
+ }
+ Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
+ force_parent = 1;
+ Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make());
+ n->move_before(q);
+ n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h());
+ for (Fl_Type *t = Fl_Type::first; t;) {
+ if (t->level != n->level || t == n || !t->selected) {
+ t = t->next; continue;}
+ Fl_Type *nxt = t->remove();
+ t->add(n);
+ t = nxt;
+ }
+ fix_group_size(n);
+}
+
+void ungroup_cb(Fl_Widget *, void *) {
+ // Find the group:
+ Fl_Type *q = Fl_Type::current;
+ while (q && (!q->is_widget() || q->is_menu_item())) q = q->parent;
+ if (q) q = q->parent;
+ if (!q || q->level <= 1) {
+ fl_message("Please select widgets in a group");
+ return;
+ }
+ Fl_Type* n;
+ for (n = q->next; n && n->level > q->level; n = n->next) {
+ if (n->level == q->level+1 && !n->selected) {
+ fl_message("Please select all widgets in group");
+ return;
+ }
+ }
+ for (n = q->next; n && n->level > q->level;) {
+ Fl_Type *nxt = n->remove();
+ n->insert(q);
+ n = nxt;
+ }
+ delete q;
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+void Fl_Group_Type::write_code1() {
+ Fl_Widget_Type::write_code1();
+}
+
+void Fl_Group_Type::write_code2() {
+ write_c("%so->end();\n", indent());
+ if (resizable()) write_c("%sFl_Group::current()->resizable(o);\n", indent());
+ Fl_Widget_Type::write_code2();
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Tabs.H>
+
+class itabs : public Fl_Tabs {
+public:
+ void resize(int,int,int,int);
+ itabs(int x,int y,int w,int h) : Fl_Tabs(x,y,w,h) {}
+};
+// Override group's resize behavior to do nothing to children:
+void itabs::resize(int X, int Y, int W, int H) {
+ Fl_Widget::resize(X,Y,W,H);
+ redraw();
+}
+
+static const char tabs_type_name[] = "Fl_Tabs";
+
+class Fl_Tabs_Type : public Fl_Group_Type {
+public:
+ virtual const char *type_name() {return tabs_type_name;}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ itabs *g = new itabs(x,y,w,h); Fl_Group::current(0); return g;}
+ Fl_Widget_Type *_make() {return new Fl_Tabs_Type();}
+ Fl_Type* click_test(int,int);
+ void add_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+};
+Fl_Tabs_Type Fl_Tabs_type; // the "factory"
+
+// This is called when user clicks on a widget in the window. See
+// if it is a tab title, and adjust visibility and return new selection:
+// If none, return o unchanged:
+
+Fl_Type* Fl_Tabs_Type::click_test(int x, int y) {
+ Fl_Tabs *t = (Fl_Tabs*)o;
+ Fl_Widget *a = t->which(x,y);
+ if (!a) return 0; // didn't click on tab
+ // okay, run the tabs ui until they let go of mouse:
+ t->handle(FL_PUSH);
+ Fl::pushed(t);
+ while (Fl::pushed()==t) Fl::wait();
+ return (Fl_Type*)(t->value()->user_data());
+}
+
+// This is called when o is created. If it is in the tab group make
+// sure it is visible:
+
+void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+ ((Fl_Group*)o)->insert(*(c->o), b);
+ o->redraw();
+}
+
+void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) {
+ Fl_Group_Type::add_child(c, before);
+ ((Fl_Tabs*)o)->value(0);
+}
+
+// This is called when o is deleted. If it is in the tab group make
+// sure it is not visible:
+
+void Fl_Group_Type::remove_child(Fl_Type* cc) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ ((Fl_Group*)o)->remove(c->o);
+ o->redraw();
+}
+
+void Fl_Tabs_Type::remove_child(Fl_Type* cc) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ Fl_Tabs *t = (Fl_Tabs*)o;
+ if (t->value() == c->o) t->value(0);
+ Fl_Group_Type::remove_child(c);
+}
+
+// move, don't change selected value:
+
+void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+ ((Fl_Group*)o)->remove(c->o);
+ ((Fl_Group*)o)->insert(*(c->o), b);
+ o->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+// some other group subclasses that fluid does not treat specially:
+
+#include <FL/Fl_Scroll.H>
+
+static const char scroll_type_name[] = "Fl_Scroll";
+
+static Fl_Menu_Item scroll_type_menu[] = {
+ {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/},
+ {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL},
+ {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL},
+ {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS},
+ {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS},
+ {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS},
+ {0}};
+
+class Fl_Scroll_Type : public Fl_Group_Type {
+ Fl_Menu_Item *subtypes() {return scroll_type_menu;}
+public:
+ virtual const char *type_name() {return scroll_type_name;}
+ Fl_Widget_Type *_make() {return new Fl_Scroll_Type();}
+};
+Fl_Scroll_Type Fl_Scroll_type; // the "factory"
+
+////////////////////////////////////////////////////////////////
+
+static const char tile_type_name[] = "Fl_Tile";
+
+class Fl_Tile_Type : public Fl_Group_Type {
+public:
+ virtual const char *type_name() {return tile_type_name;}
+ Fl_Widget_Type *_make() {return new Fl_Tile_Type();}
+};
+Fl_Tile_Type Fl_Tile_type; // the "factory"
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
new file mode 100644
index 000000000..02318602c
--- /dev/null
+++ b/fluid/Fl_Menu_Type.cxx
@@ -0,0 +1,487 @@
+// Fl_Menu_Type.C
+
+// Menu items are kludged by making a phony Fl_Box widget so the normal
+// widget panel can be used to control them.
+
+// This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar,
+// etc widgets.
+
+#include <FL/Fl.H>
+#include "Fl_Widget_Type.H"
+#include <FL/fl_message.H>
+#include <FL/Fl_Menu_.H>
+#include <FL/Fl_Button.H>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static Fl_Menu_Item menu_item_type_menu[] = {
+ {"Normal",0,0,(void*)0},
+ {"Toggle",0,0,(void*)FL_MENU_BOX},
+ {"Radio",0,0,(void*)FL_MENU_RADIO},
+ {0}};
+
+class Fl_Menu_Item_Type : public Fl_Widget_Type {
+public:
+ Fl_Menu_Item* subtypes() {return menu_item_type_menu;}
+ const char* type_name() {return "menuitem";}
+ Fl_Type* make();
+ int is_menu_item() const {return 1;}
+ int is_button() const {return 1;} // this gets shortcut to work
+ Fl_Widget* widget(int,int,int,int) {return 0;}
+ Fl_Widget_Type* _make() {return 0;}
+ void write_declare();
+ const char* menu_name(int& i);
+ int flags();
+ void write_static();
+ void write_item();
+ void write_code1();
+ void write_code2();
+};
+
+class Fl_Submenu_Type : public Fl_Menu_Item_Type {
+public:
+ Fl_Menu_Item* subtypes() {return 0;}
+ const char* type_name() {return "submenu";}
+ int is_parent() const {return 1;}
+ int is_button() const {return 0;} // disable shortcut
+ Fl_Type* make();
+ // changes to submenu must propagate up so build_menu is called
+ // on the parent Fl_Menu_Type:
+ void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);}
+ void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);}
+ void remove_child(Fl_Type*a) {parent->remove_child(a);}
+};
+
+extern int reading_file;
+extern int force_parent;
+
+static char submenuflag;
+
+Fl_Type *Fl_Menu_Item_Type::make() {
+ // Find the current menu item:
+ Fl_Type* q = Fl_Type::current;
+ Fl_Type* p = q;
+ if (p) {
+ if (force_parent && q->is_menu_item() || !q->is_parent()) p = p->parent;
+ }
+ force_parent = 0;
+ if (!p || !(p->is_menu_button() || p->is_menu_item() && p->is_parent())) {
+ fl_message("Please select a menu to add to");
+ return 0;
+ }
+ if (!o) {
+ o = new Fl_Button(0,0,100,20); // create template widget
+ }
+
+ Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type();
+ t->o = new Fl_Button(0,0,100,20);
+ t->factory = this;
+ t->add(p);
+ if (!reading_file) t->label(submenuflag ? "submenu" : "item");
+ return t;
+}
+
+Fl_Type *Fl_Submenu_Type::make() {
+ submenuflag = 1;
+ Fl_Type* t = Fl_Menu_Item_Type::make();
+ submenuflag = 0;
+ return t;
+}
+
+Fl_Menu_Item_Type Fl_Menu_Item_type;
+Fl_Submenu_Type Fl_Submenu_type;
+
+////////////////////////////////////////////////////////////////
+// Writing the C code:
+
+#include <ctype.h>
+
+// test functions in Fl_Widget_Type.C:
+int is_name(const char *c);
+const char *array_name(Fl_Widget_Type *o);
+int isdeclare(const char *c);
+
+void Fl_Menu_Item_Type::write_declare() {
+ if (callback() && is_name(callback()))
+ ::write_declare("extern void %s(Fl_Menu_*, %s);", callback(),
+ user_data_type() ? user_data_type() : "void*");
+ for (int n=0; n < NUM_EXTRA_CODE; n++) {
+ if (extra_code(n) && isdeclare(extra_code(n)))
+ ::write_declare("%s", extra_code(n));
+ }
+}
+
+const char* Fl_Menu_Item_Type::menu_name(int& i) {
+ i = 0;
+ Fl_Type* t = prev;
+ while (t && t->is_menu_item()) {
+ // be sure to count the {0} that ends a submenu:
+ if (t->level > t->next->level ||
+ // detect empty submenu:
+ t->level==t->next->level &&t->is_parent())
+ i++;
+ t = t->prev; i++;
+ }
+ return unique_id(t, "menu", t->name(), t->label());
+}
+
+#include "Fluid_Image.H"
+
+void Fl_Menu_Item_Type::write_static() {
+ if (callback() && !is_name(callback())) {
+ // see if 'o' or 'v' used, to prevent unused argument warnings:
+ int use_o = 0;
+ int use_v = 0;
+ const char *d;
+ for (d = callback(); *d;) {
+ if (*d == 'o' && !is_id(d[1])) use_o = 1;
+ if (*d == 'v' && !is_id(d[1])) use_v = 1;
+ do d++; while (is_id(*d));
+ while (*d && !is_id(*d)) d++;
+ }
+ const char* cn = callback_name();
+ const char* k = class_name();
+ if (k) {
+ write_c("\ninline void %s::%s_i(Fl_Menu_*", k, cn);
+ } else {
+ write_c("\nstatic void %s(Fl_Menu_*", cn);
+ }
+ if (use_o) write_c(" o");
+ const char* ut = user_data_type() ? user_data_type() : "void*";
+ write_c(", %s", ut);
+ if (use_v) write_c(" v");
+ write_c(") {\n %s", callback());
+ if (*(d-1) != ';') write_c(";");
+ write_c("\n}\n");
+ if (k) {
+ write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
+ write_c(" ((%s*)(o->", k);
+ Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent;
+ for (t = t->parent; t->is_widget(); t = t->parent) write_c("parent()->");
+ write_c("user_data()))->%s_i(o,v);\n}\n", cn);
+ }
+ }
+ if (image) {
+ if (image->written != write_number) {
+ image->write_static();
+ image->written = write_number;
+ }
+ }
+ if (next && next->is_menu_item()) return;
+ // okay, when we hit last item in the menu we have to write the
+ // entire array out:
+ int level;
+ const char* k = class_name();
+ if (k) {
+ write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(level));
+ } else
+ write_c("\nFl_Menu_Item %s[] = {\n", menu_name(level));
+ Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev;
+ level = t->level+1;
+ for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) {
+ ((Fl_Menu_Item_Type*)q)->write_item();
+ if (q->is_parent()) level++;
+ int l1 =
+ (q->next && q->next->is_menu_item()) ? q->next->level : t->next->level;
+ while (level > l1) {write_c(" {0},\n"); level--;}
+ level = l1;
+ }
+ write_c(" {0}\n};\n");
+}
+
+int Fl_Menu_Item_Type::flags() {
+ int i = o->type();
+ if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE;
+ if (!o->active()) i |= FL_MENU_INACTIVE;
+ if (!o->visible()) i |= FL_MENU_INVISIBLE;
+ if (is_parent()) i |= FL_SUBMENU;
+ if (hotspot()) i |= FL_MENU_DIVIDER;
+ return i;
+}
+
+void Fl_Menu_Item_Type::write_item() {
+ write_c(" {");
+ if (image) write_c("0");
+ else if (label()) write_cstring(label());
+ else write_c("\"\"");
+ if (((Fl_Button*)o)->shortcut())
+ write_c(", 0x%x, ", ((Fl_Button*)o)->shortcut());
+ else
+ write_c(", 0, ");
+ if (callback()) {
+ const char* k = class_name();
+ if (k) {
+ write_c(" (Fl_Callback*)%s::%s,", k, callback_name());
+ } else {
+ write_c(" (Fl_Callback*)%s,", callback_name());
+ }
+ } else
+ write_c(" 0,");
+ if (user_data())
+ write_c(" (void*)(%s),", user_data());
+ else
+ write_c(" 0,");
+ write_c(" %d, %d, %d, %d, %d", flags(),
+ o->labeltype(), o->labelfont(), o->labelsize(), o->labelcolor());
+ write_c("},\n");
+}
+
+void Fl_Menu_Item_Type::write_code1() {
+ if (!prev->is_menu_item()) {
+ // for first menu item, declare the array
+ int i; const char* n = menu_name(i);
+ if (class_name())
+ write_h(" static Fl_Menu_Item %s[];\n", n);
+ else
+ write_h("extern Fl_Menu_Item %s[];\n", n);
+ }
+
+ const char *c = array_name(this);
+ if (c) {
+ int i; const char* n = menu_name(i);
+ write_h("#define %s (%s+%d)\n", c, n, i);
+ }
+
+ if (callback()) {
+ if (!is_name(callback()) && class_name()) {
+ const char* cn = callback_name();
+ const char* ut = user_data_type() ? user_data_type() : "void*";
+ write_public(0);
+ write_h(" inline void %s_i(Fl_Menu_*, %s);\n", cn, ut);
+ write_h(" static void %s(Fl_Menu_*, %s);\n", cn, ut);
+ }
+ }
+
+ int init = 0;
+ if (image) {
+ int i; const char* n = menu_name(i);
+ write_c(" {Fl_Menu_Item* o = &%s[%d];\n", n, i);
+ init = 1;
+ image->write_code();
+ }
+ for (int n=0; n < NUM_EXTRA_CODE; n++)
+ if (extra_code(n) && !isdeclare(extra_code(n))) {
+ if (!init) {
+ init = 1;
+ int i; const char* n = menu_name(i);
+ write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), n, i);
+ }
+ write_c("%s %s\n", indent(), extra_code(n));
+ }
+ if (init) write_c("%s}\n",indent());
+}
+
+void Fl_Menu_Item_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+// This is the base class for widgets that contain a menu (ie
+// subclasses of Fl_Menu_.
+// This is a parent widget and menu items can be added as
+// children. An actual array of Fl_Menu_Items is kept parallel
+// with the child objects and updated as they change.
+
+class Fl_Menu_Type : public Fl_Widget_Type {
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Menu_ *o = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ int is_menu_button() const {return 1;}
+ int is_parent() const {return 1;}
+ int menusize;
+ void build_menu();
+ Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;}
+ ~Fl_Menu_Type() {
+ if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu());
+ }
+ void add_child(Fl_Type*, Fl_Type*) {build_menu();}
+ void move_child(Fl_Type*, Fl_Type*) {build_menu();}
+ void remove_child(Fl_Type*) {build_menu();}
+ Fl_Type* click_test(int x, int y);
+ void write_code2();
+};
+
+void Fl_Menu_Type::build_menu() {
+ Fl_Menu_* w = (Fl_Menu_*)o;
+ // count how many Fl_Menu_Item structures needed:
+ int n = 0;
+ Fl_Type* q;
+ for (q = next; q && q->level > level; q = q->next) {
+ if (q->is_parent()) n++; // space for null at end of submenu
+ n++;
+ }
+ if (!n) {
+ if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
+ w->menu(0);
+ menusize = 0;
+ } else {
+ n++; // space for null at end of menu
+ if (menusize<n) {
+ if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
+ menusize = n+10;
+ w->menu(new Fl_Menu_Item[menusize]);
+ }
+ // fill them all in:
+ Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu());
+ int lvl = level+1;
+ for (q = next; q && q->level > level; q = q->next) {
+ Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q;
+ m->label(i->o->label());
+ m->shortcut(((Fl_Button*)(i->o))->shortcut());
+ m->callback(0,(void*)i);
+ m->flags = i->flags();
+ m->labeltype(i->o->labeltype());
+ m->labelfont(i->o->labelfont());
+ m->labelsize(i->o->labelsize());
+ m->labelcolor(i->o->labelcolor());
+ m++;
+ if (q->is_parent()) lvl++;
+ int l1 =
+ (q->next && q->next->is_menu_item()) ? q->next->level : level;
+ while (lvl > l1) {m->label(0); m++; lvl--;}
+ lvl = l1;
+ }
+ }
+ o->redraw();
+}
+
+Fl_Type* Fl_Menu_Type::click_test(int, int) {
+ if (selected) return 0; // let user move the widget
+ Fl_Menu_* w = (Fl_Menu_*)o;
+ if (!menusize) return 0;
+ const Fl_Menu_Item* save = w->mvalue();
+ w->value((Fl_Menu_Item*)0);
+ Fl::pushed(w);
+ w->handle(FL_PUSH);
+ const Fl_Menu_Item* m = w->mvalue();
+ if (m) {
+ // restore the settings of toggles & radio items:
+ if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu();
+ return (Fl_Type*)(m->user_data());
+ }
+ w->value(save);
+ return this;
+}
+
+void Fl_Menu_Type::write_code2() {
+ if (next && next->is_menu_item())
+ write_c("%so->menu(%s);\n", indent(),
+ unique_id(this, "menu", name(), label()));
+ Fl_Widget_Type::write_code2();
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Menu_Button.H>
+static Fl_Menu_Item button_type_menu[] = {
+ {"normal",0,0,(void*)0},
+ {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1},
+ {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2},
+ {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3},
+ {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12},
+ {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23},
+ {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13},
+ {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123},
+ {0}};
+class Fl_Menu_Button_Type : public Fl_Menu_Type {
+ Fl_Menu_Item *subtypes() {return button_type_menu;}
+public:
+ virtual const char *type_name() {return "Fl_Menu_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Menu_Button(x,y,w,h,"menu");}
+ Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();}
+};
+Fl_Menu_Button_Type Fl_Menu_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Choice.H>
+
+static Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}};
+
+class Fl_Choice_Type : public Fl_Menu_Type {
+public:
+ virtual const char *type_name() {return "Fl_Choice";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Choice *o = new Fl_Choice(x,y,w,h,"choice:");
+ o->menu(dummymenu);
+ return o;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Choice_Type();}
+};
+Fl_Choice_Type Fl_Choice_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Menu_Bar.H>
+class Fl_Menu_Bar_Type : public Fl_Menu_Type {
+public:
+ virtual const char *type_name() {return "Fl_Menu_Bar";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Menu_Bar(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();}
+};
+Fl_Menu_Bar_Type Fl_Menu_Bar_type;
+
+////////////////////////////////////////////////////////////////
+// Shortcut entry item in panel:
+
+#include <FL/Fl_Output.H>
+#include "Shortcut_Button.H"
+#include <FL/fl_draw.H>
+
+void Shortcut_Button::draw() {
+ if (value()) draw_box(FL_THIN_DOWN_BOX, (Fl_Color)9);
+ else draw_box(FL_THIN_UP_BOX, FL_WHITE);
+ fl_font(FL_HELVETICA,14); fl_color(FL_BLACK);
+ fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT);
+}
+
+int Shortcut_Button::handle(int e) {
+ when(0); type(FL_TOGGLE_BUTTON);
+ if (e == FL_KEYBOARD) {
+ if (!value()) return 0;
+ int v = Fl::event_text()[0];
+ if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) {
+ v = v | Fl::event_state()&(FL_META|FL_ALT|FL_CTRL);
+ } else {
+ v = Fl::event_state()&(FL_META|FL_ALT|FL_CTRL|FL_SHIFT) | Fl::event_key();
+ if (v == FL_BackSpace && svalue) v = 0;
+ }
+ if (v != svalue) {svalue = v; set_changed(); redraw();}
+ return 1;
+ } else if (e == FL_UNFOCUS) {
+ int c = changed(); value(0); if (c) set_changed();
+ return 1;
+ } else if (e == FL_FOCUS) {
+ return value();
+ } else {
+ int r = Fl_Button::handle(e);
+ if (e == FL_RELEASE && value() && Fl::focus() != this) take_focus();
+ return r;
+ }
+}
+
+void shortcut_in_cb(Shortcut_Button* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_button()) {i->hide(); return;}
+ i->show();
+ i->svalue = ((Fl_Button*)(current_widget->o))->shortcut();
+ i->redraw();
+ } else {
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_button()) {
+ Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o);
+ b->shortcut(i->svalue);
+ if (o->is_menu_item()) ((Fl_Widget_Type*)o)->redraw();
+ }
+ }
+}
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
new file mode 100644
index 000000000..f57a970d4
--- /dev/null
+++ b/fluid/Fl_Type.cxx
@@ -0,0 +1,617 @@
+/* Fl_Type.C
+
+ Each object described by Fluid is one of these objects. They
+ are all stored in a double-linked list.
+
+ They "type" of the object is covered by the virtual functions.
+ There will probably be a lot of these virtual functions.
+
+ The type browser is also a list of these objects, but they
+ are "factory" instances, not "real" ones. These objects exist
+ only so the "make" method can be called on them. They are
+ not in the linked list and are not written to files or
+ copied or otherwise examined.
+
+*/
+
+#include <FL/Fl.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/fl_draw.H>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "Fl_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+class Widget_Browser : public Fl_Browser_ {
+ friend class Fl_Type;
+
+ // required routines for Fl_Browser_ subclass:
+ void *item_first() const ;
+ void *item_next(void *) const ;
+ void *item_prev(void *) const ;
+ int item_selected(void *) const ;
+ void item_select(void *,int);
+ int item_width(void *) const ;
+ int item_height(void *) const ;
+ void item_draw(void *,int,int,int,int) const ;
+ int incr_height() const ;
+
+public:
+
+ int handle(int);
+ void callback();
+ Widget_Browser(int,int,int,int,const char * =0);
+};
+
+static Widget_Browser *widget_browser;
+Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
+ return (widget_browser = new Widget_Browser(x,y,w,h));
+}
+
+void select(Fl_Type *o, int v) {
+ widget_browser->select(o,v,1);
+ // Fl_Type::current = o;
+}
+
+void select_only(Fl_Type *o) {
+ widget_browser->select_only(o,1);
+}
+
+void deselect() {
+ widget_browser->deselect();
+ //Fl_Type::current = 0; // this breaks the paste & merge functions
+}
+
+Fl_Type *Fl_Type::first;
+Fl_Type *Fl_Type::last;
+
+static void Widget_Browser_callback(Fl_Widget *o,void *) {
+ ((Widget_Browser *)o)->callback();
+}
+
+Widget_Browser::Widget_Browser(int x,int y,int w,int h,const char*l)
+: Fl_Browser_(x,y,w,h,l) {
+ type(FL_MULTI_BROWSER);
+ Fl_Widget::callback(Widget_Browser_callback);
+ when(FL_WHEN_RELEASE);
+}
+
+void *Widget_Browser::item_first() const {return Fl_Type::first;}
+
+void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;}
+
+void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;}
+
+int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;}
+
+void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;}
+
+int Widget_Browser::item_height(void *l) const {
+ return ((Fl_Type *)l)->visible ? textsize()+2 : 0;
+}
+
+int Widget_Browser::incr_height() const {return textsize()+2;}
+
+static Fl_Type* pushedtitle;
+
+// Generate a descriptive text for this item, to put in browser & window titles
+const char* Fl_Type::title() {
+ const char* c = name(); if (c) return c;
+ return type_name();
+}
+
+extern const char* subclassname(Fl_Type*);
+
+void Widget_Browser::item_draw(void *v, int x, int y, int, int) const {
+ Fl_Type *l = (Fl_Type *)v;
+ x += 3 + l->level * 10;
+ fl_color(FL_BLACK);
+ if (l->is_parent()) {
+ if (!l->next || l->next->level <= l->level) {
+ if (l->open_!=(l==pushedtitle)) {
+ fl_loop(x,y+7,x+5,y+12,x+10,y+7);
+ } else {
+ fl_loop(x+2,y+2,x+7,y+7,x+2,y+12);
+ }
+ } else {
+ if (l->open_!=(l==pushedtitle)) {
+ fl_polygon(x,y+7,x+5,y+12,x+10,y+7);
+ } else {
+ fl_polygon(x+2,y+2,x+7,y+7,x+2,y+12);
+ }
+ }
+ x += 10;
+ }
+ if (l->is_widget() || l->is_class()) {
+ const char* c = subclassname(l);
+ if (!strncmp(c,"Fl_",3)) c += 3;
+ fl_font(textfont(), textsize());
+ fl_draw(c, x, y+13);
+ x += int(fl_width(c)+fl_width('n'));
+ c = l->name();
+ if (c) {
+ fl_font(textfont()|FL_BOLD, textsize());
+ fl_draw(c, x, y+13);
+ } else if ((c=l->label())) {
+ char buf[50]; char* p = buf;
+ *p++ = '"';
+ for (int i = 20; i--;) {
+ if (! (*c & -32)) break;
+ *p++ = *c++;
+ }
+ if (*c) {strcpy(p,"..."); p+=3;}
+ *p++ = '"';
+ *p = 0;
+ fl_draw(buf, x, y+13);
+ }
+ } else {
+ const char* c = l->title();
+ char buf[60]; char* p = buf;
+ for (int i = 55; i--;) {
+ if (! (*c & -32)) break;
+ *p++ = *c++;
+ }
+ if (*c) {strcpy(p,"..."); p+=3;}
+ *p = 0;
+ fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+ fl_draw(buf, x, y+13);
+ }
+}
+
+int Widget_Browser::item_width(void *v) const {
+ Fl_Type *l = (Fl_Type *)v;
+
+ if (!l->visible) return 0;
+
+ int w = 3 + l->level*10;
+ if (l->is_parent()) w += 10;
+
+ if (l->is_widget() || l->is_class()) {
+ const char* c = l->type_name();
+ if (!strncmp(c,"Fl_",3)) c += 3;
+ fl_font(textfont(), textsize());
+ w += int(fl_width(c) + fl_width('n'));
+ c = l->name();
+ if (c) {
+ fl_font(textfont()|FL_BOLD, textsize());
+ w += int(fl_width(c));
+ } else if ((c=l->label())) {
+ char buf[50]; char* p = buf;
+ *p++ = '"';
+ for (int i = 20; i--;) {
+ if (! (*c & -32)) break;
+ *p++ = *c++;
+ }
+ if (*c) {strcpy(p,"..."); p+=3;}
+ *p++ = '"';
+ *p = 0;
+ w += int(fl_width(buf));
+ }
+ } else {
+ const char* c = l->title();
+ char buf[60]; char* p = buf;
+ for (int i = 55; i--;) {
+ if (! (*c & -32)) break;
+ *p++ = *c++;
+ }
+ if (*c) {strcpy(p,"..."); p+=3;}
+ *p = 0;
+ fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+ w += int(fl_width(buf));
+ }
+
+ return w;
+}
+
+void redraw_browser() {
+ widget_browser->redraw();
+}
+
+void Widget_Browser::callback() {
+ selection_changed((Fl_Type*)selection());
+}
+
+int Widget_Browser::handle(int e) {
+ static Fl_Type *title;
+ Fl_Type *l;
+ int X,Y,W,H; bbox(X,Y,W,H);
+ switch (e) {
+ case FL_PUSH:
+ if (!Fl::event_inside(X,Y,W,H)) break;
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l) {
+ X += 10*l->level;
+ if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) {
+ title = pushedtitle = l;
+ redraw_line(l);
+ return 1;
+ }
+ }
+ break;
+ case FL_DRAG:
+ if (!title) break;
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l) {
+ X += 10*l->level;
+ if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ;
+ else l = 0;
+ }
+ if (l != pushedtitle) {
+ if (pushedtitle) redraw_line(pushedtitle);
+ if (l) redraw_line(l);
+ pushedtitle = l;
+ }
+ return 1;
+ case FL_RELEASE:
+ if (!title) {
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
+ l->open();
+ break;
+ }
+ l = pushedtitle;
+ title = pushedtitle = 0;
+ if (l) {
+ if (l->open_) {
+ l->open_ = 0;
+ for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
+ k->visible = 0;
+ } else {
+ l->open_ = 1;
+ for (Fl_Type*k=l->next; k&&k->level>l->level;) {
+ k->visible = 1;
+ if (k->is_parent() && !k->open_) {
+ Fl_Type *j;
+ for (j = k->next; j && j->level>k->level; j = j->next);
+ k = j;
+ } else
+ k = k->next;
+ }
+ }
+ redraw();
+ }
+ return 1;
+ }
+ return Fl_Browser_::handle(e);
+}
+
+Fl_Type::Fl_Type() {
+ factory = 0;
+ parent = 0;
+ next = prev = 0;
+ selected = new_selected = 0;
+ visible = 0;
+ name_ = 0;
+ label_ = 0;
+ user_data_ = 0;
+ user_data_type_ = 0;
+ callback_ = 0;
+ rtti = 0;
+ level = 0;
+}
+
+static void fixvisible(Fl_Type *p) {
+ Fl_Type *t = p;
+ for (;;) {
+ if (t->parent) t->visible = t->parent->visible && t->parent->open_;
+ else t->visible = 1;
+ t = t->next;
+ if (!t || t->level <= p->level) break;
+ }
+}
+
+// turn a click at x,y on this into the actual picked object:
+Fl_Type* Fl_Type::click_test(int,int) {return 0;}
+void Fl_Type::add_child(Fl_Type*, Fl_Type*) {}
+void Fl_Type::move_child(Fl_Type*, Fl_Type*) {}
+void Fl_Type::remove_child(Fl_Type*) {}
+
+// add a list of widgets as a new child of p:
+void Fl_Type::add(Fl_Type *p) {
+ parent = p;
+ Fl_Type *end = this;
+ while (end->next) end = end->next;
+ Fl_Type *q;
+ int newlevel;
+ if (p) {
+ for (q = p->next; q && q->level > p->level; q = q->next);
+ newlevel = p->level+1;
+ } else {
+ q = 0;
+ newlevel = 0;
+ }
+ for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
+ level = newlevel;
+ if (q) {
+ prev = q->prev;
+ prev->next = this;
+ q->prev = end;
+ end->next = q;
+ } else if (first) {
+ prev = last;
+ prev->next = this;
+ end->next = 0;
+ last = end;
+ } else {
+ first = this;
+ last = end;
+ prev = end->next = 0;
+ }
+ if (p) p->add_child(this,0);
+ open_ = 1;
+ fixvisible(this);
+ modflag = 1;
+ widget_browser->redraw();
+}
+
+// add to a parent before another widget:
+void Fl_Type::insert(Fl_Type *g) {
+ Fl_Type *end = this;
+ while (end->next) end = end->next;
+ parent = g->parent;
+ int newlevel = g->level;
+ visible = g->visible;
+ for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level;
+ level = newlevel;
+ prev = g->prev;
+ if (prev) prev->next = this; else first = this;
+ end->next = g;
+ g->prev = end;
+ fixvisible(this);
+ if (parent) parent->add_child(this, g);
+ widget_browser->redraw();
+}
+
+// delete from parent:
+Fl_Type *Fl_Type::remove() {
+ Fl_Type *end = this;
+ for (;;) {
+ if (!end->next || end->next->level <= level) break;
+ end = end->next;
+ }
+ if (prev) prev->next = end->next;
+ else first = end->next;
+ if (end->next) end->next->prev = prev;
+ else last = prev;
+ Fl_Type *r = end->next;
+ prev = end->next = 0;
+ if (parent) parent->remove_child(this);
+ parent = 0;
+ widget_browser->redraw();
+ selection_changed(0);
+ return r;
+}
+
+// update a string member:
+int storestring(const char *n, const char * & p, int nostrip) {
+ if (n == p) return 0;
+ int length = 0;
+ if (n) { // see if blank, strip leading & trailing blanks
+ if (!nostrip) while (isspace(*n)) n++;
+ const char *e = n + strlen(n);
+ if (!nostrip) while (e > n && isspace(*(e-1))) e--;
+ length = e-n;
+ if (!length) n = 0;
+ }
+ if (n == p) return 0;
+ if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
+ if (p) free((void *)p);
+ if (!n || !*n) {
+ p = 0;
+ } else {
+ char *q = (char *)malloc(length+1);
+ strncpy(q,n,length);
+ q[length] = 0;
+ p = q;
+ }
+ modflag = 1;
+ return 1;
+}
+
+void Fl_Type::name(const char *n) {
+ if (storestring(n,name_)) {
+ if (visible) widget_browser->redraw();
+ }
+}
+
+void Fl_Type::label(const char *n) {
+ if (storestring(n,label_,1)) {
+ setlabel(label_);
+ if (visible && !name_) widget_browser->redraw();
+ }
+}
+
+void Fl_Type::callback(const char *n) {
+ storestring(n,callback_);
+}
+
+void Fl_Type::user_data(const char *n) {
+ storestring(n,user_data_);
+}
+
+void Fl_Type::user_data_type(const char *n) {
+ storestring(n,user_data_type_);
+}
+
+void Fl_Type::open() {
+ printf("Open of '%s' is not yet implemented\n",type_name());
+}
+
+void Fl_Type::setlabel(const char *) {}
+
+Fl_Type::~Fl_Type() {
+ if (parent) parent->remove_child(this);
+ // warning: destructor only works for widgets that have been add()ed.
+ if (widget_browser) widget_browser->deleting(this);
+ if (prev) prev->next = next; else first = next;
+ if (next) next->prev = prev; else last = prev;
+ if (current == this) current = 0;
+ modflag = 1;
+}
+
+int Fl_Type::is_parent() const {return 0;}
+int Fl_Type::is_widget() const {return 0;}
+int Fl_Type::is_valuator() const {return 0;}
+int Fl_Type::is_button() const {return 0;}
+int Fl_Type::is_menu_item() const {return 0;}
+int Fl_Type::is_menu_button() const {return 0;}
+int Fl_Type::is_group() const {return 0;}
+int Fl_Type::is_window() const {return 0;}
+int Fl_Type::is_code_block() const {return 0;}
+int Fl_Type::is_decl_block() const {return 0;}
+int Fl_Type::is_class() const {return 0;}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Type *in_this_only; // set if menu popped-up in window
+
+void select_all_cb(Fl_Widget *,void *) {
+ Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
+ if (in_this_only) {
+ Fl_Type *t = p;
+ for (; t && t != in_this_only; t = t->parent);
+ if (t != in_this_only) p = in_this_only;
+ }
+ for (;;) {
+ if (p) {
+ int foundany = 0;
+ for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
+ if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
+ }
+ if (foundany) break;
+ p = p->parent;
+ } else {
+ for (Fl_Type *t = Fl_Type::first; t; t = t->next)
+ widget_browser->select(t,1,0);
+ break;
+ }
+ }
+ selection_changed(p);
+}
+
+static void delete_children(Fl_Type *p) {
+ Fl_Type *f;
+ for (f = p; f && f->next && f->next->level > p->level; f = f->next);
+ for (; f != p; ) {
+ Fl_Type *g = f->prev;
+ delete f;
+ f = g;
+ }
+}
+
+void delete_all(int selected_only) {
+ for (Fl_Type *f = Fl_Type::first; f;) {
+ if (f->selected || !selected_only) {
+ delete_children(f);
+ Fl_Type *g = f->next;
+ delete f;
+ f = g;
+ } else f = f->next;
+ }
+ selection_changed(0);
+}
+
+// move f (and it's children) into list before g:
+// returns pointer to whatever is after f & children
+void Fl_Type::move_before(Fl_Type* g) {
+ if (level != g->level) printf("move_before levels don't match! %d %d\n",
+ level, g->level);
+ Fl_Type* n;
+ for (n = next; n && n->level > level; n = n->next);
+ if (n == g) return;
+ Fl_Type *l = n ? n->prev : Fl_Type::last;
+ prev->next = n;
+ if (n) n->prev = prev; else Fl_Type::last = prev;
+ prev = g->prev;
+ l->next = g;
+ if (prev) prev->next = this; else Fl_Type::first = this;
+ g->prev = l;
+ if (parent) parent->move_child(this,g);
+ widget_browser->redraw();
+}
+
+// move selected widgets in their parent's list:
+void earlier_cb(Fl_Widget*,void*) {
+ Fl_Type *f;
+ for (f = Fl_Type::first; f; f=f->next) if (f->selected) {
+ Fl_Type *g;
+ for (g = f->prev; g && g->level > f->level; g = g->prev);
+ if (g && g->level == f->level) f->move_before(g);
+ }
+}
+
+void later_cb(Fl_Widget*,void*) {
+ Fl_Type *f;
+ for (f = Fl_Type::last; f; f=f->prev) if (f->selected) {
+ Fl_Type *g;
+ for (g = f->next; g && g->level > f->level; g = g->next);
+ if (g && g->level == f->level && !g->selected) g->move_before(f);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// write a widget and all it's children:
+void Fl_Type::write() {
+ write_indent(level);
+ write_word(type_name());
+ write_word(name());
+ write_open(level);
+ write_properties();
+ write_close(level);
+ if (!is_parent()) return;
+ // now do children:
+ write_open(level);
+ Fl_Type *child;
+ for (child = next; child && child->level > level; child = child->next)
+ if (child->level == level+1) child->write();
+ write_close(level);
+}
+
+void Fl_Type::write_properties() {
+ // repeat this for each attribute:
+ if (label()) {
+ write_indent(level+1);
+ write_word("label");
+ write_word(label());
+ }
+ if (user_data()) {
+ write_indent(level+1);
+ write_word("user_data");
+ write_word(user_data());
+ if (user_data_type()) {
+ write_word("user_data_type");
+ write_word(user_data_type());
+ }
+ }
+ if (callback()) {
+ write_indent(level+1);
+ write_word("callback");
+ write_word(callback());
+ }
+ if (is_parent() && open_) write_word("open");
+ if (selected) write_word("selected");
+}
+
+void Fl_Type::read_property(const char *c) {
+ if (!strcmp(c,"label"))
+ label(read_word());
+ else if (!strcmp(c,"user_data"))
+ user_data(read_word());
+ else if (!strcmp(c,"user_data_type"))
+ user_data_type(read_word());
+ else if (!strcmp(c,"callback"))
+ callback(read_word());
+ else if (!strcmp(c,"open"))
+ open_ = 1;
+ else if (!strcmp(c,"selected"))
+ select(this,1);
+ else
+ read_error("Unknown property \"%s\"", c);
+}
+
+int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
new file mode 100644
index 000000000..737423a1d
--- /dev/null
+++ b/fluid/Fl_Type.h
@@ -0,0 +1,142 @@
+// Fl_Type.H
+
+// Each object described by Fluid is one of these objects. They
+// are all stored in a double-linked list.
+
+// There is also a single "factory" instance of each type of this.
+// The method "make()" is called on this factory to create a new
+// instance of this object. It could also have a "copy()" function,
+// but it was easier to implement this by using the file read/write
+// that is needed to save the setup anyways.
+
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu.H>
+
+class Fl_Type {
+
+ friend class Widget_Browser;
+ friend Fl_Widget *make_type_browser(int,int,int,int,const char *l=0);
+ friend class Fl_Window_Type;
+ virtual void setlabel(const char *); // virtual part of label(char*)
+
+protected:
+
+ Fl_Type();
+
+ const char *name_;
+ const char *label_;
+ const char *callback_;
+ const char *user_data_;
+ const char *user_data_type_;
+
+public: // things that should not be public:
+
+ Fl_Type *parent; // parent, which is previous in list
+ char new_selected; // browser highlight
+ char selected; // copied here by selection_changed()
+ char open_; // state of triangle in browser
+ char visible; // true if all parents are open
+ char rtti; // hack because I have no rtti, this is 0 for base class
+ int level; // number of parents over this
+ static Fl_Type *first, *last; // linked list of all objects
+ Fl_Type *next, *prev; // linked list of all objects
+
+ Fl_Type *factory;
+ const char *callback_name();
+
+public:
+
+ virtual ~Fl_Type();
+ virtual Fl_Type *make() = 0;
+
+ void add(Fl_Type *parent); // add as new child
+ void insert(Fl_Type *n); // insert into list before n
+ Fl_Type* remove(); // remove from list
+ void move_before(Fl_Type*); // move before a sibling
+
+ virtual const char *title(); // string for browser
+ virtual const char *type_name() = 0; // type for code output
+
+ const char *name() const {return name_;}
+ void name(const char *);
+ const char *label() const {return label_;}
+ void label(const char *);
+ const char *callback() const {return callback_;}
+ void callback(const char *);
+ const char *user_data() const {return user_data_;}
+ void user_data(const char *);
+ const char *user_data_type() const {return user_data_type_;}
+ void user_data_type(const char *);
+
+ virtual Fl_Type* click_test(int,int);
+ virtual void add_child(Fl_Type*, Fl_Type* beforethis);
+ virtual void move_child(Fl_Type*, Fl_Type* beforethis);
+ virtual void remove_child(Fl_Type*);
+
+ static Fl_Type *current; // most recently picked object
+ virtual void open(); // what happens when you double-click
+
+ // read and write data to a saved file:
+ void write();
+ virtual void write_properties();
+ virtual void read_property(const char *);
+ virtual int read_fdesign(const char*, const char*);
+
+ // write code, these are called in order:
+ virtual void write_declare(); // write #include and #define to .h file
+ virtual void write_static(); // write static stuff to .c file
+ virtual void write_code1(); // code and .h before children
+ virtual void write_code2(); // code and .h after children
+
+ // fake rtti:
+ virtual int is_parent() const;
+ virtual int is_widget() const;
+ virtual int is_button() const;
+ virtual int is_valuator() const;
+ virtual int is_menu_item() const;
+ virtual int is_menu_button() const;
+ virtual int is_group() const;
+ virtual int is_window() const;
+ virtual int is_code_block() const;
+ virtual int is_decl_block() const;
+ virtual int is_class() const;
+
+ const char* class_name() const;
+};
+
+// object list operations:
+Fl_Widget *make_widget_browser(int x,int y,int w,int h);
+extern int modflag;
+void delete_all(int selected_only=0);
+void selection_changed(Fl_Type* new_current);
+
+// file operations:
+void write_word(const char *);
+void write_string(const char *,...);
+int write_file(const char *, int selected_only = 0);
+int write_code(const char *cfile, const char *hfile);
+
+int write_declare(const char *, ...);
+int is_id(char);
+const char* unique_id(void* o, const char*, const char*, const char*);
+void write_c(const char*, ...);
+void write_h(const char*, ...);
+void write_cstring(const char *);
+void write_cstring(const char *,int length);
+void write_indent(int n);
+void write_open(int);
+void write_close(int n);
+extern int write_number;
+void write_public(int state); // writes pubic:/private: as needed
+extern int indentation;
+extern const char* indent();
+
+int read_file(const char *, int merge);
+const char *read_word(int wantbrace = 0);
+void read_error(const char *format, ...);
+
+// check legality of c code (sort of) and return error:
+const char *c_check(const char *c, int type = 0);
+
+// replace a string pointer with new value, strips leading/trailing blanks:
+int storestring(const char *n, const char * & p, int nostrip=0);
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
new file mode 100644
index 000000000..96c22acea
--- /dev/null
+++ b/fluid/Fl_Widget_Type.cxx
@@ -0,0 +1,1676 @@
+// Fl_Widget_Type.C
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include "Fl_Widget_Type.H"
+#include <FL/fl_message.H>
+#include <FL/Fl_Slider.H>
+#include <FL/Fl_Window.H>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// Make an Fl_Widget_Type subclass instance.
+// It figures out the automatic size and parent of the new widget,
+// creates the Fl_Widget (by calling the virtual function _make),
+// adds it to the Fl_Widget hierarchy, creates a new Fl_Type
+// instance, sets the widget pointers, and makes all the display
+// update correctly...
+
+extern int reading_file;
+int force_parent;
+extern int gridx;
+extern int gridy;
+
+int Fl_Widget_Type::is_widget() const {return 1;}
+
+const char* subclassname(Fl_Type* l) {
+ if (l->is_widget()) {
+ Fl_Widget_Type* p = (Fl_Widget_Type*)l;
+ const char* c = p->subclass();
+ if (c) return c;
+ if (p->o->type() == FL_WINDOW+1) return "Fl_Double_Window";
+ }
+ return l->type_name();
+}
+
+Fl_Type *Fl_Widget_Type::make() {
+ // Find the current widget, or widget to copy:
+ Fl_Type *qq = Fl_Type::current;
+ while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent;
+ if (!qq) {
+ fl_message("Please select a widget");
+ return 0;
+ }
+ Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
+ // find the parent widget:
+ Fl_Widget_Type* p = q;
+ if ((force_parent || !p->is_group()) && p->parent->is_widget())
+ p = (Fl_Widget_Type*)(p->parent);
+ force_parent = 0;
+
+ // Figure out a border between widget and window:
+ int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25;
+
+ int ULX,ULY; // parent's origin in window
+ if (!p->is_window()) { // if it is a group, add corner
+ ULX = p->o->x(); ULY = p->o->y();
+ } else {
+ ULX = ULY = 0;
+ }
+
+ // Figure out a position and size for the widget
+ int X,Y,W,H;
+ if (is_group()) { // fill the parent with the widget
+ X = ULX+B;
+ W = p->o->w()-B;
+ Y = ULY+B;
+ H = p->o->h()-B;
+ } else if (q != p) { // copy position and size of current widget
+ W = q->o->w();
+ H = q->o->h();
+ X = q->o->x()+W;
+ Y = q->o->y();
+ if (X+W > ULX+p->o->w()) {
+ X = q->o->x();
+ Y = q->o->y()+H;
+ if (Y+H > ULY+p->o->h()) Y = ULY+B;
+ }
+ } else { // just make it small and square...
+ X = ULX+B;
+ Y = ULY+B;
+ W = H = B;
+ }
+
+ // satisfy the grid requirements (otherwise it edits really strangely):
+ if (gridx>1) {
+ X = (X/gridx)*gridx;
+ W = ((W-1)/gridx+1)*gridx;
+ }
+ if (gridy>1) {
+ Y = (Y/gridy)*gridy;
+ H = ((H-1)/gridy+1)*gridy;
+ }
+
+ // Construct the Fl_Type:
+ Fl_Widget_Type *t = _make();
+ if (!o) o = widget(0,0,100,100); // create template widget
+ t->factory = this;
+ // Construct the Fl_Widget:
+ t->o = widget(X,Y,W,H);
+ if (reading_file) t->o->label(0);
+ else if (t->o->label()) t->label(t->o->label()); // allow editing
+ t->o->user_data((void*)t);
+ // Put it in the parent:
+ // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add())
+ // add to browser:
+ t->add(p);
+ t->redraw();
+ return t;
+}
+
+#include "Fluid_Image.H"
+
+void Fl_Widget_Type::setimage(Fluid_Image *i) {
+ if (i == image) return;
+ if (image) image->decrement();
+ if (i) i->increment();
+ image = i;
+ if (i) i->label(o);
+ else o->labeltype(FL_NORMAL_LABEL);
+ redraw();
+}
+
+static char dont_touch_image;
+void Fl_Widget_Type::setlabel(const char *n) {
+ if (image) {
+ if (dont_touch_image) return;
+ Fluid_Image *i = Fluid_Image::find(n);
+ setimage(i);
+ if (i) return;
+ }
+ o->label(n);
+ redraw();
+}
+
+Fl_Widget_Type::Fl_Widget_Type() {
+ for (int n=0; n<NUM_EXTRA_CODE; n++) {extra_code_[n] = 0; subclass_ = 0;}
+ hotspot_ = 0;
+ image = 0;
+ xclass = 0;
+ o = 0;
+ public_ = 1;
+}
+
+Fl_Widget_Type::~Fl_Widget_Type() {
+ if (o) {
+ o->hide();
+ if (o->parent()) ((Fl_Group*)o->parent())->remove(*o);
+ delete o;
+ }
+}
+
+void Fl_Widget_Type::extra_code(int m,const char *n) {
+ storestring(n,extra_code_[m]);
+}
+
+extern void redraw_browser();
+void Fl_Widget_Type::subclass(const char *n) {
+ if (storestring(n,subclass_) && visible)
+ redraw_browser();
+}
+
+void Fl_Widget_Type::redraw() {
+ Fl_Type *t = this;
+ if (is_menu_item()) {
+ // find the menu button that parents this menu:
+ do t = t->parent; while (t && t->is_menu_item());
+ // kludge to cause build_menu to be called again:
+ t->add_child(0,0);
+ } else {
+ while (t->parent && t->parent->is_widget()) t = t->parent;
+ ((Fl_Widget_Type*)t)->o->redraw();
+ }
+}
+
+// the recursive part sorts all children, returns pointer to next:
+Fl_Type *sort(Fl_Type *parent) {
+ Fl_Type *f,*n=0;
+ for (f = parent ? parent->next : Fl_Type::first; ; f = n) {
+ if (!f || parent && f->level <= parent->level) return f;
+ n = sort(f);
+ if (!f->selected || (!f->is_widget() || f->is_menu_item())) continue;
+ Fl_Widget* fw = ((Fl_Widget_Type*)f)->o;
+ Fl_Type *g; // we will insert before this
+ for (g = parent->next; g != f; g = g->next) {
+ if (!g->selected || g->level > f->level) continue;
+ Fl_Widget* gw = ((Fl_Widget_Type*)g)->o;
+ if (gw->y() > fw->y()) break;
+ if (gw->y() == fw->y() && gw->x() > fw->x()) break;
+ }
+ if (g != f) f->move_before(g);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// The control panels!
+
+#include "widget_panel.H"
+#include <FL/fl_show_colormap.H>
+
+// All the callbacks use the argument to indicate whether to load or store.
+// This avoids the need for pointers to all the widgets, and keeps the
+// code localized in the callbacks.
+// A value of LOAD means to load. The hope is that this will not collide
+// with any actual useful values for the argument. I also use this to
+// initialized parts of the widget that are nyi by fluid.
+
+Fl_Widget_Type *current_widget; // one of the selected ones
+static int numselected; // number selected
+static int haderror;
+
+void name_cb(Fl_Input* o, void *v) {
+ if (v == LOAD) {
+ if (numselected != 1) {
+ static char buf[16];
+ sprintf(buf,"(%d widgets)",numselected);
+ ((Fl_Window*)(o->parent()))->label(buf);
+ o->hide();
+ } else {
+ o->static_value(current_widget->name());
+ o->show();
+ ((Fl_Window*)(o->parent()))->label(current_widget->title());
+ }
+ } else {
+ if (numselected == 1) {
+ current_widget->name(o->value());
+ // I don't update window title, as it probably is being closed
+ // and wm2 (a window manager) barfs if you retitle and then
+ // hide a window:
+ // ((Fl_Window*)(o->parent()))->label(current_widget->title());
+ }
+ }
+}
+
+void name_public_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ i->value(current_widget->public_);
+ } else {
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget())
+ ((Fl_Widget_Type*)o)->public_ = i->value();
+ }
+}
+
+static char* oldlabel;
+static unsigned oldlabellen;
+static Fl_Input *label_input;
+
+void label_cb(Fl_Input* i, void *v) {
+ if (v == LOAD) {
+ label_input = i;
+ i->static_value(current_widget->label());
+ if (strlen(i->value()) >= oldlabellen) {
+ oldlabellen = strlen(i->value())+128;
+ oldlabel = (char*)realloc(oldlabel,oldlabellen);
+ }
+ strcpy(oldlabel,i->value());
+ if (current_widget->image) i->deactivate();
+ else i->activate();
+ } else {
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) o->label(i->value());
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// turn number to string or string to number for saving to file:
+// does not work for hierarchial menus!
+
+const char *item_name(Fl_Menu_Item* m, int i) {
+ if (m) {
+ while (m->label()) {
+ if (m->argument() == i) return m->label();
+ m++;
+ }
+ }
+ static char buffer[20];
+ sprintf(buffer, "%d", i);
+ return buffer;
+}
+int item_number(Fl_Menu_Item* m, const char* i) {
+ if (m && i) {
+ if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3;
+ while (m->label()) {
+ if (!strcmp(m->label(), i)) return int(m->argument());
+ m++;
+ }
+ }
+ return atoi(i);
+}
+
+#define ZERO_ENTRY 1000
+
+Fl_Menu_Item boxmenu[] = {
+{"NO_BOX",0,0,(void *)ZERO_ENTRY},
+{"boxes",0,0,0,FL_SUBMENU},
+{"UP_BOX",0,0,(void *)FL_UP_BOX},
+{"DOWN_BOX",0,0,(void *)FL_DOWN_BOX},
+{"FLAT_BOX",0,0,(void *)FL_FLAT_BOX},
+{"BORDER_BOX",0,0,(void *)FL_BORDER_BOX},
+{"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX},
+{"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX},
+{"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX},
+{"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX},
+{"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX},
+{"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX},
+{"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX},
+{"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX},
+{"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX},
+{"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX},
+{"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX},
+{"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX},
+{"OVAL_BOX",0,0,(void *)FL_OVAL_BOX},
+{"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX},
+{"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX},
+{0},
+{"frames",0,0,0,FL_SUBMENU},
+{"UP_FRAME",0,0,(void *)FL_UP_FRAME},
+{"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME},
+{"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME},
+{"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME},
+{"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME},
+{"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME},
+{"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME},
+{"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME},
+{"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME},
+{"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME},
+{0},
+{0}};
+
+const char *boxname(int i) {
+ if (!i) i = ZERO_ENTRY;
+ for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+ if (boxmenu[j].argument() == i) return boxmenu[j].label();
+ return 0;
+}
+
+int boxnumber(const char *i) {
+ if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3;
+ for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+ if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) {
+ return int(boxmenu[j].argument());
+ }
+ return 0;
+}
+
+void box_cb(Fl_Choice* i, void *v) {
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY;
+ for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+ if (boxmenu[j].argument() == n) {i->value(j); break;}
+ } else {
+ int m = i->value();
+ int n = int(boxmenu[m].argument());
+ if (!n) return; // should not happen
+ if (n == ZERO_ENTRY) n = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->box((Fl_Boxtype)n);
+ q->redraw();
+ }
+ }
+}
+
+void down_box_cb(Fl_Choice* i, void *v) {
+ if (v == LOAD) {
+ int n;
+ if (current_widget->is_button() && !current_widget->is_menu_item())
+ n = ((Fl_Button*)(current_widget->o))->down_box();
+ else if (current_widget->is_menu_button())
+ n = ((Fl_Menu_*)(current_widget->o))->down_box();
+ else {
+ i->hide(); return;
+ }
+ i->show();
+ if (!n) n = ZERO_ENTRY;
+ for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+ if (boxmenu[j].argument() == n) {i->value(j); break;}
+ } else {
+ int m = i->value();
+ int n = int(boxmenu[m].argument());
+ if (!n) return; // should not happen
+ if (n == ZERO_ENTRY) n = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+ if (o->is_button() && !o->is_menu_item()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n);
+ if (((Fl_Button*)(q->o))->value()) q->redraw();
+ } else if (o->is_menu_button()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Menu_Item whenmenu[] = {
+ {"never",0,0,(void*)ZERO_ENTRY},
+ {"Release",0,0,(void*)FL_WHEN_RELEASE},
+ {"Changed",0,0,(void*)FL_WHEN_CHANGED},
+ {"Enter key",0,0,(void*)FL_WHEN_ENTER_KEY},
+ //{"Release or Enter",0,0,(void*)(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE)},
+ {0}};
+
+void when_cb(Fl_Choice* i, void *v) {
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ int n = current_widget->o->when() & (~FL_WHEN_NOT_CHANGED);
+ if (!n) n = ZERO_ENTRY;
+ for (int j = 0; j < int(sizeof(whenmenu)/sizeof(*whenmenu)); j++)
+ if (whenmenu[j].argument() == n) {i->value(j); break;}
+ } else {
+ int m = i->value();
+ int n = int(whenmenu[m].argument());
+ if (!n) return; // should not happen
+ if (n == ZERO_ENTRY) n = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->when(n|(q->o->when()&FL_WHEN_NOT_CHANGED));
+ }
+ }
+}
+
+void when_button_cb(Fl_Light_Button* i, void *v) {
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ i->value(current_widget->o->when()&FL_WHEN_NOT_CHANGED);
+ } else {
+ int n = i->value() ? FL_WHEN_NOT_CHANGED : 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->when(n|(q->o->when()&~FL_WHEN_NOT_CHANGED));
+ }
+ }
+}
+
+uchar Fl_Widget_Type::resizable() const {
+ if (is_window()) return ((Fl_Window*)o)->resizable() != 0;
+ Fl_Group* p = (Fl_Group*)o->parent();
+ if (p) return p->resizable() == o;
+ else return 0;
+}
+
+void Fl_Widget_Type::resizable(uchar v) {
+ if (v) {
+ if (resizable()) return;
+ if (is_window()) ((Fl_Window*)o)->resizable(o);
+ else {
+ Fl_Group* p = (Fl_Group*)o->parent();
+ if (p) p->resizable(o);
+ }
+ } else {
+ if (!resizable()) return;
+ if (is_window()) {
+ ((Fl_Window*)o)->resizable(0);
+ } else {
+ Fl_Group* p = (Fl_Group*)o->parent();
+ if (p) p->resizable(0);
+ }
+ }
+}
+
+void resizable_cb(Fl_Light_Button* i,void* v) {
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;}
+ if (numselected > 1) {i->hide(); return;}
+ i->show();
+ i->value(current_widget->resizable());
+ } else {
+ current_widget->resizable(i->value());
+ }
+}
+
+void hotspot_cb(Fl_Light_Button* i,void* v) {
+ if (v == LOAD) {
+ if (numselected > 1) {i->hide(); return;}
+ if (current_widget->is_menu_item()) i->label("divider");
+ else i->label("hotspot");
+ i->show();
+ i->value(current_widget->hotspot());
+ } else {
+ current_widget->hotspot(i->value());
+ if (current_widget->is_menu_item()) {current_widget->redraw(); return;}
+ if (i->value()) {
+ Fl_Type *p = current_widget->parent;
+ if (!p || !p->is_widget()) return;
+ while (!p->is_window()) p = p->parent;
+ for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) {
+ if (o->is_widget() && o != current_widget)
+ ((Fl_Widget_Type*)o)->hotspot(0);
+ }
+ }
+ }
+}
+
+void visible_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ i->value(current_widget->o->visible());
+ } else {
+ int n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ n ? q->o->show() : q->o->hide();
+ q->redraw();
+ }
+ }
+}
+
+void active_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ i->value(current_widget->o->active());
+ } else {
+ int n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ n ? q->o->activate() : q->o->deactivate();
+ q->redraw();
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Menu_Item fontmenu[] = {
+{"Helvetica"},
+{"Helvetica bold"},
+{"Helvetica italic"},
+{"Helvetica bold italic"},
+{"Courier"},
+{"Courier bold"},
+{"Courier italic"},
+{"Courier bold italic"},
+{"Times"},
+{"Times bold"},
+{"Times italic"},
+{"Times bold italic"},
+{"Symbol"},
+{"Terminal"},
+{"Terminal Bold"},
+{"Zapf Dingbats"},
+{0}};
+
+void labelfont_cb(Fl_Choice* i, void *v) {
+ if (v == LOAD) {
+ int n = current_widget->o->labelfont();
+ if (n > 15) n = 0;
+ i->value(n);
+ } else {
+ int n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->labelfont(n);
+ q->redraw();
+ }
+ }
+}
+
+void labelsize_cb(Fl_Value_Input* i, void *v) {
+ int n;
+ if (v == LOAD) {
+ n = current_widget->o->labelsize();
+ } else {
+ n = int(i->value());
+ if (n <= 0) n = FL_NORMAL_SIZE;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->labelsize(n);
+ q->redraw();
+ }
+ }
+ i->value(n);
+}
+
+extern const char *ui_find_image_name;
+void image_cb(Fl_Widget *a, void *) {
+ Fluid_Image *i = ui_find_image(current_widget->label());
+ if (!ui_find_image_name) return; // user hit "Cancel"
+ // if i is zero then user picked a non-existent file. So that the
+ // directory they chose is preserved, we change to a normal text label.
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* p = (Fl_Widget_Type*)o;
+ dont_touch_image = 1;
+ p->setimage(i);
+ p->label(ui_find_image_name);
+ dont_touch_image = 0;
+ }
+ label_cb(label_input,LOAD);
+ a->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+}
+
+Fl_Menu_Item labeltypemenu[] = {
+ {"Image...",0,image_cb,(void*)(-1)},
+ {"NORMAL_LABEL",0,0,(void*)0},
+ {"SYMBOL_LABEL",0,0,(void*)FL_SYMBOL_LABEL},
+ {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL},
+ {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL},
+ {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL},
+ {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)},
+{0}};
+
+void labeltype_cb(Fl_Choice* i, void *v) {
+ if (v == LOAD) {
+ int n;
+ if (current_widget->image) {
+ n = -1;
+ i->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+ } else {
+ n = current_widget->o->labeltype();
+ i->when(FL_WHEN_RELEASE);
+ }
+ for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++)
+ if (labeltypemenu[j].argument() == n) {i->value(j); break;}
+ } else {
+ int m = i->value();
+ int n = int(labeltypemenu[m].argument());
+ if (n<0) return; // should not happen
+ if (current_widget->image) label_input->activate();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* p = (Fl_Widget_Type*)o;
+ if (p->image) {
+ p->setimage(0);
+ p->o->label(p->label());
+ }
+ p->o->labeltype((Fl_Labeltype)n);
+ p->redraw();
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+void color_cb(Fl_Button* i, void *v) {
+ Fl_Color c = current_widget->o->color();
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ } else {
+ Fl_Color d = fl_show_colormap(c);
+ if (d == c) return;
+ c = d;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->color(c); q->o->redraw();
+ }
+ }
+ i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+void color2_cb(Fl_Button* i, void *v) {
+ Fl_Color c = current_widget->o->selection_color();
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ } else {
+ Fl_Color d = fl_show_colormap(c);
+ if (d == c) return;
+ c = d;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->selection_color(c); q->o->redraw();
+ }
+ }
+ i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+void labelcolor_cb(Fl_Button* i, void *v) {
+ Fl_Color c = current_widget->o->labelcolor();
+ if (v != LOAD) {
+ Fl_Color d = fl_show_colormap(c);
+ if (d == c) return;
+ c = d;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->o->labelcolor(c); q->redraw();
+ }
+ }
+ i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+static Fl_Button* relative(Fl_Widget* o, int i) {
+ Fl_Group* g = (Fl_Group*)(o->parent());
+ return (Fl_Button*)(g->child(g->find(*o)+i));
+}
+
+void align_cb(Fl_Button* i, void *v) {
+ int b = int(long(i->user_data()));
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ i->value(current_widget->o->align() & b);
+ } else {
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ int x = q->o->align();
+ int y;
+ if (i->value()) {
+ y = x | b;
+ if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) {
+ Fl_Button *b1 = relative(i,+1);
+ b1->clear();
+ y = y & ~(b1->argument());
+ }
+ if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) {
+ Fl_Button *b1 = relative(i,-1);
+ b1->clear();
+ y = y & ~(b1->argument());
+ }
+ } else {
+ y = x & ~b;
+ }
+ if (x != y) {q->o->align(y); q->redraw();}
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+void callback_cb(Fl_Input* i, void *v) {
+ if (v == LOAD) {
+ i->static_value(current_widget->callback());
+ } else {
+ const char *c = i->value();
+ const char *d = c_check(c);
+ if (d) {fl_show_message("Error in callback:",d,0); haderror = 1; return;}
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+ o->callback(c);
+ }
+ }
+}
+
+void user_data_cb(Fl_Input *i, void *v) {
+ if (v == LOAD) {
+ i->static_value(current_widget->user_data());
+ } else {
+ const char *c = i->value();
+ const char *d = c_check(c);
+ if (d) {fl_show_message("Error in user_data:",d,0); haderror = 1; return;}
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+ o->user_data(c);
+ }
+ }
+}
+
+void user_data_type_cb(Fl_Input *i, void *v) {
+ static const char *dflt = "void*";
+ if (v == LOAD) {
+ const char *c = current_widget->user_data_type();
+ if (!c) c = dflt;
+ i->static_value(c);
+ } else {
+ const char *c = i->value();
+ if (!*c) i->value(dflt);
+ else if (!strcmp(c,dflt)) c = 0;
+ const char *d = c_check(c);
+ if (!d) {
+ if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long"))
+ d = "must be pointer or long";
+ }
+ if (d) {fl_show_message("Error in type:",d,0); haderror = 1; return;}
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+ o->user_data_type(c);
+ }
+ }
+}
+
+// "v_attributes" let user type in random code for attribute settings:
+
+void v_input_cb(Fl_Input* i, void* v) {
+ int n = int(long(i->user_data()));
+ if (v == LOAD) {
+ i->static_value(current_widget->extra_code(n));
+ } else {
+ const char *c = i->value();
+ const char *d = c_check(c&&c[0]=='#' ? c+1 : c);
+ if (d) {fl_show_message("Error in",i->label(),d); haderror = 1; return;}
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type *t = (Fl_Widget_Type*)o;
+ t->extra_code(n,c);
+ }
+ }
+}
+
+void subclass_cb(Fl_Input* i, void* v) {
+ if (v == LOAD) {
+ if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+ i->static_value(current_widget->subclass());
+ } else {
+ const char *c = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type *t = (Fl_Widget_Type*)o;
+ t->subclass(c);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// textstuff: set textfont, textsize, textcolor attributes:
+
+// default widget returns 0 to indicate not-implemented:
+int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) {return 0;}
+
+void textfont_cb(Fl_Choice* i, void* v) {
+ Fl_Font n; int s; Fl_Color c;
+ if (v == LOAD) {
+ if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+ i->show();
+ if (n > 15) n = FL_HELVETICA;
+ i->value(n);
+ } else {
+ n = (Fl_Font)i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->textstuff(1,n,s,c);
+ q->o->redraw();
+ }
+ }
+}
+
+void textsize_cb(Fl_Value_Input* i, void* v) {
+ Fl_Font n; int s; Fl_Color c;
+ if (v == LOAD) {
+ if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+ i->show();
+ } else {
+ s = int(i->value());
+ if (s <= 0) s = FL_NORMAL_SIZE;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->textstuff(2,n,s,c);
+ q->o->redraw();
+ }
+ }
+ i->value(s);
+}
+
+void textcolor_cb(Fl_Button* i, void* v) {
+ Fl_Font n; int s; Fl_Color c;
+ if (v == LOAD) {
+ if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+ i->show();
+ } else {
+ c = i->labelcolor();
+ Fl_Color d = fl_show_colormap(c);
+ if (d == c) return;
+ c = d;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ q->textstuff(3,n,s,c); q->o->redraw();
+ }
+ }
+ i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+// Kludges to the panel for subclasses:
+
+void slider_size_cb(Fl_Value_Input* i, void* v) {
+ if (v == LOAD) {
+ if (current_widget->is_valuator()!=2) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Slider*)(current_widget->o))->slider_size());
+ } else {
+ double n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->is_valuator()==2) {
+ ((Fl_Slider*)(q->o))->slider_size(n);
+ q->o->redraw();
+ }
+ }
+ }
+}
+
+void min_cb(Fl_Value_Input* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_valuator()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Valuator*)(current_widget->o))->minimum());
+ } else {
+ double n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->is_valuator()) {
+ ((Fl_Valuator*)(q->o))->minimum(n);
+ q->o->redraw();
+ }
+ }
+ }
+}
+
+void max_cb(Fl_Value_Input* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_valuator()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Valuator*)(current_widget->o))->maximum());
+ } else {
+ double n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->is_valuator()) {
+ ((Fl_Valuator*)(q->o))->maximum(n);
+ q->o->redraw();
+ }
+ }
+ }
+}
+
+void step_cb(Fl_Value_Input* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_valuator()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Valuator*)(current_widget->o))->step());
+ } else {
+ double n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->is_valuator()) {
+ ((Fl_Valuator*)(q->o))->step(n);
+ q->o->redraw();
+ }
+ }
+ }
+}
+
+void value_cb(Fl_Value_Input* i, void* v) {
+ if (v == LOAD) {
+ if (current_widget->is_valuator()) {
+ i->show();
+ i->value(((Fl_Valuator*)(current_widget->o))->value());
+ } else if (current_widget->is_button()) {
+ i->show();
+ i->value(((Fl_Button*)(current_widget->o))->value());
+ } else
+ i->hide();
+ } else {
+ double n = i->value();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->is_valuator()) {
+ ((Fl_Valuator*)(q->o))->value(n);
+ } else if (q->is_button()) {
+ ((Fl_Button*)(q->o))->value(n != 0);
+ if (q->is_menu_item()) q->redraw();
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// subtypes:
+
+Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;}
+
+void subtype_cb(Fl_Choice* i, void* v) {
+ if (v == LOAD) {
+ Fl_Menu_Item* m = current_widget->subtypes();
+ if (!m) {i->hide(); return;}
+ i->menu(m);
+ int j;
+ for (j = 0;; j++) {
+ if (!m[j].text) {j = 0; break;}
+ if (m[j].argument() == current_widget->o->type()) break;
+ }
+ i->value(j);
+ i->show();
+ i->redraw();
+ } else {
+ int n = int(i->mvalue()->argument());
+ Fl_Menu_Item* m = current_widget->subtypes();
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+ if (q->subtypes()==m) {
+ q->o->type(n);
+ q->redraw();
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fl_Window *the_panel;
+
+void propagate_load(Fl_Group* g, void* v) {
+ if (v == LOAD) {
+ Fl_Widget*const* a = g->array();
+ for (int i=g->children(); i--;) {
+ Fl_Widget* o = *a++;
+ o->do_callback(o,LOAD);
+ }
+ }
+}
+
+void set_cb(Fl_Button*, void*) {
+ haderror = 0;
+ Fl_Widget*const* a = the_panel->array();
+ for (int i=the_panel->children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o->changed()) {
+ o->do_callback();
+ if (haderror) return;
+ o->clear_changed();
+ }
+ }
+}
+
+void ok_cb(Fl_Return_Button* o, void* v) {
+ set_cb(o,v);
+ if (!haderror) the_panel->hide();
+}
+
+void revert_cb(Fl_Button*, void*) {
+ // We have to revert all dynamically changing fields:
+ // but for now only the first label works...
+ if (numselected == 1) current_widget->label(oldlabel);
+ propagate_load(the_panel, LOAD);
+}
+
+void cancel_cb(Fl_Button* o, void* v) {
+ revert_cb(o,v);
+ the_panel->hide();
+}
+
+void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.C
+void overlay_cb(Fl_Button*o,void *v) {
+ toggle_overlays(o,v);
+}
+
+// update the panel according to current widget set:
+static void load_panel() {
+ if (!the_panel) return;
+
+ // find all the Fl_Widget subclasses currently selected:
+ numselected = 0;
+ current_widget = 0;
+ if (Fl_Type::current) {
+ if (Fl_Type::current->is_widget())
+ current_widget=(Fl_Widget_Type*)Fl_Type::current;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+ if (o->is_widget() && o->selected) {
+ numselected++;
+ if (!current_widget) current_widget = (Fl_Widget_Type*)o;
+ }
+ }
+ }
+ if (numselected)
+ propagate_load(the_panel, LOAD);
+ else
+ the_panel->hide();
+}
+
+// This is called when user double-clicks an item, open or update the panel:
+void Fl_Widget_Type::open() {
+ if (!the_panel) the_panel = make_widget_panel();
+ load_panel();
+ if (numselected) the_panel->show();
+}
+
+Fl_Type *Fl_Type::current;
+
+extern void redraw_overlays();
+extern void redraw_browser();
+
+// Called when ui changes what objects are selected:
+// p is selected object, null for all deletions (we must throw away
+// old panel in that case, as the object may no longer exist)
+void selection_changed(Fl_Type *p) {
+ // store all changes to the current selected objects:
+ if (p && the_panel && the_panel->visible()) {
+ set_cb(0,0);
+ // if there was an error, we try to leave the selected set unchanged:
+ if (haderror) {
+ Fl_Type *q = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+ o->new_selected = o->selected;
+ if (!q && o->selected) q = o;
+ }
+ if (!p || !p->selected) p = q;
+ Fl_Type::current = p;
+ redraw_browser();
+ return;
+ }
+ }
+ // update the selected flags to new set:
+ Fl_Type *q = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+ o->selected = o->new_selected;
+ if (!q && o->selected) q = o;
+ }
+ if (!p || !p->selected) p = q;
+ Fl_Type::current = p;
+ redraw_overlays();
+ // load the panel with the new settings:
+ load_panel();
+}
+
+////////////////////////////////////////////////////////////////
+// Writing the C code:
+
+#include <ctype.h>
+
+// test to see if user named a function, or typed in code:
+int is_name(const char *c) {
+ for (; *c; c++) if (ispunct(*c) && *c!='_') return 0;
+ return 1;
+}
+
+// Test to see if name() is an array entry. If so, and this is the
+// highest number, return name[num+1]. Return null if not the highest
+// number or a field or function. Return name() if not an array entry.
+const char *array_name(Fl_Widget_Type *o) {
+ const char *c = o->name();
+ if (!c) return 0;
+ const char *d;
+ for (d = c; *d != '['; d++) {
+ if (!*d) return c;
+ if (ispunct(*d) && *d!='_') return 0;
+ }
+ int num = atoi(d+1);
+ int sawthis = 0;
+ for (Fl_Type *t = Fl_Type::first; t; t = t->next) {
+ if (t == o) {sawthis=1; continue;}
+ const char *e = t->name();
+ if (!e) continue;
+ if (strncmp(c,e,d-c)) continue;
+ int n1 = atoi(e+(d-c)+1);
+ if (n1 > num || n1==num && sawthis) return 0;
+ }
+ static char buffer[128];
+ strncpy(buffer,c,d-c+1);
+ sprintf(buffer+(d-c+1),"%d]",num+1);
+ return buffer;
+}
+
+// Test to see if extra code is a declaration:
+int isdeclare(const char *c) {
+ while (isspace(*c)) c++;
+ if (*c == '#') return 1;
+ if (!strncmp(c,"extern",6)) return 1;
+ return 0;
+}
+
+void Fl_Widget_Type::write_declare() {
+ const char *t = subclassname(this);
+ if (!subclass()) ::write_declare("#include <FL/%s.H>", t);
+ if (callback() && is_name(callback()))
+ ::write_declare("extern void %s(%s*, %s);", callback(), t,
+ user_data_type() ? user_data_type() : "void*");
+ for (int n=0; n < NUM_EXTRA_CODE; n++) {
+ if (extra_code(n) && isdeclare(extra_code(n)))
+ ::write_declare("%s", extra_code(n));
+ }
+}
+
+void Fl_Widget_Type::write_static() {
+ const char* t = subclassname(this);
+ const char* c = array_name(this);
+ const char* k = class_name();
+ if (c && !k) {
+ write_c("\n");
+ if (!public_) write_c("static ");
+ else write_h("extern %s *%s;\n", t, c);
+ write_c("%s *%s;\n", t, c);
+ }
+ if (callback() && !is_name(callback())) {
+ // see if 'o' or 'v' used, to prevent unused argument warnings:
+ int use_o = 0;
+ int use_v = 0;
+ const char *d;
+ for (d = callback(); *d;) {
+ if (*d == 'o' && !is_id(d[1])) use_o = 1;
+ if (*d == 'v' && !is_id(d[1])) use_v = 1;
+ do d++; while (is_id(*d));
+ while (*d && !is_id(*d)) d++;
+ }
+ const char* cn = callback_name();
+ if (k) {
+ write_c("\ninline void %s::%s_i(%s*", k, cn, t);
+ } else {
+ write_c("\nstatic void %s(%s*", cn, t);
+ }
+ if (use_o) write_c(" o");
+ const char* ut = user_data_type() ? user_data_type() : "void*";
+ write_c(", %s", ut);
+ if (use_v) write_c(" v");
+ write_c(") {\n %s", callback());
+ if (*(d-1) != ';') write_c(";");
+ write_c("\n}\n");
+ if (k) {
+ write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
+ write_c(" ((%s*)(o->", k);
+ for (Fl_Type* p = parent; p->is_widget(); p = p->parent)
+ write_c("parent()->");
+ write_c("user_data()))->%s_i(o,v);\n}\n", cn);
+ }
+ }
+ if (image) {
+ if (image->written != write_number) {
+ image->write_static();
+ image->written = write_number;
+ }
+ }
+}
+
+const char *Fl_Type::callback_name() {
+ if (is_name(callback())) return callback();
+ return unique_id(this, "cb", name(), label());
+}
+
+extern int varused_test, varused;
+
+void Fl_Widget_Type::write_code1() {
+ const char* t = subclassname(this);
+ const char *c = array_name(this);
+ if (c) {
+ if (class_name()) {
+ write_public(public_);
+ write_h(" %s *%s;\n", t, c);
+ } else if (!public_)
+ write_h("extern %s *%s;\n", t, c);
+ }
+ if (class_name() && callback() && !is_name(callback())) {
+ const char* cn = callback_name();
+ const char* ut = user_data_type() ? user_data_type() : "void*";
+ write_public(0);
+ write_h(" inline void %s_i(%s*, %s);\n", cn, t, ut);
+ write_h(" static void %s(%s*, %s);\n", cn, t, ut);
+ }
+ // figure out if local varaible will be used (prevent compiler warnings):
+ if (is_parent())
+ varused = 1;
+ else {
+ varused_test = 1; varused = 0;
+ write_widget_code();
+ varused_test = 0;
+ for (int n=0; n < NUM_EXTRA_CODE; n++)
+ if (extra_code(n) && !isdeclare(extra_code(n))) varused = 1;
+ }
+ write_c(indent());
+ if (varused) write_c("{ %s* o = ", t);
+ if (name()) write_c("%s = ", name());
+ if (is_window()) {
+ write_c("w = new %s(%d, %d", t, o->w(), o->h());
+ // prevent type() code from being emitted:
+ ((Fl_Widget_Type*)factory)->o->type(o->type());
+ } else {
+ write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
+ }
+ if (!image && label() && *label()) {
+ write_c(", ");
+ write_cstring(label());
+ }
+ write_c(");\n");
+ indentation += 2;
+ if (varused) write_widget_code();
+}
+
+// this is split from write_code1() for Fl_Window_Type:
+void Fl_Widget_Type::write_widget_code() {
+ Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
+ if (o->type() != tplate->type())
+ write_c("%so->type(%d);\n", indent(), o->type());
+ if (o->box() != tplate->box())
+ write_c("%so->box(FL_%s);\n", indent(), boxname(o->box()));
+ if (is_button()) {
+ Fl_Button* b = (Fl_Button*)o;
+ if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
+ boxname(b->down_box()));
+ if (b->value()) write_c("%so->value(1);\n", indent());
+ if (b->shortcut())
+ write_c("%so->shortcut(0x%x);\n", indent(), b->shortcut());
+ }
+ if (is_menu_button()) {
+ Fl_Menu_* b = (Fl_Menu_*)o;
+ if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
+ boxname(b->down_box()));
+ }
+ if (o->color() != tplate->color())
+ write_c("%so->color(%d);\n", indent(), o->color());
+ if (o->selection_color() != tplate->selection_color())
+ write_c("%so->selection_color(%d);\n", indent(), o->selection_color());
+ if (image)
+ image->write_code();
+ else if (o->labeltype() != tplate->labeltype())
+ write_c("%so->labeltype(FL_%s);\n", indent(),
+ item_name(labeltypemenu, o->labeltype()));
+ if (o->labelfont() != tplate->labelfont())
+ write_c("%so->labelfont(%d);\n", indent(), o->labelfont());
+ if (o->labelsize() != tplate->labelsize())
+ write_c("%so->labelsize(%d);\n", indent(), o->labelsize());
+ if (o->labelcolor() != tplate->labelcolor())
+ write_c("%so->labelcolor(%d);\n", indent(), o->labelcolor());
+ if (is_valuator()) {
+ Fl_Valuator* v = (Fl_Valuator*)o;
+ Fl_Valuator* f = (Fl_Valuator*)(tplate);
+ if (v->minimum()!=f->minimum())
+ write_c("%so->minimum(%g);\n", indent(), v->minimum());
+ if (v->maximum()!=f->maximum())
+ write_c("%so->maximum(%g);\n", indent(), v->maximum());
+ if (v->step()!=f->step())
+ write_c("%so->step(%g);\n", indent(), v->step());
+ if (v->value())
+ write_c("%so->value(%g);\n", indent(), v->value());
+ if (is_valuator()==2) {
+ double x = ((Fl_Slider*)v)->slider_size();
+ double y = ((Fl_Slider*)f)->slider_size();
+ if (x != y) write_c("%so->slider_size(%g);\n", indent(), x);
+ }
+ }
+ {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) {
+ Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c);
+ if (f != ff) write_c("%so->textfont(%d);\n", indent(), f);
+ if (s != fs) write_c("%so->textsize(%d);\n", indent(), s);
+ if (c != fc) write_c("%so->textcolor(%d);\n",indent(), c);
+ }}
+ const char* ud = user_data();
+ if (class_name() && !parent->is_widget()) ud = "this";
+ if (callback()) {
+ write_c("%so->callback((Fl_Callback*)%s", indent(), callback_name());
+ if (ud)
+ write_c(", (void*)(%s));\n", ud);
+ else
+ write_c(");\n");
+ } else if (ud) {
+ write_c("%so->user_data((void*)(%s));\n", indent(), ud);
+ }
+ if (o->align() != tplate->align())
+ write_c("%so->align(%d);\n", indent(), o->align());
+ if (o->when() != tplate->when())
+ write_c("%so->when(%d);\n", indent(), o->when());
+ if (!o->visible() && o->parent())
+ write_c("%so->hide();\n", indent());
+ if (!o->active())
+ write_c("%so->deactivate();\n", indent());
+ if (!is_group() && resizable())
+ write_c("%sFl_Group::current()->resizable(o);\n",indent());
+ if (hotspot())
+ write_c("%sw->hotspot(o);\n", indent());
+}
+
+void Fl_Widget_Type::write_code2() {
+ indentation -= 2;
+ if (!is_parent() && !varused) return;
+ for (int n=0; n < NUM_EXTRA_CODE; n++)
+ if (extra_code(n) && !isdeclare(extra_code(n)))
+ write_c("%s %s\n", indent(), extra_code(n));
+ write_c("%s}\n", indent());
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Widget_Type::write_properties() {
+ Fl_Type::write_properties();
+ write_indent(level+1);
+ if (!public_) write_string("private");
+ write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h());
+ Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
+ if (o->type() != tplate->type()) {
+ write_string("type");
+ write_word(item_name(subtypes(), o->type()));
+ }
+ if (o->box() != tplate->box()) {
+ write_string("box"); write_word(boxname(o->box()));}
+ if (is_button()) {
+ Fl_Button* b = (Fl_Button*)o;
+ if (b->down_box()) {
+ write_string("down_box"); write_word(boxname(b->down_box()));}
+ if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut());
+ if (b->value()) write_string("value 1");
+ }
+ if (is_menu_button()) {
+ Fl_Menu_* b = (Fl_Menu_*)o;
+ if (b->down_box()) {
+ write_string("down_box"); write_word(boxname(b->down_box()));}
+ }
+ if (o->color()!=tplate->color())
+ write_string("color %d", o->color());
+ if (o->selection_color()!=tplate->selection_color())
+ write_string("selection_color %d", o->selection_color());
+ if (image)
+ write_string("labeltype image");
+ else if (o->labeltype()!=tplate->labeltype()) {
+ write_string("labeltype");
+ write_word(item_name(labeltypemenu, o->labeltype()));
+ }
+ if (o->labelfont()!=tplate->labelfont())
+ write_string("labelfont %d", o->labelfont());
+ if (o->labelsize()!=tplate->labelsize())
+ write_string("labelsize %d", o->labelsize());
+ if (o->labelcolor()!=tplate->labelcolor())
+ write_string("labelcolor %d", o->labelcolor());
+ if (o->align()!=tplate->align())
+ write_string("align %d", o->align());
+ if (o->when() != tplate->when())
+ write_string("when %d", o->when());
+ if (is_valuator()) {
+ Fl_Valuator* v = (Fl_Valuator*)o;
+ Fl_Valuator* f = (Fl_Valuator*)(tplate);
+ if (v->minimum()!=f->minimum()) write_string("minimum %g",v->minimum());
+ if (v->maximum()!=f->maximum()) write_string("maximum %g",v->maximum());
+ if (v->step()!=f->step()) write_string("step %g",v->step());
+ if (v->value()!=0.0) write_string("value %g",v->value());
+ if (is_valuator()==2) {
+ double x = ((Fl_Slider*)v)->slider_size();
+ double y = ((Fl_Slider*)f)->slider_size();
+ if (x != y) write_string("slider_size %g", x);
+ }
+ }
+ {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) {
+ Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c);
+ if (f != ff) write_string("textfont %d", f);
+ if (s != fs) write_string("textsize %d", s);
+ if (c != fc) write_string("textcolor %d", c);
+ }}
+ if (!o->visible()) write_string("hide");
+ if (!o->active()) write_string("deactivate");
+ if (resizable()) write_string("resizable");
+ if (hotspot()) write_string(is_menu_item() ? "divider" : "hotspot");
+ for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) {
+ write_indent(level+1);
+ write_string("code%d",n);
+ write_word(extra_code(n));
+ }
+ if (subclass()) {
+ write_indent(level+1);
+ write_string("class");
+ write_word(subclass());
+ }
+}
+
+int pasteoffset;
+
+void Fl_Widget_Type::read_property(const char *c) {
+ int x,y,w,h; Fl_Font f; int s; Fl_Color cc;
+ if (!strcmp(c,"private")) {
+ public_ = 0;
+ } else if (!strcmp(c,"xywh")) {
+ if (sscanf(read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) {
+ x += pasteoffset;
+ y += pasteoffset;
+ o->resize(x,y,w,h);
+ }
+ } else if (!strcmp(c,"type")) {
+ o->type(item_number(subtypes(), read_word()));
+ } else if (!strcmp(c,"box")) {
+ const char* value = read_word();
+ if ((x = boxnumber(value))) {
+ if (x == ZERO_ENTRY) x = 0;
+ o->box((Fl_Boxtype)x);
+ } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x);
+ } else if (is_button() && !strcmp(c,"down_box")) {
+ const char* value = read_word();
+ if ((x = boxnumber(value))) {
+ if (x == ZERO_ENTRY) x = 0;
+ ((Fl_Button*)o)->down_box((Fl_Boxtype)x);
+ }
+ } else if (is_menu_button() && !strcmp(c,"down_box")) {
+ const char* value = read_word();
+ if ((x = boxnumber(value))) {
+ if (x == ZERO_ENTRY) x = 0;
+ ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x);
+ }
+ } else if (is_button() && !strcmp(c,"value")) {
+ const char* value = read_word();
+ ((Fl_Button*)o)->value(atoi(value));
+ } else if (!strcmp(c,"color")) {
+ int n = sscanf(read_word(),"%d %d",&x,&y);
+ if (n == 2) { // back compatability...
+ if (x != 47) o->color(x);
+ o->selection_color(y);
+ } else {
+ o->color(x);
+ }
+ } else if (!strcmp(c,"selection_color")) {
+ if (sscanf(read_word(),"%d",&x)) o->selection_color(x);
+ } else if (!strcmp(c,"labeltype")) {
+ c = read_word();
+ if (!strcmp(c,"image")) {
+ Fluid_Image *i = Fluid_Image::find(label());
+ if (!i) read_error("Image file '%s' not found", label());
+ else setimage(i);
+ } else {
+ o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c));
+ }
+ } else if (!strcmp(c,"labelfont")) {
+ if (sscanf(read_word(),"%d",&x) == 1) o->labelfont(x);
+ } else if (!strcmp(c,"labelsize")) {
+ if (sscanf(read_word(),"%d",&x) == 1) o->labelsize(x);
+ } else if (!strcmp(c,"labelcolor")) {
+ if (sscanf(read_word(),"%d",&x) == 1) o->labelcolor(x);
+ } else if (!strcmp(c,"align")) {
+ if (sscanf(read_word(),"%d",&x) == 1) o->align(x);
+ } else if (!strcmp(c,"when")) {
+ if (sscanf(read_word(),"%d",&x) == 1) o->when(x);
+ } else if (!strcmp(c,"minimum") && is_valuator()) {
+ ((Fl_Valuator*)o)->minimum(strtod(read_word(),0));
+ } else if (!strcmp(c,"maximum") && is_valuator()) {
+ ((Fl_Valuator*)o)->maximum(strtod(read_word(),0));
+ } else if (!strcmp(c,"step") && is_valuator()) {
+ ((Fl_Valuator*)o)->step(strtod(read_word(),0));
+ } else if (!strcmp(c,"value") && is_valuator()) {
+ ((Fl_Valuator*)o)->value(strtod(read_word(),0));
+ } else if ((!strcmp(c,"slider_size")||!strcmp(c,"size"))&&is_valuator()==2) {
+ ((Fl_Slider*)o)->slider_size(strtod(read_word(),0));
+ } else if (!strcmp(c,"textfont")) {
+ if (sscanf(read_word(),"%d",&x) == 1) {f=(Fl_Font)x; textstuff(1,f,s,cc);}
+ } else if (!strcmp(c,"textsize")) {
+ if (sscanf(read_word(),"%d",&x) == 1) {s=x; textstuff(2,f,s,cc);}
+ } else if (!strcmp(c,"textcolor")) {
+ if (sscanf(read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,f,s,cc);}
+ } else if (!strcmp(c,"hide")) {
+ o->hide();
+ } else if (!strcmp(c,"deactivate")) {
+ o->deactivate();
+ } else if (!strcmp(c,"resizable")) {
+ resizable(1);
+ } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) {
+ hotspot(1);
+ } else if (!strcmp(c,"class")) {
+ subclass(read_word());
+ } else if (is_button() && !strcmp(c,"shortcut")) {
+ ((Fl_Button*)o)->shortcut(strtol(read_word(),0,0));
+ } else {
+ if (!strncmp(c,"code",4)) {
+ int n = atoi(c+4);
+ if (n >= 0 && n <= NUM_EXTRA_CODE) {
+ extra_code(n,read_word());
+ return;
+ }
+ }
+ Fl_Type::read_property(c);
+ }
+}
+
+Fl_Menu_Item boxmenu1[] = {
+ // these extra ones are for looking up fdesign saved strings:
+ {"NO_FRAME", 0,0,(void *)FL_NO_BOX},
+ {"ROUNDED3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX},
+ {"ROUNDED3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX},
+ {"OVAL3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX},
+ {"OVAL3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX},
+ {"0", 0,0,(void *)ZERO_ENTRY},
+ {"1", 0,0,(void *)FL_UP_BOX},
+ {"2", 0,0,(void *)FL_DOWN_BOX},
+ {"3", 0,0,(void *)FL_FLAT_BOX},
+ {"4", 0,0,(void *)FL_BORDER_BOX},
+ {"5", 0,0,(void *)FL_SHADOW_BOX},
+ {"6", 0,0,(void *)FL_FRAME_BOX},
+ {"7", 0,0,(void *)FL_ROUNDED_BOX},
+ {"8", 0,0,(void *)FL_RFLAT_BOX},
+ {"9", 0,0,(void *)FL_RSHADOW_BOX},
+ {"10", 0,0,(void *)FL_UP_FRAME},
+ {"11", 0,0,(void *)FL_DOWN_FRAME},
+{0}};
+
+extern int fdesign_flip;
+int lookup_symbol(const char *, int &, int numberok = 0);
+
+int Fl_Widget_Type::read_fdesign(const char* name, const char* value) {
+ int v;
+ if (!strcmp(name,"box")) {
+ float x,y,w,h;
+ if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) {
+ if (fdesign_flip) {
+ Fl_Type *p;
+ for (p = parent; p && !p->is_window(); p = p->parent);
+ if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h);
+ }
+ x += pasteoffset;
+ y += pasteoffset;
+ o->resize(int(x),int(y),int(w),int(h));
+ }
+ } else if (!strcmp(name,"label")) {
+ label(value);
+ if (value[0] == '@') o->labeltype(FL_SYMBOL_LABEL);
+ } else if (!strcmp(name,"name")) {
+ this->name(value);
+ } else if (!strcmp(name,"callback")) {
+ callback(value); user_data_type("long");
+ } else if (!strcmp(name,"argument")) {
+ user_data(value);
+ } else if (!strcmp(name,"shortcut")) {
+ if (value[0]) {
+ char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value);
+ extra_code(0,buf);
+ }
+ } else if (!strcmp(name,"style")) {
+ if (!strncmp(value,"FL_NORMAL",9)) return 1;
+ if (!lookup_symbol(value,v,1)) return 0;
+ o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8));
+ } else if (!strcmp(name,"size")) {
+ if (!lookup_symbol(value,v,1)) return 0;
+ o->labelsize(v);
+ } else if (!strcmp(name,"type")) {
+ if (!strncmp(value,"NORMAL",6)) return 1;
+ if (lookup_symbol(value,v,1)) {o->type(v); return 1;}
+ if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE;
+ if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE;
+ return 0;
+ } else if (!strcmp(name,"lcol")) {
+ if (!lookup_symbol(value,v,1)) return 0;
+ o->labelcolor(v);
+ } else if (!strcmp(name,"return")) {
+ if (!lookup_symbol(value,v,0)) return 0;
+ o->when(v|FL_WHEN_RELEASE);
+ } else if (!strcmp(name,"alignment")) {
+ if (!lookup_symbol(value,v)) {
+ // convert old numeric values:
+ int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0;
+ v = 0;
+ if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;}
+ switch (v1) {
+ case 0: v += FL_ALIGN_TOP; break;
+ case 1: v += FL_ALIGN_BOTTOM; break;
+ case 2: v += FL_ALIGN_LEFT; break;
+ case 3: v += FL_ALIGN_RIGHT; break;
+ case 4: v += FL_ALIGN_CENTER; break;
+ default: return 0;
+ }
+ }
+ o->align(v);
+ } else if (!strcmp(name,"resizebox")) {
+ resizable(1);
+ } else if (!strcmp(name,"colors")) {
+ char* p = (char*)value;
+ while (*p != ' ') {if (!*p) return 0; p++;}
+ *p = 0;
+ int v1;
+ if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) {
+ *p=' '; return 0;}
+ o->color(v,v1);
+ } else if (!strcmp(name,"resize")) {
+ return !strcmp(value,"FL_RESIZE_ALL");
+ } else if (!strcmp(name,"gravity")) {
+ return !strcmp(value,"FL_NoGravity FL_NoGravity");
+ } else if (!strcmp(name,"boxtype")) {
+ TRY_BOXTYPE:
+ int x = boxnumber(value);
+ if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;}
+ if (x == ZERO_ENTRY) {
+ x = 0;
+ if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame
+ }
+ o->box((Fl_Boxtype)x);
+ } else {
+ return 0;
+ }
+ return 1;
+}
diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h
new file mode 100644
index 000000000..c911054fa
--- /dev/null
+++ b/fluid/Fl_Widget_Type.h
@@ -0,0 +1,67 @@
+// Fl_Widget_Type.H
+
+// Type for creating all subclasses of Fl_Widget
+// This should have the widget pointer in it, but it is still in the
+// Fl_Type base class.
+
+#include "Fl_Type.H"
+
+struct Fl_Menu_Item;
+class Fluid_Image;
+
+#define NUM_EXTRA_CODE 4
+
+class Fl_Widget_Type : public Fl_Type {
+ virtual Fl_Widget *widget(int,int,int,int) = 0;
+ virtual Fl_Widget_Type *_make() = 0; // virtual constructor
+ virtual void setlabel(const char *);
+
+ const char *extra_code_[NUM_EXTRA_CODE];
+ const char *subclass_;
+ uchar hotspot_;
+
+protected:
+
+ void write_declare();
+ void write_static();
+ void write_code1();
+ void write_widget_code();
+ void write_code2();
+
+public:
+
+ const char *xclass; // junk string, used for shortcut
+ Fl_Widget *o;
+ int public_;
+
+ Fluid_Image *image;
+ void setimage(Fluid_Image *);
+
+ Fl_Widget_Type();
+ Fl_Type *make();
+ void open();
+
+ const char *extra_code(int n) const {return extra_code_[n];}
+ void extra_code(int n,const char *);
+ const char *subclass() const {return subclass_;}
+ void subclass(const char *);
+ uchar hotspot() const {return hotspot_;}
+ void hotspot(uchar v) {hotspot_ = v;}
+ uchar resizable() const;
+ void resizable(uchar v);
+
+ virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &);
+ virtual Fl_Menu_Item *subtypes();
+
+ virtual int is_widget() const;
+
+ virtual void write_properties();
+ virtual void read_property(const char *);
+ virtual int read_fdesign(const char*, const char*);
+
+ ~Fl_Widget_Type();
+ void redraw();
+};
+
+void* const LOAD = (void *)9831;
+extern Fl_Widget_Type *current_widget; // one of the selected ones
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
new file mode 100644
index 000000000..044c8233f
--- /dev/null
+++ b/fluid/Fl_Window_Type.cxx
@@ -0,0 +1,666 @@
+/* Fl_Window_Type.C
+
+ The widget describing an Fl_Window. This is also all the code
+ for interacting with the overlay, which allows the user to
+ select, move, and resize the children widgets.
+
+*/
+
+#include <FL/Fl.H>
+#include <FL/Fl_Overlay_Window.H>
+#include <FL/fl_message.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Menu_Item.H>
+#include "Fl_Widget_Type.H"
+#include <math.h>
+#include <stdlib.h>
+#include "alignment_panel.H"
+#include <stdio.h>
+
+int gridx = 5;
+int gridy = 5;
+int snap = 3;
+
+void alignment_cb(Fl_Input *i, long v) {
+ int n = atoi(i->value());
+ if (n < 0) n = 0;
+ switch (v) {
+ case 1: gridx = n; break;
+ case 2: gridy = n; break;
+ case 3: snap = n; break;
+ }
+}
+
+extern const char* header_file_name;
+extern const char* code_file_name;
+
+void show_alignment_cb(Fl_Widget *, void *) {
+ make_alignment_window();
+ header_file_input->value(header_file_name);
+ code_file_input->value(code_file_name);
+ char buf[128];
+ sprintf(buf,"%d",gridx); horizontal_input->value(buf);
+ sprintf(buf,"%d",gridy); vertical_input->value(buf);
+ sprintf(buf,"%d",snap); snap_input->value(buf);
+ alignment_window->show();
+}
+
+void header_input_cb(Fl_Input* i, void*) {
+ header_file_name = i->value();
+}
+void code_input_cb(Fl_Input* i, void*) {
+ code_file_name = i->value();
+ printf("code file name set to %s\n", code_file_name);
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fl_Menu_Item window_type_menu[] = {
+ {"Single",0,0,(void*)FL_WINDOW},
+ {"Double",0,0,(void*)(FL_WINDOW+1)},
+ {0}};
+class Fl_Window_Type : public Fl_Widget_Type {
+ Fl_Menu_Item* subtypes() {return window_type_menu;}
+
+ friend class Overlay_Window;
+ int mx,my; // mouse position during dragging
+ int x1,y1; // initial position of selection box
+ int bx,by,br,bt; // bounding box of selection
+ int dx,dy;
+ int drag; // which parts of bbox are being moved
+ int numselected; // number of children selected
+ enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32};
+ void draw_overlay();
+ void newdx();
+ void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
+ int handle(int);
+ virtual void setlabel(const char *);
+ void write_code1();
+ void write_code2();
+ Fl_Widget_Type *_make() {return 0;} // we don't call this
+ Fl_Widget *widget(int,int,int,int) {return 0;}
+ int recalc; // set by fix_overlay()
+
+public:
+
+ uchar modal, non_modal;
+
+ Fl_Type *make();
+ virtual const char *type_name() {return "Fl_Window";}
+
+ void open();
+
+ void fix_overlay(); // update the bounding box, etc
+
+ virtual void write_properties();
+ virtual void read_property(const char *);
+ virtual int read_fdesign(const char*, const char*);
+
+ void add_child(Fl_Type*, Fl_Type*);
+ void move_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+
+ int is_parent() const {return 1;}
+ int is_group() const {return 1;}
+ int is_window() const {return 1;}
+};
+
+static int overlays_invisible;
+
+// The following Fl_Widget is used to simulate the windows. It has
+// an overlay for the fluid ui, and special-cases the FL_NO_BOX.
+
+class Overlay_Window : public Fl_Overlay_Window {
+ void draw();
+ void draw_overlay();
+public:
+ Fl_Window_Type *window;
+ int handle(int);
+ Overlay_Window(int w,int h) : Fl_Overlay_Window(w,h) {Fl_Group::current(0);}
+ void resize(int,int,int,int);
+};
+void Overlay_Window::draw() {
+ const int CHECKSIZE = 8;
+ // see if box is clear or a frame or rounded:
+ if ((damage()&128) &&
+ (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) {
+ // if so, draw checkerboard so user can see what areas are clear:
+ for (int y = 0; y < h(); y += CHECKSIZE)
+ for (int x = 0; x < w(); x += CHECKSIZE) {
+ fl_color(((y/(2*CHECKSIZE))&1) != ((x/(2*CHECKSIZE))&1) ?
+ FL_WHITE : FL_BLACK);
+ fl_rectf(x,y,CHECKSIZE,CHECKSIZE);
+ }
+ }
+ Fl_Overlay_Window::draw();
+}
+
+void Overlay_Window::draw_overlay() {
+ window->draw_overlay();
+}
+int Overlay_Window::handle(int e) {
+ return window->handle(e);
+}
+
+Fl_Type *Fl_Window_Type::make() {
+ Fl_Type *p = Fl_Type::current;
+ while (p && !p->is_code_block()) p = p->parent;
+ if (!p) {
+ fl_message("Please select a function");
+ return 0;
+ }
+ Fl_Window_Type *o = new Fl_Window_Type();
+ if (!this->o) {// template widget
+ this->o = new Fl_Window(100,100);
+ Fl_Group::current(0);
+ }
+ o->factory = this;
+ o->drag = 0;
+ o->numselected = 0;
+ Overlay_Window *w = new Overlay_Window(100,100);
+ w->window = o;
+ o->o = w;
+ o->add(p);
+ o->modal = 0;
+ o->non_modal = 0;
+ return o;
+}
+
+void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+ ((Fl_Window*)o)->insert(*(c->o), b);
+ o->redraw();
+}
+
+void Fl_Window_Type::remove_child(Fl_Type* cc) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ ((Fl_Window*)o)->remove(c->o);
+ o->redraw();
+}
+
+void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) {
+ Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+ ((Fl_Window*)o)->remove(c->o);
+ Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+ ((Fl_Window*)o)->insert(*(c->o), b);
+ o->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+
+// Double-click on window widget shows the window, or if already shown,
+// it shows the control panel.
+void Fl_Window_Type::open() {
+ Overlay_Window *w = (Overlay_Window *)o;
+ if (w->shown()) {
+ w->show();
+ Fl_Widget_Type::open();
+ } else {
+ Fl_Widget *p = w->resizable();
+ if (!p) w->resizable(w);
+ w->show();
+ w->resizable(p);
+ }
+}
+
+// control panel items:
+#include "widget_panel.H"
+
+void modal_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_window()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Window_Type *)current_widget)->modal);
+ } else {
+ ((Fl_Window_Type *)current_widget)->modal = i->value();
+ }
+}
+
+void non_modal_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_window()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Window_Type *)current_widget)->non_modal);
+ } else {
+ ((Fl_Window_Type *)current_widget)->non_modal = i->value();
+ }
+}
+
+void border_cb(Fl_Light_Button* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_window()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Window*)(current_widget->o))->border());
+ } else {
+ ((Fl_Window*)(current_widget->o))->border(i->value());
+ }
+}
+
+void xclass_cb(Fl_Input* i, void* v) {
+ if (v == LOAD) {
+ if (!current_widget->is_window()) {i->hide(); return;}
+ i->show();
+ i->value(((Fl_Widget_Type *)current_widget)->xclass);
+ } else {
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected && o->is_widget()) {
+ Fl_Widget_Type* w = (Fl_Widget_Type*)o;
+ if (w->is_window() || w->is_button())
+ storestring(i->value(),w->xclass);
+ if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass);
+ else if (w->is_menu_item()) w->redraw();
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window_Type::setlabel(const char *n) {
+ if (o) ((Fl_Window *)o)->label(n);
+}
+
+// make() is called on this widget when user picks window off New menu:
+Fl_Window_Type Fl_Window_type;
+
+// Resize from window manager, try to resize it back to a legal size.
+// This is not proper X behavior, but works on 4DWM and fvwm
+void Overlay_Window::resize(int X,int Y,int W,int H) {
+ if (!visible() || W==w() && H==h()) {
+ Fl_Overlay_Window::resize(X,Y,W,H);
+ return;
+ }
+ int nw = gridx&&W!=w() ? ((W+gridx/2)/gridx)*gridx : W;
+ int nh = gridy&&H!=h() ? ((H+gridy/2)/gridy)*gridy : H;
+ Fl_Widget* t = resizable(); resizable(0);
+ Fl_Overlay_Window::resize(X,Y,W,H);
+ resizable(t);
+ // make sure new window size surrounds the widgets:
+ int b = 0;
+ int r = 0;
+ for (Fl_Type *o=window->next; o && o->level>window->level; o=o->next)
+ if (o->is_widget() && !o->is_menu_item()) {
+ Fl_Widget* w = ((Fl_Widget_Type*)o)->o;
+ if (w->x()+w->w() > r) r = w->x()+w->w();
+ if (w->y()+w->h() > b) b = w->y()+w->h();
+ }
+ if (nh < b) nh = b;
+ if (nw < r) nw = r;
+ // If changed, tell the window manager. Skip really big windows
+ // that might be bigger than screen:
+ if (nw != W && nw < Fl::w()-100 || nh != H && nh < Fl::h()-100) size(nw,nh);
+}
+
+// calculate actual move by moving mouse position (mx,my) to
+// nearest multiple of gridsize, and snap to original position
+void Fl_Window_Type::newdx() {
+ int dx, dy;
+ if (Fl::event_state(FL_ALT)) {
+ dx = mx-x1;
+ dy = my-y1;
+ } else {
+ int dx0 = mx-x1;
+ int ix = (drag&RIGHT) ? br : bx;
+ dx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0;
+ if (dx0 > snap) {
+ if (dx < 0) dx = 0;
+ } else if (dx0 < -snap) {
+ if (dx > 0) dx = 0;
+ } else
+ dx = 0;
+ int dy0 = my-y1;
+ int iy = (drag&BOTTOM) ? by : bt;
+ dy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0;
+ if (dy0 > snap) {
+ if (dy < 0) dy = 0;
+ } else if (dy0 < -snap) {
+ if (dy > 0) dy = 0;
+ } else
+ dy = 0;
+ }
+ if (this->dx != dx || this->dy != dy) {
+ this->dx = dx; this->dy = dy;
+ ((Overlay_Window *)(this->o))->redraw_overlay();
+ }
+}
+
+// Move a widget according to dx and dy calculated above
+void Fl_Window_Type::newposition(Fl_Widget_Type *o,int &X,int &Y,int &R,int &T) {
+ X = o->o->x();
+ Y = o->o->y();
+ R = X+o->o->w();
+ T = Y+o->o->h();
+ if (!drag) return;
+ if (drag&DRAG) {
+ X += dx;
+ Y += dy;
+ R += dx;
+ T += dy;
+ } else {
+ if (drag&LEFT) if (X==bx) X += dx; else if (X<bx+dx) X = bx+dx;
+ if (drag&BOTTOM) if (Y==by) Y += dy; else if (Y<by+dy) Y = by+dy;
+ if (drag&RIGHT) if (R==br) R += dx; else if (R>br+dx) R = br+dx;
+ if (drag&TOP) if (T==bt) T += dy; else if (T>bt+dx) T = bt+dx;
+ }
+ if (R<X) {int n = X; X = R; R = n;}
+ if (T<Y) {int n = Y; Y = T; T = n;}
+}
+
+void Fl_Window_Type::draw_overlay() {
+ if (recalc) {
+ bx = o->w(); by = o->h(); br = 0; bt = 0;
+ numselected = 0;
+ for (Fl_Type *q=next; q && q->level>level; q=q->next)
+ if (q->selected && q->is_widget() && !q->is_menu_item()) {
+ numselected++;
+ Fl_Widget_Type* o = (Fl_Widget_Type*)q;
+ if (o->o->x() < bx) bx = o->o->x();
+ if (o->o->y() < by) by = o->o->y();
+ if (o->o->x()+o->o->w() > br) br = o->o->x()+o->o->w();
+ if (o->o->y()+o->o->h() > bt) bt = o->o->y()+o->o->h();
+ }
+ recalc = 0;
+ }
+ fl_color(FL_RED);
+ if (drag==BOX && (x1 != mx || y1 != my)) {
+ int x = x1; int r = mx; if (x > r) {x = mx; r = x1;}
+ int y = y1; int b = my; if (y > b) {y = my; b = y1;}
+ fl_rect(x,y,r-x,b-y);
+ }
+ if (overlays_invisible) return;
+ if (selected) fl_rect(0,0,o->w(),o->h());
+ if (!numselected) return;
+ int bx,by,br,bt;
+ bx = o->w(); by = o->h(); br = 0; bt = 0;
+ for (Fl_Type *q=next; q && q->level>level; q = q->next)
+ if (q->selected && q->is_widget() && !q->is_menu_item()) {
+ Fl_Widget_Type* o = (Fl_Widget_Type*)q;
+ int x,y,r,t;
+ newposition(o,x,y,r,t);
+ fl_rect(x,y,r-x,t-y);
+ if (x < bx) bx = x;
+ if (y < by) by = y;
+ if (r > br) br = r;
+ if (t > bt) bt = t;
+ }
+ if (selected) return;
+ if (numselected>1) fl_rect(bx,by,br-bx,bt-by);
+ fl_rectf(bx,by,5,5);
+ fl_rectf(br-5,by,5,5);
+ fl_rectf(br-5,bt-5,5,5);
+ fl_rectf(bx,bt-5,5,5);
+}
+
+// Calculate new bounding box of selected widgets:
+void Fl_Window_Type::fix_overlay() {
+ overlays_invisible = 0;
+ recalc = 1;
+ ((Overlay_Window *)(this->o))->redraw_overlay();
+}
+
+// do that for every window (when selected set changes):
+void redraw_overlays() {
+ for (Fl_Type *o=Fl_Type::first; o; o=o->next)
+ if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay();
+}
+
+void toggle_overlays(Fl_Widget *,void *) {
+ overlays_invisible = !overlays_invisible;
+ for (Fl_Type *o=Fl_Type::first; o; o=o->next)
+ if (o->is_window()) {
+ Fl_Widget_Type* w = (Fl_Widget_Type*)o;
+ ((Overlay_Window*)(w->o))->redraw_overlay();
+ }
+}
+
+extern void select(Fl_Type *,int);
+extern void select_only(Fl_Type *);
+extern void deselect();
+extern Fl_Type* in_this_only;
+extern void fix_group_size(Fl_Type *t);
+
+extern Fl_Menu_Item Main_Menu[];
+extern Fl_Menu_Item New_Menu[];
+
+int Fl_Window_Type::handle(int event) {
+ static Fl_Type* selection;
+ switch (event) {
+ case FL_PUSH:
+ x1 = mx = Fl::event_x();
+ y1 = my = Fl::event_y();
+ drag = 0;
+ // test for popup menu:
+ if (Fl::event_button() >= 3) {
+ in_this_only = this; // modifies how some menu items work.
+ static const Fl_Menu_Item* prev;
+ const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",prev);
+ if (m && m->callback()) {prev = m; m->do_callback(this->o);}
+ in_this_only = 0;
+ return 1;
+ }
+ // find the innermost item clicked on:
+ selection = this;
+ {for (Fl_Type* i=next; i && i->level>level; i=i->next)
+ if (i->is_widget() && !i->is_menu_item()) {
+ Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+ for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent())
+ if (!o1->visible()) goto CONTINUE2;
+ if (Fl::event_inside(o->o)) selection = o;
+ CONTINUE2:;
+ }}
+ // do object-specific selection of other objects:
+ {Fl_Type* t = selection->click_test(mx, my);
+ if (t) {
+ //if (t == selection) return 1; // indicates mouse eaten w/o change
+ if (Fl::event_state(FL_SHIFT)) {
+ Fl::event_is_click(0);
+ select(t, !t->selected);
+ } else {
+ deselect();
+ select(t, 1);
+ if (t->is_menu_item()) t->open();
+ }
+ selection = t;
+ return 1;
+ }}
+ // see if user grabs edges of selected region:
+ if (numselected && !overlays_invisible && !(Fl::event_state(FL_SHIFT)) &&
+ mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) {
+ int snap1 = snap>5 ? snap : 5;
+ int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1;
+ if (mx>=br-w1) drag |= RIGHT;
+ else if (mx<bx+w1) drag |= LEFT;
+ w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1;
+ if (my<=by+w1) drag |= BOTTOM;
+ else if (my>bt-w1) drag |= TOP;
+ if (!drag) drag = DRAG;
+ } else {
+ drag = BOX; // start a new selection region
+ }
+ return 1;
+ case FL_DRAG:
+ if (!drag) return 0;
+ mx = Fl::event_x();
+ my = Fl::event_y();
+ newdx();
+ return 1;
+ case FL_RELEASE:
+ if (!drag) return 0;
+ mx = Fl::event_x();
+ my = Fl::event_y();
+ newdx();
+ if (drag != BOX && (dx || dy || !Fl::event_is_click())) {
+ if (dx || dy) {
+ Fl_Type *i;
+ for (i=next; i && i->level>level;) {
+ if (i->selected && i->is_widget() && !i->is_menu_item()) {
+ Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+ int x,y,r,t;
+ newposition(o,x,y,r,t);
+ o->o->resize(x,y,r-x,t-y);
+ // move all the children, whether selected or not:
+ Fl_Type* p;
+ for (p = o->next; p && p->level>o->level; p = p->next)
+ if (p->is_widget() && !p->is_menu_item()) {
+ Fl_Widget_Type* o = (Fl_Widget_Type*)p;
+ int x,y,r,t;
+ newposition(o,x,y,r,t);
+ o->o->resize(x,y,r-x,t-y);
+ }
+ i = p;
+ } else {
+ i = i->next;
+ }
+ }
+ for (i=next; i && i->level>level; i=i->next) fix_group_size(i);
+ this->o->redraw();
+ fix_overlay();
+ modflag = 1;
+ }
+ } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) {
+ Fl_Widget_Type::open();
+ } else {
+ if (mx<x1) {int t = x1; x1 = mx; mx = t;}
+ if (my<y1) {int t = y1; y1 = my; my = t;}
+ int n = 0;
+ int toggle = Fl::event_state(FL_SHIFT);
+ // clear selection on everything:
+ if (!toggle) deselect(); else Fl::event_is_click(0);
+ // select everything in box:
+ for (Fl_Type*i=next; i&&i->level>level; i=i->next)
+ if (i->is_widget() && !i->is_menu_item()) {
+ Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+ for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent())
+ if (!o1->visible()) goto CONTINUE;
+ if (Fl::event_inside(o->o)) selection = o;
+ if (o->o->x()>=x1 && o->o->y()>y1 &&
+ o->o->x()+o->o->w()<mx && o->o->y()+o->o->h()<my) {
+ n++;
+ select(o, toggle ? !o->selected : 1);
+ }
+ CONTINUE:;
+ }
+ // if nothing in box, select what was clicked on:
+ if (!n) {
+ select(selection, toggle ? !selection->selected : 1);
+ }
+ }
+ drag = 0;
+ return 1;
+
+ case FL_KEYBOARD: {
+ if (Fl::event_key() == FL_Escape) {((Fl_Window*)o)->hide(); return 1;}
+ // find current child:
+ Fl_Type *i = Fl_Type::current;
+ while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent;
+ if (!i) return 0;
+ Fl_Type *p = i->parent;
+ while (p && p != this) p = p->parent;
+ if (!p || !p->is_widget()) {i=next; if (!i || i->level <= level) return 0;}
+ p = i;
+ // try to navigate to another child:
+ for (;;) {
+ switch (Fl::event_key()) {
+ case FL_Tab:
+ if (Fl::event_state(FL_SHIFT)) goto LEFT;
+ case FL_Right:
+ case FL_Down:
+ i = i->next; break;
+ case FL_Left:
+ case FL_Up:
+ LEFT:
+ i = i->prev; break;
+ default:
+ return 0;
+ }
+ if (!i || i->level <= level) {i = p; break;}
+ if (!i->is_widget() || i->is_menu_item()) continue;
+ switch (Fl::event_key()) {
+ case FL_Up:
+ case FL_Down: if (p->is_widget() && !p->is_menu_item()) {
+ Fl_Widget* w = ((Fl_Widget_Type*)i)->o;
+ Fl_Widget* pw = ((Fl_Widget_Type*)p)->o;
+ if (w->x() >= pw->x()+pw->w() ||
+ w->x()+w->w() <= pw->x()) continue;
+ }}
+ break;
+ }
+ // select it:
+ deselect(); select(i,1);
+ } return 1;
+
+ case FL_SHORTCUT: {
+ in_this_only = this; // modifies how some menu items work.
+ const Fl_Menu_Item* m = Main_Menu->test_shortcut();
+ if (m && m->callback()) m->do_callback(this->o);
+ in_this_only = 0;
+ return (m != 0);
+ }
+ default:
+ return 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <string.h>
+
+void Fl_Window_Type::write_code1() {
+ Fl_Widget_Type::write_code1();
+}
+
+void Fl_Window_Type::write_code2() {
+ if (modal) write_c("%so->set_modal();\n", indent());
+ else if (non_modal) write_c("%so->set_non_modal();\n", indent());
+ if (!((Fl_Window*)o)->border()) write_c("%so->clear_border();\n", indent());
+ write_c("%so->end();\n", indent());
+ if (((Fl_Window*)o)->resizable() == o)
+ write_c("%so->resizable(o);\n", indent());
+ Fl_Widget_Type::write_code2();
+}
+
+void Fl_Window_Type::write_properties() {
+ Fl_Widget_Type::write_properties();
+ if (modal) write_string("modal");
+ else if (non_modal) write_string("non_modal");
+ if (!((Fl_Window*)o)->border()) write_string("noborder");
+ if (xclass) {write_string("xclass"); write_word(xclass);}
+ if (o->visible()) write_string("visible");
+}
+
+void Fl_Window_Type::read_property(const char *c) {
+ if (!strcmp(c,"modal")) {
+ modal = 1;
+ } else if (!strcmp(c,"non_modal")) {
+ non_modal = 1;
+ } else if (!strcmp(c, "visible")) {
+ if (Fl::first_window()) open(); // only if we are using user interface
+ } else if (!strcmp(c,"noborder")) {
+ ((Fl_Window*)o)->border(0);
+ } else if (!strcmp(c,"xclass")) {
+ storestring(read_word(),xclass);
+ ((Fl_Window*)o)->xclass(xclass);
+ } else {
+ Fl_Widget_Type::read_property(c);
+ }
+}
+
+int Fl_Window_Type::read_fdesign(const char* name, const char* value) {
+ int x;
+ o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next
+ if (!strcmp(name,"Width")) {
+ if (sscanf(value,"%d",&x) == 1) o->size(x,o->h());
+ } else if (!strcmp(name,"Height")) {
+ if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x);
+ } else if (!strcmp(name,"NumberofWidgets")) {
+ return 1; // we can figure out count from file
+ } else if (!strcmp(name,"border")) {
+ if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x);
+ } else if (!strcmp(name,"title")) {
+ label(value);
+ } else {
+ return Fl_Widget_Type::read_fdesign(name,value);
+ }
+ return 1;
+}
diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx
new file mode 100644
index 000000000..e01022502
--- /dev/null
+++ b/fluid/Fluid_Image.cxx
@@ -0,0 +1,384 @@
+// Fluid_Image.C
+
+// For pixmap labels.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include "Fl_Type.H"
+#include "Fluid_Image.H"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <stdlib.h> // needed for DEC's Alpha cxx ?
+#include <FL/filename.H>
+
+extern void goto_source_dir(); // in fluid.C
+extern void leave_source_dir(); // in fluid.C
+
+////////////////////////////////////////////////////////////////
+#include <FL/Fl_Pixmap.H>
+
+class pixmap_image : public Fluid_Image {
+protected:
+ Fl_Pixmap *p;
+ int *linelength;
+public:
+ pixmap_image(const char *name, FILE *);
+ ~pixmap_image();
+ virtual void label(Fl_Widget *); // set the label of this widget
+ virtual void write_static();
+ virtual void write_code();
+ static int test_file(char *buffer);
+};
+
+int pixmap_image::test_file(char *buffer) {
+ return (strstr(buffer,"/* XPM") != 0);
+}
+
+void pixmap_image::label(Fl_Widget *o) {
+ if (p) p->label(o);
+}
+
+static int pixmap_header_written;
+
+void pixmap_image::write_static() {
+ if (!p) return;
+ write_c("\n");
+ if (pixmap_header_written != write_number) {
+ write_c("#include <FL/Fl_Pixmap.H>\n");
+ pixmap_header_written = write_number;
+ }
+ write_c("static char *%s[] = {\n",
+ unique_id(this, "image", filename_name(name()), 0));
+ int l;
+ for (l = 0; p->data[l]; l++) {
+ if (l) write_c(",\n");
+ write_cstring(p->data[l],linelength[l]);
+ }
+ write_c("\n};\n");
+ write_c("static Fl_Pixmap %s(%s);\n",
+ unique_id(this, "pixmap", filename_name(name()), 0),
+ unique_id(this, "image", filename_name(name()), 0));
+}
+
+void pixmap_image::write_code() {
+ if (!p) return;
+ write_c("%s%s.label(o);\n", indent(),
+ unique_id(this, "pixmap", filename_name(name()), 0));
+}
+
+static int hexdigit(int x) {
+ if (isdigit(x)) return x-'0';
+ if (isupper(x)) return x-'A'+10;
+ if (islower(x)) return x-'a'+10;
+ return 20;
+}
+
+#define MAXSIZE 1024
+
+pixmap_image::pixmap_image(const char *name, FILE *f) : Fluid_Image(name) {
+ if (!f) return; // for subclasses
+ // read all the c-strings out of the file:
+ char *data[MAXSIZE+1];
+ int length[MAXSIZE+1];
+ char buffer[MAXSIZE+20];
+ int i = 0;
+ while (i < MAXSIZE && fgets(buffer,MAXSIZE+20,f)) {
+ if (buffer[0] != '\"') continue;
+ char *p = buffer;
+ char *q = buffer+1;
+ while (*q != '\"') {
+ if (*q == '\\') switch (*++q) {
+ case '\n':
+ fgets(q,(buffer+MAXSIZE+20)-q,f); break;
+ case 0:
+ break;
+ case 'x': {
+ q++;
+ int n = 0;
+ for (int x = 0; x < 3; x++) {
+ int d = hexdigit(*q);
+ if (d > 15) break;
+ n = (n<<4)+d;
+ q++;
+ }
+ *p++ = n;
+ } break;
+ default: {
+ int c = *q++;
+ if (c>='0' && c<='7') {
+ c -= '0';
+ for (int x=0; x<2; x++) {
+ int d = hexdigit(*q);
+ if (d>7) break;
+ c = (c<<3)+d;
+ q++;
+ }
+ }
+ *p++ = c;
+ } break;
+ } else {
+ *p++ = *q++;
+ }
+ }
+ *p++ = 0;
+ data[i] = new char[p-buffer];
+ memcpy(data[i],buffer,p-buffer);
+ length[i] = p-buffer-1;
+ i++;
+ }
+ data[i++] = 0; // put a null at the end
+
+ char** real_data = new char*[i];
+ linelength = new int[i];
+ while (i--) {real_data[i] = data[i]; linelength[i] = length[i];}
+ p = new Fl_Pixmap(real_data);
+}
+
+pixmap_image::~pixmap_image() {
+ if (p && p->data) {
+ char** real_data = (char**)(p->data);
+ for (int i = 0; real_data[i]; i++) delete[] real_data[i];
+ delete[] real_data;
+ }
+ delete[] linelength;
+ delete p;
+}
+
+////////////////////////////////////////////////////////////////
+
+class gif_image : public pixmap_image {
+public:
+ gif_image(const char *name, FILE *);
+ ~gif_image();
+ static int test_file(char *buffer);
+};
+
+int gif_image::test_file(char *buffer) {
+ return !strncmp(buffer,"GIF",3);
+}
+
+// function in gif.C:
+int gif2xpm(
+ const char *infname,// filename for error messages
+ FILE *GifFile, // file to read
+ char*** datap, // return xpm data here
+ int** lengthp, // return line lengths here
+ int inumber // which image in movie (0 = first)
+);
+
+gif_image::gif_image(const char *name, FILE *f) : pixmap_image(name,0) {
+ char** datap;
+ if (gif2xpm(name,f,&datap,&linelength,0)) {
+ p = new Fl_Pixmap(datap);
+ } else
+ p = 0;
+}
+
+gif_image::~gif_image() {
+ if (p && p->data) {
+ char** real_data = (char**)(p->data);
+ for (int i = 0; i < 3; i++) delete[] real_data[i];
+ delete[] real_data;
+ p->data = 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+#include <FL/Fl_Bitmap.H>
+
+class bitmap_image : public Fluid_Image {
+ Fl_Bitmap *p;
+public:
+ ~bitmap_image();
+ bitmap_image(const char *name, FILE *);
+ virtual void label(Fl_Widget *); // set the label of this widget
+ virtual void write_static();
+ virtual void write_code();
+ static int test_file(char *buffer);
+};
+
+// bad test, always do this last!
+int bitmap_image::test_file(char *buffer) {
+ return (strstr(buffer,"#define ") != 0);
+}
+
+void bitmap_image::label(Fl_Widget *o) {
+ if (p) p->label(o); else o->labeltype(FL_NORMAL_LABEL);
+}
+
+static int bitmap_header_written;
+
+void bitmap_image::write_static() {
+ if (!p) return;
+ write_c("\n");
+ if (bitmap_header_written != write_number) {
+ write_c("#include <FL/Fl_Bitmap.H>\n");
+ bitmap_header_written = write_number;
+ }
+ write_c("static char %s[] = { \n",
+ unique_id(this, "bits", filename_name(name()), 0));
+ int n = ((p->w+7)/8)*p->h;
+ for (int i = 0; i < n; i++) {
+ if (i) write_c(", ");
+ write_c("%d",p->array[i]);
+ }
+ write_c("\n};\n");
+ write_c("static Fl_Bitmap %s(%s, %d, %d);\n",
+ unique_id(this, "bitmap", filename_name(name()), 0),
+ unique_id(this, "bits", filename_name(name()), 0),
+ p->w, p->h);
+}
+
+void bitmap_image::write_code() {
+ if (!p) return;
+ write_c("%s%s.label(o);\n", indent(),
+ unique_id(this, "bitmap", filename_name(name()), 0));
+}
+
+bitmap_image::bitmap_image(const char *name, FILE *f) : Fluid_Image(name) {
+ p = 0; // if any problems with parse we exit with this zero
+ char buffer[1024];
+ char junk[1024];
+ int wh[2]; // width and height
+ int i;
+ for (i = 0; i<2; i++) {
+ for (;;) {
+ if (!fgets(buffer,1024,f)) return;
+ int r = sscanf(buffer,"#define %s %d",junk,&wh[i]);
+ if (r >= 2) break;
+ }
+ }
+ // skip to data array:
+ for (;;) {
+ if (!fgets(buffer,1024,f)) return;
+ if (!strncmp(buffer,"static ",7)) break;
+ }
+ int n = ((wh[0]+7)/8)*wh[1];
+ uchar *data = new uchar[n];
+ // read the data:
+ i = 0;
+ for (;i<n;) {
+ if (!fgets(buffer,1024,f)) return;
+ const char *a = buffer;
+ while (*a && i<n) {
+ int t;
+ if (sscanf(a," 0x%x",&t)>0) data[i++] = t;
+ while (*a && *a++ != ',');
+ }
+ }
+ p = new Fl_Bitmap(data,wh[0],wh[1]);
+}
+
+bitmap_image::~bitmap_image() {
+ if (p) {
+ delete[] (uchar*)(p->array);
+ delete p;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fluid_Image** images; // sorted list
+static int numimages;
+static int tablesize;
+
+Fluid_Image* Fluid_Image::find(const char *name) {
+ if (!name || !*name) return 0;
+
+ // first search to see if it exists already:
+ int a = 0;
+ int b = numimages;
+ while (a < b) {
+ int c = (a+b)/2;
+ int i = strcmp(name,images[c]->name_);
+ if (i < 0) b = c;
+ else if (i > 0) a = c+1;
+ else return images[c];
+ }
+
+ // no, so now see if the file exists:
+
+ goto_source_dir();
+ FILE *f = fopen(name,"rb");
+ if (!f) {
+ read_error("%s : %s",name,strerror(errno));
+ leave_source_dir();
+ return 0;
+ }
+
+ Fluid_Image *ret;
+
+ // now see if we can identify the type, by reading in some data
+ // and asking all the types we know about:
+
+ char buffer[1025];
+ fread(buffer, 1, 1024, f);
+ rewind(f);
+ buffer[1024] = 0; // null-terminate so strstr() works
+
+ if (pixmap_image::test_file(buffer)) {
+ ret = new pixmap_image(name,f);
+ } else if (gif_image::test_file(buffer)) {
+ ret = new gif_image(name,f);
+ } else if (bitmap_image::test_file(buffer)) {
+ ret = new bitmap_image(name,f);
+ } else {
+ ret = 0;
+ read_error("%s : unrecognized image format", name);
+ }
+ fclose(f);
+ leave_source_dir();
+ if (!ret) return 0;
+
+ // make a new entry in the table:
+ numimages++;
+ if (numimages > tablesize) {
+ tablesize = tablesize ? 2*tablesize : 16;
+ images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*));
+ }
+ for (b = numimages-1; b > a; b--) images[b] = images[b-1];
+ images[a] = ret;
+
+ return ret;
+}
+
+Fluid_Image::Fluid_Image(const char *name) {
+ name_ = strdup(name);
+ written = 0;
+ refcount = 0;
+}
+
+void Fluid_Image::increment() {
+ ++refcount;
+}
+
+void Fluid_Image::decrement() {
+ --refcount;
+ if (refcount > 0) return;
+ delete this;
+}
+
+Fluid_Image::~Fluid_Image() {
+ int a;
+ for (a = 0;; a++) if (images[a] == this) break;
+ numimages--;
+ for (; a < numimages; a++) images[a] = images[a+1];
+ free((void*)name_);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/fl_file_chooser.H>
+
+const char *ui_find_image_name;
+Fluid_Image *ui_find_image(const char *oldname) {
+ goto_source_dir();
+ const char *name = fl_file_chooser("Image","*.{bm|xbm|xpm|gif}",oldname);
+ ui_find_image_name = name;
+ Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0;
+ leave_source_dir();
+ return ret;
+}
diff --git a/fluid/Fluid_Image.h b/fluid/Fluid_Image.h
new file mode 100644
index 000000000..fdc7937bc
--- /dev/null
+++ b/fluid/Fluid_Image.h
@@ -0,0 +1,28 @@
+// Fluid_Image.H
+
+// This class stores the image labels for widgets in fluid. This is
+// not a class in fltk itself, and this will produce different types of
+// code depending on what the image type is. There are private subclasses
+// in Fluid_Image.C for each type of image format. Right now only xpm
+// files are supported.
+
+class Fluid_Image {
+ const char *name_;
+ int refcount;
+protected:
+ Fluid_Image(const char *name); // no public constructor
+ virtual ~Fluid_Image(); // no public destructor
+public:
+ int written;
+ static Fluid_Image* find(const char *);
+ void decrement(); // reference counting & automatic free
+ void increment();
+ virtual void label(Fl_Widget *) = 0; // set the label of this widget
+ virtual void write_static() = 0;
+ virtual void write_code() = 0;
+ const char *name() const {return name_;}
+};
+
+// pop up file chooser and return a legal image selected by user,
+// or zero for any errors:
+Fluid_Image *ui_find_image(const char *);
diff --git a/fluid/Makefile b/fluid/Makefile
new file mode 100644
index 000000000..876b52a09
--- /dev/null
+++ b/fluid/Makefile
@@ -0,0 +1,83 @@
+PROGRAM = fluid
+
+CPPFILES = \
+ Fl_Function_Type.C \
+ Fl_Menu_Type.C \
+ Fl_Group_Type.C \
+ Fl_Widget_Type.C \
+ Fl_Type.C \
+ Fl_Window_Type.C \
+ Fluid_Image.C \
+ code.C \
+ factory.C \
+ file.C \
+ fluid.C \
+ about_panel.C \
+ widget_panel.C \
+ alignment_panel.C \
+ function_panel.C \
+ gif.C
+
+################################################################
+
+OBJECTS = $(CPPFILES:.C=.o)
+
+include ../makeinclude
+
+.SUFFIXES : .C .c .o .do .fl .H
+
+.C.o :
+ @echo $<:
+ @$(CXX) -I.. $(CXXFLAGS) -c $<
+.c.o :
+ @echo $<:
+ @$(CC) -I.. $(CFLAGS) -c $<
+.C :
+ @echo $@:
+ @$(CXX) -I.. $(CXXFLAGS) -o $@ $< -L../lib -lfltk $(LDLIBS)
+
+.fl.C .fl.H :
+ -fluid -c $<
+
+# better way to do this for gnu make:
+# %.H %.C: %.fl
+# fluid -c $<
+
+$(PROGRAM) : $(OBJECTS) ../lib/$(LIBNAME)
+ @echo linking $@:
+ @$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJECTS) -L../lib -lfltk $(LDLIBS)
+
+clean :
+ -@ rm -f *.o $(PROGRAM) $(CLEAN) core *~ makedepend
+ @touch makedepend
+
+depend:
+ $(MAKEDEPEND) -I.. $(CXXFLAGS) $(CPPFILES) $(CFILES) > makedepend
+include makedepend
+
+install: $(PROGRAM)
+ strip $(PROGRAM)
+ cp $(PROGRAM) $(bindir)/$(PROGRAM)
+ @chmod a+rx,g-w,o-w $(bindir)/$(PROGRAM)
+
+uninstall:
+ -@ rm -f $(bindir)/$(PROGRAM)
+
+################################################################
+
+PROGRAM_D = $(PROGRAM)_d
+
+debug: $(PROGRAM_D)
+
+OBJECTS_D = $(CPPFILES:.C=.do) $(CFILES:.c=.do)
+
+.C.do :
+ @echo $<:
+ @$(CXX) -I.. $(CXXFLAGS_D) -c -o $@ $<
+.c.do :
+ @echo $<:
+ @$(CC) -I.. $(CFLAGS_D) -c -o $@ $<
+
+$(PROGRAM_D) : $(OBJECTS_D) ../lib/$(LIBNAME_D)
+ @echo linking $@:
+ @$(CXX) $(CXXFLAGS_D) -o $(PROGRAM_D) $(OBJECTS_D) -L../lib -lfltk_d $(LDLIBS)
diff --git a/fluid/README b/fluid/README
new file mode 100644
index 000000000..9fe6d6c36
--- /dev/null
+++ b/fluid/README
@@ -0,0 +1,214 @@
+Fluid (the FL User Interface Designer) is a graphical editor that
+is used to produce FL source code.
+
+Fluid edits and saves it's state in ".fl" files. These files are
+text, and you could (with care) edit them in a text editor, perhaps to
+get some special effects.
+
+When asked to "compile", fluid outputs a .C source file and a .H
+header file: The .C file contains one or more public functions, each
+of which will create one or more FL windows and all the objects in
+those windows. The .H file declares (as externs) all the functions
+and named objects created by the .C file, and includes all the
+necessary FL header files for those objects.
+
+The C file must be compiled and linked with a "main" source file(s)
+that you write. This source code must include the .H output, and
+should call the functions in the .C file to create windows. The main
+code must do show() on the windows and run the Fl::wait() loop.
+
+ _________
+ / /
+ __________ +->/.C file /--------+
+ / / / /________/ |
+ /.fl file /<==>[fluid]< #include |
+ /_________/ \ ___v_____ |
+ \ / / |
+ +>/.H file / |
+ /________/ |
+ ^ |
+ #include |
+ ___|_____ | __________
+ / / V / /
+ / main.C /--->[c++,link]-->/ program /
+ /________/ /_________/
+
+
+Objects created by fluid are either "named" or "unnamed". If they
+are named, the .C file will declare a global variable with that name
+of type "<type>*". This pointer has a value of zero until the fluid
+function is called, the fluid function will set it to the instance of
+the . Unnamed objects are only accessible through
+pointers from other objects.
+
+Windows may be named or unnamed. Named windows are only created
+once even if you call the function several times (fluid outputs "if
+(!name) {...}" around the code that creates the window). Unnamed
+windows lets you create many instances of the same window structure, a
+pointer to the unnamed window is returned from the fluid function (you
+can only put one unnamed window in a function).
+
+Objects may either call a named callback function that you write in
+another source file, or you can supply a small piece of C++ source and
+fluid will write a private callback function into the .C file.
+
+================================================================
+Worlds shortest tutorial:
+================================================================
+
+Type "fluid&"
+
+Pick "New/Function" off the menu.
+
+Delete the function name in the popup window and hit OK. The text
+"main()" with a triangle next to it should appear highlighted in the
+main window.
+
+Pick "New/Window" off the menu.
+
+Move the window and resize it to the size you want.
+
+Pick "New/buttons/Button" off the menu.
+
+Hit the "OK" button to dismiss the panel that appears.
+
+In the window you created, try moving the button by dragging it
+around. Notice that it "snaps" to fixed locations. If you want to
+drag it smoothly, hold down Alt. You can also change the size of the
+steps with Edit/Preferences.
+
+Try resizing the object by dragging the edges and corners.
+
+Type Alt+c to copy the object.
+
+Type Alt+v to paste a copy into the window.
+
+Type Alt+v several times.
+
+Drag the objects and resize them so they don't overlap. Notice
+that you have to click an object to pick it first, then drag it.
+
+Try selecting several objects by dragging a box around them. Check
+what happens when you move them, or when you drag an edge to resize
+them.
+
+You can also use Shift+click to toggle objects on and off.
+
+You can also select objects by clicking on them in the list in the
+main window, try that.
+
+Double-click one of the buttons. You will get a control panel.
+
+Try changing the "label". Try changing other items near the top of
+the panel. To see any changes to the box type clearer, type "Alt+o"
+to make the red overlay disappear.
+
+Type "#include <stdlib.h>" into the first line of "extra code:".
+
+Type "exit(0);" into the "callback:".
+
+Hit OK.
+
+Pick "File/Save As" off the menu.
+
+Type "test.fl" into the file chooser and hit return.
+
+Pick "File/Write Code" off the menu.
+
+Go back to your terminal window. Type "more test.C" and "more
+test.H" and you can see the code it made.
+
+Type "make test" (you may have to add libaries to your Makefile).
+
+Type "./test" to run your program.
+
+Try the buttons. The one you put the code into will exit the
+program.
+
+Type "Alt+Q" to exit fluid.
+
+Ok, now try to make a real program.
+
+================================================================
+
+This code is quite a kludge and probably impossible to figure out. I
+hope it will be fixed someday, but my intention was to make FL itself
+clean and simple, even if the user interface designer is forced to be
+more complex as a result.
+
+An object in fluid is represented by a subclass of "Fl_Type".
+
+Creating a new instance of an object is done by calling the virtual
+method "make()" on Fl_Type. To allow an initial version of each type
+to be created, there is a static "factory" instance of every subclass
+of Fl_Type. For now, make() is only called on these. The intention
+was to use make() to copy objects, but that did not happen. Instead I
+write the descriptions and read them back from a file in /usr/tmp,
+which is much more reliable because the read/write code is tested
+every time a file is saved!
+
+The (non-factory) instances are linked into a list by the previous and
+next pointers. The "hierarchy" is stored by a "level" number on each
+object, and an "isparent" flag on the parent. To find the "brother"
+of an object, code must search forward for the next object whose level
+is equal to this one. A null pointer or an object with a lower level
+number indicates no brother.
+
+If the type is a subclass of Fl_Object, the "o" pointer points at an
+Fl_Object. This allows the code in FL to be used to draw the object.
+The user_data() field on the Fl_Object is used as a back pointer to
+the Fl_Type. The "factory" has an "o" pointer that points at the
+"template object". This is an Fl_Object created the first time make()
+is called and is used to figure out what the default values for the
+fields are for the object.
+
+This "o" pointer exists in all Fl_Type objects, even the base class.
+If this is not an Fl_Object item, then the "o" pointer is zero. This
+avoided a lot of virtual functions, but is mostly for historical
+reasons. Rather than RTTI, I use some tests to determine subclasses:
+
+ if (o && level == 1)
+ this is an Fl_Window_Type
+ else if (o && isparent)
+ this is a Fl_Group_Type
+ else if (o)
+ this is a Fl_Object_Type
+ else if (!level)
+ this is a function
+ else
+ this is a menu item or something
+ (none of these implemented yet)
+
+
+ Fl_Type::first
+ |
+ | NULL
+ | ^
+ V |
+ +---------+ +-----------+
+ | Fl_Type |------ o ---> | Fl_Window |
+ | level=0 |<-user_data()-| |
+ |isparent |<-+ +-----------+
+ +---------+ | | ^
+ | ^ parent first |
+ next prev / | parent
+ V | / V |
+ +---------+ +-----------+
+ | Fl_Type |------ o ---> | Fl_Object |
+ | level=1 | | |
+ | |<-user_data()-| |
+ | | +-----------+
+ | | +---------+
+ | |-factory->| Fl_Type |---- o ---->[Fl_Object]
+ +---------+ | | template object
+ | ^ +---------+
+ next prev (next,prev=NULL)
+ V |
+ +---------+
+ | Fl_Type |
+ +---------+
+ | ^
+ V |
+ NULL |
+ |
+ Fl_Type::last
diff --git a/fluid/Shortcut_Button.h b/fluid/Shortcut_Button.h
new file mode 100644
index 000000000..eea4ddc70
--- /dev/null
+++ b/fluid/Shortcut_Button.h
@@ -0,0 +1,10 @@
+#include <FL/Fl_Button.H>
+
+class Shortcut_Button : public Fl_Button {
+public:
+ int svalue;
+ int handle(int);
+ void draw();
+ Shortcut_Button(int x, int y, int w, int h, const char* l = 0) :
+ Fl_Button(x,y,w,h,l) {svalue = 0;}
+};
diff --git a/fluid/about_panel.cxx b/fluid/about_panel.cxx
new file mode 100644
index 000000000..a880d39dd
--- /dev/null
+++ b/fluid/about_panel.cxx
@@ -0,0 +1,122 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "about_panel.H"
+
+Fl_Window *about_panel;
+
+Fl_Group *display_group;
+
+static void cb_1998(Fl_Button*, void*) {
+ display_group->hide();
+copyright_box->show();
+}
+
+Fl_Box *copyright_box;
+
+static void cb_OK(Fl_Return_Button* o, void*) {
+ ((Fl_Window*)(o->parent()))->hide();
+}
+
+Fl_Window* make_about_panel(const char *copyright) {
+ Fl_Window* w;
+ { Fl_Window* o = about_panel = w = new Fl_Window(309, 221, "about fluid");
+ o->box(FL_UP_BOX);
+ o->color(97);
+ o->selection_color(47);
+ w->hotspot(o);
+ { Fl_Group* o = display_group = new Fl_Group(24, 14, 275, 186);
+ { Fl_Box* o = new Fl_Box(64, 14, 50, 126);
+ o->box(FL_ROUND_UP_BOX);
+ o->color(14);
+ o->selection_color(47);
+ o->labelcolor(6);
+ }
+ { Fl_Box* o = new Fl_Box(54, 14, 70, 16);
+ o->box(FL_FLAT_BOX);
+ o->color(97);
+ o->selection_color(47);
+ }
+ { Fl_Box* o = new Fl_Box(68, 30, 42, 50);
+ o->box(FL_DOWN_BOX);
+ o->color(6);
+ o->selection_color(47);
+ }
+ { Fl_Box* o = new Fl_Box(54, 20, 70, 20);
+ o->box(FL_ROUND_UP_BOX);
+ o->color(6);
+ o->selection_color(47);
+ o->labelcolor(6);
+ o->align(16);
+ }
+ { Fl_Box* o = new Fl_Box(24, 110, 130, 90, "fluid");
+ o->box(FL_ROUND_UP_BOX);
+ o->color(14);
+ o->selection_color(47);
+ o->labeltype(FL_SHADOW_LABEL);
+ o->labelfont(1);
+ o->labelsize(40);
+ o->labelcolor(6);
+ }
+ { Fl_Box* o = new Fl_Box(67, 110, 44, 10);
+ o->box(FL_FLAT_BOX);
+ o->color(14);
+ o->selection_color(47);
+ }
+ { Fl_Box* o = new Fl_Box(84, 120, 15, 15, "` ");
+ o->box(FL_OVAL_BOX);
+ o->color(6);
+ o->selection_color(47);
+ o->labelsize(20);
+ o->labelcolor(7);
+ o->align(17);
+ }
+ { Fl_Box* o = new Fl_Box(75, 105, 15, 15, "` ");
+ o->box(FL_OVAL_BOX);
+ o->color(6);
+ o->selection_color(47);
+ o->labelsize(20);
+ o->labelcolor(7);
+ o->align(17);
+ }
+ { Fl_Box* o = new Fl_Box(89, 85, 15, 15, "` ");
+ o->box(FL_OVAL_BOX);
+ o->color(6);
+ o->selection_color(47);
+ o->labelsize(20);
+ o->labelcolor(7);
+ o->align(17);
+ }
+ { Fl_Box* o = new Fl_Box(159, 27, 131, 95, "Fltk User\nInterface\nDesigner\nVersion 1.00");
+ o->box(FL_OVAL_BOX);
+ o->color(12);
+ o->selection_color(47);
+ o->labeltype(FL_SHADOW_LABEL);
+ o->labelfont(1);
+ o->labelsize(18);
+ o->labelcolor(7);
+ }
+ { Fl_Button* o = new Fl_Button(169, 138, 115, 30, "\xa9\x31\x39\x39\x38 Bill Spitzak\n(click here)");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->labelcolor(136);
+ o->callback((Fl_Callback*)cb_1998);
+ }
+ o->end();
+ }
+ { Fl_Box* o = copyright_box = new Fl_Box(5, 5, 300, 210);
+ o->labelsize(8);
+ o->labelcolor(6);
+ o->align(148);
+ o->hide();
+ o->label(copyright);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(168, 182, 116, 22, "OK");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)cb_OK);
+ }
+ o->set_non_modal();
+ o->clear_border();
+ o->end();
+ }
+ return w;
+}
diff --git a/fluid/about_panel.fl b/fluid/about_panel.fl
new file mode 100644
index 000000000..b35c59251
--- /dev/null
+++ b/fluid/about_panel.fl
@@ -0,0 +1,71 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99
+gridx 2
+gridy 2
+snap 3
+Function {make_about_panel(const char *copyright)} {open
+} {
+ Fl_Window about_panel {
+ label {about fluid} open
+ xywh {345 417 309 221} box UP_BOX color {97 47} hide hotspot non_modal noborder
+ } {
+ Fl_Group display_group {open
+ xywh {24 14 275 186}
+ } {
+ Fl_Box {} {
+ xywh {64 14 50 126} box ROUND_UP_BOX color {14 47} labelcolor 6
+ }
+ Fl_Box {} {
+ xywh {54 14 70 16} box FLAT_BOX color {97 47}
+ }
+ Fl_Box {} {
+ xywh {68 30 42 50} box DOWN_BOX color {6 47}
+ }
+ Fl_Box {} {
+ xywh {54 20 70 20} box ROUND_UP_BOX color {6 47} labelcolor 6 align 16
+ }
+ Fl_Box {} {
+ label fluid
+ xywh {24 110 130 90} box ROUND_UP_BOX color {14 47} labeltype SHADOW_LABEL labelfont 1 labelsize 40 labelcolor 6
+ }
+ Fl_Box {} {
+ xywh {67 110 44 10} box FLAT_BOX color {14 47}
+ }
+ Fl_Box {} {
+ label {` }
+ xywh {84 120 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+ }
+ Fl_Box {} {
+ label {` }
+ xywh {75 105 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+ }
+ Fl_Box {} {
+ label {` }
+ xywh {89 85 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+ }
+ Fl_Box {} {
+ label {Fltk User
+Interface
+Designer
+Version 1.00}
+ xywh {159 27 131 95} box OVAL_BOX color {12 47} labeltype SHADOW_LABEL labelfont 1 labelsize 18 labelcolor 7
+ }
+ Fl_Button {} {
+ label {©1998 Bill Spitzak
+(click here)}
+ callback {display_group->hide();
+copyright_box->show();}
+ xywh {169 138 115 30} box THIN_UP_BOX labelsize 10 labelcolor 136
+ }
+ }
+ Fl_Box copyright_box {selected
+ xywh {5 5 300 210} labelsize 8 labelcolor 6 align 148 hide
+ code0 {o->label(copyright);}
+ }
+ Fl_Return_Button {} {
+ label OK
+ callback {((Fl_Window*)(o->parent()))->hide();}
+ xywh {168 182 116 22} labelsize 10
+ }
+ }
+}
diff --git a/fluid/about_panel.h b/fluid/about_panel.h
new file mode 100644
index 000000000..7113cf5cf
--- /dev/null
+++ b/fluid/about_panel.h
@@ -0,0 +1,12 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Window.H>
+extern Fl_Window *about_panel;
+extern Fl_Group *display_group;
+extern Fl_Box *copyright_box;
+Fl_Window* make_about_panel(const char *copyright);
diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx
new file mode 100644
index 000000000..fa8c7c089
--- /dev/null
+++ b/fluid/alignment_panel.cxx
@@ -0,0 +1,73 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "alignment_panel.H"
+
+Fl_Window *alignment_window;
+
+Fl_Input *horizontal_input;
+
+Fl_Input *vertical_input;
+
+Fl_Input *snap_input;
+
+static void cb_close(Fl_Button*, void*) {
+ alignment_window->hide();
+}
+
+Fl_Input *header_file_input;
+
+Fl_Input *code_file_input;
+
+Fl_Window* make_alignment_window() {
+ Fl_Window *w;
+ { Fl_Window* o = alignment_window = w = new Fl_Window(210, 282, "fluid Preferences");
+ { Fl_Box* o = new Fl_Box(10, 20, 190, 100, "ALIGNMENT:");
+ o->box(FL_ENGRAVED_FRAME);
+ o->labelsize(10);
+ o->align(5);
+ }
+ { Fl_Input* o = horizontal_input = new Fl_Input(90, 30, 100, 20, "horizontal:");
+ o->type(2);
+ o->box(FL_THIN_DOWN_BOX);
+ o->callback((Fl_Callback*)alignment_cb, (void*)(1));
+ o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+ }
+ { Fl_Input* o = vertical_input = new Fl_Input(90, 60, 100, 20, "vertical:");
+ o->type(2);
+ o->box(FL_THIN_DOWN_BOX);
+ o->callback((Fl_Callback*)alignment_cb, (void*)(2));
+ o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+ }
+ { Fl_Input* o = snap_input = new Fl_Input(90, 90, 100, 20, "snap:");
+ o->type(2);
+ o->box(FL_THIN_DOWN_BOX);
+ o->callback((Fl_Callback*)alignment_cb, (void*)(3));
+ o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+ }
+ { Fl_Button* o = new Fl_Button(10, 250, 190, 20, "close");
+ o->callback((Fl_Callback*)cb_close);
+ w->hotspot(o);
+ }
+ { Fl_Box* o = new Fl_Box(10, 140, 190, 100, "OUTPUT FILE NAMES:");
+ o->box(FL_ENGRAVED_FRAME);
+ o->labelsize(10);
+ o->align(5);
+ }
+ { Fl_Box* o = new Fl_Box(10, 140, 190, 40, "Use \"name.ext\" to set name, use just \".ext\" to set only extension.");
+ o->labelsize(10);
+ o->align(128);
+ }
+ { Fl_Input* o = header_file_input = new Fl_Input(90, 180, 100, 20, "header file:");
+ o->box(FL_THIN_DOWN_BOX);
+ o->callback((Fl_Callback*)header_input_cb, (void*)(1));
+ o->when(1);
+ }
+ { Fl_Input* o = code_file_input = new Fl_Input(90, 210, 100, 20, "code file:");
+ o->box(FL_THIN_DOWN_BOX);
+ o->callback((Fl_Callback*)code_input_cb, (void*)(1));
+ o->when(1);
+ }
+ o->end();
+ }
+ return w;
+}
diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl
new file mode 100644
index 000000000..c2e7f9286
--- /dev/null
+++ b/fluid/alignment_panel.fl
@@ -0,0 +1,65 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99
+header_name {.H}
+code_name {.C}
+gridx 10
+gridy 10
+snap 3
+Function {make_alignment_window()} {open
+} {
+ Fl_Window alignment_window {
+ label {fluid Preferences} open selected
+ xywh {303 187 210 282} visible
+ } {
+ Fl_Box {} {
+ label {ALIGNMENT:}
+ xywh {10 20 190 100} box ENGRAVED_FRAME labelsize 10 align 5
+ }
+ Fl_Input horizontal_input {
+ label {horizontal:}
+ user_data 1 user_data_type long
+ callback alignment_cb
+ xywh {90 30 100 20} type Int box THIN_DOWN_BOX
+ code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+ }
+ Fl_Input vertical_input {
+ label {vertical:}
+ user_data 2 user_data_type long
+ callback alignment_cb
+ xywh {90 60 100 20} type Int box THIN_DOWN_BOX
+ code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+ }
+ Fl_Input snap_input {
+ label {snap:}
+ user_data 3 user_data_type long
+ callback alignment_cb
+ xywh {90 90 100 20} type Int box THIN_DOWN_BOX
+ code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+ }
+ Fl_Button {} {
+ label close
+ callback {alignment_window->hide();}
+ xywh {10 250 190 20} hotspot
+ }
+ Fl_Box {} {
+ label {OUTPUT FILE NAMES:}
+ xywh {10 140 190 100} box ENGRAVED_FRAME labelsize 10 align 5
+ }
+ Fl_Box {} {
+ label {Use "name.ext" to set name, use just ".ext" to set only extension.}
+ xywh {10 140 190 40} labelsize 10 align 128
+ }
+ Fl_Input header_file_input {
+ label {header file:}
+ user_data 1 user_data_type {void*}
+ callback header_input_cb
+ xywh {90 180 100 20} box THIN_DOWN_BOX when 1
+ }
+ Fl_Input code_file_input {
+ label {code file:}
+ user_data 1 user_data_type {void*}
+ callback code_input_cb
+ xywh {90 210 100 20} box THIN_DOWN_BOX when 1
+ }
+ }
+}
diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h
new file mode 100644
index 000000000..437d7640f
--- /dev/null
+++ b/fluid/alignment_panel.h
@@ -0,0 +1,17 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Window.H>
+extern void alignment_cb(Fl_Input*, long);
+extern void code_input_cb(Fl_Input*, void*);
+extern void header_input_cb(Fl_Input*, void*);
+extern Fl_Window *alignment_window;
+extern Fl_Input *horizontal_input;
+extern Fl_Input *vertical_input;
+extern Fl_Input *snap_input;
+extern Fl_Input *header_file_input;
+extern Fl_Input *code_file_input;
+Fl_Window* make_alignment_window();
diff --git a/fluid/class.C b/fluid/class.C
new file mode 100644
index 000000000..e547cf2a7
--- /dev/null
+++ b/fluid/class.C
@@ -0,0 +1,123 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "class.H"
+
+inline void essai::cb_button_i(Fl_Button*, void*) {
+ printf("button\n");
+}
+void essai::cb_button(Fl_Button* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_button_i(o,v);
+}
+
+inline void essai::cb_unnamed_i(Fl_Button*, void*) {
+ printf("unnamed\n");
+}
+void essai::cb_unnamed(Fl_Button* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_unnamed_i(o,v);
+}
+
+inline void essai::cb_src_i(Fl_Button*, void*) {
+ (new essai)->win->show();
+}
+void essai::cb_src(Fl_Button* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_src_i(o,v);
+}
+
+#include <FL/Fl_Bitmap.H>
+static char bits_ew_mask[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 28, 56, 254, 127, 255, 255, 255, 255, 254, 127, 28, 56, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static Fl_Bitmap bitmap_ew_mask(bits_ew_mask, 16, 16);
+
+inline void essai::cb_change_i(Fl_Menu_*, void*) {
+ cbox->color(cbox->color()+1);
+cbox->redraw();
+}
+void essai::cb_change(Fl_Menu_* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_change_i(o,v);
+}
+
+Fl_Menu_Item essai::menu_menu[] = {
+ {"change color", 0, (Fl_Callback*)essai::cb_change, 0, 0, 0, 3, 14, 0},
+ {"radio off", 0, 0, 0, 8, 0, 3, 14, 0},
+ {"radio on", 0, 0, 0, 12, 0, 3, 14, 0},
+ {"toggle off", 0, 0, 0, 2, 0, 3, 14, 0},
+ {"toggle on", 0, 0, 0, 6, 0, 3, 14, 0},
+ {"new item 5", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 6", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 7", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 8", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 9", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 10", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 11", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 12", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 13", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 14", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 15", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 16", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 17", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 18", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 19", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 20", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 21", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 22", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 23", 0, 0, 0, 0, 0, 3, 14, 0},
+ {"new item 24", 0, 0, 0, 0, 0, 3, 14, 0},
+ {0}
+};
+
+inline void essai::cb_color_i(Fl_Button*, void*) {
+ cbox->color(cbox->color()+1);
+cbox->redraw();
+}
+void essai::cb_color(Fl_Button* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_color_i(o,v);
+}
+
+inline void essai::cb_delete_i(Fl_Button*, void*) {
+ delete this;
+}
+void essai::cb_delete(Fl_Button* o, void* v) {
+ ((essai*)(o->parent()->user_data()))->cb_delete_i(o,v);
+}
+
+essai::essai() {
+ Fl_Window *w;
+ { Fl_Window* o = win = w = new Fl_Window(282, 193);
+ o->user_data((void*)(this));
+ { Fl_Button* o = new Fl_Button(10, 10, 55, 35, "button");
+ o->callback((Fl_Callback*)cb_button);
+ }
+ { Fl_Button* o = new Fl_Button(10, 45, 145, 35, "unnamed");
+ o->callback((Fl_Callback*)cb_unnamed);
+ }
+ { Fl_Button* o = new Fl_Button(10, 80, 145, 35);
+ bitmap_ew_mask.label(o);
+ o->callback((Fl_Callback*)cb_src);
+ }
+ { Fl_Menu_Button* o = new Fl_Menu_Button(10, 115, 145, 35, "menu");
+ o->menu(menu_menu);
+ }
+ { Fl_Button* o = new Fl_Button(70, 150, 85, 35, "color");
+ o->callback((Fl_Callback*)cb_color);
+ }
+ new Fl_Button(200, 10, 55, 35, "boring");
+ { Fl_Box* o = cbox = new Fl_Box(165, 80, 55, 35, "color");
+ o->box(FL_FLAT_BOX);
+ }
+ { Fl_Button* o = new Fl_Button(200, 125, 55, 35, "delete this");
+ o->callback((Fl_Callback*)cb_delete);
+ }
+ button_variable = new Fl_Button(100, 10, 55, 35, "button");
+ w->end();
+ }
+}
+
+essai::~essai() {
+ delete win;
+}
+
+int main(int argc, char **argv) {
+ essai E; E.win->show();
+ return Fl::run();
+}
diff --git a/fluid/class.H b/fluid/class.H
new file mode 100644
index 000000000..302ce0486
--- /dev/null
+++ b/fluid/class.H
@@ -0,0 +1,34 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Window.H>
+#include <stdio.h>
+
+class essai {
+public:
+ essai();
+ Fl_Window *win;
+private:
+ inline void cb_button_i(Fl_Button*, void*);
+ static void cb_button(Fl_Button*, void*);
+ inline void cb_unnamed_i(Fl_Button*, void*);
+ static void cb_unnamed(Fl_Button*, void*);
+ inline void cb_src_i(Fl_Button*, void*);
+ static void cb_src(Fl_Button*, void*);
+ static Fl_Menu_Item menu_menu[];
+ inline void cb_change_i(Fl_Menu_*, void*);
+ static void cb_change(Fl_Menu_*, void*);
+ inline void cb_color_i(Fl_Button*, void*);
+ static void cb_color(Fl_Button*, void*);
+public:
+ Fl_Box *cbox;
+private:
+ inline void cb_delete_i(Fl_Button*, void*);
+ static void cb_delete(Fl_Button*, void*);
+public:
+ Fl_Button *button_variable;
+ ~essai();
+};
diff --git a/fluid/code.cxx b/fluid/code.cxx
new file mode 100644
index 000000000..171593fff
--- /dev/null
+++ b/fluid/code.cxx
@@ -0,0 +1,263 @@
+/* code.C
+
+ Code to write .C files from Fluid
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <FL/Fl.H>
+#include "Fl_Type.H"
+
+static FILE *code_file;
+static FILE *header_file;
+
+// return true if c can be in a C identifier. I needed this so
+// it is not messed up by locale settings:
+int is_id(char c) {
+ return c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_';
+}
+
+////////////////////////////////////////////////////////////////
+// Generate unique but human-readable identifiers:
+
+struct id {
+ char* text;
+ void* object;
+ id *left, *right;
+ id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
+ ~id();
+};
+
+id::~id() {
+ delete left;
+ free((void *)text);
+ delete right;
+}
+
+static id* id_root;
+
+const char* unique_id(void* o, const char* type, const char* name, const char* label) {
+ char buffer[128];
+ char* q = buffer;
+ while (*type) *q++ = *type++;
+ *q++ = '_';
+ const char* n = name;
+ if (!n || !*n) n = label;
+ if (n && *n) {
+ while (!is_id(*n)) n++;
+ while (is_id(*n)) *q++ = *n++;
+ }
+ *q = 0;
+ // okay, search the tree and see if the name was already used:
+ id** p = &id_root;
+ int which = 0;
+ while (*p) {
+ int i = strcmp(buffer, (*p)->text);
+ if (!i) {
+ if ((*p)->object == o) return (*p)->text;
+ // already used, we need to pick a new name:
+ sprintf(q,"%x",++which);
+ p = &id_root;
+ continue;
+ }
+ else if (i < 0) p = &((*p)->left);
+ else p = &((*p)->right);
+ }
+ *p = new id(buffer, o);
+ return (*p)->text;
+}
+
+////////////////////////////////////////////////////////////////
+// return current indentation:
+
+static const char* spaces = " ";
+int indentation;
+const char* indent() {
+ int i = indentation; if (i>16) i = 16;
+ return spaces+16-i;
+}
+
+////////////////////////////////////////////////////////////////
+// declarations/include files:
+// These are sorted in alphabetical order and only included once each:
+// Relies on '#' being less than any letter to put #include first.
+// I use a binary tree to sort these out.
+
+struct included {
+ char *text;
+ included *left, *right;
+ included(const char *t) {
+ text = strdup(t);
+ left = right = 0;
+ }
+ ~included();
+};
+
+included::~included() {
+ delete left;
+ fprintf(header_file,"%s\n",text);
+ free((void *)text);
+ delete right;
+}
+static included *included_root;
+
+int write_declare(const char *format, ...) {
+ va_list args;
+ char buf[1024];
+ va_start(args, format);
+ vsprintf(buf, format, args);
+ va_end(args);
+ included **p = &included_root;
+ while (*p) {
+ int i = strcmp(buf,(*p)->text);
+ if (!i) return 0;
+ else if (i < 0) p = &((*p)->left);
+ else p = &((*p)->right);
+ }
+ *p = new included(buf);
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+// silly thing to prevent declaring unused variables:
+// When this symbol is on, all attempts to write code don't write
+// anything, but set a variable if it looks like the varaible "o" is used:
+int varused_test;
+int varused;
+
+// write an array of C characters (adds a null):
+void write_cstring(const char *w, int length) {
+ if (varused_test) return;
+ const char *e = w+length;
+ int linelength = 1;
+ putc('\"', code_file);
+ for (; w < e;) {
+ if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;}
+ int c = *w++;
+ switch (c) {
+ case '\b': c = 'b'; goto QUOTED;
+ case '\t': c = 't'; goto QUOTED;
+ case '\n': c = 'n'; goto QUOTED;
+ case '\f': c = 'f'; goto QUOTED;
+ case '\r': c = 'r'; goto QUOTED;
+ case '\"':
+ case '\'':
+ case '\\':
+ QUOTED:
+ putc('\\',code_file);
+ putc(c,code_file);
+ linelength += 2;
+ break;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ if (*w < '0' || *w > '9') {c += '0'; goto QUOTED;}
+ // else fall through:
+ default:
+ if (c < ' ' || c >= 127) {
+ QUOTENEXT:
+ fprintf(code_file, "\\x%02x",c&255);
+ linelength += 4;
+ c = *w;
+ if (w < e && (c>='0'&&c<='9' || c>='a'&&c<='f' || c>='A'&&c<='F')) {
+ w++; goto QUOTENEXT;
+ }
+ } else {
+ putc(c,code_file);
+ linelength++;
+ }
+ break;
+ }
+ }
+ putc('\"', code_file);
+}
+
+// write a C string, quoting characters if necessary:
+void write_cstring(const char *w) {write_cstring(w,strlen(w));}
+
+void write_c(const char* format,...) {
+ if (varused_test) {varused = 1; return;}
+ va_list args;
+ va_start(args, format);
+ vfprintf(code_file, format, args);
+ va_end(args);
+}
+
+void write_h(const char* format,...) {
+ if (varused_test) return;
+ va_list args;
+ va_start(args, format);
+ vfprintf(header_file, format, args);
+ va_end(args);
+}
+
+#include <FL/filename.H>
+int write_number;
+
+// recursively dump code, putting children between the two parts
+// of the parent code:
+static Fl_Type* write_code(Fl_Type* p) {
+ p->write_code1();
+ Fl_Type* q;
+ for (q = p->next; q && q->level > p->level;) q = write_code(q);
+ p->write_code2();
+ return q;
+}
+
+int write_code(const char *s, const char *t) {
+ write_number++;
+ delete id_root; id_root = 0;
+ indentation = 0;
+ if (!s) code_file = stdout;
+ else {
+ FILE *f = fopen(s,"w");
+ if (!f) return 0;
+ code_file = f;
+ }
+ if (!t) header_file = stdout;
+ else {
+ FILE *f = fopen(t,"w");
+ if (!f) {fclose(code_file); return 0;}
+ header_file = f;
+ }
+ const char *hdr = "\
+// generated by Fast Light User Interface Designer (fluid) version %.2f\n\n";
+ fprintf(header_file, hdr, FL_VERSION);
+ fprintf(code_file, hdr, FL_VERSION);
+ Fl_Type *p;
+
+ for (p = Fl_Type::first; p; p = p->next) p->write_declare();
+ delete included_root; included_root = 0;
+
+ if (t) write_c("#include \"%s\"\n", filename_name(t));
+ for (p = Fl_Type::first; p; p = p->next) p->write_static();
+ for (p = Fl_Type::first; p;) p = write_code(p);
+
+ if (!s) return 1;
+ int x = fclose(code_file);
+ code_file = 0;
+ int y = fclose(header_file);
+ header_file = 0;
+ return x >= 0 && y >= 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Type::write_declare() {}
+void Fl_Type::write_static() {}
+void Fl_Type::write_code1() {
+ write_h("// Header for %s\n", title());
+ write_c("// Code for %s\n", title());
+}
+void Fl_Type::write_code2() {}
diff --git a/fluid/factory.cxx b/fluid/factory.cxx
new file mode 100644
index 000000000..5a5ff5383
--- /dev/null
+++ b/fluid/factory.cxx
@@ -0,0 +1,651 @@
+/* factory.C
+
+ Type classes for most of the fltk widgets. Most of the work
+ is done by code in Fl_Widget_Type.C. Also a factory instance
+ of each of these type classes.
+
+ This file also contains the "new" menu, which has a pointer
+ to a factory instance for every class (both the ones defined
+ here and ones in other files)
+*/
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Menu_Item.H>
+#include <string.h>
+#include <stdio.h>
+
+#if defined(WIN32) || defined(__EMX__)
+#define strcasecmp stricmp
+#endif
+
+#include "Fl_Widget_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Box.H>
+class Fl_Box_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Box";}
+ Fl_Widget *widget(int x,int y,int w, int h) {
+ return new Fl_Box(x,y,w,h,"label");}
+ Fl_Widget_Type *_make() {return new Fl_Box_Type();}
+};
+static Fl_Box_Type Fl_Box_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Button.H>
+static Fl_Menu_Item button_type_menu[] = {
+ {"Normal",0,0,(void*)0},
+ {"Toggle",0,0,(void*)FL_TOGGLE_BUTTON},
+ {"Radio",0,0,(void*)FL_RADIO_BUTTON},
+ {0}};
+class Fl_Button_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return button_type_menu;}
+public:
+ virtual const char *type_name() {return "Fl_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Button(x,y,w,h,"button");}
+ Fl_Widget_Type *_make() {return new Fl_Button_Type();}
+ int is_button() const {return 1;}
+};
+static Fl_Button_Type Fl_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Return_Button.H>
+class Fl_Return_Button_Type : public Fl_Button_Type {
+public:
+ virtual const char *type_name() {return "Fl_Return_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Return_Button(x,y,w,h,0);}
+ Fl_Widget_Type *_make() {return new Fl_Return_Button_Type();}
+};
+static Fl_Return_Button_Type Fl_Return_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Repeat_Button.H>
+class Fl_Repeat_Button_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Repeat_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Repeat_Button(x,y,w,h,0);}
+ Fl_Widget_Type *_make() {return new Fl_Repeat_Button_Type();}
+};
+static Fl_Repeat_Button_Type Fl_Repeat_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Light_Button.H>
+class Fl_Light_Button_Type : public Fl_Button_Type {
+public:
+ virtual const char *type_name() {return "Fl_Light_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Light_Button(x,y,w,h,"button");}
+ Fl_Widget_Type *_make() {return new Fl_Light_Button_Type();}
+};
+static Fl_Light_Button_Type Fl_Light_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Check_Button.H>
+class Fl_Check_Button_Type : public Fl_Button_Type {
+public:
+ virtual const char *type_name() {return "Fl_Check_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Check_Button(x,y,w,h,"button");}
+ Fl_Widget_Type *_make() {return new Fl_Check_Button_Type();}
+};
+static Fl_Check_Button_Type Fl_Check_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Round_Button.H>
+class Fl_Round_Button_Type : public Fl_Button_Type {
+public:
+ virtual const char *type_name() {return "Fl_Round_Button";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Round_Button(x,y,w,h,"button");}
+ Fl_Widget_Type *_make() {return new Fl_Round_Button_Type();}
+};
+static Fl_Round_Button_Type Fl_Round_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Browser.H>
+static Fl_Menu_Item browser_type_menu[] = {
+ {"No Select",0,0,(void*)FL_NORMAL_BROWSER},
+ {"Select",0,0,(void*)FL_SELECT_BROWSER},
+ {"Hold",0,0,(void*)FL_HOLD_BROWSER},
+ {"Multi",0,0,(void*)FL_MULTI_BROWSER},
+ {0}};
+class Fl_Browser_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return browser_type_menu;}
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Browser *o = (Fl_Browser*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ virtual const char *type_name() {return "Fl_Browser";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Browser* b = new Fl_Browser(x,y,w,h);
+ char buffer[20];
+ for (int i = 1; i <= 20; i++) {
+ sprintf(buffer,"Browser Line %d",i);
+ b->add(buffer);
+ }
+ return b;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Browser_Type();}
+};
+static Fl_Browser_Type Fl_Browser_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Counter.H>
+static Fl_Menu_Item counter_type_menu[] = {
+ {"Normal",0,0,(void*)FL_NORMAL_COUNTER},
+ {"Simple",0,0,(void*)FL_SIMPLE_COUNTER},
+ {0}};
+class Fl_Counter_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return counter_type_menu;}
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Counter *o = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+ int is_valuator() const {return 1;}
+public:
+ virtual const char *type_name() {return "Fl_Counter";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Counter(x,y,w,h,"counter:");}
+ Fl_Widget_Type *_make() {return new Fl_Counter_Type();}
+};
+static Fl_Counter_Type Fl_Counter_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Input.H>
+static Fl_Menu_Item input_type_menu[] = {
+ {"Normal",0,0,(void*)FL_NORMAL_INPUT},
+ {"Multiline",0,0,(void*)FL_MULTILINE_INPUT},
+ {"Secret",0,0,(void*)FL_SECRET_INPUT},
+ {"Int",0,0,(void*)FL_INT_INPUT},
+ {"Float",0,0,(void*)FL_FLOAT_INPUT},
+ {0}};
+class Fl_Input_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return input_type_menu;}
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Input_ *o = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ virtual const char *type_name() {return "Fl_Input";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Input *o = new Fl_Input(x,y,w,h,"input:");
+ o->value("Text Input");
+ return o;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Input_Type();}
+};
+static Fl_Input_Type Fl_Input_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Clock.H>
+class Fl_Clock_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Clock";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Clock(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Clock_Type();}
+};
+static Fl_Clock_Type Fl_Clock_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Adjuster.H>
+class Fl_Adjuster_Type : public Fl_Widget_Type {
+ int is_valuator() const {return 1;}
+public:
+ virtual const char *type_name() {return "Fl_Adjuster";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Adjuster(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Adjuster_Type();}
+};
+static Fl_Adjuster_Type Fl_Adjuster_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Dial.H>
+static Fl_Menu_Item dial_type_menu[] = {
+ {"Dot",0,0,(void*)0},
+ {"Line",0,0,(void*)FL_LINE_DIAL},
+ {"Fill",0,0,(void*)FL_FILL_DIAL},
+ {0}};
+class Fl_Dial_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return dial_type_menu;}
+ int is_valuator() const {return 1;}
+public:
+ virtual const char *type_name() {return "Fl_Dial";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Dial(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Dial_Type();}
+};
+static Fl_Dial_Type Fl_Dial_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Roller.H>
+static Fl_Menu_Item roller_type_menu[] = {
+ {"Vertical",0,0,(void*)0},
+ {"Horizontal",0,0,(void*)FL_HORIZONTAL},
+ {0}};
+class Fl_Roller_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return roller_type_menu;}
+ int is_valuator() const {return 1;}
+public:
+ virtual const char *type_name() {return "Fl_Roller";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Roller(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Roller_Type();}
+};
+static Fl_Roller_Type Fl_Roller_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Scrollbar.H>
+static Fl_Menu_Item slider_type_menu[] = {
+ {"Vertical",0,0,(void*)FL_VERT_SLIDER},
+ {"Horizontal",0,0,(void*)FL_HOR_SLIDER},
+ {"Vert Fill",0,0,(void*)FL_VERT_FILL_SLIDER},
+ {"Horz Fill",0,0,(void*)FL_HOR_FILL_SLIDER},
+ {"Vert Knob",0,0,(void*)FL_VERT_NICE_SLIDER},
+ {"Horz Knob",0,0,(void*)FL_HOR_NICE_SLIDER},
+ {0}};
+class Fl_Slider_Type : public Fl_Widget_Type {
+ Fl_Menu_Item *subtypes() {return slider_type_menu;}
+ int is_valuator() const {return 2;}
+public:
+ virtual const char *type_name() {return "Fl_Slider";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Slider(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Slider_Type();}
+};
+static Fl_Slider_Type Fl_Slider_type;
+
+static Fl_Menu_Item scrollbar_type_menu[] = {
+ {"Vertical",0,0,(void*)FL_VERT_SLIDER},
+ {"Horizontal",0,0,(void*)FL_HOR_SLIDER},
+ {0}};
+class Fl_Scrollbar_Type : public Fl_Slider_Type {
+ Fl_Menu_Item *subtypes() {return scrollbar_type_menu;}
+public:
+ virtual const char *type_name() {return "Fl_Scrollbar";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Scrollbar(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Scrollbar_Type();}
+};
+static Fl_Scrollbar_Type Fl_Scrollbar_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Output.H>
+static Fl_Menu_Item output_type_menu[] = {
+ {"Normal",0,0,(void*)FL_NORMAL_INPUT},
+ {"Multiline",0,0,(void*)FL_MULTILINE_INPUT},
+ {0}};
+class Fl_Output_Type : public Fl_Input_Type {
+ Fl_Menu_Item *subtypes() {return output_type_menu;}
+public:
+ virtual const char *type_name() {return "Fl_Output";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Output *o = new Fl_Output(x,y,w,h,"output:");
+ o->value("Text Output");
+ return o;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Output_Type();}
+};
+static Fl_Output_Type Fl_Output_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Value_Input.H>
+class Fl_Value_Input_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Value_Input";}
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Value_Input *o = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+ int is_valuator() const {return 1;}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Value_Input *o = new Fl_Value_Input(x,y,w,h,"value:");
+ return o;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Value_Input_Type();}
+};
+static Fl_Value_Input_Type Fl_Value_Input_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Value_Output.H>
+class Fl_Value_Output_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Value_Output";}
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Value_Output *o = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+ int is_valuator() const {return 1;}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ Fl_Value_Output *o = new Fl_Value_Output(x,y,w,h,"value:");
+ return o;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Value_Output_Type();}
+};
+static Fl_Value_Output_Type Fl_Value_Output_type;
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl_Value_Slider.H>
+class Fl_Value_Slider_Type : public Fl_Slider_Type {
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Value_Slider *o = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+ case 1: o->textfont(f); break;
+ case 2: o->textsize(s); break;
+ case 3: o->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ virtual const char *type_name() {return "Fl_Value_Slider";}
+ Fl_Widget *widget(int x,int y,int w,int h) {
+ return new Fl_Value_Slider(x,y,w,h);}
+ Fl_Widget_Type *_make() {return new Fl_Value_Slider_Type();}
+};
+static Fl_Value_Slider_Type Fl_Value_Slider_type;
+
+////////////////////////////////////////////////////////////////
+
+extern class Fl_Function_Type Fl_Function_type;
+extern class Fl_Code_Type Fl_Code_type;
+extern class Fl_CodeBlock_Type Fl_CodeBlock_type;
+extern class Fl_Decl_Type Fl_Decl_type;
+extern class Fl_DeclBlock_Type Fl_DeclBlock_type;
+extern class Fl_Class_Type Fl_Class_type;
+extern class Fl_Window_Type Fl_Window_type;
+extern class Fl_Group_Type Fl_Group_type;
+extern class Fl_Tabs_Type Fl_Tabs_type;
+extern class Fl_Scroll_Type Fl_Scroll_type;
+extern class Fl_Tile_Type Fl_Tile_type;
+extern class Fl_Choice_Type Fl_Choice_type;
+extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type;
+extern class Fl_Menu_Button_Type Fl_Menu_Button_type;
+extern class Fl_Menu_Item_Type Fl_Menu_Item_type;
+extern class Fl_Submenu_Type Fl_Submenu_type;
+
+extern void select(Fl_Type *,int);
+extern void select_only(Fl_Type *);
+
+static void cb(Fl_Widget *, void *v) {
+ Fl_Type *t = ((Fl_Type*)v)->make();
+ if (t) {select_only(t); modflag = 1; t->open();}
+}
+
+Fl_Menu_Item New_Menu[] = {
+{"code",0,0,0,FL_SUBMENU},
+ {"function/method",0,cb,(void*)&Fl_Function_type},
+ {"code",0,cb,(void*)&Fl_Code_type},
+ {"code block",0,cb,(void*)&Fl_CodeBlock_type},
+ {"declaration",0,cb,(void*)&Fl_Decl_type},
+ {"declaration block",0,cb,(void*)&Fl_DeclBlock_type},
+ {"class",0,cb,(void*)&Fl_Class_type},
+{0},
+{"group",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Window_type},
+ {0,0,cb,(void*)&Fl_Group_type},
+ {0,0,cb,(void*)&Fl_Tabs_type},
+ {0,0,cb,(void*)&Fl_Scroll_type},
+ {0,0,cb,(void*)&Fl_Tile_type},
+{0},
+{"buttons",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Button_type},
+ {0,0,cb,(void*)&Fl_Return_Button_type},
+ {0,0,cb,(void*)&Fl_Light_Button_type},
+ {0,0,cb,(void*)&Fl_Check_Button_type},
+ {0,0,cb,(void*)&Fl_Round_Button_type},
+ {0,0,cb,(void*)&Fl_Repeat_Button_type},
+{0},
+{"valuators",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Slider_type},
+ {0,0,cb,(void*)&Fl_Scrollbar_type},
+ {0,0,cb,(void*)&Fl_Value_Slider_type},
+ {0,0,cb,(void*)&Fl_Adjuster_type},
+ {0,0,cb,(void*)&Fl_Counter_type},
+ {0,0,cb,(void*)&Fl_Dial_type},
+ {0,0,cb,(void*)&Fl_Roller_type},
+ {0,0,cb,(void*)&Fl_Value_Input_type},
+ {0,0,cb,(void*)&Fl_Value_Output_type},
+{0},
+{"text",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Input_type},
+ {0,0,cb,(void*)&Fl_Output_type},
+{0},
+{"menus",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Menu_Bar_type},
+ {0,0,cb,(void*)&Fl_Menu_Button_type},
+ {0,0,cb,(void*)&Fl_Choice_type},
+ {0,0,cb, (void*)&Fl_Submenu_type},
+ {0,0,cb, (void*)&Fl_Menu_Item_type},
+{0},
+{"other",0,0,0,FL_SUBMENU},
+ {0,0,cb,(void*)&Fl_Browser_type},
+ {0,0,cb,(void*)&Fl_Box_type},
+ {0,0,cb,(void*)&Fl_Clock_type},
+{0},
+{0}};
+
+void fill_in_New_Menu() {
+ for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) {
+ Fl_Menu_Item *m = New_Menu+i;
+ if (m->user_data() && !m->text) {
+ const char *n = ((Fl_Type*)(m->user_data()))->type_name();
+ if (!strncmp(n,"Fl_",3)) n += 3;
+ m->text = n;
+ }
+ }
+}
+
+// use keyword to pick the type, this is used to parse files:
+int reading_file;
+Fl_Type *Fl_Type_make(const char *tn) {
+ reading_file = 1; // makes labels be null
+ Fl_Type *r = 0;
+ for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) {
+ Fl_Menu_Item *m = New_Menu+i;
+ if (!m->user_data()) continue;
+ Fl_Type *t = (Fl_Type*)(m->user_data());
+ if (!strcasecmp(tn,t->type_name())) {r = t->make(); break;}
+ }
+ reading_file = 0;
+ return r;
+}
+
+////////////////////////////////////////////////////////////////
+
+// Since I have included all the .H files, do this table here:
+// This table is only used to read fdesign files:
+
+struct symbol {const char *name; int value;};
+
+static symbol table[] = {
+ {"BLACK", FL_BLACK},
+ {"RED", FL_RED},
+ {"GREEN", FL_GREEN},
+ {"YELLOW", FL_YELLOW},
+ {"BLUE", FL_BLUE},
+ {"MAGENTA", FL_MAGENTA},
+ {"CYAN", FL_CYAN},
+ {"WHITE", FL_WHITE},
+
+ {"LCOL", FL_BLACK},
+ {"COL1", FL_GRAY},
+ {"MCOL", FL_LIGHT1},
+ {"LEFT_BCOL", FL_LIGHT3},
+ {"TOP_BCOL", FL_LIGHT2},
+ {"BOTTOM_BCOL", FL_DARK2},
+ {"RIGHT_BCOL", FL_DARK3},
+ {"INACTIVE", FL_INACTIVE_COLOR},
+ {"INACTIVE_COL", FL_INACTIVE_COLOR},
+ {"FREE_COL1", FL_FREE_COLOR},
+ {"FREE_COL2", FL_FREE_COLOR+1},
+ {"FREE_COL3", FL_FREE_COLOR+2},
+ {"FREE_COL4", FL_FREE_COLOR+3},
+ {"FREE_COL5", FL_FREE_COLOR+4},
+ {"FREE_COL6", FL_FREE_COLOR+5},
+ {"FREE_COL7", FL_FREE_COLOR+6},
+ {"FREE_COL8", FL_FREE_COLOR+7},
+ {"FREE_COL9", FL_FREE_COLOR+8},
+ {"FREE_COL10", FL_FREE_COLOR+9},
+ {"FREE_COL11", FL_FREE_COLOR+10},
+ {"FREE_COL12", FL_FREE_COLOR+11},
+ {"FREE_COL13", FL_FREE_COLOR+12},
+ {"FREE_COL14", FL_FREE_COLOR+13},
+ {"FREE_COL15", FL_FREE_COLOR+14},
+ {"FREE_COL16", FL_FREE_COLOR+15},
+ {"TOMATO", 131},
+ {"INDIANRED", 164},
+ {"SLATEBLUE", 195},
+ {"DARKGOLD", 84},
+ {"PALEGREEN", 157},
+ {"ORCHID", 203},
+ {"DARKCYAN", 189},
+ {"DARKTOMATO", 113},
+ {"WHEAT", 174},
+ {"ALIGN_CENTER", FL_ALIGN_CENTER},
+ {"ALIGN_TOP", FL_ALIGN_TOP},
+ {"ALIGN_BOTTOM", FL_ALIGN_BOTTOM},
+ {"ALIGN_LEFT", FL_ALIGN_LEFT},
+ {"ALIGN_RIGHT", FL_ALIGN_RIGHT},
+ {"ALIGN_INSIDE", FL_ALIGN_INSIDE},
+ {"ALIGN_TOP_LEFT", FL_ALIGN_TOP | FL_ALIGN_LEFT},
+ {"ALIGN_TOP_RIGHT", FL_ALIGN_TOP | FL_ALIGN_RIGHT},
+ {"ALIGN_BOTTOM_LEFT", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT},
+ {"ALIGN_BOTTOM_RIGHT", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT},
+ {"ALIGN_CENTER|FL_ALIGN_INSIDE", FL_ALIGN_CENTER|FL_ALIGN_INSIDE},
+ {"ALIGN_TOP|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_INSIDE},
+ {"ALIGN_BOTTOM|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE},
+ {"ALIGN_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+ {"ALIGN_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+ {"ALIGN_INSIDE|FL_ALIGN_INSIDE", FL_ALIGN_INSIDE|FL_ALIGN_INSIDE},
+ {"ALIGN_TOP_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+ {"ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+ {"ALIGN_BOTTOM_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+ {"ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE",FL_ALIGN_BOTTOM|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+
+ {"ALIGN_LEFT_TOP", FL_ALIGN_TOP | FL_ALIGN_LEFT},
+ {"ALIGN_RIGHT_TOP", FL_ALIGN_TOP | FL_ALIGN_RIGHT},
+ {"ALIGN_LEFT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT},
+ {"ALIGN_RIGHT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT},
+ {"INVALID_STYLE", 255},
+ {"NORMAL_STYLE", FL_HELVETICA},
+ {"BOLD_STYLE", FL_HELVETICA|FL_BOLD},
+ {"ITALIC_STYLE", FL_HELVETICA|FL_ITALIC},
+ {"BOLDITALIC_STYLE", FL_HELVETICA|FL_BOLD|FL_ITALIC},
+ {"FIXED_STYLE", FL_COURIER},
+ {"FIXEDBOLD_STYLE", FL_COURIER|FL_BOLD},
+ {"FIXEDITALIC_STYLE", FL_COURIER|FL_ITALIC},
+ {"FIXEDBOLDITALIC_STYLE", FL_COURIER|FL_BOLD|FL_ITALIC},
+ {"TIMES_STYLE", FL_TIMES},
+ {"TIMESBOLD_STYLE", FL_TIMES|FL_BOLD},
+ {"TIMESITALIC_STYLE", FL_TIMES|FL_ITALIC},
+ {"TIMESBOLDITALIC_STYLE", FL_TIMES|FL_BOLD|FL_ITALIC},
+ {"SHADOW_STYLE", (_FL_SHADOW_LABEL<<8)},
+ {"ENGRAVED_STYLE", (_FL_ENGRAVED_LABEL<<8)},
+ {"EMBOSSED_STYLE", (_FL_EMBOSSED_LABEL<<0)},
+ {"TINY_SIZE", 8},
+ {"SMALL_SIZE", 11},
+ {"NORMAL_SIZE", FL_NORMAL_SIZE},
+ {"MEDIUM_SIZE", 18},
+ {"LARGE_SIZE", 24},
+ {"HUGE_SIZE", 32},
+ {"DEFAULT_SIZE", FL_NORMAL_SIZE},
+ {"TINY_FONT", 8},
+ {"SMALL_FONT", 11},
+ {"NORMAL_FONT", FL_NORMAL_SIZE},
+ {"MEDIUM_FONT", 18},
+ {"LARGE_FONT", 24},
+ {"HUGE_FONT", 32},
+ {"NORMAL_FONT1", 11},
+ {"NORMAL_FONT2", FL_NORMAL_SIZE},
+ {"DEFAULT_FONT", 11},
+ {"RETURN_END_CHANGED", 0},
+ {"RETURN_CHANGED", 1},
+ {"RETURN_END", 2},
+ {"RETURN_ALWAYS", 3},
+ {"PUSH_BUTTON", FL_TOGGLE_BUTTON},
+ {"RADIO_BUTTON", FL_RADIO_BUTTON},
+ {"HIDDEN_BUTTON", FL_HIDDEN_BUTTON},
+ {"SELECT_BROWSER", FL_SELECT_BROWSER},
+ {"HOLD_BROWSER", FL_HOLD_BROWSER},
+ {"MULTI_BROWSER", FL_MULTI_BROWSER},
+ {"SIMPLE_COUNTER", FL_SIMPLE_COUNTER},
+ {"LINE_DIAL", FL_LINE_DIAL},
+ {"FILL_DIAL", FL_FILL_DIAL},
+ {"VERT_SLIDER", FL_VERT_SLIDER},
+ {"HOR_SLIDER", FL_HOR_SLIDER},
+ {"VERT_FILL_SLIDER", FL_VERT_FILL_SLIDER},
+ {"HOR_FILL_SLIDER", FL_HOR_FILL_SLIDER},
+ {"VERT_NICE_SLIDER", FL_VERT_NICE_SLIDER},
+ {"HOR_NICE_SLIDER", FL_HOR_NICE_SLIDER},
+};
+
+#include <stdlib.h>
+
+int lookup_symbol(const char *name, int &v, int numberok) {
+ if (name[0]=='F' && name[1]=='L' && name[2]=='_') name += 3;
+ for (int i=0; i < int(sizeof(table)/sizeof(*table)); i++)
+ if (!strcasecmp(name,table[i].name)) {v = table[i].value; return 1;}
+ if (numberok && ((v = atoi(name)) || !strcmp(name,"0"))) return 1;
+ return 0;
+}
diff --git a/fluid/file.cxx b/fluid/file.cxx
new file mode 100644
index 000000000..69bc97d17
--- /dev/null
+++ b/fluid/file.cxx
@@ -0,0 +1,562 @@
+/* file.C
+
+ Code to read and write Fluid .fl files
+
+ You may find the basic read_* and write_* routines to
+ be useful for other programs. I have used them many times.
+ They are somewhat similar to tcl, using matching { and }
+ to quote strings.
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+////////////////////////////////////////////////////////////////
+// BASIC FILE WRITING:
+
+static FILE *fout;
+
+int open_write(const char *s) {
+ if (!s) {fout = stdout; return 1;}
+ FILE *f = fopen(s,"w");
+ if (!f) return 0;
+ fout = f;
+ return 1;
+}
+
+int close_write() {
+ if (fout != stdout) {
+ int x = fclose(fout);
+ fout = stdout;
+ return x >= 0;
+ }
+ return 1;
+}
+
+static int needspace;
+int is_id(char); // in code.C
+
+// write a string, quoting characters if necessary:
+void write_word(const char *w) {
+ if (needspace) putc(' ', fout);
+ needspace = 1;
+ if (!w || !*w) {fprintf(fout,"{}"); return;}
+ const char *p;
+ // see if it is a single word:
+ for (p = w; is_id(*p); p++) ;
+ if (!*p) {fprintf(fout,"%s",w); return;}
+ // see if there are matching braces:
+ int n = 0;
+ for (p = w; *p; p++) {
+ if (*p == '{') n++;
+ else if (*p == '}') {n--; if (n<0) break;}
+ }
+ int mismatched = (n != 0);
+ // write out brace-quoted string:
+ putc('{', fout);
+ for (; *w; w++) {
+ switch (*w) {
+ case '{':
+ case '}':
+ if (!mismatched) break;
+ case '\\':
+ case '#':
+ putc('\\',fout);
+ break;
+ }
+ putc(*w,fout);
+ }
+ putc('}', fout);
+}
+
+// write an arbitrary formatted word, or a comment, etc:
+void write_string(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ if (needspace) fputc(' ',fout);
+ vfprintf(fout, format, args);
+ va_end(args);
+ needspace = !isspace(format[strlen(format)-1]);
+}
+
+// start a new line and indent it for a given nesting level:
+void write_indent(int n) {
+ fputc('\n',fout);
+ while (n--) {fputc(' ',fout); fputc(' ',fout);}
+ needspace = 0;
+}
+
+// write a '{' at the given indenting level:
+void write_open(int) {
+ if (needspace) fputc(' ',fout);
+ fputc('{',fout);
+ needspace = 0;
+}
+
+// write a '}' at the given indenting level:
+void write_close(int n) {
+ if (needspace) write_indent(n);
+ fputc('}',fout);
+ needspace = 1;
+}
+
+////////////////////////////////////////////////////////////////
+// BASIC FILE READING:
+
+static FILE *fin;
+static int lineno;
+static const char *fname;
+
+int open_read(const char *s) {
+ lineno = 1;
+ if (!s) {fin = stdin; fname = "stdin"; return 1;}
+ FILE *f = fopen(s,"r");
+ if (!f) return 0;
+ fin = f;
+ fname = s;
+ return 1;
+}
+
+int close_read() {
+ if (fin != stdin) {
+ int x = fclose(fin);
+ fin = 0;
+ return x >= 0;
+ }
+ return 1;
+}
+
+#include <FL/fl_message.H>
+
+void read_error(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ if (!fin) {
+ char buffer[1024];
+ vsprintf(buffer, format, args);
+ fl_message(buffer);
+ } else {
+ fprintf(stderr, "%s:%d: ", fname, lineno);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ }
+ va_end(args);
+}
+
+static int hexdigit(int x) {
+ if (isdigit(x)) return x-'0';
+ if (isupper(x)) return x-'A'+10;
+ if (islower(x)) return x-'a'+10;
+ return 20;
+}
+
+
+static int read_quoted() { // read whatever character is after a \ .
+ int c,d,x;
+ switch(c = fgetc(fin)) {
+ case '\n': lineno++; return -1;
+ case 'a' : return('\a');
+ case 'b' : return('\b');
+ case 'f' : return('\f');
+ case 'n' : return('\n');
+ case 'r' : return('\r');
+ case 't' : return('\t');
+ case 'v' : return('\v');
+ case 'x' : /* read hex */
+ for (c=x=0; x<3; x++) {
+ int ch = fgetc(fin);
+ d = hexdigit(ch);
+ if (d > 15) {ungetc(ch,fin); break;}
+ c = (c<<4)+d;
+ }
+ break;
+ default: /* read octal */
+ if (c<'0' || c>'7') break;
+ c -= '0';
+ for (x=0; x<2; x++) {
+ int ch = fgetc(fin);
+ d = hexdigit(ch);
+ if (d>7) {ungetc(ch,fin); break;}
+ c = (c<<3)+d;
+ }
+ break;
+ }
+ return(c);
+}
+
+// return a word read from the file, or NULL at the EOF:
+// This will skip all comments (# to end of line), and evaluate
+// all \xxx sequences and use \ at the end of line to remove the newline.
+// A word is any one of:
+// a continuous string of non-space chars except { and } and #
+// everything between matching {...} (unless wantbrace != 0)
+// the characters '{' and '}'
+
+static char *buffer;
+static int buflen;
+static void expand_buffer(int length) {
+ if (length >= buflen) {
+ if (!buflen) {
+ buflen = length+1;
+ buffer = (char*)malloc(buflen);
+ } else {
+ buflen = 2*buflen;
+ if (length >= buflen) buflen = length+1;
+ buffer = (char *)realloc((void *)buffer,buflen);
+ }
+ }
+}
+
+const char *read_word(int wantbrace) {
+ int x;
+
+ // skip all the whitespace before it:
+ for (;;) {
+ x = getc(fin);
+ if (x < 0) { // eof
+ return 0;
+ } else if (x == '#') { // comment
+ do x = getc(fin); while (x >= 0 && x != '\n');
+ lineno++;
+ continue;
+ } else if (x == '\n') {
+ lineno++;
+ } else if (!isspace(x)) {
+ break;
+ }
+ }
+
+ expand_buffer(100);
+
+ if (x == '{' && !wantbrace) {
+
+ // read in whatever is between braces
+ int length = 0;
+ int nesting = 0;
+ for (;;) {
+ x = getc(fin);
+ if (x<0) {read_error("Missing '}'"); break;}
+ else if (x == '#') { // embedded comment
+ do x = getc(fin); while (x >= 0 && x != '\n');
+ lineno++;
+ continue;
+ } else if (x == '\n') lineno++;
+ else if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+ else if (x == '{') nesting++;
+ else if (x == '}') {if (!nesting--) break;}
+ buffer[length++] = x;
+ expand_buffer(length);
+ }
+ buffer[length] = 0;
+ return buffer;
+
+ } else if (x == '{' || x == '}') {
+ // all the punctuation is a word:
+ buffer[0] = x;
+ buffer[1] = 0;
+ return buffer;
+
+ } else {
+
+ // read in an unquoted word:
+ int length = 0;
+ for (;;) {
+ if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+ else if (x<0 || isspace(x) || x=='{' || x=='}' || x=='#') break;
+ buffer[length++] = x;
+ expand_buffer(length);
+ x = getc(fin);
+ }
+ ungetc(x, fin);
+ buffer[length] = 0;
+ return buffer;
+
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <FL/Fl.H>
+#include "Fl_Widget_Type.H"
+
+// global int variables:
+extern int gridx, gridy, snap;
+static struct {const char* name; int* value;} inttable[] = {
+ {"gridx", &gridx},
+ {"gridy", &gridy},
+ {"snap", &snap}
+};
+
+extern const char* header_file_name;
+extern const char* code_file_name;
+
+int write_file(const char *filename, int selected_only) {
+ if (!open_write(filename)) return 0;
+ write_string("# data file for the Fltk User Interface Designer (fluid)\n"
+ "version %.2f",FL_VERSION);
+ if (!selected_only) {
+ write_string("\nheader_name"); write_word(header_file_name);
+ write_string("\ncode_name"); write_word(code_file_name);
+ for (unsigned int i=0; i<sizeof(inttable)/sizeof(*inttable); i++)
+ write_string("\n%s %d",inttable[i].name, *inttable[i].value);
+ }
+ for (Fl_Type *p = Fl_Type::first; p;) {
+ if (!selected_only || p->selected) {
+ p->write();
+ write_string("\n");
+ int q = p->level;
+ for (p = p->next; p && p->level > q; p = p->next);
+ } else {
+ p = p->next;
+ }
+ }
+ return close_write();
+}
+
+////////////////////////////////////////////////////////////////
+// read all the objects out of the input file:
+
+void read_fdesign();
+
+double read_version;
+
+extern Fl_Type *Fl_Type_make(const char *tn);
+
+static void read_children(Fl_Type *p, int paste) {
+ Fl_Type::current = p;
+ for (;;) {
+ unsigned int i;
+ const char *c = read_word();
+ REUSE_C:
+ if (!c) {
+ if (p && !paste) read_error("Missing '}'");
+ break;
+ }
+
+ if (!strcmp(c,"}")) {
+ if (!p) read_error("Unexpected '}'");
+ break;
+ }
+
+ // this is the first word in a .fd file:
+ if (!strcmp(c,"Magic:")) {
+ read_fdesign();
+ return;
+ }
+
+ if (!strcmp(c,"version")) {
+ c = read_word();
+ read_version = strtod(c,0);
+ if (read_version<=0 || read_version>FL_VERSION)
+ read_error("unknown version '%s'",c);
+ continue;
+ }
+
+ // back compatability with Vincent Penne's original class code:
+ if (!p && !strcmp(c,"define_in_struct")) {
+ Fl_Type *t = Fl_Type_make("class");
+ t->name(read_word());
+ Fl_Type::current = p = t;
+ paste = 1; // stops "missing }" error
+ continue;
+ }
+
+ if (!strcmp(c,"header_name")) {
+ header_file_name = strdup(read_word());
+ goto CONTINUE;
+ }
+
+ if (!strcmp(c,"code_name")) {
+ code_file_name = strdup(read_word());
+ goto CONTINUE;
+ }
+
+ for (i=0; i<sizeof(inttable)/sizeof(*inttable); i++) {
+ if (!strcmp(c,inttable[i].name)) {
+ c = read_word();
+ *inttable[i].value = atoi(c);
+ goto CONTINUE;
+ }
+ }
+
+ {Fl_Type *t = Fl_Type_make(c);
+ if (!t) {
+ read_error("Unknown word \"%s\"", c);
+ continue;
+ }
+ t->name(read_word());
+
+ c = read_word(1);
+ if (strcmp(c,"{")) {
+ read_error("Missing property list for %s\n",t->title());
+ goto REUSE_C;
+ }
+
+ t->open_ = 0;
+ for (;;) {
+ const char *c = read_word();
+ if (!c || !strcmp(c,"}")) break;
+ t->read_property(c);
+ }
+
+ if (!t->is_parent()) continue;
+ c = read_word(1);
+ if (strcmp(c,"{")) {
+ read_error("Missing child list for %s\n",t->title());
+ goto REUSE_C;
+ }
+ read_children(t, 0);}
+ Fl_Type::current = p;
+ CONTINUE:;
+ }
+}
+
+extern void deselect();
+
+int read_file(const char *filename, int merge) {
+ read_version = 0.0;
+ if (!open_read(filename)) return 0;
+ if (merge) deselect(); else delete_all();
+ read_children(Fl_Type::current, merge);
+ Fl_Type::current = 0;
+ for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+ if (o->selected) {Fl_Type::current = o; break;}
+ return close_read();
+}
+
+////////////////////////////////////////////////////////////////
+// Read Forms and XForms fdesign files:
+
+int read_fdesign_line(const char*& name, const char*& value) {
+
+ int length = 0;
+ int x;
+ // find a colon:
+ for (;;) {
+ x = getc(fin);
+ if (x < 0) return 0;
+ if (x == '\n') {length = 0; continue;} // no colon this line...
+ if (!isspace(x)) {
+ buffer[length++] = x;
+ expand_buffer(length);
+ }
+ if (x == ':') break;
+ }
+ int valueoffset = length;
+ buffer[length-1] = 0;
+
+ // skip to start of value:
+ for (;;) {
+ x = getc(fin);
+ if (x < 0 || x == '\n' || !isspace(x)) break;
+ }
+
+ // read the value:
+ for (;;) {
+ if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+ else if (x == '\n') break;
+ buffer[length++] = x;
+ expand_buffer(length);
+ x = getc(fin);
+ }
+ buffer[length] = 0;
+ name = buffer;
+ value = buffer+valueoffset;
+ return 1;
+}
+
+int fdesign_flip;
+int fdesign_magic;
+#include <FL/Fl_Group.H>
+
+static const char *class_matcher[] = {
+"FL_CHECKBUTTON", "Fl_Check_Button",
+"FL_ROUNDBUTTON", "Fl_Round_Button",
+"FL_ROUND3DBUTTON", "Fl_Round_Button",
+"FL_LIGHTBUTTON", "Fl_Light_Button",
+"FL_FRAME", "Fl_Box",
+"FL_LABELFRAME", "Fl_Box",
+"FL_TEXT", "Fl_Box",
+"FL_VALSLIDER", "Fl_Value_Slider",
+"FL_MENU", "Fl_Menu_Button",
+"3", "FL_BITMAP",
+"1", "FL_BOX",
+"71","FL_BROWSER",
+"11","FL_BUTTON",
+"4", "FL_CHART",
+"42","FL_CHOICE",
+"61","FL_CLOCK",
+"25","FL_COUNTER",
+"22","FL_DIAL",
+"101","FL_FREE",
+"31","FL_INPUT",
+"12","Fl_Light_Button",
+"41","FL_MENU",
+"23","FL_POSITIONER",
+"13","Fl_Round_Button",
+"21","FL_SLIDER",
+"2", "FL_BOX", // was FL_TEXT
+"62","FL_TIMER",
+"24","Fl_Value_Slider",
+0};
+
+void read_fdesign() {
+ fdesign_magic = atoi(read_word());
+ fdesign_flip = (fdesign_magic < 13000);
+ Fl_Widget_Type *window = 0;
+ Fl_Widget_Type *group = 0;
+ Fl_Widget_Type *widget = 0;
+ if (!Fl_Type::current) {
+ Fl_Type *t = Fl_Type_make("Function");
+ t->name("create_the_forms()");
+ Fl_Type::current = t;
+ }
+ for (;;) {
+ const char *name;
+ const char *value;
+ if (!read_fdesign_line(name, value)) break;
+
+ if (!strcmp(name,"Name")) {
+
+ window = (Fl_Widget_Type*)Fl_Type_make("Fl_Window");
+ window->name(value);
+ window->label(value);
+ Fl_Type::current = widget = window;
+
+ } else if (!strcmp(name,"class")) {
+
+ if (!strcmp(value,"FL_BEGIN_GROUP")) {
+ group = widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Group");
+ Fl_Type::current = group;
+ } else if (!strcmp(value,"FL_END_GROUP")) {
+ if (group) {
+ Fl_Group* g = (Fl_Group*)(group->o);
+ g->begin();
+ g->forms_end();
+ Fl_Group::current(0);
+ }
+ group = widget = 0;
+ Fl_Type::current = window;
+ } else {
+ for (int i = 0; class_matcher[i]; i += 2)
+ if (!strcmp(value,class_matcher[i])) {
+ value = class_matcher[i+1]; break;}
+ widget = (Fl_Widget_Type*)Fl_Type_make(value);
+ if (!widget) {
+ printf("class %s not found, using Fl_Button\n", value);
+ widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Button");
+ }
+ }
+
+ } else if (widget) {
+ if (!widget->read_fdesign(name, value))
+ printf("Ignoring \"%s: %s\"\n", name, value);
+ }
+ }
+}
+
+
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
new file mode 100644
index 000000000..384eb5104
--- /dev/null
+++ b/fluid/fluid.cxx
@@ -0,0 +1,387 @@
+// fluid.C
+
+// Please see README for some information about the construction of this
+// rather nasty piece of code.
+
+const char *copyright =
+"The FLTK user interface designer version 0.99\n"
+"Copyright \xa9 1998 Bill Spitzak\n"
+"\n"
+"This library is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU Library General Public "
+"License as published by the Free Software Foundation; either "
+"version 2 of the License, or (at your option) any later version.\n"
+"\n"
+"This library is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
+"See the GNU Library General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU Library General Public "
+"License along with this library; if not, write to the Free Software "
+"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 "
+"USA.\n"
+"\n"
+"Written by Bill Spitzak spitzak@d2.com\n";
+
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Hold_Browser.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Input.H>
+#include <FL/fl_ask.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_file_chooser.H>
+#include <FL/fl_message.H>
+#include <FL/filename.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#if defined(WIN32) && !defined(CYGNUS)
+# include <direct.h>
+#else
+# include <unistd.h>
+#endif
+
+#include "about_panel.H"
+
+#include "Fl_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+void nyi(Fl_Widget *,void *) {
+ fl_message("That's not yet implemented, sorry");
+}
+
+static const char *filename;
+void set_filename(const char *c);
+int modflag;
+
+static char* pwd;
+static char in_source_dir;
+void goto_source_dir() {
+ if (in_source_dir) return;
+ if (!filename || !*filename) return;
+ const char *p = filename_name(filename);
+ if (p <= filename) return; // it is in the current directory
+ char buffer[1024];
+ strcpy(buffer,filename);
+ int n = p-filename; if (n>1) n--; buffer[n] = 0;
+ if (!pwd) {
+ pwd = getcwd(0,1024);
+ if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;}
+ }
+ if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
+ buffer, strerror(errno)); return;}
+ in_source_dir = 1;
+}
+
+void leave_source_dir() {
+ if (!in_source_dir) return;
+ if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
+ pwd, strerror(errno));}
+ in_source_dir = 0;
+}
+
+Fl_Window *main_window;
+
+void exit_cb(Fl_Widget *,void *) {
+ if (!modflag || fl_ask("Exit without saving changes?")) exit(0);
+}
+
+void save_cb(Fl_Widget *, void *v) {
+ const char *c = filename;
+ if (v || !c || !*c) {
+ if (!(c=fl_file_chooser("Save to:", "*.f[ld]", c))) return;
+ set_filename(c);
+ }
+ if (!write_file(c)) {
+ fl_show_message("Error writing", c, strerror(errno));
+ return;
+ }
+ modflag = 0;
+}
+
+void open_cb(Fl_Widget *, void *v) {
+ if (!v && modflag && !fl_ask("Discard changes?")) return;
+ const char *c;
+ if (!(c = fl_file_chooser("Open:", "*.f[ld]", filename))) return;
+ if (!read_file(c, v!=0)) {
+ fl_show_message("Can't read", c, strerror(errno));
+ return;
+ }
+ if (!v) {set_filename(c); modflag = 0;}
+ else modflag = 1;
+}
+
+void new_cb(Fl_Widget *, void *v) {
+ if (!v && modflag && !fl_ask("Discard changes?")) return;
+ const char *c;
+ if (!(c = fl_file_chooser("New:", "*.f[ld]", 0))) return;
+ delete_all();
+ set_filename(c);
+ modflag = 0;
+}
+
+static int compile_only;
+
+const char* header_file_name = ".H";
+const char* code_file_name = ".C";
+
+void write_cb(Fl_Widget *, void *) {
+ if (!filename) {
+ save_cb(0,0);
+ if (!filename) return;
+ }
+ char cname[1024];
+ char hname[1024];
+ if (*code_file_name == '.') {
+ strcpy(cname,filename_name(filename));
+ filename_setext(cname, code_file_name);
+ } else {
+ strcpy(cname, code_file_name);
+ }
+ if (*header_file_name == '.') {
+ strcpy(hname,filename_name(filename));
+ filename_setext(hname, header_file_name);
+ } else {
+ strcpy(hname, header_file_name);
+ }
+ int x = write_code(cname,hname);
+ strcat(cname, "/"); strcat(cname,header_file_name);
+ if (compile_only) {
+ if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);}
+ } else {
+ if (!x) {
+ fl_show_message("Can't write", cname, strerror(errno));
+ } else {
+ fl_show_message("Wrote", cname, 0);
+ }
+ }
+}
+
+void openwidget_cb(Fl_Widget *, void *) {
+ if (!Fl_Type::current) {
+ fl_message("Please select a widget");
+ return;
+ }
+ Fl_Type::current->open();
+}
+
+void toggle_overlays(Fl_Widget *,void *);
+
+void select_all_cb(Fl_Widget *,void *);
+
+void group_cb(Fl_Widget *, void *);
+
+void ungroup_cb(Fl_Widget *, void *);
+
+extern int pasteoffset;
+static int ipasteoffset;
+
+static char* cutfname() {
+#ifdef WIN32
+ return ".fluid_cut_buffer";
+#else
+ static char name[256] = "~/.fluid_cut_buffer";
+ static char beenhere;
+ if (!beenhere) {beenhere = 1; filename_expand(name,name);}
+ return name;
+#endif
+}
+
+void copy_cb(Fl_Widget*, void*) {
+ if (!Fl_Type::current) return;
+ ipasteoffset = 10;
+ if (!write_file(cutfname(),1)) {
+ fl_show_message("Can't write", cutfname(), strerror(errno));
+ return;
+ }
+}
+
+extern void select_only(Fl_Type *);
+void cut_cb(Fl_Widget *, void *) {
+ if (!Fl_Type::current) return;
+ ipasteoffset = 0;
+ Fl_Type *p = Fl_Type::current->parent;
+ while (p && p->selected) p = p->parent;
+ if (!write_file(cutfname(),1)) {
+ fl_show_message("Can't write", cutfname(), strerror(errno));
+ return;
+ }
+ delete_all(1);
+ if (p) select_only(p);
+}
+
+extern int force_parent, gridx, gridy;
+
+void paste_cb(Fl_Widget*, void*) {
+ if (ipasteoffset) force_parent = 1;
+ pasteoffset = ipasteoffset;
+ if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx;
+ if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy;
+ if (!read_file(cutfname(), 1)) {
+ fl_show_message("Can't read", cutfname(), strerror(errno));
+ }
+ pasteoffset = 0;
+ ipasteoffset += 10;
+ force_parent = 0;
+}
+
+void earlier_cb(Fl_Widget*,void*);
+
+void later_cb(Fl_Widget*,void*);
+
+Fl_Type *sort(Fl_Type *parent);
+
+static void sort_cb(Fl_Widget *,void *) {
+ sort((Fl_Type*)0);
+}
+
+void show_alignment_cb(Fl_Widget *, void *);
+
+void about_cb(Fl_Widget *, void *) {
+ if (!about_panel) make_about_panel(copyright);
+ copyright_box->hide();
+ display_group->show();
+ about_panel->show();
+}
+
+////////////////////////////////////////////////////////////////
+
+extern Fl_Menu_Item New_Menu[];
+
+Fl_Menu_Item Main_Menu[] = {
+{"File",0,0,0,FL_SUBMENU},
+ {"New", FL_ALT+'N', new_cb, 0},
+ {"Open...", FL_ALT+'O', open_cb, 0},
+ {"Save", FL_ALT+'s', save_cb, 0},
+ {"Save As...", FL_ALT+'S', save_cb, (void*)1},
+ {"Merge...", FL_ALT+'i', open_cb, (void*)1, FL_MENU_DIVIDER},
+ {"Write code", FL_ALT+'C', write_cb, 0},
+ {"Quit", FL_ALT+'q', exit_cb},
+ {0},
+{"Edit",0,0,0,FL_SUBMENU},
+ {"Undo", FL_ALT+'z', nyi},
+ {"Cut", FL_ALT+'x', cut_cb},
+ {"Copy", FL_ALT+'c', copy_cb},
+ {"Paste", FL_ALT+'v', paste_cb},
+ {"Select All", FL_ALT+'a', select_all_cb, 0, FL_MENU_DIVIDER},
+ {"Open...", FL_F+1, openwidget_cb},
+ {"Sort",0,sort_cb},
+ {"Earlier", FL_F+2, earlier_cb},
+ {"Later", FL_F+3, later_cb},
+//{"Show", FL_F+5, show_cb},
+//{"Hide", FL_F+6, hide_cb},
+ {"Group", FL_F+7, group_cb},
+ {"Ungroup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER},
+//{"Deactivate", 0, nyi},
+//{"Activate", 0, nyi, 0, FL_MENU_DIVIDER},
+ {"Overlays on/off",FL_ALT+'o',toggle_overlays},
+ {"Preferences",FL_ALT+'p',show_alignment_cb},
+ {0},
+{"New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER},
+{"Help",0,0,0,FL_SUBMENU},
+ {"About fluid",0,about_cb},
+ {"Manual",0,nyi},
+ {0},
+{0}};
+
+#define BROWSERWIDTH 300
+#define BROWSERHEIGHT 500
+#define WINWIDTH 300
+#define MENUHEIGHT 30
+#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT)
+
+extern void fill_in_New_Menu();
+
+void make_main_window() {
+ if (!main_window) {
+ Fl_Widget *o;
+ main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid");
+ main_window->box(FL_NO_BOX);
+ o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT);
+ o->box(FL_FLAT_BOX);
+ main_window->resizable(o);
+ Fl_Menu_Bar *m = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT);
+ m->menu(Main_Menu);
+ m->global();
+ fill_in_New_Menu();
+ main_window->end();
+ }
+}
+
+void set_filename(const char *c) {
+ if (filename) free((void *)filename);
+ filename = strdup(c);
+ if (main_window) main_window->label(filename);
+}
+
+////////////////////////////////////////////////////////////////
+
+static int arg(int argc, char** argv, int& i) {
+ if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;}
+ if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) {
+ code_file_name = argv[i+1]; i += 2; return 2;}
+ if (argv[i][1] == 'h' && !argv[i][2]) {
+ header_file_name = argv[i+1]; i += 2; return 2;}
+ return 0;
+}
+
+#ifndef WIN32
+
+#include <signal.h>
+#ifdef _sigargs
+#define SIGARG _sigargs
+#else
+#ifdef __sigargs
+#define SIGARG __sigargs
+#else
+#define SIGARG int // you may need to fix this for older systems
+#endif
+#endif
+
+static void sigint(SIGARG) {
+ signal(SIGINT,sigint);
+ exit_cb(0,0);
+}
+
+#endif
+
+int main(int argc,char **argv) {
+ int i = 1;
+ if (!Fl::args(argc,argv,i,arg) || i < argc-1) {
+ fprintf(stderr,"usage: %s <switches> name.fl\n"
+" -c : write .C and .H and exit\n"
+" -o <name> : .C output filename, or extension if <name> starts with '.'\n"
+" -h <name> : .H output filename, or extension if <name> starts with '.'\n"
+"%s\n", argv[0], Fl::help);
+ return 1;
+ }
+ const char *c = argv[i];
+ make_main_window();
+ if (c) set_filename(c);
+ if (!compile_only) {
+ Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX));
+ main_window->callback(exit_cb);
+ main_window->show(argc,argv);
+ }
+ if (c && !read_file(c,0)) {
+ if (compile_only) {
+ fprintf(stderr,"%s : %s\n", c, strerror(errno));
+ exit(1);
+ }
+ fl_show_message("Can't read", c, strerror(errno));
+ }
+ if (compile_only) {write_cb(0,0); exit(0);}
+ modflag = 0;
+#ifndef WIN32
+ signal(SIGINT,sigint);
+#endif
+ return Fl::run();
+}
diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx
new file mode 100644
index 000000000..0b6bccd61
--- /dev/null
+++ b/fluid/function_panel.cxx
@@ -0,0 +1,262 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "function_panel.H"
+
+Fl_Window *function_panel;
+
+Fl_Light_Button *f_public_button;
+
+Fl_Input *f_name_input;
+
+Fl_Input *f_return_type_input;
+
+Fl_Return_Button *f_panel_ok;
+
+Fl_Button *f_panel_cancel;
+
+Fl_Window *code_panel;
+
+Fl_Input *code_input;
+
+Fl_Return_Button *code_panel_ok;
+
+Fl_Button *code_panel_cancel;
+
+Fl_Window *codeblock_panel;
+
+Fl_Input *code_before_input;
+
+Fl_Input *code_after_input;
+
+Fl_Return_Button *codeblock_panel_ok;
+
+Fl_Button *codeblock_panel_cancel;
+
+Fl_Window *declblock_panel;
+
+Fl_Input *decl_before_input;
+
+Fl_Input *decl_after_input;
+
+Fl_Return_Button *declblock_panel_ok;
+
+Fl_Button *declblock_panel_cancel;
+
+Fl_Window *decl_panel;
+
+Fl_Light_Button *decl_public_button;
+
+Fl_Input *decl_input;
+
+Fl_Return_Button *decl_panel_ok;
+
+Fl_Button *decl_panel_cancel;
+
+Fl_Window *class_panel;
+
+Fl_Light_Button *c_public_button;
+
+Fl_Input *c_name_input;
+
+Fl_Input *c_subclass_input;
+
+Fl_Return_Button *c_panel_ok;
+
+Fl_Button *c_panel_cancel;
+
+Fl_Window* make_function_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(287, 173, "function/method");
+ w = function_panel = o;
+ w->set_modal();
+ { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public");
+ f_public_button = o;
+ o->labelsize(10);
+ o->when(0);
+ }
+ { Fl_Input* o = new Fl_Input(10, 60, 270, 25, "name(args): (blank for main())");
+ f_name_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Input* o = new Fl_Input(10, 105, 270, 25, "return type: (blank to return outermost widget)");
+ f_return_type_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(110, 140, 80, 25, "OK");
+ f_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(200, 140, 80, 25, "cancel");
+ f_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
+
+Fl_Window* make_code_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(291, 178, "code");
+ w = code_panel = o;
+ w->set_modal();
+ { Fl_Input* o = new Fl_Input(6, 5, 280, 135);
+ code_input = o;
+ o->type(4);
+ o->labelsize(12);
+ o->align(0);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK");
+ code_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel");
+ code_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
+
+Fl_Window* make_codeblock_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(293, 134, "codeblock");
+ w = codeblock_panel = o;
+ w->set_modal();
+ { Fl_Input* o = new Fl_Input(10, 5, 275, 25);
+ code_before_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Box* o = new Fl_Box(10, 35, 270, 25, "\"{...child code...}\" is inserted here");
+ o->align(20);
+ }
+ { Fl_Input* o = new Fl_Input(10, 65, 275, 25);
+ code_after_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(115, 100, 80, 25, "OK");
+ codeblock_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(205, 100, 80, 25, "cancel");
+ codeblock_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
+
+Fl_Window* make_declblock_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(293, 134, "declaration block");
+ w = declblock_panel = o;
+ w->set_modal();
+ { Fl_Input* o = new Fl_Input(15, 10, 275, 25);
+ decl_before_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Box* o = new Fl_Box(15, 40, 270, 25, "\"\\n...child code...\\n\" is inserted here");
+ o->align(20);
+ }
+ { Fl_Input* o = new Fl_Input(15, 70, 275, 25);
+ decl_after_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(120, 105, 80, 25, "OK");
+ declblock_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(210, 105, 80, 25, "cancel");
+ declblock_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
+
+Fl_Window* make_decl_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(290, 176, "declaration");
+ w = decl_panel = o;
+ { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public");
+ decl_public_button = o;
+ o->labelsize(10);
+ o->when(0);
+ }
+ { Fl_Input* o = new Fl_Input(10, 50, 270, 25, "can be any declartion, like \"int x;\",\nan external symbol like \"extern \
+int foo();\",\na #directive like \"#include <foo.h>\",\nor a comment like \"\
+//foo\" or \"/*foo*/\"");
+ decl_input = o;
+ o->labelsize(12);
+ o->align(6);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK");
+ decl_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel");
+ decl_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
+
+Fl_Window* make_class_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(287, 173, "class");
+ w = class_panel = o;
+ w->set_modal();
+ { Fl_Light_Button* o = new Fl_Light_Button(10, 10, 65, 25, "public");
+ c_public_button = o;
+ o->labelsize(10);
+ o->when(0);
+ }
+ { Fl_Input* o = new Fl_Input(10, 55, 270, 25, "name:");
+ c_name_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Input* o = new Fl_Input(10, 100, 270, 25, "subclass of (text between : and {)");
+ c_subclass_input = o;
+ o->labelsize(12);
+ o->align(5);
+ o->when(0);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(110, 135, 80, 25, "OK");
+ c_panel_ok = o;
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(200, 135, 80, 25, "cancel");
+ c_panel_cancel = o;
+ o->shortcut(0xff1b);
+ }
+ w->end();
+ }
+ return w;
+}
diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl
new file mode 100644
index 000000000..e4ad307f1
--- /dev/null
+++ b/fluid/function_panel.fl
@@ -0,0 +1,164 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99
+gridx 10
+gridy 5
+snap 3
+Function {make_function_panel()} {open
+} {
+ Fl_Window function_panel {
+ label {function/method} open
+ xywh {281 608 287 173} modal visible
+ } {
+ Fl_Light_Button f_public_button {
+ label public
+ xywh {10 15 65 25} labelsize 10 when 0
+ }
+ Fl_Input f_name_input {
+ label {name(args): (blank for main())}
+ xywh {10 60 270 25} labelsize 12 align 5 when 0 resizable
+ }
+ Fl_Input f_return_type_input {
+ label {return type: (blank to return outermost widget)}
+ xywh {10 105 270 25} labelsize 12 align 5 when 0
+ }
+ Fl_Return_Button f_panel_ok {
+ label OK
+ xywh {110 140 80 25} hotspot
+ }
+ Fl_Button f_panel_cancel {
+ label cancel
+ xywh {200 140 80 25} shortcut 0xff1b
+ }
+ }
+}
+
+Function {make_code_panel()} {open
+} {
+ Fl_Window code_panel {
+ label code open
+ xywh {256 219 291 178} modal visible
+ } {
+ Fl_Input code_input {
+ xywh {6 5 280 135} type Multiline labelsize 12 align 0 when 0 resizable
+ }
+ Fl_Return_Button code_panel_ok {
+ label OK
+ xywh {115 145 80 25} hotspot
+ }
+ Fl_Button code_panel_cancel {
+ label cancel
+ xywh {205 145 80 25} shortcut 0xff1b
+ }
+ }
+}
+
+Function {make_codeblock_panel()} {open
+} {
+ Fl_Window codeblock_panel {
+ label codeblock open
+ xywh {285 439 293 134} modal visible
+ } {
+ Fl_Input code_before_input {
+ xywh {10 5 275 25} labelsize 12 align 5 when 0 resizable
+ }
+ Fl_Box {} {
+ label {"{...child code...}" is inserted here}
+ xywh {10 35 270 25} align 20
+ }
+ Fl_Input code_after_input {
+ xywh {10 65 275 25} labelsize 12 align 5 when 0
+ }
+ Fl_Return_Button codeblock_panel_ok {
+ label OK
+ xywh {115 100 80 25} hotspot
+ }
+ Fl_Button codeblock_panel_cancel {
+ label cancel
+ xywh {205 100 80 25} shortcut 0xff1b
+ }
+ }
+}
+
+Function {make_declblock_panel()} {open
+} {
+ Fl_Window declblock_panel {
+ label {declaration block} open
+ xywh {296 118 293 134} modal visible
+ } {
+ Fl_Input decl_before_input {
+ xywh {15 10 275 25} labelsize 12 align 5 when 0 resizable
+ }
+ Fl_Box {} {
+ label {"\\n...child code...\\n" is inserted here}
+ xywh {15 40 270 25} align 20
+ }
+ Fl_Input decl_after_input {
+ xywh {15 70 275 25} labelsize 12 align 5 when 0
+ }
+ Fl_Return_Button declblock_panel_ok {
+ label OK
+ xywh {120 105 80 25} hotspot
+ }
+ Fl_Button declblock_panel_cancel {
+ label cancel
+ xywh {210 105 80 25} shortcut 0xff1b
+ }
+ }
+}
+
+Function {make_decl_panel()} {open
+} {
+ Fl_Window decl_panel {
+ label declaration open
+ xywh {278 800 290 176} visible
+ } {
+ Fl_Light_Button decl_public_button {
+ label public
+ xywh {10 15 65 25} labelsize 10 when 0
+ }
+ Fl_Input decl_input {
+ label {can be any declartion, like "int x;",
+an external symbol like "extern int foo();",
+a \#directive like "\#include <foo.h>",
+or a comment like "//foo" or "/*foo*/"}
+ xywh {10 50 270 25} labelsize 12 align 6 when 0 resizable
+ }
+ Fl_Return_Button decl_panel_ok {
+ label OK
+ xywh {115 145 80 25} hotspot
+ }
+ Fl_Button decl_panel_cancel {
+ label cancel
+ xywh {205 145 80 25} shortcut 0xff1b
+ }
+ }
+}
+
+Function {make_class_panel()} {open
+} {
+ Fl_Window class_panel {
+ label class open selected
+ xywh {291 618 287 173} modal visible
+ } {
+ Fl_Light_Button c_public_button {
+ label public
+ xywh {10 10 65 25} labelsize 10 when 0
+ }
+ Fl_Input c_name_input {
+ label {name:}
+ xywh {10 55 270 25} labelsize 12 align 5 when 0 resizable
+ }
+ Fl_Input c_subclass_input {
+ label {subclass of (text between : and \{)}
+ xywh {10 100 270 25} labelsize 12 align 5 when 0
+ }
+ Fl_Return_Button c_panel_ok {
+ label OK
+ xywh {110 135 80 25} hotspot
+ }
+ Fl_Button c_panel_cancel {
+ label cancel
+ xywh {200 135 80 25} shortcut 0xff1b
+ }
+ }
+}
diff --git a/fluid/function_panel.h b/fluid/function_panel.h
new file mode 100644
index 000000000..f0a9d2506
--- /dev/null
+++ b/fluid/function_panel.h
@@ -0,0 +1,46 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Window.H>
+extern Fl_Window *function_panel;
+extern Fl_Light_Button *f_public_button;
+extern Fl_Input *f_name_input;
+extern Fl_Input *f_return_type_input;
+extern Fl_Return_Button *f_panel_ok;
+extern Fl_Button *f_panel_cancel;
+extern Fl_Window *code_panel;
+extern Fl_Input *code_input;
+extern Fl_Return_Button *code_panel_ok;
+extern Fl_Button *code_panel_cancel;
+extern Fl_Window *codeblock_panel;
+extern Fl_Input *code_before_input;
+extern Fl_Input *code_after_input;
+extern Fl_Return_Button *codeblock_panel_ok;
+extern Fl_Button *codeblock_panel_cancel;
+extern Fl_Window *declblock_panel;
+extern Fl_Input *decl_before_input;
+extern Fl_Input *decl_after_input;
+extern Fl_Return_Button *declblock_panel_ok;
+extern Fl_Button *declblock_panel_cancel;
+extern Fl_Window *decl_panel;
+extern Fl_Light_Button *decl_public_button;
+extern Fl_Input *decl_input;
+extern Fl_Return_Button *decl_panel_ok;
+extern Fl_Button *decl_panel_cancel;
+extern Fl_Window *class_panel;
+extern Fl_Light_Button *c_public_button;
+extern Fl_Input *c_name_input;
+extern Fl_Input *c_subclass_input;
+extern Fl_Return_Button *c_panel_ok;
+extern Fl_Button *c_panel_cancel;
+Fl_Window* make_function_panel();
+Fl_Window* make_code_panel();
+Fl_Window* make_codeblock_panel();
+Fl_Window* make_declblock_panel();
+Fl_Window* make_decl_panel();
+Fl_Window* make_class_panel();
diff --git a/fluid/gif.cxx b/fluid/gif.cxx
new file mode 100644
index 000000000..1af6556a7
--- /dev/null
+++ b/fluid/gif.cxx
@@ -0,0 +1,336 @@
+// gif.C
+
+// Read a .gif file and convert it to a "xpm" format (actually my
+// modified one with compressed colormaps).
+
+// Extensively modified from original code for gif2ras by
+// Patrick J. Naughton of Sun Microsystems. The original
+// copyright notice follows:
+
+/* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
+ *
+ * Copyright (c) 1988 by Patrick J. Naughton
+ *
+ * Author: Patrick J. Naughton
+ * naughton@wind.sun.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ * Patrick J. Naughton
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Ave, MS 14-40
+ * Mountain View, CA 94043
+ * (415) 336-1080
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+#define NEXTBYTE getc(GifFile)
+#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8
+
+int gif2xpm(
+ const char *infname,// filename for error messages
+ FILE *GifFile, // file to read
+ char*** datap, // return xpm data here
+ int** lengthp, // return line lengths here
+ int inumber // which image in movie (0 = first)
+) {
+
+ {char b[6];
+ if (fread(b,1,6,GifFile)<6) return 0; /* quit on eof */
+ if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
+ fprintf(stderr,"%s is not a GIF file.\n", infname); return 0;}
+ if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
+ fprintf(stderr,"%s is version %c%c%c.\n",infname,b[3],b[4],b[5]);
+ }
+
+ int Width; GETSHORT(Width);
+ int Height; GETSHORT(Height);
+
+ uchar ch = NEXTBYTE;
+ char HasColormap = ((ch & 0x80) != 0);
+ int BitsPerPixel = (ch & 7) + 1;
+ int ColorMapSize = 1 << BitsPerPixel;
+ // int OriginalResolution = ((ch>>4)&7)+1;
+ // int SortedTable = (ch&8)!=0;
+ NEXTBYTE; // Background Color index
+ NEXTBYTE; // Aspect ratio is N/64
+
+ // Read in global colormap:
+ uchar transparent_pixel = 0;
+ char has_transparent = 0;
+ uchar Red[256], Green[256], Blue[256]; /* color map */
+ if (HasColormap) {
+ for (int i=0; i < ColorMapSize; i++) {
+ Red[i] = NEXTBYTE;
+ Green[i] = NEXTBYTE;
+ Blue[i] = NEXTBYTE;
+ }
+ } else {
+ fprintf(stderr,"%s does not have a colormap.\n", infname);
+ for (int i = 0; i < ColorMapSize; i++)
+ Red[i] = Green[i] = Blue[i] = (i*256+ColorMapSize-1)/ColorMapSize;
+ }
+
+ int CodeSize; /* Code size, init from GIF header, increases... */
+ char Interlace;
+
+ for (;;) {
+
+ int i = NEXTBYTE;
+ if (i<0) {fprintf(stderr,"%s: unexpected EOF\n",infname); return 0;}
+ int blocklen;
+
+ // if (i == 0x3B) return 0; eof code
+
+ if (i == 0x21) { // a "gif extension"
+
+ ch = NEXTBYTE;
+ blocklen = NEXTBYTE;
+
+ if (ch==0xF9 && blocklen==4) { // Netscape animation extension
+
+ char bits;
+ bits = NEXTBYTE;
+ NEXTBYTE; NEXTBYTE; // GETSHORT(delay);
+ transparent_pixel = NEXTBYTE;
+ if (bits & 1) has_transparent = 1;
+ blocklen = NEXTBYTE;
+
+ } else if (ch == 0xFF) { // Netscape repeat count
+ ;
+
+ } else if (ch == 0xFE) { //Gif Comment
+#if 0
+ if(blocklen>0) {
+ char *comment=new char[blocklen+1];
+ int l;
+ for(l=0;blocklen;l++,blocklen--)
+ comment[l]=NEXTBYTE;
+ comment[l]=0;
+ fprintf(stderr,"%s: Gif Comment: '%s'\n", infname, comment);
+ delete comment;
+ NEXTBYTE; //End marker
+ }
+#endif
+ } else {
+ fprintf(stderr,"%s: unknown gif extension 0x%02x\n", infname, ch);
+
+ }
+
+ } else if (i == 0x2c) { // an image
+
+ NEXTBYTE; NEXTBYTE; // GETSHORT(x_position);
+ NEXTBYTE; NEXTBYTE; // GETSHORT(y_position);
+ GETSHORT(Width);
+ GETSHORT(Height);
+ ch = NEXTBYTE;
+ Interlace = ((ch & 0x40) != 0);
+ if (ch&0x80) {
+ // read local color map
+ int n = 1<<((ch&7)+1); // does this replace ColorMapSize ??
+ for (i=0; i < n; i++) {
+ Red[i] = NEXTBYTE;
+ Green[i] = NEXTBYTE;
+ Blue[i] = NEXTBYTE;
+ }
+ }
+ CodeSize = NEXTBYTE+1;
+
+ if (!inumber--) break; // okay, this is the image we want
+ blocklen = NEXTBYTE;
+
+ } else {
+ fprintf(stderr,"%s: unknown gif code 0x%02x\n", infname, i);
+ blocklen = 0;
+ }
+
+ // skip the data:
+ while (blocklen>0) {while (blocklen--) {NEXTBYTE;} blocklen=NEXTBYTE;}
+ }
+
+ uchar *Image = new uchar[Width*Height];
+ if (!Image) {
+ fprintf (stderr, "Insufficient memory\n");
+ exit (2);
+ }
+ int YC = 0, Pass = 0; /* Used to de-interlace the picture */
+ uchar *p = Image;
+ uchar *eol = p+Width;
+
+ int InitCodeSize = CodeSize;
+ int ClearCode = (1 << (CodeSize-1));
+ int EOFCode = ClearCode + 1;
+ int FirstFree = ClearCode + 2;
+ int FinChar = 0;
+ int ReadMask = (1<<CodeSize) - 1;
+ int FreeCode = FirstFree;
+ int OldCode = ClearCode;
+
+ // tables used by LZW decompresser:
+ short int Prefix[4096];
+ uchar Suffix[4096];
+
+ int blocklen = NEXTBYTE;
+ uchar thisbyte = NEXTBYTE; blocklen--;
+ int frombit = 0;
+
+ for (;;) {
+
+/* Fetch the next code from the raster data stream. The codes can be
+ * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
+ * maintain our location as a pointer and a bit offset.
+ * In addition, gif adds totally useless and annoying block counts
+ * that must be correctly skipped over. */
+ int CurCode = thisbyte;
+ if (frombit+CodeSize > 7) {
+ if (blocklen <= 0) {
+ blocklen = NEXTBYTE;
+ if (blocklen <= 0) break;
+ }
+ thisbyte = NEXTBYTE; blocklen--;
+ CurCode |= thisbyte<<8;
+ }
+ if (frombit+CodeSize > 15) {
+ if (blocklen <= 0) {
+ blocklen = NEXTBYTE;
+ if (blocklen <= 0) break;
+ }
+ thisbyte = NEXTBYTE; blocklen--;
+ CurCode |= thisbyte<<16;
+ }
+ CurCode = (CurCode>>frombit)&ReadMask;
+ frombit = (frombit+CodeSize)%8;
+
+ if (CurCode == ClearCode) {
+ CodeSize = InitCodeSize;
+ ReadMask = (1<<CodeSize) - 1;
+ FreeCode = FirstFree;
+ OldCode = ClearCode;
+ continue;
+ }
+
+ if (CurCode == EOFCode) break;
+
+ uchar OutCode[1025]; // temporary array for reversing codes
+ uchar *tp = OutCode;
+ int i;
+ if (CurCode < FreeCode) i = CurCode;
+ else if (CurCode == FreeCode) {*tp++ = FinChar; i = OldCode;}
+ else {fprintf(stderr,"%s : LZW Barf!\n",infname); break;}
+
+ while (i >= ColorMapSize) {*tp++ = Suffix[i]; i = Prefix[i];}
+ *tp++ = FinChar = i;
+ while (tp > OutCode) {
+ *p++ = *--tp;
+ if (p >= eol) {
+ if (!Interlace) YC++;
+ else switch (Pass) {
+ case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break;
+ case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break;
+ case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break;
+ case 3: YC += 2; break;
+ }
+ if (YC>=Height) YC=0; /* cheap bug fix when excess data */
+ p = Image + YC*Width;
+ eol = p+Width;
+ }
+ }
+
+ if (OldCode != ClearCode) {
+ Prefix[FreeCode] = OldCode;
+ Suffix[FreeCode] = FinChar;
+ FreeCode++;
+ if (FreeCode > ReadMask) {
+ if (CodeSize < 12) {
+ CodeSize++;
+ ReadMask = (1 << CodeSize) - 1;
+ }
+ else FreeCode--;
+ }
+ }
+ OldCode = CurCode;
+ }
+
+ // We are done reading the file, now convert to xpm:
+
+ // allocate line pointer arrays:
+ char** data = new char*[Height+3];
+ *datap = data;
+ int* length = new int[Height+2];
+ *lengthp = length;
+
+ // transparent pixel must be zero, swap if it isn't:
+ if (has_transparent && transparent_pixel != 0) {
+ // swap transparent pixel with zero
+ p = Image+Width*Height;
+ while (p-- > Image) {
+ if (*p==transparent_pixel) *p = 0;
+ else if (!*p) *p = transparent_pixel;
+ }
+ uchar t;
+ t = Red[0]; Red[0] = Red[transparent_pixel]; Red[transparent_pixel] = t;
+ t =Green[0];Green[0]=Green[transparent_pixel];Green[transparent_pixel]=t;
+ t =Blue[0];Blue[0] =Blue[transparent_pixel];Blue[transparent_pixel] = t;
+ }
+
+ // find out what colors are actually used:
+ uchar used[256]; uchar remap[256];
+ int i;
+ for (i = 0; i < ColorMapSize; i++) used[i] = 0;
+ p = Image+Width*Height;
+ while (p-- > Image) used[*p] = 1;
+
+ // remap them to start with printing characters:
+ int base = has_transparent && used[0] ? ' ' : ' '+1;
+ int numcolors = 0;
+ for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+ remap[i] = base++;
+ numcolors++;
+ }
+
+ // write the first line of xpm data (use suffix as temp array):
+ length[0] = sprintf((char*)(Suffix),
+ "%d %d %d %d",Width,Height,-numcolors,1);
+ data[0] = new char[length[0]+1];
+ strcpy(data[0], (char*)Suffix);
+
+ // write the colormap
+ length[1] = 4*numcolors;
+ data[1] = (char*)(p = new uchar[4*numcolors]);
+ for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+ *p++ = remap[i];
+ *p++ = Red[i];
+ *p++ = Green[i];
+ *p++ = Blue[i];
+ }
+
+ // remap the image data:
+ p = Image+Width*Height;
+ while (p-- > Image) *p = remap[*p];
+
+ // split the image data into lines:
+ for (i=0; i<Height; i++) {
+ data[i+2] = (char*)(Image + i*Width);
+ length[i+2] = Width;
+ }
+
+ data[Height+2] = 0; // null to end string array
+ return 1;
+}
diff --git a/fluid/keyboard_ui.cxx b/fluid/keyboard_ui.cxx
new file mode 100644
index 000000000..7c7b65ae6
--- /dev/null
+++ b/fluid/keyboard_ui.cxx
@@ -0,0 +1,536 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "keyboard_ui.H"
+
+Fl_Window *make_window() {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(494, 193);
+ w = o;
+ }
+ {Fl_Button* o = new Fl_Button(15, 50, 20, 20, "Esc");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Escape));
+ }
+ {Fl_Button* o = new Fl_Button(50, 50, 20, 20, "F1");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+1));
+ }
+ {Fl_Button* o = new Fl_Button(70, 50, 20, 20, "F2");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+2));
+ }
+ {Fl_Button* o = new Fl_Button(90, 50, 20, 20, "F3");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+3));
+ }
+ {Fl_Button* o = new Fl_Button(110, 50, 20, 20, "F4");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+4));
+ }
+ {Fl_Button* o = new Fl_Button(140, 50, 20, 20, "F5");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+5));
+ }
+ {Fl_Button* o = new Fl_Button(160, 50, 20, 20, "F6");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+6));
+ }
+ {Fl_Button* o = new Fl_Button(180, 50, 20, 20, "F7");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+7));
+ }
+ {Fl_Button* o = new Fl_Button(200, 50, 20, 20, "F8");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+8));
+ }
+ {Fl_Button* o = new Fl_Button(230, 50, 20, 20, "F9");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+9));
+ }
+ {Fl_Button* o = new Fl_Button(250, 50, 20, 20, "F10");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+10));
+ }
+ {Fl_Button* o = new Fl_Button(270, 50, 20, 20, "F11");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+11));
+ }
+ {Fl_Button* o = new Fl_Button(290, 50, 20, 20, "F12");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_F+12));
+ }
+ {Fl_Button* o = new Fl_Button(325, 50, 20, 20, "Print");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Print));
+ }
+ {Fl_Button* o = new Fl_Button(345, 50, 20, 20, "Sclk");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Scroll_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(365, 50, 20, 20, "Paus");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Pause));
+ }
+ {Fl_Button* o = new Fl_Button(15, 80, 20, 20, "`");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(35, 80, 20, 20, "1");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(55, 80, 20, 20, "2");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(75, 80, 20, 20, "3");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(95, 80, 20, 20, "4");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(115, 80, 20, 20, "5");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(135, 80, 20, 20, "6");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(155, 80, 20, 20, "7");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(175, 80, 20, 20, "8");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(195, 80, 20, 20, "9");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(215, 80, 20, 20, "0");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(235, 80, 20, 20, "-");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(255, 80, 20, 20, "=");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(275, 80, 35, 20, "Bksp");
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_BackSpace));
+ }
+ {Fl_Button* o = new Fl_Button(325, 80, 20, 20, "Ins");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Insert));
+ }
+ {Fl_Button* o = new Fl_Button(345, 80, 20, 20, "Home");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Home));
+ }
+ {Fl_Button* o = new Fl_Button(365, 80, 20, 20, "pgup");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 80, 20, 20, "Num");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Num_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(420, 80, 20, 20, "/");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'/'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 80, 20, 20, "*");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'*'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 80, 20, 20, "-");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'-'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 100, 27, 20, "Tab");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Tab));
+ }
+ {Fl_Button* o = new Fl_Button(42, 100, 20, 20, "Q");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(62, 100, 20, 20, "W");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(82, 100, 20, 20, "E");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(102, 100, 20, 20, "R");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(122, 100, 20, 20, "T");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(142, 100, 20, 20, "Y");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(162, 100, 20, 20, "U");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(182, 100, 20, 20, "I");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(202, 100, 20, 20, "O");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(222, 100, 20, 20, "P");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(242, 100, 20, 20, "[");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(262, 100, 20, 20, "]");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(282, 100, 28, 20, "\\");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)('|'));
+ o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(325, 100, 20, 20, "Del");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Delete));
+ }
+ {Fl_Button* o = new Fl_Button(345, 100, 20, 20, "End");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_End));
+ }
+ {Fl_Button* o = new Fl_Button(365, 100, 20, 20, "pgdn");
+ o->labelsize(8);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Down));
+ }
+ {Fl_Button* o = new Fl_Button(400, 100, 20, 20, "7");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'7'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 100, 20, 20, "8");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'8'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 100, 20, 20, "9");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'9'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 100, 20, 40, "+");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'+'));
+ o->align(17);
+ }
+ {Fl_Button* o = new Fl_Button(15, 120, 36, 20, "Lock");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Caps_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(51, 120, 20, 20, "A");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(71, 120, 20, 20, "S");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(91, 120, 20, 20, "D");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(111, 120, 20, 20, "F");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(131, 120, 20, 20, "G");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(151, 120, 20, 20, "H");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(171, 120, 20, 20, "J");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(191, 120, 20, 20, "K");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(211, 120, 20, 20, "L");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(231, 120, 20, 20, ";");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(251, 120, 20, 20, "\'");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(271, 120, 39, 20, "Enter");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Enter));
+ }
+ {Fl_Button* o = new Fl_Button(400, 120, 20, 20, "4");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'4'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 120, 20, 20, "5");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'5'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 120, 20, 20, "6");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'6'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 140, 45, 20, "Shift");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_L));
+ }
+ {Fl_Button* o = new Fl_Button(60, 140, 20, 20, "Z");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(80, 140, 20, 20, "X");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(100, 140, 20, 20, "C");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(120, 140, 20, 20, "V");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(140, 140, 20, 20, "B");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(160, 140, 20, 20, "N");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(180, 140, 20, 20, "M");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(200, 140, 20, 20, ",");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(220, 140, 20, 20, ".");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(240, 140, 20, 20, "/");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(260, 140, 50, 20, "Shift");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_R));
+ }
+ {Fl_Button* o = new Fl_Button(345, 140, 20, 20, "@8->");
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelsize(10);
+ o->labelcolor(47);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 140, 20, 20, "1");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'1'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 140, 20, 20, "2");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'2'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 140, 20, 20, "3");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'3'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 140, 20, 40);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP_Enter));
+ }
+ {Fl_Button* o = new Fl_Button(15, 160, 30, 20, "Ctrl");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_L));
+ }
+ {Fl_Button* o = new Fl_Button(45, 160, 30, 20, "Meta");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_L));
+ }
+ {Fl_Button* o = new Fl_Button(75, 160, 30, 20, "Alt");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_L));
+ }
+ {Fl_Button* o = new Fl_Button(105, 160, 85, 20);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(' '));
+ }
+ {Fl_Button* o = new Fl_Button(190, 160, 30, 20, "Alt");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_R));
+ }
+ {Fl_Button* o = new Fl_Button(220, 160, 30, 20, "Meta");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_R));
+ }
+ {Fl_Button* o = new Fl_Button(250, 160, 30, 20, "Menu");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Menu));
+ }
+ {Fl_Button* o = new Fl_Button(280, 160, 30, 20, "Ctrl");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_R));
+ }
+ {Fl_Button* o = new Fl_Button(325, 160, 20, 20, "@4->");
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelsize(10);
+ o->labelcolor(47);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Left));
+ }
+ {Fl_Button* o = new Fl_Button(345, 160, 20, 20, "@2->");
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelsize(10);
+ o->labelcolor(47);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Down));
+ }
+ {Fl_Button* o = new Fl_Button(365, 160, 20, 20, "@6->");
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelsize(10);
+ o->labelcolor(47);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_Right));
+ }
+ {Fl_Button* o = new Fl_Button(400, 160, 40, 20, "0");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'0'));
+ o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(440, 160, 20, 20, ".");
+ o->labelsize(10);
+ o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'.'));
+ }
+ {Fl_Input* o = new Fl_Input(15, 10, 370, 30);
+ }
+ {Fl_Button* o = new Fl_Button(400, 5, 20, 10, "shift");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_SHIFT));
+ }
+ {Fl_Button* o = new Fl_Button(420, 5, 20, 10, "lock");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_CAPS_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(440, 5, 20, 10, "ctrl");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_CTRL));
+ }
+ {Fl_Button* o = new Fl_Button(460, 5, 20, 10, "alt");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_ALT));
+ }
+ {Fl_Button* o = new Fl_Button(440, 15, 20, 10, "meta");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_META));
+ }
+ {Fl_Button* o = new Fl_Button(420, 15, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x20));
+ }
+ {Fl_Button* o = new Fl_Button(400, 15, 20, 10, "num");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_NUM_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(400, 25, 20, 10, "b1");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON1));
+ }
+ {Fl_Button* o = new Fl_Button(420, 25, 20, 10, "b2");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON2));
+ }
+ {Fl_Button* o = new Fl_Button(440, 25, 20, 10, "b3");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON3));
+ }
+ {Fl_Button* o = new Fl_Button(460, 15, 20, 10, "sclk");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(FL_SCROLL_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(460, 25, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x800));
+ }
+ {Fl_Button* o = new Fl_Button(400, 35, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x1000));
+ }
+ {Fl_Button* o = new Fl_Button(420, 35, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x2000));
+ }
+ {Fl_Button* o = new Fl_Button(440, 35, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x4000));
+ }
+ {Fl_Button* o = new Fl_Button(460, 35, 20, 10, "?");
+ o->box(FL_THIN_UP_BOX);
+ o->color2(3);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)shift_cb, (void*)(0x8000));
+ }
+ w->end();
+ return w;
+}
diff --git a/fluid/keyboard_ui.h b/fluid/keyboard_ui.h
new file mode 100644
index 000000000..ec1ba7722
--- /dev/null
+++ b/fluid/keyboard_ui.h
@@ -0,0 +1,8 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include <FL/Fl.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Window.H>
+extern void key_cb(Fl_Button*, void*);
+extern void shift_cb(Fl_Button*, void*);
+Fl_Window *make_window();
diff --git a/fluid/penne.C b/fluid/penne.C
new file mode 100644
index 000000000..cc1db0937
--- /dev/null
+++ b/fluid/penne.C
@@ -0,0 +1,85 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "penne.H"
+
+inline void UserInterface::cb_New_i(Fl_Button*, void*) {
+ new UserInterface;
+}
+void UserInterface::cb_New(Fl_Button* o, void* v) {
+ ((UserInterface*)(o->parent()->user_data()))->cb_New_i(o,v);
+}
+
+inline void UserInterface::cb_Delete_i(Fl_Button*, void*) {
+ delete this;
+}
+void UserInterface::cb_Delete(Fl_Button* o, void* v) {
+ ((UserInterface*)(o->parent()->user_data()))->cb_Delete_i(o,v);
+}
+
+inline void UserInterface::cb_button1_i(Fl_Light_Button* o, void*) {
+ Button->value(o->value());
+}
+void UserInterface::cb_button1(Fl_Light_Button* o, void* v) {
+ ((UserInterface*)(o->parent()->user_data()))->cb_button1_i(o,v);
+}
+
+inline void UserInterface::cb_When_i(Fl_Menu_* o, void*) {
+ Button->value(o->value());
+}
+void UserInterface::cb_When(Fl_Menu_* o, void* v) {
+ ((UserInterface*)(o->parent()->user_data()))->cb_When_i(o,v);
+}
+
+Fl_Menu_Item UserInterface::menu_[] = {
+ {"coucou", 0, 0, 0, 64, 0, 3, 14, 0},
+ {"When you press this, it should crash !", 0, (Fl_Callback*)UserInterface::cb_When, 0, 2, 0, 3, 14, 0},
+ {0},
+ {0}
+};
+
+UserInterface::UserInterface() {
+ Fl_Window *w;
+ { Fl_Window* o = new Fl_Window(375, 199);
+ w = Win = o;
+ o->user_data((void*)(this));
+ { Fl_Button* o = new Fl_Button(35, 145, 120, 35, "New window");
+ o->callback((Fl_Callback*)cb_New);
+ }
+ { Fl_Button* o = new Fl_Button(215, 145, 120, 35, "Delete window");
+ o->callback((Fl_Callback*)cb_Delete);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(45, 25, 95, 25, "button1");
+ o->callback((Fl_Callback*)cb_button1);
+ }
+ { Fl_Check_Button* o = new Fl_Check_Button(220, 25, 95, 25, "button2");
+ Button = o;
+ o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+ { Fl_Tile* o = new Fl_Tile(110, 55, 165, 80);
+ { Fl_Box* o = new Fl_Box(110, 55, 165, 50, "label");
+ o->box(FL_DOWN_BOX);
+ }
+ { Fl_Box* o = new Fl_Box(110, 105, 80, 30, "label");
+ o->box(FL_DOWN_BOX);
+ }
+ { Fl_Box* o = new Fl_Box(190, 105, 85, 30, "label");
+ o->box(FL_DOWN_BOX);
+ }
+ o->end();
+ }
+ { Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, 375, 25);
+ o->menu(menu_);
+ }
+ w->end();
+ }
+ Win->show();
+}
+
+UserInterface::~UserInterface() {
+ delete Win;
+}
+
+int main() {
+ new UserInterface;
+return Fl::run();
+}
diff --git a/fluid/penne.H b/fluid/penne.H
new file mode 100644
index 000000000..ebabab473
--- /dev/null
+++ b/fluid/penne.H
@@ -0,0 +1,32 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Window.H>
+
+class UserInterface {
+public:
+ UserInterface();
+ Fl_Window *Win;
+private:
+ inline void cb_New_i(Fl_Button*, void*);
+ static void cb_New(Fl_Button*, void*);
+ inline void cb_Delete_i(Fl_Button*, void*);
+ static void cb_Delete(Fl_Button*, void*);
+ inline void cb_button1_i(Fl_Light_Button*, void*);
+ static void cb_button1(Fl_Light_Button*, void*);
+public:
+ Fl_Check_Button *Button;
+ static Fl_Menu_Item menu_[];
+private:
+ inline void cb_When_i(Fl_Menu_*, void*);
+ static void cb_When(Fl_Menu_*, void*);
+public:
+ ~UserInterface();
+};
+int main();
diff --git a/fluid/primes.fl b/fluid/primes.fl
new file mode 100644
index 000000000..e221b739a
--- /dev/null
+++ b/fluid/primes.fl
@@ -0,0 +1,22 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99
+gridx 10
+gridy 10
+snap 3
+decl {// This is a demo of fluid used to write a normal C program} {}
+
+decl {\#include <stdio.h>} {}
+
+Function {main()} {open selected
+} {
+ code {printf("%d ", 2);} {}
+ codeblock {for (int x=3; x < 10000; x += 2)} {open
+ } {
+ code {for (int y=3; x%y; y += 2)} {}
+ codeblock {if (y*y > x)} {open
+ } {
+ code {printf("%d ", x);
+break;} {}
+ }
+ }
+}
diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx
new file mode 100644
index 000000000..23ee01e19
--- /dev/null
+++ b/fluid/widget_panel.cxx
@@ -0,0 +1,316 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "widget_panel.H"
+
+Fl_Input *v_input[4];
+
+Fl_Window* make_widget_panel() {
+ Fl_Window *w;
+ { Fl_Window* o = w = new Fl_Window(370, 480);
+ w->hotspot(o);
+ { Fl_Input* o = new Fl_Input(90, 10, 210, 20, "name:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)name_cb);
+ o->when(0);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(300, 10, 60, 20, "public");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)name_public_cb);
+ o->when(1);
+ }
+ { Fl_Input* o = new Fl_Input(90, 35, 170, 20, "class:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)subclass_cb, (void*)(4));
+ o->when(0);
+ }
+ { Fl_Choice* o = new Fl_Choice(260, 35, 100, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)subtype_cb);
+ }
+ { Fl_Input* o = new Fl_Input(90, 60, 270, 20, "label:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)label_cb);
+ o->when(1);
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 80, 150, 20, "labeltype:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)labeltype_cb);
+ o->menu(labeltypemenu);
+ }
+ { Fl_Button* o = new Fl_Button(240, 80, 20, 20, "@-1<-");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_LEFT));
+ }
+ { Fl_Button* o = new Fl_Button(260, 80, 20, 20, "@-1->");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_RIGHT));
+ }
+ { Fl_Button* o = new Fl_Button(280, 80, 20, 20, "@-18");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_TOP));
+ }
+ { Fl_Button* o = new Fl_Button(300, 80, 20, 20, "@-12");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_BOTTOM));
+ }
+ { Fl_Button* o = new Fl_Button(320, 80, 20, 20, "@-3square");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_INSIDE));
+ }
+ { Fl_Button* o = new Fl_Button(340, 80, 20, 10, "wrap");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_WRAP));
+ }
+ { Fl_Button* o = new Fl_Button(340, 90, 20, 10, "clip");
+ o->type(1);
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_CLIP));
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 100, 170, 20, "labelfont:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)labelfont_cb);
+ o->menu(fontmenu);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(260, 100, 50, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->maximum(100);
+ o->step(1);
+ o->value(14);
+ o->callback((Fl_Callback*)labelsize_cb);
+ }
+ { Fl_Button* o = new Fl_Button(310, 100, 50, 20, "labelcolor");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)labelcolor_cb);
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 125, 220, 20, "box:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)box_cb);
+ o->menu(boxmenu);
+ }
+ { Fl_Button* o = new Fl_Button(310, 125, 50, 20, "color");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)color_cb);
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 145, 220, 20, "down_box:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)down_box_cb);
+ o->menu(boxmenu);
+ }
+ { Fl_Button* o = new Fl_Button(310, 145, 50, 20, "select color");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)color2_cb);
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 170, 170, 20, "textfont:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)textfont_cb);
+ o->hide();
+ o->menu(fontmenu);
+ }
+ { Fl_Input* o = new Fl_Input(90, 170, 170, 20, "xclass:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)xclass_cb);
+ o->when(0);
+ }
+ { Shortcut_Button* o = new Shortcut_Button(90, 170, 270, 20, "shortcut:");
+ o->box(FL_THIN_UP_BOX);
+ o->color(7);
+ o->selection_color(7);
+ o->callback((Fl_Callback*)shortcut_in_cb);
+ o->align(4);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(260, 170, 50, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->maximum(100);
+ o->step(1);
+ o->value(14);
+ o->callback((Fl_Callback*)textsize_cb);
+ o->hide();
+ }
+ { Fl_Button* o = new Fl_Button(310, 170, 50, 20, "textcolor");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)textcolor_cb);
+ o->hide();
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(20, 205, 60, 20, "size:");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->step(0.010101);
+ o->callback((Fl_Callback*)slider_size_cb);
+ o->align(5);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(90, 205, 60, 20, "minimum:");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)min_cb);
+ o->align(5);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(160, 205, 60, 20, "maximum:");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->value(1);
+ o->callback((Fl_Callback*)max_cb);
+ o->align(5);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(230, 205, 60, 20, "step:");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)step_cb);
+ o->align(5);
+ }
+ { Fl_Value_Input* o = new Fl_Value_Input(300, 205, 60, 20, "value:");
+ o->box(FL_THIN_UP_BOX);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)value_cb);
+ o->align(5);
+ }
+ { Fl_Group* o = new Fl_Group(20, 230, 340, 20);
+ o->callback((Fl_Callback*)propagate_load);
+ o->align(5);
+ { Fl_Light_Button* o = new Fl_Light_Button(20, 230, 70, 20, "non_modal");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(9);
+ o->callback((Fl_Callback*)non_modal_cb);
+ o->align(148);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "visible");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)visible_cb);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "modal");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)modal_cb);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "active");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)active_cb);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "border");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)border_cb);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(230, 230, 60, 20, "resizable");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)resizable_cb);
+ o->when(1);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(300, 230, 60, 20, "hotspot");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)hotspot_cb);
+ o->when(1);
+ }
+ o->end();
+ }
+ { Fl_Input* o = v_input[0] = new Fl_Input(90, 260, 270, 20, "extra code:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)v_input_cb, (void*)(0));
+ o->when(0);
+ }
+ { Fl_Input* o = v_input[1] = new Fl_Input(90, 280, 270, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)v_input_cb, (void*)(1));
+ o->when(0);
+ }
+ { Fl_Input* o = v_input[2] = new Fl_Input(90, 300, 270, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)v_input_cb, (void*)(2));
+ o->when(0);
+ }
+ { Fl_Input* o = v_input[3] = new Fl_Input(90, 320, 270, 20);
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)v_input_cb, (void*)(3));
+ o->when(0);
+ }
+ { Fl_Box* o = new Fl_Box(0, 350, 90, 20, "callback:");
+ o->align(24);
+ }
+ { Fl_Input* o = new Fl_Input(90, 350, 270, 50);
+ o->type(4);
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)callback_cb);
+ o->when(0);
+ }
+ { Fl_Box* o = new Fl_Box(90, 370, 100, 30, "label");
+ o->hide();
+ o->deactivate();
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Input* o = new Fl_Input(90, 400, 170, 20, "user_data:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)user_data_cb);
+ o->when(0);
+ }
+ { Fl_Input* o = new Fl_Input(300, 400, 60, 20, "type:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)user_data_type_cb);
+ o->when(0);
+ }
+ { Fl_Choice* o = new Fl_Choice(90, 420, 100, 20, "when:");
+ o->box(FL_THIN_UP_BOX);
+ o->callback((Fl_Callback*)when_cb);
+ o->when(0);
+ o->menu(whenmenu);
+ }
+ { Fl_Light_Button* o = new Fl_Light_Button(190, 420, 70, 20, "no change");
+ o->box(FL_THIN_UP_BOX);
+ o->selection_color(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)when_button_cb);
+ o->when(0);
+ }
+ { Fl_Group* o = new Fl_Group(10, 450, 350, 20);
+ { Fl_Button* o = new Fl_Button(10, 450, 80, 20, "no &overlay");
+ o->labelcolor(1);
+ o->callback((Fl_Callback*)overlay_cb);
+ }
+ { Fl_Button* o = new Fl_Button(100, 450, 80, 20, "Revert");
+ o->callback((Fl_Callback*)revert_cb);
+ }
+ { Fl_Button* o = new Fl_Button(190, 450, 80, 20, "Cancel");
+ o->callback((Fl_Callback*)cancel_cb);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(280, 450, 80, 20, "OK");
+ o->callback((Fl_Callback*)ok_cb);
+ }
+ o->end();
+ }
+ o->end();
+ }
+ return w;
+}
diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl
new file mode 100644
index 000000000..0fb973c51
--- /dev/null
+++ b/fluid/widget_panel.fl
@@ -0,0 +1,300 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99
+header_name {.H}
+code_name {.C}
+gridx 10
+gridy 5
+snap 3
+Function {make_widget_panel()} {open
+} {
+ Fl_Window {} {open
+ xywh {189 164 370 480} hotspot visible
+ } {
+ Fl_Input {} {
+ label {name:}
+ callback name_cb
+ xywh {90 10 210 20} box THIN_UP_BOX when 0
+ }
+ Fl_Light_Button {} {
+ label public
+ callback name_public_cb
+ xywh {300 10 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+ }
+ Fl_Input {} {
+ label {class:}
+ user_data 4
+ callback subclass_cb
+ xywh {90 35 170 20} box THIN_UP_BOX when 0
+ }
+ Fl_Choice {} {
+ callback subtype_cb
+ xywh {260 35 100 20} box THIN_UP_BOX
+ } {}
+ Fl_Input {} {
+ label {label:}
+ callback label_cb
+ xywh {90 60 270 20} box THIN_UP_BOX when 1
+ }
+ Fl_Choice {} {
+ label {labeltype:}
+ callback labeltype_cb
+ xywh {90 80 150 20} box THIN_UP_BOX
+ code0 {extern Fl_Menu_Item labeltypemenu[];}
+ code1 {o->menu(labeltypemenu);}
+ } {}
+ Fl_Button {} {
+ label {@-1<-}
+ user_data FL_ALIGN_LEFT
+ callback align_cb
+ xywh {240 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+ }
+ Fl_Button {} {
+ label {@-1->}
+ user_data FL_ALIGN_RIGHT
+ callback align_cb
+ xywh {260 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+ }
+ Fl_Button {} {
+ label {@-18}
+ user_data FL_ALIGN_TOP
+ callback align_cb
+ xywh {280 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+ }
+ Fl_Button {} {
+ label {@-12}
+ user_data FL_ALIGN_BOTTOM
+ callback align_cb
+ xywh {300 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+ }
+ Fl_Button {} {
+ label {@-3square}
+ user_data FL_ALIGN_INSIDE
+ callback align_cb
+ xywh {320 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+ }
+ Fl_Button {} {
+ label wrap
+ user_data FL_ALIGN_WRAP
+ callback align_cb
+ xywh {340 80 20 10} type Toggle box THIN_UP_BOX labelsize 8
+ }
+ Fl_Button {} {
+ label clip
+ user_data FL_ALIGN_CLIP
+ callback align_cb
+ xywh {340 90 20 10} type Toggle box THIN_UP_BOX labelsize 8
+ }
+ Fl_Choice {} {
+ label {labelfont:}
+ callback labelfont_cb
+ xywh {90 100 170 20} box THIN_UP_BOX
+ code0 {extern Fl_Menu_Item fontmenu[];}
+ code1 {o->menu(fontmenu);}
+ } {}
+ Fl_Value_Input {} {
+ callback labelsize_cb
+ xywh {260 100 50 20} box THIN_UP_BOX maximum 100 step 1 value 14
+ }
+ Fl_Button {} {
+ label labelcolor
+ callback labelcolor_cb
+ xywh {310 100 50 20} box THIN_UP_BOX labelsize 8
+ }
+ Fl_Choice {} {
+ label {box:}
+ callback box_cb
+ xywh {90 125 220 20} box THIN_UP_BOX
+ code0 {extern Fl_Menu_Item boxmenu[];}
+ code1 {o->menu(boxmenu);}
+ } {}
+ Fl_Button {} {
+ label color
+ callback color_cb
+ xywh {310 125 50 20} box THIN_UP_BOX labelsize 8
+ }
+ Fl_Choice {} {
+ label {down_box:}
+ callback down_box_cb
+ xywh {90 145 220 20} box THIN_UP_BOX
+ code0 {extern Fl_Menu_Item boxmenu[];}
+ code1 {o->menu(boxmenu);}
+ } {}
+ Fl_Button {} {
+ label {select color}
+ callback color2_cb
+ xywh {310 145 50 20} box THIN_UP_BOX labelsize 8
+ }
+ Fl_Choice {} {
+ label {textfont:}
+ callback textfont_cb selected
+ xywh {90 170 170 20} box THIN_UP_BOX hide
+ code0 {extern Fl_Menu_Item fontmenu[];}
+ code1 {o->menu(fontmenu);}
+ } {}
+ Fl_Input {} {
+ label {xclass:}
+ callback xclass_cb
+ xywh {90 170 170 20} box THIN_UP_BOX when 0
+ }
+ Fl_Button {} {
+ label {shortcut:}
+ callback shortcut_in_cb
+ xywh {90 170 270 20} box THIN_UP_BOX color {7 7} align 4
+ code0 {\#include "Shortcut_Button.H"}
+ class Shortcut_Button
+ }
+ Fl_Value_Input {} {
+ callback textsize_cb
+ xywh {260 170 50 20} box THIN_UP_BOX maximum 100 step 1 value 14 hide
+ }
+ Fl_Button {} {
+ label textcolor
+ callback textcolor_cb
+ xywh {310 170 50 20} box THIN_UP_BOX labelsize 8 hide
+ }
+ Fl_Value_Input {} {
+ label {size:}
+ callback slider_size_cb
+ xywh {20 205 60 20} box THIN_UP_BOX labelsize 10 align 5 step 0.010101
+ }
+ Fl_Value_Input {} {
+ label {minimum:}
+ callback min_cb
+ xywh {90 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+ }
+ Fl_Value_Input {} {
+ label {maximum:}
+ callback max_cb
+ xywh {160 205 60 20} box THIN_UP_BOX labelsize 10 align 5 value 1
+ }
+ Fl_Value_Input {} {
+ label {step:}
+ callback step_cb
+ xywh {230 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+ }
+ Fl_Value_Input {} {
+ label {value:}
+ callback value_cb
+ xywh {300 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+ }
+ Fl_Group {} {
+ callback propagate_load open
+ xywh {20 230 340 20} align 5
+ } {
+ Fl_Light_Button {} {
+ label non_modal
+ callback non_modal_cb
+ xywh {20 230 70 20} box THIN_UP_BOX color {49 1} labelsize 9 align 148
+ }
+ Fl_Light_Button {} {
+ label visible
+ callback visible_cb
+ xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+ }
+ Fl_Light_Button {} {
+ label modal
+ callback modal_cb
+ xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+ }
+ Fl_Light_Button {} {
+ label active
+ callback active_cb
+ xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+ }
+ Fl_Light_Button {} {
+ label border
+ callback border_cb
+ xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+ }
+ Fl_Light_Button {} {
+ label resizable
+ callback resizable_cb
+ xywh {230 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+ }
+ Fl_Light_Button {} {
+ label hotspot
+ callback hotspot_cb
+ xywh {300 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+ }
+ }
+ Fl_Input {v_input[0]} {
+ label {extra code:}
+ user_data 0
+ callback v_input_cb
+ xywh {90 260 270 20} box THIN_UP_BOX when 0
+ }
+ Fl_Input {v_input[1]} {
+ user_data 1
+ callback v_input_cb
+ xywh {90 280 270 20} box THIN_UP_BOX when 0
+ }
+ Fl_Input {v_input[2]} {
+ user_data 2
+ callback v_input_cb
+ xywh {90 300 270 20} box THIN_UP_BOX when 0
+ }
+ Fl_Input {v_input[3]} {
+ user_data 3
+ callback v_input_cb
+ xywh {90 320 270 20} box THIN_UP_BOX when 0
+ }
+ Fl_Box {} {
+ label {callback:}
+ xywh {0 350 90 20} align 24
+ }
+ Fl_Input {} {
+ callback callback_cb
+ xywh {90 350 270 50} type Multiline box THIN_UP_BOX when 0
+ }
+ Fl_Box {} {
+ label label
+ xywh {90 370 100 30} hide deactivate resizable
+ }
+ Fl_Input {} {
+ label {user_data:}
+ callback user_data_cb
+ xywh {90 400 170 20} box THIN_UP_BOX when 0
+ }
+ Fl_Input {} {
+ label {type:}
+ callback user_data_type_cb
+ xywh {300 400 60 20} box THIN_UP_BOX when 0
+ }
+ Fl_Choice {} {
+ label {when:}
+ callback when_cb
+ xywh {90 420 100 20} box THIN_UP_BOX when 0
+ code0 {extern Fl_Menu_Item whenmenu[];}
+ code1 {o->menu(whenmenu);}
+ } {}
+ Fl_Light_Button {} {
+ label {no change}
+ callback when_button_cb
+ xywh {190 420 70 20} box THIN_UP_BOX color {49 1} labelsize 10 when 0
+ }
+ Fl_Group {} {open
+ xywh {10 450 350 20}
+ } {
+ Fl_Button {} {
+ label {no &overlay}
+ callback overlay_cb
+ xywh {10 450 80 20} labelcolor 1
+ }
+ Fl_Button {} {
+ label Revert
+ callback revert_cb
+ xywh {100 450 80 20}
+ }
+ Fl_Button {} {
+ label Cancel
+ callback cancel_cb
+ xywh {190 450 80 20}
+ }
+ Fl_Return_Button {} {
+ label OK
+ callback ok_cb
+ xywh {280 450 80 20}
+ }
+ }
+ }
+}
diff --git a/fluid/widget_panel.h b/fluid/widget_panel.h
new file mode 100644
index 000000000..9e304d16a
--- /dev/null
+++ b/fluid/widget_panel.h
@@ -0,0 +1,61 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "Shortcut_Button.H"
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Window.H>
+extern Fl_Menu_Item boxmenu[];
+extern Fl_Menu_Item fontmenu[];
+extern Fl_Menu_Item labeltypemenu[];
+extern Fl_Menu_Item whenmenu[];
+extern void active_cb(Fl_Light_Button*, void*);
+extern void align_cb(Fl_Button*, void*);
+extern void border_cb(Fl_Light_Button*, void*);
+extern void box_cb(Fl_Choice*, void*);
+extern void callback_cb(Fl_Input*, void*);
+extern void cancel_cb(Fl_Button*, void*);
+extern void color2_cb(Fl_Button*, void*);
+extern void color_cb(Fl_Button*, void*);
+extern void down_box_cb(Fl_Choice*, void*);
+extern void hotspot_cb(Fl_Light_Button*, void*);
+extern void label_cb(Fl_Input*, void*);
+extern void labelcolor_cb(Fl_Button*, void*);
+extern void labelfont_cb(Fl_Choice*, void*);
+extern void labelsize_cb(Fl_Value_Input*, void*);
+extern void labeltype_cb(Fl_Choice*, void*);
+extern void max_cb(Fl_Value_Input*, void*);
+extern void min_cb(Fl_Value_Input*, void*);
+extern void modal_cb(Fl_Light_Button*, void*);
+extern void name_cb(Fl_Input*, void*);
+extern void name_public_cb(Fl_Light_Button*, void*);
+extern void non_modal_cb(Fl_Light_Button*, void*);
+extern void ok_cb(Fl_Return_Button*, void*);
+extern void overlay_cb(Fl_Button*, void*);
+extern void propagate_load(Fl_Group*, void*);
+extern void resizable_cb(Fl_Light_Button*, void*);
+extern void revert_cb(Fl_Button*, void*);
+extern void shortcut_in_cb(Shortcut_Button*, void*);
+extern void slider_size_cb(Fl_Value_Input*, void*);
+extern void step_cb(Fl_Value_Input*, void*);
+extern void subclass_cb(Fl_Input*, void*);
+extern void subtype_cb(Fl_Choice*, void*);
+extern void textcolor_cb(Fl_Button*, void*);
+extern void textfont_cb(Fl_Choice*, void*);
+extern void textsize_cb(Fl_Value_Input*, void*);
+extern void user_data_cb(Fl_Input*, void*);
+extern void user_data_type_cb(Fl_Input*, void*);
+extern void v_input_cb(Fl_Input*, void*);
+extern void value_cb(Fl_Value_Input*, void*);
+extern void visible_cb(Fl_Light_Button*, void*);
+extern void when_button_cb(Fl_Light_Button*, void*);
+extern void when_cb(Fl_Choice*, void*);
+extern void xclass_cb(Fl_Input*, void*);
+extern Fl_Input *v_input[4];
+Fl_Window* make_widget_panel();