Fixing FLUID file corruption from issue #653 (#662)

Removing all globals in file writer (#653 )
Fix some static analyser complaints
Valgrind: handle width==0 in GfxDrivers on Wayland and X11
Don't use `Fl_Input_::static_value`, it accesses previous
buffer that may be deleted
Project file write encapsulated, removing globals
Encapsulating project file reader, removing states in glbals
Project i/o increased source code readability
This commit is contained in:
Matthias Melcher 2023-01-26 15:23:43 +01:00 committed by GitHub
parent f314ca75fe
commit 179771acd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1870 additions and 1668 deletions

View File

@ -209,16 +209,16 @@ Fl_Type *Fl_Function_Type::make(Strategy strategy) {
- "C" is written if we want a C signature instead of C++
- "return_type" is followed by the return type of the function
*/
void Fl_Function_Type::write_properties() {
Fl_Type::write_properties();
void Fl_Function_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
switch (public_) {
case 0: write_string("private"); break;
case 2: write_string("protected"); break;
case 0: f.write_string("private"); break;
case 2: f.write_string("protected"); break;
}
if (cdecl_) write_string("C");
if (cdecl_) f.write_string("C");
if (return_type) {
write_string("return_type");
write_word(return_type);
f.write_string("return_type");
f.write_word(return_type);
}
}
@ -226,7 +226,7 @@ void Fl_Function_Type::write_properties() {
Read function specific properties fron an .fl file.
\param[in] c read from this string
*/
void Fl_Function_Type::read_property(const char *c) {
void Fl_Function_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"private")) {
public_ = 0;
} else if (!strcmp(c,"protected")) {
@ -234,9 +234,9 @@ void Fl_Function_Type::read_property(const char *c) {
} else if (!strcmp(c,"C")) {
cdecl_ = 1;
} else if (!strcmp(c,"return_type")) {
storestring(read_word(),return_type);
storestring(f.read_word(),return_type);
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -245,8 +245,8 @@ void Fl_Function_Type::read_property(const char *c) {
*/
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_return_type_input->value(return_type);
f_name_input->value(name());
if (is_in_class()) {
f_public_member_choice->value(public_);
f_public_member_choice->show();
@ -328,9 +328,9 @@ int Fl_Function_Type::is_public() const {
/**
Write the code for the source and the header file.
This writes the code that goes \b before all children of this class.
\see write_code2()
\see write_code2(Fd_Code_Writer& f)
*/
void Fl_Function_Type::write_code1() {
void Fl_Function_Type::write_code1(Fd_Code_Writer& f) {
constructor=0;
havewidgets = 0;
Fl_Type *child;
@ -346,10 +346,10 @@ void Fl_Function_Type::write_code1() {
}
}
if (havechildren)
write_c("\n");
f.write_c("\n");
if (ismain()) {
if (havechildren)
write_c("int main(int argc, char **argv) {\n");
f.write_c("int main(int argc, char **argv) {\n");
} else {
const char* rtype = return_type;
const char* star = "";
@ -375,24 +375,24 @@ void Fl_Function_Type::write_code1() {
const char* k = class_name(0);
if (k) {
if (havechildren)
write_comment_c();
write_public(public_);
write_comment_c(f);
f.write_public(public_);
if (name()[0] == '~')
constructor = 1;
else {
size_t n = strlen(k);
if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1;
}
write_h("%s", indent(1));
if (is_static) write_h("static ");
if (is_virtual) write_h("virtual ");
f.write_h("%s", f.indent(1));
if (is_static) f.write_h("static ");
if (is_virtual) f.write_h("virtual ");
if (!constructor) {
write_h("%s%s ", rtype, star);
f.write_h("%s%s ", rtype, star);
if (havechildren)
write_c("%s%s ", rtype, star);
f.write_c("%s%s ", rtype, star);
}
// if this is a subclass, only write_h() the part before the ':'
// if this is a subclass, only f.write_h() the part before the ':'
char s[1024], *sptr = s;
char *nptr = (char *)name();
@ -407,9 +407,9 @@ void Fl_Function_Type::write_code1() {
*sptr = '\0';
if (s[strlen(s)-1] == '}') { // special case for inlined functions
write_h("%s\n", s);
f.write_h("%s\n", s);
} else {
write_h("%s;\n", s);
f.write_h("%s;\n", s);
}
// skip all function default param. init in body:
int skips=0,skipc=0;
@ -437,20 +437,20 @@ void Fl_Function_Type::write_code1() {
*sptr = '\0';
if (havechildren)
write_c("%s::%s {\n", k, s);
f.write_c("%s::%s {\n", k, s);
} else {
if (havechildren)
write_comment_c();
write_comment_c(f);
if (public_==1) {
if (cdecl_)
write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name());
f.write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name());
else
write_h("%s%s %s;\n", rtype, star, name());
f.write_h("%s%s %s;\n", rtype, star, name());
} else if (public_==2) {
// write neither the prototype nor static, the function may be declared elsewhere
} else {
if (havechildren)
write_c("static ");
f.write_c("static ");
}
// write everything but the default parameters (if any)
@ -481,21 +481,21 @@ void Fl_Function_Type::write_code1() {
*sptr = '\0';
if (havechildren)
write_c("%s%s %s {\n", rtype, star, s);
f.write_c("%s%s %s {\n", rtype, star, s);
}
}
if (havewidgets && child && !child->name())
write_c("%s%s* w;\n", indent(1), subclassname(child));
indentation++;
f.write_c("%s%s* w;\n", f.indent(1), subclassname(child));
f.indentation++;
}
/**
Write the code for the source and the header file.
This writes the code that goes \b after all children of this class.
\see write_code1()
\see write_code1(Fd_Code_Writer& f)
*/
void Fl_Function_Type::write_code2() {
void Fl_Function_Type::write_code2(Fd_Code_Writer& f) {
Fl_Type *child;
const char *var = "w";
char havechildren = 0;
@ -506,15 +506,15 @@ void Fl_Function_Type::write_code2() {
if (ismain()) {
if (havewidgets)
write_c("%s%s->show(argc, argv);\n", indent(1), var);
f.write_c("%s%s->show(argc, argv);\n", f.indent(1), var);
if (havechildren)
write_c("%sreturn Fl::run();\n", indent(1));
f.write_c("%sreturn Fl::run();\n", f.indent(1));
} else if (havewidgets && !constructor && !return_type) {
write_c("%sreturn %s;\n", indent(1), var);
f.write_c("%sreturn %s;\n", f.indent(1), var);
}
if (havechildren)
write_c("}\n");
indentation = 0;
f.write_c("}\n");
f.indentation = 0;
}
/**
@ -619,24 +619,24 @@ BREAK2:
/**
Grab changes from an external editor and write this node.
*/
void Fl_Code_Type::write() {
void Fl_Code_Type::write(Fd_Project_Writer &f) {
// External editor changes? If so, load changes into ram, update mtime/size
if ( handle_editor_changes() == 1 ) {
main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents
}
Fl_Type::write();
Fl_Type::write(f);
}
/**
Write the code block with the correct indentation.
*/
void Fl_Code_Type::write_code1() {
void Fl_Code_Type::write_code1(Fd_Code_Writer& f) {
// External editor changes? If so, load changes into ram, update mtime/size
if ( handle_editor_changes() == 1 ) {
main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents
}
write_c_indented(name(), 0, '\n');
f.write_c_indented(name(), 0, '\n');
}
/**
@ -737,22 +737,22 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
- "after" is followed by the code that comes after the children
The "before" code is stored in the name() field.
*/
void Fl_CodeBlock_Type::write_properties() {
Fl_Type::write_properties();
void Fl_CodeBlock_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
if (after) {
write_string("after");
write_word(after);
f.write_string("after");
f.write_word(after);
}
}
/**
Read the node specifc properties.
*/
void Fl_CodeBlock_Type::read_property(const char *c) {
void Fl_CodeBlock_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"after")) {
storestring(read_word(),after);
storestring(f.read_word(),after);
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -761,8 +761,8 @@ void Fl_CodeBlock_Type::read_property(const char *c) {
*/
void Fl_CodeBlock_Type::open() {
if (!codeblock_panel) make_codeblock_panel();
code_before_input->static_value(name());
code_after_input->static_value(after);
code_before_input->value(name());
code_after_input->value(after);
codeblock_panel->show();
const char* message = 0;
for (;;) { // repeat as long as there are errors
@ -788,19 +788,19 @@ BREAK2:
/**
Write the "before" code.
*/
void Fl_CodeBlock_Type::write_code1() {
void Fl_CodeBlock_Type::write_code1(Fd_Code_Writer& f) {
const char* c = name();
write_c("%s%s {\n", indent(), c ? c : "");
indentation++;
f.write_c("%s%s {\n", f.indent(), c ? c : "");
f.indentation++;
}
/**
Write the "after" code.
*/
void Fl_CodeBlock_Type::write_code2() {
indentation--;
if (after) write_c("%s} %s\n", indent(), after);
else write_c("%s}\n", indent());
void Fl_CodeBlock_Type::write_code2(Fd_Code_Writer& f) {
f.indentation--;
if (after) f.write_c("%s} %s\n", f.indent(), after);
else f.write_c("%s}\n", f.indent());
}
// ---- Fl_Decl_Type declaration
@ -861,23 +861,23 @@ Fl_Type *Fl_Decl_Type::make(Strategy strategy) {
- "private"/"public"/"protected"
- "local"/"global" if this is static or not
*/
void Fl_Decl_Type::write_properties() {
Fl_Type::write_properties();
void Fl_Decl_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
switch (public_) {
case 0: write_string("private"); break;
case 1: write_string("public"); break;
case 2: write_string("protected"); break;
case 0: f.write_string("private"); break;
case 1: f.write_string("public"); break;
case 2: f.write_string("protected"); break;
}
if (static_)
write_string("local");
f.write_string("local");
else
write_string("global");
f.write_string("global");
}
/**
Read the specific properties.
*/
void Fl_Decl_Type::read_property(const char *c) {
void Fl_Decl_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"public")) {
public_ = 1;
} else if (!strcmp(c,"private")) {
@ -889,7 +889,7 @@ void Fl_Decl_Type::read_property(const char *c) {
} else if (!strcmp(c,"global")) {
static_ = 0;
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -898,7 +898,7 @@ void Fl_Decl_Type::read_property(const char *c) {
*/
void Fl_Decl_Type::open() {
if (!decl_panel) make_decl_panel();
decl_input->static_value(name());
decl_input->value(name());
if (is_in_class()) {
decl_class_choice->value(public_);
decl_class_choice->show();
@ -960,7 +960,7 @@ BREAK2:
\todo There are a lot of side effect in this node depending on the given text
and the parent node. They need to be understood and documented.
*/
void Fl_Decl_Type::write_code1() {
void Fl_Decl_Type::write_code1(Fd_Code_Writer& f) {
const char* c = name();
if (!c) return;
// handle a few keywords differently if inside a class
@ -969,9 +969,9 @@ void Fl_Decl_Type::write_code1() {
|| (!strncmp(c,"FL_EXPORT",9) && isspace(c[9]))
|| (!strncmp(c,"struct",6) && isspace(c[6]))
) ) {
write_public(public_);
write_comment_h(indent(1));
write_h("%s%s\n", indent(1), c);
f.write_public(public_);
write_comment_h(f, f.indent(1));
f.write_h("%s%s\n", f.indent(1), c);
return;
}
// handle putting #include, extern, using or typedef into decl:
@ -984,11 +984,11 @@ void Fl_Decl_Type::write_code1() {
// || !strncmp(c,"struct",6) && isspace(c[6])
) {
if (public_) {
write_comment_h();
write_h("%s\n", c);
write_comment_h(f);
f.write_h("%s\n", c);
} else {
write_comment_c();
write_c("%s\n", c);
write_comment_c(f);
f.write_c("%s\n", c);
}
return;
}
@ -999,26 +999,26 @@ void Fl_Decl_Type::write_code1() {
// lose spaces between text and comment, if any
while (e>c && e[-1]==' ') e--;
if (class_name(1)) {
write_public(public_);
write_comment_h(indent(1));
write_hc(indent(1), int(e-c), c, csc);
f.write_public(public_);
write_comment_h(f, f.indent(1));
f.write_hc(f.indent(1), int(e-c), c, csc);
} else {
if (public_) {
if (static_)
write_h("extern ");
f.write_h("extern ");
else
write_comment_h();
write_hc("", int(e-c), c, csc);
write_comment_h(f);
f.write_hc("", int(e-c), c, csc);
if (static_) {
write_comment_c();
write_cc("", int(e-c), c, csc);
write_comment_c(f);
f.write_cc("", int(e-c), c, csc);
}
} else {
write_comment_c();
write_comment_c(f);
if (static_)
write_c("static ");
write_cc("", int(e-c), c, csc);
f.write_c("static ");
f.write_cc("", int(e-c), c, csc);
}
}
}
@ -1076,27 +1076,27 @@ Fl_Type *Fl_Data_Type::make(Strategy strategy) {
- "filename" followed by the filename of the file to inline
- "textmode" if data is written in ASCII vs. binary
*/
void Fl_Data_Type::write_properties() {
Fl_Decl_Type::write_properties();
void Fl_Data_Type::write_properties(Fd_Project_Writer &f) {
Fl_Decl_Type::write_properties(f);
if (filename_) {
write_string("filename");
write_word(filename_);
f.write_string("filename");
f.write_word(filename_);
}
if (text_mode_) {
write_string("textmode");
f.write_string("textmode");
}
}
/**
Read specific properties.
*/
void Fl_Data_Type::read_property(const char *c) {
void Fl_Data_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"filename")) {
storestring(read_word(), filename_, 1);
storestring(f.read_word(), filename_, 1);
} else if (!strcmp(c,"textmode")) {
text_mode_ = 1;
} else {
Fl_Decl_Type::read_property(c);
Fl_Decl_Type::read_property(f, c);
}
}
@ -1105,7 +1105,7 @@ void Fl_Data_Type::read_property(const char *c) {
*/
void Fl_Data_Type::open() {
if (!data_panel) make_data_panel();
data_input->static_value(name());
data_input->value(name());
if (is_in_class()) {
data_class_choice->value(public_);
data_class_choice->show();
@ -1208,7 +1208,7 @@ BREAK2:
/**
Write the content of the external file inline into the source code.
*/
void Fl_Data_Type::write_code1() {
void Fl_Data_Type::write_code1(Fd_Code_Writer& f) {
const char *message = 0;
const char *c = name();
if (!c) return;
@ -1216,7 +1216,7 @@ void Fl_Data_Type::write_code1() {
char *data = 0;
int nData = -1;
// path should be set correctly already
if (filename_ && !write_sourceview) {
if (filename_ && !f.write_sourceview) {
enter_project_dir();
FILE *f = fl_fopen(filename_, "rb");
leave_project_dir();
@ -1236,71 +1236,71 @@ void Fl_Data_Type::write_code1() {
fn = filename_ ? filename_ : "<no filename>";
}
if (is_in_class()) {
write_public(public_);
f.write_public(public_);
if (text_mode_) {
write_h("%sstatic const char *%s;\n", indent(1), c);
write_c("\n");
write_comment_c();
write_c("const char *%s::%s = /* text inlined from %s */\n", class_name(1), c, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cstring(data, nData);
f.write_h("%sstatic const char *%s;\n", f.indent(1), c);
f.write_c("\n");
write_comment_c(f);
f.write_c("const char *%s::%s = /* text inlined from %s */\n", class_name(1), c, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cstring(data, nData);
} else {
write_h("%sstatic unsigned char %s[%d];\n", indent(1), c, nData);
write_c("\n");
write_comment_c();
write_c("unsigned char %s::%s[%d] = /* data inlined from %s */\n", class_name(1), c, nData, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cdata(data, nData);
f.write_h("%sstatic unsigned char %s[%d];\n", f.indent(1), c, nData);
f.write_c("\n");
write_comment_c(f);
f.write_c("unsigned char %s::%s[%d] = /* data inlined from %s */\n", class_name(1), c, nData, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cdata(data, nData);
}
write_c(";\n");
f.write_c(";\n");
} else {
// the "header only" option does not apply here!
if (public_) {
if (static_) {
if (text_mode_) {
write_h("extern const char *%s;\n", c);
write_c("\n");
write_comment_c();
write_c("const char *%s = /* text inlined from %s */\n", c, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cstring(data, nData);
f.write_h("extern const char *%s;\n", c);
f.write_c("\n");
write_comment_c(f);
f.write_c("const char *%s = /* text inlined from %s */\n", c, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cstring(data, nData);
} else {
write_h("extern unsigned char %s[%d];\n", c, nData);
write_c("\n");
write_comment_c();
write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cdata(data, nData);
f.write_h("extern unsigned char %s[%d];\n", c, nData);
f.write_c("\n");
write_comment_c(f);
f.write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cdata(data, nData);
}
write_c(";\n");
f.write_c(";\n");
} else {
write_comment_h();
write_h("#error Unsupported declaration loading inline data %s\n", fn);
write_comment_h(f);
f.write_h("#error Unsupported declaration loading inline data %s\n", fn);
if (text_mode_)
write_h("const char *%s = \"abc...\";\n", c);
f.write_h("const char *%s = \"abc...\";\n", c);
else
write_h("unsigned char %s[3] = { 1, 2, 3 };\n", c);
f.write_h("unsigned char %s[3] = { 1, 2, 3 };\n", c);
}
} else {
write_c("\n");
write_comment_c();
f.write_c("\n");
write_comment_c(f);
if (static_)
write_c("static ");
f.write_c("static ");
if (text_mode_) {
write_c("const char *%s = /* text inlined from %s */\n", c, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cstring(data, nData);
f.write_c("const char *%s = /* text inlined from %s */\n", c, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cstring(data, nData);
} else {
write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn);
if (message) write_c("#error %s %s\n", message, fn);
write_cdata(data, nData);
f.write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn);
if (message) f.write_c("#error %s %s\n", message, fn);
f.write_cdata(data, nData);
}
write_c(";\n");
f.write_c(";\n");
}
}
// if we are in interactive mode, we pop up a warning dialog
// giving the error: (batch_mode && !write_sourceview) ???
if (message && !write_sourceview) {
if (message && !f.write_sourceview) {
if (batch_mode)
fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn);
else
@ -1365,28 +1365,28 @@ Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) {
- "public"/"protected"
- "after" followed by the second code block.
*/
void Fl_DeclBlock_Type::write_properties() {
Fl_Type::write_properties();
void Fl_DeclBlock_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
switch (public_) {
case 1: write_string("public"); break;
case 2: write_string("protected"); break;
case 1: f.write_string("public"); break;
case 2: f.write_string("protected"); break;
}
write_string("after");
write_word(after);
f.write_string("after");
f.write_word(after);
}
/**
Read the specific properties.
*/
void Fl_DeclBlock_Type::read_property(const char *c) {
void Fl_DeclBlock_Type::read_property(Fd_Project_Reader &f, const char *c) {
if(!strcmp(c,"public")) {
public_ = 1;
} else if(!strcmp(c,"protected")) {
public_ = 2;
} else if (!strcmp(c,"after")) {
storestring(read_word(),after);
storestring(f.read_word(),after);
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -1395,9 +1395,9 @@ void Fl_DeclBlock_Type::read_property(const char *c) {
*/
void Fl_DeclBlock_Type::open() {
if (!declblock_panel) make_declblock_panel();
decl_before_input->static_value(name());
decl_before_input->value(name());
declblock_public_choice->value((public_>0));
decl_after_input->static_value(after);
decl_after_input->value(after);
declblock_panel->show();
const char* message = 0;
for (;;) { // repeat as long as there are errors
@ -1433,21 +1433,21 @@ BREAK2:
Write the \b before code to the source file, and to the header file if declared public.
The before code is stored in the name() field.
*/
void Fl_DeclBlock_Type::write_code1() {
void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) {
const char* c = name();
if (public_)
write_h("%s\n", c);
write_c("%s\n", c);
f.write_h("%s\n", c);
f.write_c("%s\n", c);
}
/**
Write the \b after code to the source file, and to the header file if declared public.
*/
void Fl_DeclBlock_Type::write_code2() {
void Fl_DeclBlock_Type::write_code2(Fd_Code_Writer& f) {
const char* c = after;
if (public_)
write_h("%s\n", c);
write_c("%s\n", c);
f.write_h("%s\n", c);
f.write_c("%s\n", c);
}
// ---- Fl_Comment_Type declaration
@ -1496,16 +1496,16 @@ Fl_Type *Fl_Comment_Type::make(Strategy strategy) {
- "in_source"/"not_in_source" if the comment will be written to the source code
- "in_header"/"not_in_header" if the comment will be written to the header file
*/
void Fl_Comment_Type::write_properties() {
Fl_Type::write_properties();
if (in_c_) write_string("in_source"); else write_string("not_in_source");
if (in_h_) write_string("in_header"); else write_string("not_in_header");
void Fl_Comment_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
if (in_c_) f.write_string("in_source"); else f.write_string("not_in_source");
if (in_h_) f.write_string("in_header"); else f.write_string("not_in_header");
}
/**
Read extra properties.
*/
void Fl_Comment_Type::read_property(const char *c) {
void Fl_Comment_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"in_source")) {
in_c_ = 1;
} else if (!strcmp(c,"not_in_source")) {
@ -1515,7 +1515,7 @@ void Fl_Comment_Type::read_property(const char *c) {
} else if (!strcmp(c,"not_in_header")) {
in_h_ = 0;
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -1688,7 +1688,7 @@ const char *Fl_Comment_Type::title() {
/**
Write the comment to the files.
*/
void Fl_Comment_Type::write_code1() {
void Fl_Comment_Type::write_code1(Fd_Code_Writer& f) {
const char* c = name();
if (!c) return;
if (!in_c_ && !in_h_) return;
@ -1698,8 +1698,8 @@ void Fl_Comment_Type::write_code1() {
// if this seems to be a C style comment, copy the block as is
// (it's up to the user to correctly close the comment)
if (s[0]=='/' && s[1]=='*') {
if (in_h_) write_h("%s\n", c);
if (in_c_) write_c("%s\n", c);
if (in_h_) f.write_h("%s\n", c);
if (in_c_) f.write_c("%s\n", c);
return;
}
// copy the comment line by line, add the double slash if needed
@ -1715,12 +1715,12 @@ void Fl_Comment_Type::write_code1() {
while (isspace(*s)) s++;
if (s!=e && ( s[0]!='/' || s[1]!='/') ) {
// if no comment marker was found, we add one ourselves
if (in_h_) write_h("// ");
if (in_c_) write_c("// ");
if (in_h_) f.write_h("// ");
if (in_c_) f.write_c("// ");
}
// now copy the rest of the line
if (in_h_) write_h("%s\n", b);
if (in_c_) write_c("%s\n", b);
if (in_h_) f.write_h("%s\n", b);
if (in_c_) f.write_c("%s\n", b);
if (eol==0) break;
*e++ = eol;
b = e;
@ -1795,30 +1795,30 @@ Fl_Type *Fl_Class_Type::make(Strategy strategy) {
- ":" followed by the super class
- "private"/"protected"
*/
void Fl_Class_Type::write_properties() {
Fl_Type::write_properties();
void Fl_Class_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
if (subclass_of) {
write_string(":");
write_word(subclass_of);
f.write_string(":");
f.write_word(subclass_of);
}
switch (public_) {
case 0: write_string("private"); break;
case 2: write_string("protected"); break;
case 0: f.write_string("private"); break;
case 2: f.write_string("protected"); break;
}
}
/**
Read additional properties.
*/
void Fl_Class_Type::read_property(const char *c) {
void Fl_Class_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"private")) {
public_ = 0;
} else if (!strcmp(c,"protected")) {
public_ = 2;
} else if (!strcmp(c,":")) {
storestring(read_word(), subclass_of);
storestring(f.read_word(), subclass_of);
} else {
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}
@ -1832,8 +1832,8 @@ void Fl_Class_Type::open() {
sprintf(fullname,"%s %s",prefix(),name());
else
strcpy(fullname, name());
c_name_input->static_value(fullname);
c_subclass_input->static_value(subclass_of);
c_name_input->value(fullname);
c_subclass_input->value(subclass_of);
c_public_button->value(public_);
const char *c = comment();
c_comment_input->buffer()->text(c?c:"");
@ -1898,25 +1898,25 @@ BREAK2:
/**
Write the header code that declares this class.
*/
void Fl_Class_Type::write_code1() {
void Fl_Class_Type::write_code1(Fd_Code_Writer& f) {
parent_class = current_class;
current_class = this;
write_public_state = 0;
write_h("\n");
write_comment_h();
f.write_h("\n");
write_comment_h(f);
if (prefix() && strlen(prefix()))
write_h("class %s %s ", prefix(), name());
f.write_h("class %s %s ", prefix(), name());
else
write_h("class %s ", name());
if (subclass_of) write_h(": %s ", subclass_of);
write_h("{\n");
f.write_h("class %s ", name());
if (subclass_of) f.write_h(": %s ", subclass_of);
f.write_h("{\n");
}
/**
Write the header code that ends the declaration of this class.
*/
void Fl_Class_Type::write_code2() {
write_h("};\n");
void Fl_Class_Type::write_code2(Fd_Code_Writer& f) {
f.write_h("};\n");
current_class = parent_class;
}

View File

@ -50,8 +50,8 @@ public:
Fl_Function_Type();
~Fl_Function_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void open() FL_OVERRIDE;
int ismain() {return name_ == 0;}
const char *type_name() FL_OVERRIDE {return "Function";}
@ -62,8 +62,8 @@ public:
int is_code_block() const FL_OVERRIDE {return 1;}
int is_public() const FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 7; }
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int has_signature(const char *, const char*) const;
};
@ -78,9 +78,9 @@ class Fl_Code_Type : public Fl_Type {
public:
Fl_Code_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write() FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE { }
void write(Fd_Project_Writer &f) FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { }
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "code";}
int is_code_block() const FL_OVERRIDE {return 0;}
@ -101,16 +101,16 @@ public:
Fl_CodeBlock_Type();
~Fl_CodeBlock_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "codeblock";}
int is_code_block() const FL_OVERRIDE {return 1;}
int is_parent() const FL_OVERRIDE {return 1;}
int is_public() const FL_OVERRIDE { return -1; }
int pixmapID() FL_OVERRIDE { return 9; }
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
};
// ---- Fl_Decl_Type declaration
@ -124,12 +124,12 @@ protected:
public:
Fl_Decl_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE { }
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { }
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "decl";}
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int is_public() const FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 10; }
};
@ -144,12 +144,12 @@ public:
Fl_Data_Type();
~Fl_Data_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE {}
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE {}
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "data";}
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 49; }
};
@ -163,12 +163,12 @@ public:
Fl_DeclBlock_Type();
~Fl_DeclBlock_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "declblock";}
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int is_parent() const FL_OVERRIDE {return 1;}
int is_decl_block() const FL_OVERRIDE {return 1;}
int is_public() const FL_OVERRIDE;
@ -184,13 +184,13 @@ class Fl_Comment_Type : public Fl_Type {
public:
Fl_Comment_Type();
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE { }
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { }
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "comment";}
const char *title() FL_OVERRIDE; // string for browser
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int is_public() const FL_OVERRIDE { return 1; }
int is_comment() const FL_OVERRIDE { return 1; }
int pixmapID() FL_OVERRIDE { return 46; }
@ -211,8 +211,8 @@ public:
Fl_Class_Type* parent_class; // save class if nested
//
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void open() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "class";}
int is_parent() const FL_OVERRIDE {return 1;}
@ -220,8 +220,8 @@ public:
int is_class() const FL_OVERRIDE {return 1;}
int is_public() const FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 12; }
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
// class prefix attribute access
void prefix(const char* p);

View File

@ -131,18 +131,18 @@ void ungroup_cb(Fl_Widget *, void *) {
set_modflag(1);
}
void Fl_Group_Type::write_code1() {
Fl_Widget_Type::write_code1();
void Fl_Group_Type::write_code1(Fd_Code_Writer& f) {
Fl_Widget_Type::write_code1(f);
}
void Fl_Group_Type::write_code2() {
void Fl_Group_Type::write_code2(Fd_Code_Writer& f) {
const char *var = name() ? name() : "o";
write_extra_code();
write_c("%s%s->end();\n", indent(), var);
write_extra_code(f);
f.write_c("%s%s->end();\n", f.indent(), var);
if (resizable()) {
write_c("%sFl_Group::current()->resizable(%s);\n", indent(), var);
f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var);
}
write_block_close();
write_block_close(f);
}
// This is called when o is created. If it is in the tab group make
@ -247,95 +247,95 @@ void Fl_Flex_Type::copy_properties()
d->gap( s->gap() );
}
void Fl_Flex_Type::write_properties()
void Fl_Flex_Type::write_properties(Fd_Project_Writer &f)
{
Fl_Group_Type::write_properties();
Fl_Flex* f = (Fl_Flex*)o;
Fl_Group_Type::write_properties(f);
Fl_Flex* flex = (Fl_Flex*)o;
int lm, tm, rm, bm;
f->margin(&lm, &tm, &rm, &bm);
flex->margin(&lm, &tm, &rm, &bm);
if (lm!=0 || tm!=0 || rm!=0 || bm!=0)
write_string("margin {%d %d %d %d}", lm, tm, rm, bm);
if (f->gap())
write_string("gap %d", f->gap());
f.write_string("margin {%d %d %d %d}", lm, tm, rm, bm);
if (flex->gap())
f.write_string("gap %d", flex->gap());
int nSet = 0;
for (int i=0; i<f->children(); i++)
if (f->fixed(f->child(i)))
for (int i=0; i<flex->children(); i++)
if (flex->fixed(flex->child(i)))
nSet++;
if (nSet) {
write_string("fixed_size_tuples {%d", nSet);
for (int i=0; i<f->children(); i++) {
Fl_Widget *ci = f->child(i);
if (f->fixed(ci))
write_string(" %d %d", i, f->horizontal() ? ci->w() : ci->h());
f.write_string("fixed_size_tuples {%d", nSet);
for (int i=0; i<flex->children(); i++) {
Fl_Widget *ci = flex->child(i);
if (flex->fixed(ci))
f.write_string(" %d %d", i, flex->horizontal() ? ci->w() : ci->h());
}
write_string("}");
f.write_string("}");
}
}
void Fl_Flex_Type::read_property(const char *c)
void Fl_Flex_Type::read_property(Fd_Project_Reader &f, const char *c)
{
Fl_Flex* f = (Fl_Flex*)o;
Fl_Flex* flex = (Fl_Flex*)o;
suspend_auto_layout = 1;
if (!strcmp(c,"margin")) {
int lm, tm, rm, bm;
if (sscanf(read_word(),"%d %d %d %d",&lm,&tm,&rm,&bm) == 4)
f->margin(lm, tm, rm, bm);
if (sscanf(f.read_word(),"%d %d %d %d",&lm,&tm,&rm,&bm) == 4)
flex->margin(lm, tm, rm, bm);
} else if (!strcmp(c,"gap")) {
int g;
if (sscanf(read_word(),"%d",&g))
f->gap(g);
if (sscanf(f.read_word(),"%d",&g))
flex->gap(g);
} else if (!strcmp(c,"fixed_size_tuples")) {
read_word(1); // must be '{'
const char *nStr = read_word(1); // number of indices in table
f.read_word(1); // must be '{'
const char *nStr = f.read_word(1); // number of indices in table
fixedSizeTupleSize = atoi(nStr);
fixedSizeTuple = new int[fixedSizeTupleSize*2];
for (int i=0; i<fixedSizeTupleSize; i++) {
const char *ix = read_word(1); // child at that index is fixed in size
const char *ix = f.read_word(1); // child at that index is fixed in size
fixedSizeTuple[i*2] = atoi(ix);
const char *size = read_word(1); // fixed size of that child
const char *size = f.read_word(1); // fixed size of that child
fixedSizeTuple[i*2+1] = atoi(size);
}
read_word(1); // must be '}'
f.read_word(1); // must be '}'
} else {
Fl_Group_Type::read_property(c);
Fl_Group_Type::read_property(f, c);
}
}
void Fl_Flex_Type::postprocess_read()
{
if (fixedSizeTupleSize==0) return;
Fl_Flex* f = (Fl_Flex*)o;
Fl_Flex* flex = (Fl_Flex*)o;
for (int i=0; i<fixedSizeTupleSize; i++) {
int ix = fixedSizeTuple[2*i];
int size = fixedSizeTuple[2*i+1];
if (ix>=0 && ix<f->children()) {
Fl_Widget *ci = f->child(ix);
f->fixed(ci, size);
if (ix>=0 && ix<flex->children()) {
Fl_Widget *ci = flex->child(ix);
flex->fixed(ci, size);
}
}
fixedSizeTupleSize = 0;
delete[] fixedSizeTuple;
fixedSizeTuple = NULL;
f->layout();
flex->layout();
suspend_auto_layout = 0;
}
void Fl_Flex_Type::write_code2() {
void Fl_Flex_Type::write_code2(Fd_Code_Writer& f) {
const char *var = name() ? name() : "o";
Fl_Flex* f = (Fl_Flex*)o;
Fl_Flex* flex = (Fl_Flex*)o;
int lm, tm, rm, bm;
f->margin(&lm, &tm, &rm, &bm);
flex->margin(&lm, &tm, &rm, &bm);
if (lm!=0 || tm!=0 || rm!=0 || bm!=0)
write_c("%s%s->margin(%d, %d, %d, %d);\n", indent(), var, lm, tm, rm, bm);
if (f->gap())
write_c("%s%s->gap(%d);\n", indent(), var, f->gap());
for (int i=0; i<f->children(); ++i) {
Fl_Widget *ci = f->child(i);
if (f->fixed(ci))
write_c("%s%s->fixed(%s->child(%d), %d);\n", indent(), var, var, i,
f->horizontal() ? ci->w() : ci->h());
f.write_c("%s%s->margin(%d, %d, %d, %d);\n", f.indent(), var, lm, tm, rm, bm);
if (flex->gap())
f.write_c("%s%s->gap(%d);\n", f.indent(), var, flex->gap());
for (int i=0; i<flex->children(); ++i) {
Fl_Widget *ci = flex->child(i);
if (flex->fixed(ci))
f.write_c("%s%s->fixed(%s->child(%d), %d);\n", f.indent(), var, var, i,
flex->horizontal() ? ci->w() : ci->h());
}
Fl_Group_Type::write_code2();
Fl_Group_Type::write_code2(f);
}
void Fl_Flex_Type::add_child(Fl_Type* a, Fl_Type* b) {

View File

@ -44,8 +44,8 @@ public:
igroup *g = new igroup(X,Y,W,H); Fl_Group::current(0); return g;}
Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Group_Type();}
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void remove_child(Fl_Type*) FL_OVERRIDE;
@ -91,12 +91,12 @@ public:
Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {
Fl_Flex *g = new Fl_Flex(X,Y,W,H); Fl_Group::current(0); return g;}
int pixmapID() FL_OVERRIDE { return 56; }
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE;
void copy_properties() FL_OVERRIDE;
void postprocess_read() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void remove_child(Fl_Type*) FL_OVERRIDE;

View File

@ -227,7 +227,7 @@ int isdeclare(const char *c);
// Search backwards to find the parent menu button and return it's name.
// Also put in i the index into the button's menu item array belonging
// to this menu item.
const char* Fl_Menu_Item_Type::menu_name(int& i) {
const char* Fl_Menu_Item_Type::menu_name(Fd_Code_Writer& f, int& i) {
i = 0;
Fl_Type* t = prev;
while (t && t->is_menu_item()) {
@ -238,20 +238,21 @@ const char* Fl_Menu_Item_Type::menu_name(int& i) {
t = t->prev;
i++;
}
return unique_id(t, "menu", t->name(), t->label());
if (!t) return "\n#error Fl_Menu_Item_Type::menu_name, invalid f\n";
return f.unique_id(t, "menu", t->name(), t->label());
}
void Fl_Menu_Item_Type::write_static() {
void Fl_Menu_Item_Type::write_static(Fd_Code_Writer& f) {
if (image && label() && label()[0]) {
write_declare("#include <FL/Fl.H>");
write_declare("#include <FL/Fl_Multi_Label.H>");
f.write_h_once("#include <FL/Fl.H>");
f.write_h_once("#include <FL/Fl_Multi_Label.H>");
}
if (callback() && is_name(callback()) && !user_defined(callback()))
write_declare("extern void %s(Fl_Menu_*, %s);", callback(),
f.write_h_once("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));
f.write_h_once("%s", extra_code(n));
}
if (callback() && !is_name(callback())) {
// see if 'o' or 'v' used, to prevent unused argument warnings:
@ -264,48 +265,46 @@ void Fl_Menu_Item_Type::write_static() {
do d++; while (is_id(*d));
while (*d && !is_id(*d)) d++;
}
const char* cn = callback_name();
const char* cn = callback_name(f);
const char* k = class_name(1);
if (k) {
write_c("\nvoid %s::%s_i(Fl_Menu_*", k, cn);
f.write_c("\nvoid %s::%s_i(Fl_Menu_*", k, cn);
} else {
write_c("\nstatic void %s(Fl_Menu_*", cn);
f.write_c("\nstatic void %s(Fl_Menu_*", cn);
}
if (use_o) write_c(" o");
if (use_o) f.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");
write_c_indented(callback(), 1, 0);
f.write_c(", %s", ut);
if (use_v) f.write_c(" v");
f.write_c(") {\n");
f.write_c_indented(callback(), 1, 0);
if (*(d-1) != ';' && *(d-1) != '}') {
const char *p = strrchr(callback(), '\n');
if (p) p ++;
else p = callback();
// Only add trailing semicolon if the last line is not a preprocessor
// statement...
if (*p != '#' && *p) write_c(";");
if (*p != '#' && *p) f.write_c(";");
}
write_c("\n}\n");
f.write_c("\n}\n");
if (k) {
write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
write_c("%s((%s*)(o", indent(1), k);
f.write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
f.write_c("%s((%s*)(o", f.indent(1), k);
Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent;
Fl_Type *q = 0;
// Go up one more level for Fl_Input_Choice, as these are groups themselves
if (t && !strcmp(t->type_name(), "Fl_Input_Choice"))
write_c("->parent()");
f.write_c("->parent()");
for (t = t->parent; t && t->is_widget() && !is_class(); q = t, t = t->parent)
write_c("->parent()");
f.write_c("->parent()");
if (!q || strcmp(q->type_name(), "widget_class"))
write_c("->user_data()");
write_c("))->%s_i(o,v);\n}\n", cn);
f.write_c("->user_data()");
f.write_c("))->%s_i(o,v);\n}\n", cn);
}
}
if (image) {
if (image->written != write_number) {
image->write_static(compress_image_);
image->written = write_number;
}
if (!f.c_contains(image))
image->write_static(f, compress_image_);
}
if (next && next->is_menu_item()) return;
// okay, when we hit last item in the menu we have to write the
@ -313,20 +312,20 @@ void Fl_Menu_Item_Type::write_static() {
const char* k = class_name(1);
if (k) {
int i;
write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(i));
f.write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(f, i));
} else {
int i;
write_c("\nFl_Menu_Item %s[] = {\n", menu_name(i));
f.write_c("\nFl_Menu_Item %s[] = {\n", menu_name(f, i));
}
Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev;
for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) {
((Fl_Menu_Item_Type*)q)->write_item();
((Fl_Menu_Item_Type*)q)->write_item(f);
int thislevel = q->level; if (q->is_parent()) thislevel++;
int nextlevel =
(q->next && q->next->is_menu_item()) ? q->next->level : t->level+1;
while (thislevel > nextlevel) {write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;}
while (thislevel > nextlevel) {f.write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;}
}
write_c(" {0,0,0,0,0,0,0,0,0}\n};\n");
f.write_c(" {0,0,0,0,0,0,0,0,0}\n};\n");
if (k) {
// Write menu item variables...
@ -338,12 +337,12 @@ void Fl_Menu_Item_Type::write_static() {
if (c==m->name()) {
// assign a menu item address directly to a variable
int i;
const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(i);
write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i);
const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(f, i);
f.write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i);
} else {
// if the name is an array, only define the array.
// The actual assignment is in write_code1()
write_c("Fl_Menu_Item* %s::%s;\n", k, c);
// The actual assignment is in write_code1(Fd_Code_Writer& f)
f.write_c("Fl_Menu_Item* %s::%s;\n", k, c);
}
}
}
@ -363,7 +362,7 @@ int Fl_Menu_Item_Type::flags() {
return i;
}
void Fl_Menu_Item_Type::write_item() {
void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) {
static const char * const labeltypes[] = {
"FL_NORMAL_LABEL",
"FL_NO_LABEL",
@ -375,120 +374,120 @@ void Fl_Menu_Item_Type::write_item() {
"FL_IMAGE_LABEL"
};
write_comment_inline_c(" ");
write_c(" {");
write_comment_inline_c(f, " ");
f.write_c(" {");
if (label() && label()[0])
switch (g_project.i18n_type) {
case 1:
// we will call i18n when the menu is instantiated for the first time
write_c("%s(", g_project.i18n_static_function.value());
write_cstring(label());
write_c(")");
f.write_c("%s(", g_project.i18n_static_function.value());
f.write_cstring(label());
f.write_c(")");
break;
case 2:
// fall through: strings can't be translated before a catalog is choosen
default:
write_cstring(label());
f.write_cstring(label());
}
else
write_c("\"\"");
f.write_c("\"\"");
if (((Fl_Button*)o)->shortcut()) {
int s = ((Fl_Button*)o)->shortcut();
if (g_project.use_FL_COMMAND && (s & (FL_CTRL|FL_META))) {
write_c(", FL_COMMAND|0x%x, ", s & ~(FL_CTRL|FL_META));
f.write_c(", FL_COMMAND|0x%x, ", s & ~(FL_CTRL|FL_META));
} else {
write_c(", 0x%x, ", s);
f.write_c(", 0x%x, ", s);
}
} else
write_c(", 0, ");
f.write_c(", 0, ");
if (callback()) {
const char* k = is_name(callback()) ? 0 : class_name(1);
if (k) {
write_c(" (Fl_Callback*)%s::%s,", k, callback_name());
f.write_c(" (Fl_Callback*)%s::%s,", k, callback_name(f));
} else {
write_c(" (Fl_Callback*)%s,", callback_name());
f.write_c(" (Fl_Callback*)%s,", callback_name(f));
}
} else
write_c(" 0,");
f.write_c(" 0,");
if (user_data())
write_c(" (void*)(%s),", user_data());
f.write_c(" (void*)(%s),", user_data());
else
write_c(" 0,");
write_c(" %d, (uchar)%s, %d, %d, %d", flags(),
f.write_c(" 0,");
f.write_c(" %d, (uchar)%s, %d, %d, %d", flags(),
labeltypes[o->labeltype()], o->labelfont(), o->labelsize(), o->labelcolor());
write_c("},\n");
f.write_c("},\n");
}
void start_menu_initialiser(int &initialized, const char *name, int index) {
void start_menu_initialiser(Fd_Code_Writer& f, int &initialized, const char *name, int index) {
if (!initialized) {
initialized = 1;
write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), name, index);
indentation++;
f.write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", f.indent(), name, index);
f.indentation++;
}
}
void Fl_Menu_Item_Type::write_code1() {
int i; const char* mname = menu_name(i);
void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) {
int i; const char* mname = menu_name(f, i);
if (!prev->is_menu_item()) {
// for first menu item, declare the array
if (class_name(1)) {
write_h("%sstatic Fl_Menu_Item %s[];\n", indent(1), mname);
f.write_h("%sstatic Fl_Menu_Item %s[];\n", f.indent(1), mname);
} else {
write_h("extern Fl_Menu_Item %s[];\n", mname);
f.write_h("extern Fl_Menu_Item %s[];\n", mname);
}
}
const char *c = array_name(this);
if (c) {
if (class_name(1)) {
write_public(public_);
write_h("%sstatic Fl_Menu_Item *%s;\n", indent(1), c);
f.write_public(public_);
f.write_h("%sstatic Fl_Menu_Item *%s;\n", f.indent(1), c);
} else {
if (c==name())
write_h("#define %s (%s+%d)\n", c, mname, i);
f.write_h("#define %s (%s+%d)\n", c, mname, i);
else
write_h("extern Fl_Menu_Item *%s;\n", c);
f.write_h("extern Fl_Menu_Item *%s;\n", c);
}
}
if (callback()) {
if (!is_name(callback()) && class_name(1)) {
const char* cn = callback_name();
const char* cn = callback_name(f);
const char* ut = user_data_type() ? user_data_type() : "void*";
write_public(0);
write_h("%sinline void %s_i(Fl_Menu_*, %s);\n", indent(1), cn, ut);
write_h("%sstatic void %s(Fl_Menu_*, %s);\n", indent(1), cn, ut);
f.write_public(0);
f.write_h("%sinline void %s_i(Fl_Menu_*, %s);\n", f.indent(1), cn, ut);
f.write_h("%sstatic void %s(Fl_Menu_*, %s);\n", f.indent(1), cn, ut);
}
}
int menuItemInitialized = 0;
// if the name is an array variable, assign the value here
if (name() && strchr(name(), '[')) {
write_c("%s%s = &%s[%d];\n", indent_plus(1), name(), mname, i);
f.write_c("%s%s = &%s[%d];\n", f.indent_plus(1), name(), mname, i);
}
if (image) {
start_menu_initialiser(menuItemInitialized, mname, i);
start_menu_initialiser(f, menuItemInitialized, mname, i);
if (label() && label()[0]) {
write_c("%sFl_Multi_Label *ml = new Fl_Multi_Label;\n", indent());
write_c("%sml->labela = (char*)", indent());
image->write_inline();
write_c(";\n");
f.write_c("%sFl_Multi_Label *ml = new Fl_Multi_Label;\n", f.indent());
f.write_c("%sml->labela = (char*)", f.indent());
image->write_inline(f);
f.write_c(";\n");
if (g_project.i18n_type==0) {
write_c("%sml->labelb = o->label();\n", indent());
f.write_c("%sml->labelb = o->label();\n", f.indent());
} else if (g_project.i18n_type==1) {
write_c("%sml->labelb = %s(o->label());\n",
indent(), g_project.i18n_function.value());
f.write_c("%sml->labelb = %s(o->label());\n",
f.indent(), g_project.i18n_function.value());
} else if (g_project.i18n_type==2) {
write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n",
indent(), g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n",
f.indent(), g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
g_project.i18n_set.value(), msgnum());
}
write_c("%sml->typea = FL_IMAGE_LABEL;\n", indent());
write_c("%sml->typeb = FL_NORMAL_LABEL;\n", indent());
write_c("%sml->label(o);\n", indent());
f.write_c("%sml->typea = FL_IMAGE_LABEL;\n", f.indent());
f.write_c("%sml->typeb = FL_NORMAL_LABEL;\n", f.indent());
f.write_c("%sml->label(o);\n", f.indent());
} else {
image->write_code(0, "o");
image->write_code(f, 0, "o");
}
}
if (g_project.i18n_type && label() && label()[0]) {
@ -497,30 +496,30 @@ void Fl_Menu_Item_Type::write_code1() {
// label was already copied a few lines up
} else if ( t==FL_NORMAL_LABEL || t==FL_SHADOW_LABEL
|| t==FL_ENGRAVED_LABEL || t==FL_EMBOSSED_LABEL) {
start_menu_initialiser(menuItemInitialized, mname, i);
start_menu_initialiser(f, menuItemInitialized, mname, i);
if (g_project.i18n_type==1) {
write_c("%so->label(%s(o->label()));\n",
indent(), g_project.i18n_function.value());
f.write_c("%so->label(%s(o->label()));\n",
f.indent(), g_project.i18n_function.value());
} else if (g_project.i18n_type==2) {
write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n",
indent(), g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n",
f.indent(), g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
g_project.i18n_set.value(), msgnum());
}
}
}
for (int n=0; n < NUM_EXTRA_CODE; n++) {
if (extra_code(n) && !isdeclare(extra_code(n))) {
start_menu_initialiser(menuItemInitialized, mname, i);
write_c("%s%s\n", indent(), extra_code(n));
start_menu_initialiser(f, menuItemInitialized, mname, i);
f.write_c("%s%s\n", f.indent(), extra_code(n));
}
}
if (menuItemInitialized) {
indentation--;
write_c("%s}\n",indent());
f.indentation--;
f.write_c("%s}\n",f.indent());
}
}
void Fl_Menu_Item_Type::write_code2() {}
void Fl_Menu_Item_Type::write_code2(Fd_Code_Writer&) {}
////////////////////////////////////////////////////////////////
// This is the base class for widgets that contain a menu (ie
@ -612,12 +611,12 @@ Fl_Type* Fl_Menu_Type::click_test(int, int) {
return this;
}
void Fl_Menu_Type::write_code2() {
void Fl_Menu_Type::write_code2(Fd_Code_Writer& f) {
if (next && next->is_menu_item()) {
write_c("%s%s->menu(%s);\n", indent(), name() ? name() : "o",
unique_id(this, "menu", name(), label()));
f.write_c("%s%s->menu(%s);\n", f.indent(), name() ? name() : "o",
f.unique_id(this, "menu", name(), label()));
}
Fl_Widget_Type::write_code2();
Fl_Widget_Type::write_code2(f);
}
void Fl_Menu_Type::copy_properties() {

View File

@ -41,12 +41,12 @@ public:
int is_button() const FL_OVERRIDE {return 1;} // this gets shortcut to work
Fl_Widget* widget(int,int,int,int) FL_OVERRIDE {return 0;}
Fl_Widget_Type* _make() FL_OVERRIDE {return 0;}
virtual const char* menu_name(int& i);
virtual const char* menu_name(Fd_Code_Writer& f, int& i);
int flags();
void write_static() FL_OVERRIDE;
void write_item();
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_static(Fd_Code_Writer& f) FL_OVERRIDE;
void write_item(Fd_Code_Writer& f);
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 16; }
};
@ -105,7 +105,7 @@ public:
void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE {build_menu();}
void remove_child(Fl_Type*) FL_OVERRIDE {build_menu();}
Fl_Type* click_test(int x, int y) FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void copy_properties() FL_OVERRIDE;
};

View File

@ -160,9 +160,14 @@ void later_cb(Fl_Widget*,void*) {
widget_browser->rebuild();
}
/** \brief Delete all children of a Type.
*/
static void delete_children(Fl_Type *p) {
Fl_Type *f;
// find all types following p that are higher in level, effectively finding
// the last child of the last child
for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/}
// now loop back up to p, deleting all children on the way
for (; f != p; ) {
Fl_Type *g = f->prev;
delete f;
@ -178,7 +183,9 @@ void delete_all(int selected_only) {
Fl_Type *g = f->next;
delete f;
f = g;
} else f = f->next;
} else {
f = f->next;
}
}
if(!selected_only) {
// reset the setting for the external shell command
@ -281,11 +288,11 @@ Fl_Type::Fl_Type() {
*/
Fl_Type::~Fl_Type() {
// warning: destructor only works for widgets that have been add()ed.
if (prev) prev->next = next; else first = next;
if (next) next->prev = prev; else last = prev;
if (Fl_Type::last==this) Fl_Type::last = prev;
if (Fl_Type::first==this) Fl_Type::first = next;
if (current == this) current = 0;
if (prev) prev->next = next; // else first = next; // don't do that! The Type may not be part of the main list
if (next) next->prev = prev; // else last = prev;
if (Fl_Type::last == this) Fl_Type::last = prev;
if (Fl_Type::first == this) Fl_Type::first = next;
if (current == this) current = NULL;
if (parent) parent->remove_child(this);
if (name_) free((void*)name_);
if (label_) free((void*)label_);
@ -576,76 +583,76 @@ void Fl_Type::move_before(Fl_Type* g) {
// write a widget and all its children:
void Fl_Type::write() {
write_indent(level);
write_word(type_name());
void Fl_Type::write(Fd_Project_Writer &f) {
f.write_indent(level);
f.write_word(type_name());
if (is_class()) {
const char * p = ((Fl_Class_Type*)this)->prefix();
if (p && strlen(p))
write_word(p);
}
if (is_class()) {
const char * p = ((Fl_Class_Type*)this)->prefix();
if (p && strlen(p))
f.write_word(p);
}
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);
f.write_word(name());
f.write_open(level);
write_properties(f);
f.write_close(level);
if (!is_parent()) return;
// now do children:
f.write_open(level);
Fl_Type *child;
for (child = next; child && child->level > level; child = child->next)
if (child->level == level+1) child->write(f);
f.write_close(level);
}
void Fl_Type::write_properties() {
void Fl_Type::write_properties(Fd_Project_Writer &f) {
// repeat this for each attribute:
if (label()) {
write_indent(level+1);
write_word("label");
write_word(label());
f.write_indent(level+1);
f.write_word("label");
f.write_word(label());
}
if (user_data()) {
write_indent(level+1);
write_word("user_data");
write_word(user_data());
f.write_indent(level+1);
f.write_word("user_data");
f.write_word(user_data());
}
if (user_data_type()) {
write_word("user_data_type");
write_word(user_data_type());
f.write_word("user_data_type");
f.write_word(user_data_type());
}
if (callback()) {
write_indent(level+1);
write_word("callback");
write_word(callback());
f.write_indent(level+1);
f.write_word("callback");
f.write_word(callback());
}
if (comment()) {
write_indent(level+1);
write_word("comment");
write_word(comment());
f.write_indent(level+1);
f.write_word("comment");
f.write_word(comment());
}
if (is_parent() && open_) write_word("open");
if (selected) write_word("selected");
if (is_parent() && open_) f.write_word("open");
if (selected) f.write_word("selected");
}
void Fl_Type::read_property(const char *c) {
void Fl_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"label"))
label(read_word());
label(f.read_word());
else if (!strcmp(c,"user_data"))
user_data(read_word());
user_data(f.read_word());
else if (!strcmp(c,"user_data_type"))
user_data_type(read_word());
user_data_type(f.read_word());
else if (!strcmp(c,"callback"))
callback(read_word());
callback(f.read_word());
else if (!strcmp(c,"comment"))
comment(read_word());
comment(f.read_word());
else if (!strcmp(c,"open"))
open_ = 1;
else if (!strcmp(c,"selected"))
select(this,1);
else
read_error("Unknown property \"%s\"", c);
f.read_error("Unknown property \"%s\"", c);
}
int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
@ -654,86 +661,86 @@ int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
Write a comment into the header file.
\param[in] pre indent the comment by this string
*/
void Fl_Type::write_comment_h(const char *pre)
void Fl_Type::write_comment_h(Fd_Code_Writer& f, const char *pre)
{
if (comment() && *comment()) {
write_h("%s/**\n", pre);
f.write_h("%s/**\n", pre);
const char *s = comment();
write_h("%s ", pre);
f.write_h("%s ", pre);
while(*s) {
if (*s=='\n') {
if (s[1]) {
write_h("\n%s ", pre);
f.write_h("\n%s ", pre);
}
} else {
write_h("%c", *s); // FIXME this is much too slow!
f.write_h("%c", *s); // FIXME this is much too slow!
}
s++;
}
write_h("\n%s*/\n", pre);
f.write_h("\n%s*/\n", pre);
}
}
/**
Write a comment into the source file.
*/
void Fl_Type::write_comment_c(const char *pre)
void Fl_Type::write_comment_c(Fd_Code_Writer& f, const char *pre)
{
if (comment() && *comment()) {
write_c("%s/**\n", pre);
f.write_c("%s/**\n", pre);
const char *s = comment();
write_c("%s ", pre);
f.write_c("%s ", pre);
while(*s) {
if (*s=='\n') {
if (s[1]) {
write_c("\n%s ", pre);
f.write_c("\n%s ", pre);
}
} else {
write_c("%c", *s); // FIXME this is much too slow!
f.write_c("%c", *s); // FIXME this is much too slow!
}
s++;
}
write_c("\n%s*/\n", pre);
f.write_c("\n%s*/\n", pre);
}
}
/**
Write a comment into the source file.
*/
void Fl_Type::write_comment_inline_c(const char *pre)
void Fl_Type::write_comment_inline_c(Fd_Code_Writer& f, const char *pre)
{
if (comment() && *comment()) {
const char *s = comment();
if (strchr(s, '\n')==0L) {
// single line comment
if (pre) write_c("%s", pre);
write_c("// %s\n", s);
if (!pre) write_c("%s", indent_plus(1));
if (pre) f.write_c("%s", pre);
f.write_c("// %s\n", s);
if (!pre) f.write_c("%s", f.indent_plus(1));
} else {
write_c("%s/*\n", pre?pre:"");
f.write_c("%s/*\n", pre?pre:"");
if (pre)
write_c("%s ", pre);
f.write_c("%s ", pre);
else
write_c("%s ", indent_plus(1));
f.write_c("%s ", f.indent_plus(1));
while(*s) {
if (*s=='\n') {
if (s[1]) {
if (pre)
write_c("\n%s ", pre);
f.write_c("\n%s ", pre);
else
write_c("\n%s ", indent_plus(1));
f.write_c("\n%s ", f.indent_plus(1));
}
} else {
write_c("%c", *s); // FIXME this is much too slow!
f.write_c("%c", *s); // FIXME this is much too slow!
}
s++;
}
if (pre)
write_c("\n%s */\n", pre);
f.write_c("\n%s */\n", pre);
else
write_c("\n%s */\n", indent_plus(1));
f.write_c("\n%s */\n", f.indent_plus(1));
if (!pre)
write_c("%s", indent_plus(1));
f.write_c("%s", f.indent_plus(1));
}
}
}
@ -777,9 +784,9 @@ int Fl_Type::user_defined(const char* cbname) const {
return 0;
}
const char *Fl_Type::callback_name() {
const char *Fl_Type::callback_name(Fd_Code_Writer& f) {
if (is_name(callback())) return callback();
return unique_id(this, "cb", name(), label());
return f.unique_id(this, "cb", name(), label());
}
const char* Fl_Type::class_name(const int need_nest) const {
@ -818,15 +825,15 @@ const Fl_Class_Type *Fl_Type::is_in_class() const {
return 0;
}
void Fl_Type::write_static() {
void Fl_Type::write_static(Fd_Code_Writer&) {
}
void Fl_Type::write_code1() {
write_h("// Header for %s\n", title());
write_c("// Code for %s\n", title());
void Fl_Type::write_code1(Fd_Code_Writer& f) {
f.write_h("// Header for %s\n", title());
f.write_c("// Code for %s\n", title());
}
void Fl_Type::write_code2() {
void Fl_Type::write_code2(Fd_Code_Writer&) {
}
/// \}

View File

@ -20,10 +20,15 @@
#include <FL/Fl_Widget.H>
#include <FL/fl_draw.H>
#include "code.h"
class Fl_Type;
class Fl_Group_Type;
class Fl_Window_Type;
class Fd_Project_Reader;
class Fd_Project_Writer;
typedef enum {
kAddAsLastChild = 0,
kAddAfterCurrent
@ -72,7 +77,7 @@ public: // things that should not be public:
Fl_Type *first_child();
Fl_Type *factory;
const char *callback_name();
const char *callback_name(Fd_Code_Writer& f);
int code_position, header_position;
int code_position_end, header_position_end;
@ -121,19 +126,19 @@ public:
virtual void open(); // what happens when you double-click
// read and write data to a saved file:
virtual void write();
virtual void write_properties();
virtual void read_property(const char *);
virtual void write(Fd_Project_Writer &f);
virtual void write_properties(Fd_Project_Writer &f);
virtual void read_property(Fd_Project_Reader &f, const char *);
virtual int read_fdesign(const char*, const char*);
virtual void postprocess_read() { }
// write code, these are called in order:
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
void write_comment_h(const char *ind=""); // write the commentary text into the header file
void write_comment_c(const char *ind=""); // write the commentary text into the source file
void write_comment_inline_c(const char *ind=0L); // write the commentary text
virtual void write_static(Fd_Code_Writer& f); // write static stuff to .c file
virtual void write_code1(Fd_Code_Writer& f); // code and .h before children
virtual void write_code2(Fd_Code_Writer& f); // code and .h after children
void write_comment_h(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the header file
void write_comment_c(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the source file
void write_comment_inline_c(Fd_Code_Writer& f, const char *ind=0L); // write the commentary text
// live mode
virtual Fl_Widget *enter_live_mode(int top=0); // build wdgets needed for live mode

View File

@ -286,7 +286,7 @@ Fl_Type *sort(Fl_Type *parent) {
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) {
for (g = parent ? parent->next : Fl_Type::first; 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;
@ -320,7 +320,7 @@ void name_cb(Fl_Input* o, void *v) {
snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected);
o->hide();
} else {
o->static_value(current_widget->name());
o->value(current_widget->name());
o->show();
snprintf(buf, sizeof(buf), "%s Properties", current_widget->title());
}
@ -384,7 +384,7 @@ void name_public_cb(Fl_Choice* i, void* v) {
/* Treating UNDO for text widget.
Goal: we want to continiously update the UI while the user is typing text
(changing the label, in this case). Source View does deferred uodates, and
(changing the label, in this case). Source View does deferred updates, and
the widget browser and widget panel update on every keystroke. At the same
time, we want to limit undo actions to few and logical units.
@ -397,7 +397,7 @@ void name_public_cb(Fl_Choice* i, void* v) {
The edit process has these main states:
1: starting to edit [first_change==1 && !unfocus]; we must create a single undo checkpoint before anything changes
2: continue editing [first_change==0 && !unfocus] ; we must suspend any undo checkpoints
2: continue editing [first_change==0 && !unfocus]; we must suspend any undo checkpoints
3: done editing, unfocus [first_change==0 && unfocus]; we must make sure that undo checkpoints are enabled again
4: losing focus without editing [first_change==1 && unfocus]; don't create and checkpoints
@ -409,7 +409,7 @@ void name_public_cb(Fl_Choice* i, void* v) {
void label_cb(Fl_Input* i, void *v) {
static int first_change = 1;
if (v == LOAD) {
i->static_value(current_widget->label());
i->value(current_widget->label());
first_change = 1;
} else {
if (i->changed()) {
@ -444,7 +444,7 @@ void image_cb(Fl_Input* i, void *v) {
image_input = i;
if (current_widget->is_widget() && !current_widget->is_window()) {
i->activate();
i->static_value(((Fl_Widget_Type*)current_widget)->image_name());
i->value(((Fl_Widget_Type*)current_widget)->image_name());
} else i->deactivate();
} else {
int mod = 0;
@ -526,7 +526,7 @@ void inactive_cb(Fl_Input* i, void *v) {
inactive_input = i;
if (current_widget->is_widget() && !current_widget->is_window()) {
i->activate();
i->static_value(((Fl_Widget_Type*)current_widget)->inactive_name());
i->value(((Fl_Widget_Type*)current_widget)->inactive_name());
} else i->deactivate();
} else {
int mod = 0;
@ -605,7 +605,7 @@ void tooltip_cb(Fl_Input* i, void *v) {
if (v == LOAD) {
if (current_widget->is_widget()) {
i->activate();
i->static_value(((Fl_Widget_Type*)current_widget)->tooltip());
i->value(((Fl_Widget_Type*)current_widget)->tooltip());
} else i->deactivate();
} else {
int mod = 0;
@ -1736,7 +1736,7 @@ void comment_cb(Fl_Text_Editor* i, void *v) {
void user_data_cb(Fl_Input *i, void *v) {
if (v == LOAD) {
i->static_value(current_widget->user_data());
i->value(current_widget->user_data());
} else {
int mod = 0;
const char *c = i->value();
@ -1784,7 +1784,7 @@ void user_data_type_cb(Fl_Input_Choice *i, void *v) {
void v_input_cb(Fl_Input* i, void* v) {
int n = fl_int(i->user_data());
if (v == LOAD) {
i->static_value(current_widget->extra_code(n));
i->value(current_widget->extra_code(n));
} else {
int mod = 0;
const char *c = i->value();
@ -1804,7 +1804,7 @@ void v_input_cb(Fl_Input* i, void* v) {
void subclass_cb(Fl_Input* i, void* v) {
if (v == LOAD) {
if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate();
i->static_value(current_widget->subclass());
i->value(current_widget->subclass());
} else {
int mod = 0;
const char *c = i->value();
@ -2735,15 +2735,15 @@ int isdeclare(const char *c) {
return 0;
}
void Fl_Widget_Type::write_static() {
void Fl_Widget_Type::write_static(Fd_Code_Writer& f) {
const char* t = subclassname(this);
if (!subclass() || (is_class() && !strncmp(t, "Fl_", 3))) {
write_declare("#include <FL/Fl.H>");
write_declare("#include <FL/%s.H>", t);
f.write_h_once("#include <FL/Fl.H>");
f.write_h_once("#include <FL/%s.H>", t);
}
for (int n=0; n < NUM_EXTRA_CODE; n++) {
if (extra_code(n) && isdeclare(extra_code(n)))
write_declare("%s", extra_code(n));
f.write_h_once("%s", extra_code(n));
}
if (callback() && is_name(callback())) {
int write_extern_declaration = 1;
@ -2757,17 +2757,17 @@ void Fl_Widget_Type::write_static() {
write_extern_declaration = 0;
}
if (write_extern_declaration)
write_declare("extern void %s(%s*, %s);", callback(), t,
f.write_h_once("extern void %s(%s*, %s);", callback(), t,
user_data_type() ? user_data_type() : "void*");
}
const char* k = class_name(1);
const char* c = array_name(this);
if (c && !k && !is_class()) {
write_c("\n");
if (!public_) write_c("static ");
else write_h("extern %s *%s;\n", t, c);
if (strchr(c, '[') == NULL) write_c("%s *%s=(%s *)0;\n", t, c, t);
else write_c("%s *%s={(%s *)0};\n", t, c, t);
f.write_c("\n");
if (!public_) f.write_c("static ");
else f.write_h("extern %s *%s;\n", t, c);
if (strchr(c, '[') == NULL) f.write_c("%s *%s=(%s *)0;\n", t, c, t);
else f.write_c("%s *%s={(%s *)0};\n", t, c, t);
}
if (callback() && !is_name(callback())) {
// see if 'o' or 'v' used, to prevent unused argument warnings:
@ -2780,157 +2780,167 @@ void Fl_Widget_Type::write_static() {
do d++; while (is_id(*d));
while (*d && !is_id(*d)) d++;
}
const char* cn = callback_name();
const char* cn = callback_name(f);
if (k) {
write_c("\nvoid %s::%s_i(%s*", k, cn, t);
f.write_c("\nvoid %s::%s_i(%s*", k, cn, t);
} else {
write_c("\nstatic void %s(%s*", cn, t);
f.write_c("\nstatic void %s(%s*", cn, t);
}
if (use_o) write_c(" o");
if (use_o) f.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");
write_c_indented(callback(), 1, 0);
f.write_c(", %s", ut);
if (use_v) f.write_c(" v");
f.write_c(") {\n");
f.write_c_indented(callback(), 1, 0);
if (*(d-1) != ';' && *(d-1) != '}') {
const char *p = strrchr(callback(), '\n');
if (p) p ++;
else p = callback();
// Only add trailing semicolon if the last line is not a preprocessor
// statement...
if (*p != '#' && *p) write_c(";");
if (*p != '#' && *p) f.write_c(";");
}
write_c("\n}\n");
f.write_c("\n}\n");
if (k) {
write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
write_c("%s((%s*)(o", indent(1), k);
f.write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
f.write_c("%s((%s*)(o", f.indent(1), k);
Fl_Type *q = 0;
for (Fl_Type* p = parent; p && p->is_widget(); q = p, p = p->parent)
write_c("->parent()");
f.write_c("->parent()");
if (!q || strcmp(q->type_name(), "widget_class"))
write_c("->user_data()");
write_c("))->%s_i(o,v);\n}\n", cn);
f.write_c("->user_data()");
f.write_c("))->%s_i(o,v);\n}\n", cn);
}
}
if (image) {
if (image->written != write_number) {
image->write_static(compress_image_);
image->written = write_number;
}
if (!f.c_contains(image))
image->write_static(f, compress_image_);
}
if (inactive) {
if (inactive->written != write_number) {
inactive->write_static(compress_deimage_);
inactive->written = write_number;
}
if (!f.c_contains(inactive))
inactive->write_static(f, compress_deimage_);
}
}
extern int varused_test, varused;
void Fl_Widget_Type::write_code1() {
void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) {
const char* t = subclassname(this);
const char *c = array_name(this);
if (c) {
if (class_name(1)) {
write_public(public_);
write_h("%s%s *%s;\n", indent(1), t, c);
f.write_public(public_);
f.write_h("%s%s *%s;\n", f.indent(1), t, c);
}
}
if (class_name(1) && callback() && !is_name(callback())) {
const char* cn = callback_name();
const char* cn = callback_name(f);
const char* ut = user_data_type() ? user_data_type() : "void*";
write_public(0);
write_h("%sinline void %s_i(%s*, %s);\n", indent(1), cn, t, ut);
write_h("%sstatic void %s(%s*, %s);\n", indent(1), cn, t, ut);
f.write_public(0);
f.write_h("%sinline void %s_i(%s*, %s);\n", f.indent(1), cn, t, ut);
f.write_h("%sstatic void %s(%s*, %s);\n", f.indent(1), cn, t, ut);
}
// figure out if local variable will be used (prevent compiler warnings):
int wused = !name() && is_window();
const char *ptr;
varused = wused;
f.varused = wused;
if (!name() && !varused) {
varused |= is_parent();
if (!name() && !f.varused) {
f.varused |= is_parent();
if (!varused) {
varused_test = 1;
write_widget_code();
varused_test = 0;
if (!f.varused) {
f.varused_test = 1;
write_widget_code(f);
f.varused_test = 0;
}
}
if (!varused) {
if (!f.varused) {
for (int n=0; n < NUM_EXTRA_CODE; n++)
if (extra_code(n) && !isdeclare(extra_code(n)))
{
int instring = 0;
int inname = 0;
int incomment = 0;
int incppcomment = 0;
for (ptr = extra_code(n); *ptr; ptr ++) {
if (instring) {
if (*ptr == '\\') ptr++;
else if (*ptr == '\"') instring = 0;
} else if (inname && !isalnum(*ptr & 255)) inname = 0;
else if (*ptr == '\"') instring = 1;
else if (isalnum(*ptr & 255) || *ptr == '_') {
} else if (inname && !isalnum(*ptr & 255)) {
inname = 0;
} else if (*ptr == '/' && ptr[1]=='*') {
incomment = 1; ptr++;
} else if (incomment) {
if (*ptr == '*' && ptr[1]=='/') {
incomment = 0; ptr++;
}
} else if (*ptr == '/' && ptr[1]=='/') {
incppcomment = 1; ptr++;
} else if (incppcomment) {
if (*ptr == '\n')
incppcomment = 0;
} else if (*ptr == '\"') {
instring = 1;
} else if (isalnum(*ptr & 255) || *ptr == '_') {
size_t len = strspn(ptr, "0123456789_"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (!strncmp(ptr, "o", len)) {
varused = 1;
f.varused = 1;
break;
} else ptr += len - 1;
} else {
ptr += len - 1;
}
}
}
}
}
write_c("%s{ ", indent());
write_comment_inline_c();
if (varused) write_c("%s* o = ", t);
if (name()) write_c("%s = ", name());
f.write_c("%s{ ", f.indent());
write_comment_inline_c(f);
if (f.varused) f.write_c("%s* o = ", t);
if (name()) f.write_c("%s = ", name());
if (is_window()) {
// Handle special case where user is faking a Fl_Group type as a window,
// there is no 2-argument constructor in that case:
if (!strstr(t, "Window"))
write_c("new %s(0, 0, %d, %d", t, o->w(), o->h());
f.write_c("new %s(0, 0, %d, %d", t, o->w(), o->h());
else
write_c("new %s(%d, %d", t, o->w(), o->h());
f.write_c("new %s(%d, %d", t, o->w(), o->h());
} else {
write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
f.write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
}
if (label() && *label()) {
write_c(", ");
f.write_c(", ");
switch (g_project.i18n_type) {
case 0 : /* None */
write_cstring(label());
f.write_cstring(label());
break;
case 1 : /* GNU gettext */
write_c("%s(", g_project.i18n_function.value());
write_cstring(label());
write_c(")");
f.write_c("%s(", g_project.i18n_function.value());
f.write_cstring(label());
f.write_c(")");
break;
case 2 : /* POSIX catgets */
write_c("catgets(%s,%s,%d,", g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
f.write_c("catgets(%s,%s,%d,", g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
g_project.i18n_set.value(), msgnum());
write_cstring(label());
write_c(")");
f.write_cstring(label());
f.write_c(")");
break;
}
}
write_c(");\n");
f.write_c(");\n");
indentation++;
f.indentation++;
// Avoid compiler warning for unused variable.
// Also avoid quality control warnings about incorrect allocation error handling.
if (wused) write_c("%sw = o; (void)w;\n", indent());
if (wused) f.write_c("%sw = o; (void)w;\n", f.indent());
write_widget_code();
write_widget_code(f);
}
void Fl_Widget_Type::write_color(const char* field, Fl_Color color) {
void Fl_Widget_Type::write_color(Fd_Code_Writer& f, const char* field, Fl_Color color) {
const char* color_name = 0;
switch (color) {
case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break;
@ -2962,44 +2972,44 @@ void Fl_Widget_Type::write_color(const char* field, Fl_Color color) {
}
const char *var = is_class() ? "this" : name() ? name() : "o";
if (color_name) {
write_c("%s%s->%s(%s);\n", indent(), var, field, color_name);
f.write_c("%s%s->%s(%s);\n", f.indent(), var, field, color_name);
} else {
write_c("%s%s->%s((Fl_Color)%d);\n", indent(), var, field, color);
f.write_c("%s%s->%s((Fl_Color)%d);\n", f.indent(), var, field, color);
}
}
// this is split from write_code1() for Fl_Window_Type:
void Fl_Widget_Type::write_widget_code() {
// this is split from write_code1(Fd_Code_Writer& f) for Fl_Window_Type:
void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) {
Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
const char *var = is_class() ? "this" : name() ? name() : "o";
if (tooltip() && *tooltip()) {
write_c("%s%s->tooltip(",indent(), var);
f.write_c("%s%s->tooltip(",f.indent(), var);
switch (g_project.i18n_type) {
case 0 : /* None */
write_cstring(tooltip());
f.write_cstring(tooltip());
break;
case 1 : /* GNU gettext */
write_c("%s(", g_project.i18n_function.value());
write_cstring(tooltip());
write_c(")");
f.write_c("%s(", g_project.i18n_function.value());
f.write_cstring(tooltip());
f.write_c(")");
break;
case 2 : /* POSIX catgets */
write_c("catgets(%s,%s,%d,", g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
f.write_c("catgets(%s,%s,%d,", g_project.i18n_file[0] ? g_project.i18n_file.value() : "_catalog",
g_project.i18n_set.value(), msgnum() + 1);
write_cstring(tooltip());
write_c(")");
f.write_cstring(tooltip());
f.write_c(")");
break;
}
write_c(");\n");
f.write_c(");\n");
}
if (is_spinner() && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type())
write_c("%s%s->type(%d);\n", indent(), var, ((Fl_Spinner*)o)->type());
f.write_c("%s%s->type(%d);\n", f.indent(), var, ((Fl_Spinner*)o)->type());
else if (o->type() != tplate->type() && !is_window())
write_c("%s%s->type(%d);\n", indent(), var, o->type());
f.write_c("%s%s->type(%d);\n", f.indent(), var, o->type());
if (o->box() != tplate->box() || subclass())
write_c("%s%s->box(FL_%s);\n", indent(), var, boxname(o->box()));
f.write_c("%s%s->box(FL_%s);\n", f.indent(), var, boxname(o->box()));
// write shortcut command if needed
int shortcut = 0;
@ -3009,284 +3019,284 @@ void Fl_Widget_Type::write_widget_code() {
else if (is_text_display()) shortcut = ((Fl_Text_Display*)o)->shortcut();
if (shortcut) {
if (g_project.use_FL_COMMAND && (shortcut & (FL_CTRL|FL_META))) {
write_c("%s%s->shortcut(FL_COMMAND|0x%x);\n", indent(), var, shortcut & ~(FL_CTRL|FL_META));
f.write_c("%s%s->shortcut(FL_COMMAND|0x%x);\n", f.indent(), var, shortcut & ~(FL_CTRL|FL_META));
} else {
write_c("%s%s->shortcut(0x%x);\n", indent(), var, shortcut);
f.write_c("%s%s->shortcut(0x%x);\n", f.indent(), var, shortcut);
}
}
if (is_button()) {
Fl_Button* b = (Fl_Button*)o;
if (b->down_box()) write_c("%s%s->down_box(FL_%s);\n", indent(), var,
if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var,
boxname(b->down_box()));
if (b->value()) write_c("%s%s->value(1);\n", indent(), var);
if (b->value()) f.write_c("%s%s->value(1);\n", f.indent(), var);
} else if (!strcmp(type_name(), "Fl_Input_Choice")) {
Fl_Input_Choice* b = (Fl_Input_Choice*)o;
if (b->down_box()) write_c("%s%s->down_box(FL_%s);\n", indent(), var,
if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var,
boxname(b->down_box()));
} else if (is_menu_button()) {
Fl_Menu_* b = (Fl_Menu_*)o;
if (b->down_box()) write_c("%s%s->down_box(FL_%s);\n", indent(), var,
if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var,
boxname(b->down_box()));
}
if (o->color() != tplate->color() || subclass())
write_color("color", o->color());
write_color(f, "color", o->color());
if (o->selection_color() != tplate->selection_color() || subclass())
write_color("selection_color", o->selection_color());
if (image) image->write_code(bind_image_, var);
if (inactive) inactive->write_code(bind_deimage_, var, 1);
write_color(f, "selection_color", o->selection_color());
if (image) image->write_code(f, bind_image_, var);
if (inactive) inactive->write_code(f, bind_deimage_, var, 1);
if (o->labeltype() != tplate->labeltype() || subclass())
write_c("%s%s->labeltype(FL_%s);\n", indent(), var,
f.write_c("%s%s->labeltype(FL_%s);\n", f.indent(), var,
item_name(labeltypemenu, o->labeltype()));
if (o->labelfont() != tplate->labelfont() || subclass())
write_c("%s%s->labelfont(%d);\n", indent(), var, o->labelfont());
f.write_c("%s%s->labelfont(%d);\n", f.indent(), var, o->labelfont());
if (o->labelsize() != tplate->labelsize() || subclass())
write_c("%s%s->labelsize(%d);\n", indent(), var, o->labelsize());
f.write_c("%s%s->labelsize(%d);\n", f.indent(), var, o->labelsize());
if (o->labelcolor() != tplate->labelcolor() || subclass())
write_color("labelcolor", o->labelcolor());
write_color(f, "labelcolor", o->labelcolor());
if (is_valuator()) {
Fl_Valuator* v = (Fl_Valuator*)o;
Fl_Valuator* f = (Fl_Valuator*)(tplate);
if (v->minimum()!=f->minimum())
write_c("%s%s->minimum(%g);\n", indent(), var, v->minimum());
if (v->maximum()!=f->maximum())
write_c("%s%s->maximum(%g);\n", indent(), var, v->maximum());
if (v->step()!=f->step())
write_c("%s%s->step(%g);\n", indent(), var, v->step());
Fl_Valuator* t = (Fl_Valuator*)(tplate);
if (v->minimum()!=t->minimum())
f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum());
if (v->maximum()!=t->maximum())
f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum());
if (v->step()!=t->step())
f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step());
if (v->value()) {
if (is_valuator()==3) { // Fl_Scrollbar::value(double) is nott available
write_c("%s%s->Fl_Slider::value(%g);\n", indent(), var, v->value());
f.write_c("%s%s->Fl_Slider::value(%g);\n", f.indent(), var, v->value());
} else {
write_c("%s%s->value(%g);\n", indent(), var, v->value());
f.write_c("%s%s->value(%g);\n", f.indent(), var, 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("%s%s->slider_size(%g);\n", indent(), var, x);
double y = ((Fl_Slider*)t)->slider_size();
if (x != y) f.write_c("%s%s->slider_size(%g);\n", f.indent(), var, x);
}
}
if (is_spinner()) {
Fl_Spinner* v = (Fl_Spinner*)o;
Fl_Spinner* f = (Fl_Spinner*)(tplate);
if (v->minimum()!=f->minimum())
write_c("%s%s->minimum(%g);\n", indent(), var, v->minimum());
if (v->maximum()!=f->maximum())
write_c("%s%s->maximum(%g);\n", indent(), var, v->maximum());
if (v->step()!=f->step())
write_c("%s%s->step(%g);\n", indent(), var, v->step());
Fl_Spinner* t = (Fl_Spinner*)(tplate);
if (v->minimum()!=t->minimum())
f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum());
if (v->maximum()!=t->maximum())
f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum());
if (v->step()!=t->step())
f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step());
if (v->value()!=1.0f)
write_c("%s%s->value(%g);\n", indent(), var, v->value());
f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value());
}
{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("%s%s->textfont(%d);\n", indent(), var, f);
if (s != fs) write_c("%s%s->textsize(%d);\n", indent(), var, s);
if (c != fc) write_color("textcolor", c);
Fl_Font g; int s; Fl_Color c; textstuff(0,g,s,c);
if (g != ff) f.write_c("%s%s->textfont(%d);\n", f.indent(), var, g);
if (s != fs) f.write_c("%s%s->textsize(%d);\n", f.indent(), var, s);
if (c != fc) write_color(f, "textcolor", c);
}}
const char* ud = user_data();
if (class_name(1) && !parent->is_widget()) ud = "this";
if (callback()) {
write_c("%s%s->callback((Fl_Callback*)%s", indent(), var, callback_name());
f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f));
if (ud)
write_c(", (void*)(%s));\n", ud);
f.write_c(", (void*)(%s));\n", ud);
else
write_c(");\n");
f.write_c(");\n");
} else if (ud) {
write_c("%s%s->user_data((void*)(%s));\n", indent(), var, ud);
f.write_c("%s%s->user_data((void*)(%s));\n", f.indent(), var, ud);
}
if (o->align() != tplate->align() || subclass()) {
int i = o->align();
write_c("%s%s->align(Fl_Align(%s", indent(), var,
f.write_c("%s%s->align(Fl_Align(%s", f.indent(), var,
item_name(alignmenu, i & ~FL_ALIGN_INSIDE));
if (i & FL_ALIGN_INSIDE) write_c("|FL_ALIGN_INSIDE");
write_c("));\n");
if (i & FL_ALIGN_INSIDE) f.write_c("|FL_ALIGN_INSIDE");
f.write_c("));\n");
}
Fl_When ww = o->when();
if (ww==FL_WHEN_NOT_CHANGED)
ww = FL_WHEN_NEVER;
if (ww != tplate->when() || subclass())
write_c("%s%s->when(%s);\n", indent(), var, when_symbol_name(ww));
f.write_c("%s%s->when(%s);\n", f.indent(), var, when_symbol_name(ww));
if (!o->visible() && o->parent())
write_c("%s%s->hide();\n", indent(), var);
f.write_c("%s%s->hide();\n", f.indent(), var);
if (!o->active())
write_c("%s%s->deactivate();\n", indent(), var);
f.write_c("%s%s->deactivate();\n", f.indent(), var);
if (!is_group() && resizable())
write_c("%sFl_Group::current()->resizable(%s);\n", indent(), var);
f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var);
if (hotspot()) {
if (is_class())
write_c("%shotspot(%s);\n", indent(), var);
f.write_c("%shotspot(%s);\n", f.indent(), var);
else if (is_window())
write_c("%s%s->hotspot(%s);\n", indent(), var, var);
f.write_c("%s%s->hotspot(%s);\n", f.indent(), var, var);
else
write_c("%s%s->window()->hotspot(%s);\n", indent(), var, var);
f.write_c("%s%s->window()->hotspot(%s);\n", f.indent(), var, var);
}
}
void Fl_Widget_Type::write_extra_code() {
void Fl_Widget_Type::write_extra_code(Fd_Code_Writer& f) {
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));
f.write_c("%s%s\n", f.indent(), extra_code(n));
}
void Fl_Widget_Type::write_block_close() {
indentation--;
write_c("%s} // %s* %s\n", indent(), subclassname(this),
void Fl_Widget_Type::write_block_close(Fd_Code_Writer& f) {
f.indentation--;
f.write_c("%s} // %s* %s\n", f.indent(), subclassname(this),
name() ? name() : "o");
}
void Fl_Widget_Type::write_code2() {
write_extra_code();
write_block_close();
void Fl_Widget_Type::write_code2(Fd_Code_Writer& f) {
write_extra_code(f);
write_block_close(f);
}
////////////////////////////////////////////////////////////////
void Fl_Widget_Type::write_properties() {
Fl_Type::write_properties();
write_indent(level+1);
void Fl_Widget_Type::write_properties(Fd_Project_Writer &f) {
Fl_Type::write_properties(f);
f.write_indent(level+1);
switch (public_) {
case 0: write_string("private"); break;
case 0: f.write_string("private"); break;
case 1: break;
case 2: write_string("protected"); break;
case 2: f.write_string("protected"); break;
}
if (tooltip() && *tooltip()) {
write_string("tooltip");
write_word(tooltip());
f.write_string("tooltip");
f.write_word(tooltip());
}
if (image_name() && *image_name()) {
write_string("image");
write_word(image_name());
write_string("compress_image %d", compress_image_);
f.write_string("image");
f.write_word(image_name());
f.write_string("compress_image %d", compress_image_);
}
if (bind_image_) write_string("bind_image 1");
if (bind_image_) f.write_string("bind_image 1");
if (inactive_name() && *inactive_name()) {
write_string("deimage");
write_word(inactive_name());
write_string("compress_deimage %d", compress_deimage_);
f.write_string("deimage");
f.write_word(inactive_name());
f.write_string("compress_deimage %d", compress_deimage_);
}
if (bind_deimage_) write_string("bind_deimage 1");
write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h());
if (bind_deimage_) f.write_string("bind_deimage 1");
f.write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h());
Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
if (is_spinner() && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) {
write_string("type");
write_word(item_name(subtypes(), ((Fl_Spinner*)o)->type()));
f.write_string("type");
f.write_word(item_name(subtypes(), ((Fl_Spinner*)o)->type()));
} else if (subtypes() && (o->type() != tplate->type() || is_window())) {
write_string("type");
write_word(item_name(subtypes(), o->type()));
f.write_string("type");
f.write_word(item_name(subtypes(), o->type()));
}
if (o->box() != tplate->box()) {
write_string("box"); write_word(boxname(o->box()));}
f.write_string("box"); f.write_word(boxname(o->box()));}
if (is_input()) {
Fl_Input_* b = (Fl_Input_*)o;
if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut());
if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut());
}
if (is_value_input()) {
Fl_Value_Input* b = (Fl_Value_Input*)o;
if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut());
if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut());
}
if (is_text_display()) {
Fl_Text_Display* b = (Fl_Text_Display*)o;
if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut());
if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut());
}
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");
f.write_string("down_box"); f.write_word(boxname(b->down_box()));}
if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut());
if (b->value()) f.write_string("value 1");
} else if (!strcmp(type_name(), "Fl_Input_Choice")) {
Fl_Input_Choice* b = (Fl_Input_Choice*)o;
if (b->down_box()) {
write_string("down_box"); write_word(boxname(b->down_box()));}
f.write_string("down_box"); f.write_word(boxname(b->down_box()));}
} else if (is_menu_button()) {
Fl_Menu_* b = (Fl_Menu_*)o;
if (b->down_box()) {
write_string("down_box"); write_word(boxname(b->down_box()));}
f.write_string("down_box"); f.write_word(boxname(b->down_box()));}
}
if (o->color()!=tplate->color())
write_string("color %d", o->color());
f.write_string("color %d", o->color());
if (o->selection_color()!=tplate->selection_color())
write_string("selection_color %d", o->selection_color());
f.write_string("selection_color %d", o->selection_color());
if (o->labeltype()!=tplate->labeltype()) {
write_string("labeltype");
write_word(item_name(labeltypemenu, o->labeltype()));
f.write_string("labeltype");
f.write_word(item_name(labeltypemenu, o->labeltype()));
}
if (o->labelfont()!=tplate->labelfont())
write_string("labelfont %d", o->labelfont());
f.write_string("labelfont %d", o->labelfont());
if (o->labelsize()!=tplate->labelsize())
write_string("labelsize %d", o->labelsize());
f.write_string("labelsize %d", o->labelsize());
if (o->labelcolor()!=tplate->labelcolor())
write_string("labelcolor %d", o->labelcolor());
f.write_string("labelcolor %d", o->labelcolor());
if (o->align()!=tplate->align())
write_string("align %d", o->align());
f.write_string("align %d", o->align());
if (o->when() != tplate->when())
write_string("when %d", o->when());
f.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());
Fl_Valuator* t = (Fl_Valuator*)(tplate);
if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum());
if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum());
if (v->step()!=t->step()) f.write_string("step %g",v->step());
if (v->value()!=0.0) f.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);
double y = ((Fl_Slider*)t)->slider_size();
if (x != y) f.write_string("slider_size %g", x);
}
}
if (is_spinner()) {
Fl_Spinner* v = (Fl_Spinner*)o;
Fl_Spinner* f = (Fl_Spinner*)(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()!=1.0) write_string("value %g",v->value());
Fl_Spinner* t = (Fl_Spinner*)(tplate);
if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum());
if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum());
if (v->step()!=t->step()) f.write_string("step %g",v->step());
if (v->value()!=1.0) f.write_string("value %g",v->value());
}
{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);
Fl_Font ft; int s; Fl_Color c; textstuff(0,ft,s,c);
if (ft != ff) f.write_string("textfont %d", ft);
if (s != fs) f.write_string("textsize %d", s);
if (c != fc) f.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");
if (!o->visible()) f.write_string("hide");
if (!o->active()) f.write_string("deactivate");
if (resizable()) f.write_string("resizable");
if (hotspot()) f.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));
f.write_indent(level+1);
f.write_string("code%d",n);
f.write_word(extra_code(n));
}
if (subclass()) {
write_indent(level+1);
write_string("class");
write_word(subclass());
f.write_indent(level+1);
f.write_string("class");
f.write_word(subclass());
}
}
void Fl_Widget_Type::read_property(const char *c) {
int x,y,w,h; Fl_Font f; int s; Fl_Color cc;
void Fl_Widget_Type::read_property(Fd_Project_Reader &f, const char *c) {
int x,y,w,h; Fl_Font ft; int s; Fl_Color cc;
if (!strcmp(c,"private")) {
public_ = 0;
} else if (!strcmp(c,"protected")) {
public_ = 2;
} else if (!strcmp(c,"xywh")) {
if (sscanf(read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) {
if (sscanf(f.read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) {
x += pasteoffset;
y += pasteoffset;
// FIXME temporary change!
if (read_version>=2.0 && o->parent() && o->parent()!=o->window()) {
if (f.read_version>=2.0 && o->parent() && o->parent()!=o->window()) {
x += o->parent()->x();
y += o->parent()->y();
}
o->resize(x,y,w,h);
}
} else if (!strcmp(c,"tooltip")) {
tooltip(read_word());
tooltip(f.read_word());
} else if (!strcmp(c,"image")) {
image_name(read_word());
image_name(f.read_word());
// starting in 2023, `image` is always followed by `compress_image`
// the code below is for compatibility with older .fl files
const char *ext = fl_filename_ext(image_name_);
@ -3295,11 +3305,11 @@ void Fl_Widget_Type::read_property(const char *c) {
&& strcmp(ext, ".svgz"))
compress_image_ = 0; // if it is neither of those, default to uncompressed
} else if (!strcmp(c,"bind_image")) {
bind_image_ = (int)atol(read_word());
bind_image_ = (int)atol(f.read_word());
} else if (!strcmp(c,"compress_image")) {
compress_image_ = (int)atol(read_word());
compress_image_ = (int)atol(f.read_word());
} else if (!strcmp(c,"deimage")) {
inactive_name(read_word());
inactive_name(f.read_word());
// starting in 2023, `deimage` is always followed by `compress_deimage`
// the code below is for compatibility with older .fl files
const char *ext = fl_filename_ext(inactive_name_);
@ -3308,43 +3318,43 @@ void Fl_Widget_Type::read_property(const char *c) {
&& strcmp(ext, ".svgz"))
compress_deimage_ = 0; // if it is neither of those, default to uncompressed
} else if (!strcmp(c,"bind_deimage")) {
bind_deimage_ = (int)atol(read_word());
bind_deimage_ = (int)atol(f.read_word());
} else if (!strcmp(c,"compress_deimage")) {
compress_deimage_ = (int)atol(read_word());
compress_deimage_ = (int)atol(f.read_word());
} else if (!strcmp(c,"type")) {
if (is_spinner())
((Fl_Spinner*)o)->type(item_number(subtypes(), read_word()));
((Fl_Spinner*)o)->type(item_number(subtypes(), f.read_word()));
else
o->type(item_number(subtypes(), read_word()));
o->type(item_number(subtypes(), f.read_word()));
} else if (!strcmp(c,"box")) {
const char* value = read_word();
const char* value = f.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();
const char* value = f.read_word();
if ((x = boxnumber(value))) {
if (x == ZERO_ENTRY) x = 0;
((Fl_Button*)o)->down_box((Fl_Boxtype)x);
}
} else if (!strcmp(type_name(), "Fl_Input_Choice") && !strcmp(c,"down_box")) {
const char* value = read_word();
const char* value = f.read_word();
if ((x = boxnumber(value))) {
if (x == ZERO_ENTRY) x = 0;
((Fl_Input_Choice*)o)->down_box((Fl_Boxtype)x);
}
} else if (is_menu_button() && !strcmp(c,"down_box")) {
const char* value = read_word();
const char* value = f.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();
const char* value = f.read_word();
((Fl_Button*)o)->value(atoi(value));
} else if (!strcmp(c,"color")) {
const char *cw = read_word();
const char *cw = f.read_word();
if (cw[0]=='0' && cw[1]=='x') {
sscanf(cw,"0x%x",&x);
o->color(x);
@ -3358,12 +3368,12 @@ void Fl_Widget_Type::read_property(const char *c) {
}
}
} else if (!strcmp(c,"selection_color")) {
if (sscanf(read_word(),"%d",&x)) o->selection_color(x);
if (sscanf(f.read_word(),"%d",&x)) o->selection_color(x);
} else if (!strcmp(c,"labeltype")) {
c = read_word();
c = f.read_word();
if (!strcmp(c,"image")) {
Fluid_Image *i = Fluid_Image::find(label());
if (!i) read_error("Image file '%s' not found", label());
if (!i) f.read_error("Image file '%s' not found", label());
else setimage(i);
image_name(label());
label("");
@ -3371,35 +3381,35 @@ void Fl_Widget_Type::read_property(const char *c) {
o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c));
}
} else if (!strcmp(c,"labelfont")) {
if (sscanf(read_word(),"%d",&x) == 1) o->labelfont(x);
if (sscanf(f.read_word(),"%d",&x) == 1) o->labelfont(x);
} else if (!strcmp(c,"labelsize")) {
if (sscanf(read_word(),"%d",&x) == 1) o->labelsize(x);
if (sscanf(f.read_word(),"%d",&x) == 1) o->labelsize(x);
} else if (!strcmp(c,"labelcolor")) {
if (sscanf(read_word(),"%d",&x) == 1) o->labelcolor(x);
if (sscanf(f.read_word(),"%d",&x) == 1) o->labelcolor(x);
} else if (!strcmp(c,"align")) {
if (sscanf(read_word(),"%d",&x) == 1) o->align(x);
if (sscanf(f.read_word(),"%d",&x) == 1) o->align(x);
} else if (!strcmp(c,"when")) {
if (sscanf(read_word(),"%d",&x) == 1) o->when(x);
if (sscanf(f.read_word(),"%d",&x) == 1) o->when(x);
} else if (!strcmp(c,"minimum")) {
if (is_valuator()) ((Fl_Valuator*)o)->minimum(strtod(read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->minimum(strtod(read_word(),0));
if (is_valuator()) ((Fl_Valuator*)o)->minimum(strtod(f.read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->minimum(strtod(f.read_word(),0));
} else if (!strcmp(c,"maximum")) {
if (is_valuator()) ((Fl_Valuator*)o)->maximum(strtod(read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->maximum(strtod(read_word(),0));
if (is_valuator()) ((Fl_Valuator*)o)->maximum(strtod(f.read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->maximum(strtod(f.read_word(),0));
} else if (!strcmp(c,"step")) {
if (is_valuator()) ((Fl_Valuator*)o)->step(strtod(read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->step(strtod(read_word(),0));
if (is_valuator()) ((Fl_Valuator*)o)->step(strtod(f.read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->step(strtod(f.read_word(),0));
} else if (!strcmp(c,"value")) {
if (is_valuator()) ((Fl_Valuator*)o)->value(strtod(read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->value(strtod(read_word(),0));
if (is_valuator()) ((Fl_Valuator*)o)->value(strtod(f.read_word(),0));
if (is_spinner()) ((Fl_Spinner*)o)->value(strtod(f.read_word(),0));
} else if ((!strcmp(c,"slider_size")||!strcmp(c,"size"))&&is_valuator()==2) {
((Fl_Slider*)o)->slider_size(strtod(read_word(),0));
((Fl_Slider*)o)->slider_size(strtod(f.read_word(),0));
} else if (!strcmp(c,"textfont")) {
if (sscanf(read_word(),"%d",&x) == 1) {f=(Fl_Font)x; textstuff(1,f,s,cc);}
if (sscanf(f.read_word(),"%d",&x) == 1) {ft=(Fl_Font)x; textstuff(1,ft,s,cc);}
} else if (!strcmp(c,"textsize")) {
if (sscanf(read_word(),"%d",&x) == 1) {s=x; textstuff(2,f,s,cc);}
if (sscanf(f.read_word(),"%d",&x) == 1) {s=x; textstuff(2,ft,s,cc);}
} else if (!strcmp(c,"textcolor")) {
if (sscanf(read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,f,s,cc);}
if (sscanf(f.read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,ft,s,cc);}
} else if (!strcmp(c,"hide")) {
o->hide();
} else if (!strcmp(c,"deactivate")) {
@ -3409,9 +3419,9 @@ void Fl_Widget_Type::read_property(const char *c) {
} else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) {
hotspot(1);
} else if (!strcmp(c,"class")) {
subclass(read_word());
subclass(f.read_word());
} else if (!strcmp(c,"shortcut")) {
int shortcut = (int)strtol(read_word(),0,0);
int shortcut = (int)strtol(f.read_word(),0,0);
if (is_button()) ((Fl_Button*)o)->shortcut(shortcut);
else if (is_input()) ((Fl_Input_*)o)->shortcut(shortcut);
else if (is_value_input()) ((Fl_Value_Input*)o)->shortcut(shortcut);
@ -3420,14 +3430,14 @@ void Fl_Widget_Type::read_property(const char *c) {
if (!strncmp(c,"code",4)) {
int n = atoi(c+4);
if (n >= 0 && n <= NUM_EXTRA_CODE) {
extra_code(n,read_word());
extra_code(n,f.read_word());
return;
}
} else if (!strcmp(c,"extra_code")) {
extra_code(0,read_word());
extra_code(0,f.read_word());
return;
}
Fl_Type::read_property(c);
Fl_Type::read_property(f, c);
}
}

View File

@ -51,13 +51,13 @@ class Fl_Widget_Type : public Fl_Type {
protected:
void write_static() FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_widget_code();
void write_extra_code();
void write_block_close();
void write_code2() FL_OVERRIDE;
void write_color(const char*, Fl_Color);
void write_static(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_widget_code(Fd_Code_Writer& f);
void write_extra_code(Fd_Code_Writer& f);
void write_block_close(Fd_Code_Writer& f);
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void write_color(Fd_Code_Writer& f, const char*, Fl_Color);
Fl_Widget *live_widget;
public:
@ -101,8 +101,8 @@ public:
int is_widget() const FL_OVERRIDE;
int is_public() const FL_OVERRIDE;
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int read_fdesign(const char*, const char*) FL_OVERRIDE;
Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE;

View File

@ -941,7 +941,7 @@ void Fl_Window_Type::draw_overlay() {
}
// Check spacing and alignment between individual widgets
if (drag && selection->is_widget()) {
if (drag && selection && selection->is_widget()) {
for (Fl_Type *q=next; q && q->level>level; q = q->next)
if (q != selection && q->is_widget()) {
Fl_Widget_Type *qw = (Fl_Widget_Type*)q;
@ -1354,7 +1354,7 @@ int Fl_Window_Type::handle(int event) {
// or in the same group, add after selection. Otherwise, just add
// at the end of the selected group.
if ( Fl_Type::current_dnd->group()
&& selection->group()
&& selection && selection->group()
&& Fl_Type::current_dnd->group()==selection->group())
{
Fl_Type *cc = Fl_Type::current;
@ -1460,7 +1460,7 @@ int Fl_Window_Type::handle(int event) {
for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent())
if (!o1->visible()) goto CONTINUE;
if (Fl::event_inside(myo->o)) selection = myo;
if (myo->o->x()>=x1 && myo->o->y()>y1 &&
if (myo && myo->o && myo->o->x()>=x1 && myo->o->y()>y1 &&
myo->o->x()+myo->o->w()<mx && myo->o->y()+myo->o->h()<my) {
n++;
select(myo, toggle ? !myo->selected : 1);
@ -1468,7 +1468,7 @@ int Fl_Window_Type::handle(int event) {
CONTINUE:;
}
// if nothing in box, select what was clicked on:
if (!n) {
if (selection && !n) {
select(selection, toggle ? !selection->selected : 1);
}
}
@ -1538,47 +1538,47 @@ int Fl_Window_Type::handle(int event) {
////////////////////////////////////////////////////////////////
void Fl_Window_Type::write_code1() {
Fl_Widget_Type::write_code1();
void Fl_Window_Type::write_code1(Fd_Code_Writer& f) {
Fl_Widget_Type::write_code1(f);
}
void Fl_Window_Type::write_code2() {
void Fl_Window_Type::write_code2(Fd_Code_Writer& f) {
const char *var = is_class() ? "this" : name() ? name() : "o";
write_extra_code();
if (modal) write_c("%s%s->set_modal();\n", indent(), var);
else if (non_modal) write_c("%s%s->set_non_modal();\n", indent(), var);
write_extra_code(f);
if (modal) f.write_c("%s%s->set_modal();\n", f.indent(), var);
else if (non_modal) f.write_c("%s%s->set_non_modal();\n", f.indent(), var);
if (!((Fl_Window*)o)->border()) {
write_c("%s%s->clear_border();\n", indent(), var);
f.write_c("%s%s->clear_border();\n", f.indent(), var);
}
if (xclass) {
write_c("%s%s->xclass(", indent(), var);
write_cstring(xclass);
write_c(");\n");
f.write_c("%s%s->xclass(", f.indent(), var);
f.write_cstring(xclass);
f.write_c(");\n");
}
if (sr_max_w || sr_max_h) {
write_c("%s%s->size_range(%d, %d, %d, %d);\n", indent(), var,
f.write_c("%s%s->size_range(%d, %d, %d, %d);\n", f.indent(), var,
sr_min_w, sr_min_h, sr_max_w, sr_max_h);
} else if (sr_min_w || sr_min_h) {
write_c("%s%s->size_range(%d, %d);\n", indent(), var, sr_min_w, sr_min_h);
f.write_c("%s%s->size_range(%d, %d);\n", f.indent(), var, sr_min_w, sr_min_h);
}
write_c("%s%s->end();\n", indent(), var);
f.write_c("%s%s->end();\n", f.indent(), var);
if (((Fl_Window*)o)->resizable() == o)
write_c("%s%s->resizable(%s);\n", indent(), var, var);
write_block_close();
f.write_c("%s%s->resizable(%s);\n", f.indent(), var, var);
write_block_close(f);
}
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);}
void Fl_Window_Type::write_properties(Fd_Project_Writer &f) {
Fl_Widget_Type::write_properties(f);
if (modal) f.write_string("modal");
else if (non_modal) f.write_string("non_modal");
if (!((Fl_Window*)o)->border()) f.write_string("noborder");
if (xclass) {f.write_string("xclass"); f.write_word(xclass);}
if (sr_min_w || sr_min_h || sr_max_w || sr_max_h)
write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h);
if (o->visible()) write_string("visible");
f.write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h);
if (o->visible()) f.write_string("visible");
}
void Fl_Window_Type::read_property(const char *c) {
void Fl_Window_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"modal")) {
modal = 1;
} else if (!strcmp(c,"non_modal")) {
@ -1588,18 +1588,18 @@ void Fl_Window_Type::read_property(const char *c) {
} else if (!strcmp(c,"noborder")) {
((Fl_Window*)o)->border(0);
} else if (!strcmp(c,"xclass")) {
storestring(read_word(),xclass);
storestring(f.read_word(),xclass);
((Fl_Window*)o)->xclass(xclass);
} else if (!strcmp(c,"size_range")) {
int mw, mh, MW, MH;
if (sscanf(read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) {
if (sscanf(f.read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) {
sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH;
}
} else if (!strcmp(c,"xywh")) {
Fl_Widget_Type::read_property(c);
Fl_Widget_Type::read_property(f, c);
pasteoffset = 0; // make it not apply to contents
} else {
Fl_Widget_Type::read_property(c);
Fl_Widget_Type::read_property(f, c);
}
}
@ -1659,21 +1659,21 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
return myo;
}
void Fl_Widget_Class_Type::write_properties() {
Fl_Window_Type::write_properties();
void Fl_Widget_Class_Type::write_properties(Fd_Project_Writer &f) {
Fl_Window_Type::write_properties(f);
if (wc_relative==1)
write_string("position_relative");
f.write_string("position_relative");
else if (wc_relative==2)
write_string("position_relative_rescale");
f.write_string("position_relative_rescale");
}
void Fl_Widget_Class_Type::read_property(const char *c) {
void Fl_Widget_Class_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (!strcmp(c,"position_relative")) {
wc_relative = 1;
} else if (!strcmp(c,"position_relative_rescale")) {
wc_relative = 2;
} else {
Fl_Window_Type::read_property(c);
Fl_Window_Type::read_property(f, c);
}
}
@ -1690,9 +1690,9 @@ static const char *trimclassname(const char *n) {
}
void Fl_Widget_Class_Type::write_code1() {
void Fl_Widget_Class_Type::write_code1(Fd_Code_Writer& f) {
#if 0
Fl_Widget_Type::write_code1();
Fl_Widget_Type::write_code1(Fd_Code_Writer& f);
#endif // 0
current_widget_class = this;
@ -1701,80 +1701,80 @@ void Fl_Widget_Class_Type::write_code1() {
const char *c = subclass();
if (!c) c = "Fl_Group";
write_c("\n");
write_comment_h();
write_h("\nclass %s : public %s {\n", name(), c);
f.write_c("\n");
write_comment_h(f);
f.write_h("\nclass %s : public %s {\n", name(), c);
if (strstr(c, "Window")) {
write_h("%svoid _%s();\n", indent(1), trimclassname(name()));
write_h("public:\n");
write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n", indent(1), trimclassname(name()));
write_h("%s%s(int W, int H, const char *L = 0);\n", indent(1), trimclassname(name()));
write_h("%s%s();\n", indent(1), trimclassname(name()));
f.write_h("%svoid _%s();\n", f.indent(1), trimclassname(name()));
f.write_h("public:\n");
f.write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n", f.indent(1), trimclassname(name()));
f.write_h("%s%s(int W, int H, const char *L = 0);\n", f.indent(1), trimclassname(name()));
f.write_h("%s%s();\n", f.indent(1), trimclassname(name()));
// a constructor with all four dimensions plus label
write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name()));
write_c("%s%s(X, Y, W, H, L)\n{\n", indent(1), c);
write_c("%s_%s();\n", indent(1), trimclassname(name()));
write_c("}\n\n");
f.write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name()));
f.write_c("%s%s(X, Y, W, H, L)\n{\n", f.indent(1), c);
f.write_c("%s_%s();\n", f.indent(1), trimclassname(name()));
f.write_c("}\n\n");
// a constructor with just the size and label. The window manager will position the window
write_c("%s::%s(int W, int H, const char *L) :\n", name(), trimclassname(name()));
write_c("%s%s(0, 0, W, H, L)\n{\n", indent(1), c);
write_c("%sclear_flag(16);\n", indent(1));
write_c("%s_%s();\n", indent(1), trimclassname(name()));
write_c("}\n\n");
f.write_c("%s::%s(int W, int H, const char *L) :\n", name(), trimclassname(name()));
f.write_c("%s%s(0, 0, W, H, L)\n{\n", f.indent(1), c);
f.write_c("%sclear_flag(16);\n", f.indent(1));
f.write_c("%s_%s();\n", f.indent(1), trimclassname(name()));
f.write_c("}\n\n");
// a constructor that takes size and label from the Fluid database
write_c("%s::%s() :\n", name(), trimclassname(name()));
write_c("%s%s(0, 0, %d, %d, ", indent(1), c, o->w(), o->h());
f.write_c("%s::%s() :\n", name(), trimclassname(name()));
f.write_c("%s%s(0, 0, %d, %d, ", f.indent(1), c, o->w(), o->h());
const char *cstr = label();
if (cstr) write_cstring(cstr);
else write_c("0");
write_c(")\n{\n");
write_c("%sclear_flag(16);\n", indent(1));
write_c("%s_%s();\n", indent(1), trimclassname(name()));
write_c("}\n\n");
if (cstr) f.write_cstring(cstr);
else f.write_c("0");
f.write_c(")\n{\n");
f.write_c("%sclear_flag(16);\n", f.indent(1));
f.write_c("%s_%s();\n", f.indent(1), trimclassname(name()));
f.write_c("}\n\n");
write_c("void %s::_%s() {\n", name(), trimclassname(name()));
// write_c("%s%s *w = this;\n", indent(1), name());
f.write_c("void %s::_%s() {\n", name(), trimclassname(name()));
// f.write_c("%s%s *w = this;\n", f.indent(1), name());
} else {
write_h("public:\n");
write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n",
indent(1), trimclassname(name()));
write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name()));
f.write_h("public:\n");
f.write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n",
f.indent(1), trimclassname(name()));
f.write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name()));
if (wc_relative==1)
write_c("%s%s(0, 0, W, H, L)\n{\n", indent(1), c);
f.write_c("%s%s(0, 0, W, H, L)\n{\n", f.indent(1), c);
else if (wc_relative==2)
write_c("%s%s(0, 0, %d, %d, L)\n{\n", indent(1), c, o->w(), o->h());
f.write_c("%s%s(0, 0, %d, %d, L)\n{\n", f.indent(1), c, o->w(), o->h());
else
write_c("%s%s(X, Y, W, H, L)\n{\n", indent(1), c);
f.write_c("%s%s(X, Y, W, H, L)\n{\n", f.indent(1), c);
}
// write_c("%s%s *o = this;\n", indent(1), name());
// f.write_c("%s%s *o = this;\n", f.indent(1), name());
indentation++;
write_widget_code();
f.indentation++;
write_widget_code(f);
}
void Fl_Widget_Class_Type::write_code2() {
write_extra_code();
void Fl_Widget_Class_Type::write_code2(Fd_Code_Writer& f) {
write_extra_code(f);
if (wc_relative==1)
write_c("%sposition(X, Y);\n", indent());
f.write_c("%sposition(X, Y);\n", f.indent());
else if (wc_relative==2)
write_c("%sresize(X, Y, W, H);\n", indent());
if (modal) write_c("%sset_modal();\n", indent());
else if (non_modal) write_c("%sset_non_modal();\n", indent());
if (!((Fl_Window*)o)->border()) write_c("%sclear_border();\n", indent());
f.write_c("%sresize(X, Y, W, H);\n", f.indent());
if (modal) f.write_c("%sset_modal();\n", f.indent());
else if (non_modal) f.write_c("%sset_non_modal();\n", f.indent());
if (!((Fl_Window*)o)->border()) f.write_c("%sclear_border();\n", f.indent());
if (xclass) {
write_c("%sxclass(", indent());
write_cstring(xclass);
write_c(");\n");
f.write_c("%sxclass(", f.indent());
f.write_cstring(xclass);
f.write_c(");\n");
}
write_c("%send();\n", indent());
f.write_c("%send();\n", f.indent());
if (((Fl_Window*)o)->resizable() == o)
write_c("%sresizable(this);\n", indent());
indentation--;
write_c("}\n");
f.write_c("%sresizable(this);\n", f.indent());
f.indentation--;
f.write_c("}\n");
}
////////////////////////////////////////////////////////////////

View File

@ -51,8 +51,8 @@ protected:
void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
int handle(int);
void setlabel(const char *) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
Fl_Widget_Type *_make() FL_OVERRIDE {return 0;} // we don't call this
Fl_Widget *widget(int,int,int,int) FL_OVERRIDE {return 0;}
int recalc; // set by fix_overlay()
@ -84,8 +84,8 @@ public:
void fix_overlay(); // Update the bounding box, etc
uchar *read_image(int &ww, int &hh); // Read an image of the window
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
int read_fdesign(const char*, const char*) FL_OVERRIDE;
void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
@ -118,11 +118,11 @@ public:
char write_public_state; // true when public: has been printed
char wc_relative; // if 1, reposition all children, if 2, reposition and resize
void write_properties() FL_OVERRIDE;
void read_property(const char *) FL_OVERRIDE;
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
void write_code1() FL_OVERRIDE;
void write_code2() FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "widget_class";}
int pixmapID() FL_OVERRIDE { return 48; }

View File

@ -46,38 +46,28 @@ void Fluid_Image::deimage(Fl_Widget *o) {
if (o->window() != o) o->deimage(img);
}
static int pixmap_header_written = 0;
static int bitmap_header_written = 0;
static int image_header_written = 0;
static int jpeg_header_written = 0;
static int png_header_written = 0;
static int gif_header_written = 0;
static int animated_gif_header_written = 0;
static int bmp_header_written = 0;
static int svg_header_written = 0;
/** Write the contents of the name() file as binary source code.
\param fmt short name of file contents for error message
\return 0 if the file could not be opened or read */
size_t Fluid_Image::write_static_binary(const char* fmt) {
size_t Fluid_Image::write_static_binary(Fd_Code_Writer& f, const char* fmt) {
size_t nData = 0;
enter_project_dir();
FILE *f = fl_fopen(name(), "rb");
FILE *in = fl_fopen(name(), "rb");
leave_project_dir();
if (!f) {
write_file_error(fmt);
if (!in) {
write_file_error(f, fmt);
return 0;
} else {
fseek(f, 0, SEEK_END);
nData = ftell(f);
fseek(f, 0, SEEK_SET);
fseek(in, 0, SEEK_END);
nData = ftell(in);
fseek(in, 0, SEEK_SET);
if (nData) {
char *data = (char*)calloc(nData, 1);
if (fread(data, nData, 1, f)==0) { /* ignore */ }
write_cdata(data, (int)nData);
if (fread(data, nData, 1, in)==0) { /* ignore */ }
f.write_cdata(data, (int)nData);
free(data);
}
fclose(f);
fclose(in);
}
return nData;
}
@ -85,41 +75,38 @@ size_t Fluid_Image::write_static_binary(const char* fmt) {
/** Write the contents of the name() file as textual source code.
\param fmt short name of file contents for error message
\return 0 if the file could not be opened or read */
size_t Fluid_Image::write_static_text(const char* fmt) {
size_t Fluid_Image::write_static_text(Fd_Code_Writer& f, const char* fmt) {
size_t nData = 0;
enter_project_dir();
FILE *f = fl_fopen(name(), "rb");
FILE *in = fl_fopen(name(), "rb");
leave_project_dir();
if (!f) {
write_file_error(fmt);
if (!in) {
write_file_error(f, fmt);
return 0;
} else {
fseek(f, 0, SEEK_END);
nData = ftell(f);
fseek(f, 0, SEEK_SET);
fseek(in, 0, SEEK_END);
nData = ftell(in);
fseek(in, 0, SEEK_SET);
if (nData) {
char *data = (char*)calloc(nData+1, 1);
if (fread(data, nData, 1, f)==0) { /* ignore */ }
write_cstring(data, (int)nData);
if (fread(data, nData, 1, in)==0) { /* ignore */ }
f.write_cstring(data, (int)nData);
free(data);
}
fclose(f);
fclose(in);
}
return nData;
}
void Fluid_Image::write_static_rgb(const char* idata_name) {
void Fluid_Image::write_static_rgb(Fd_Code_Writer& f, const char* idata_name) {
// Write image data...
write_c("\n");
if (image_header_written != write_number) {
write_c("#include <FL/Fl_Image.H>\n");
image_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0;
write_cdata(img->data()[0], (img->w() * img->d() + extra_data) * img->h());
write_c(";\n");
write_initializer("Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, img->w(), img->h(), img->d(), img->ld());
f.write_cdata(img->data()[0], (img->w() * img->d() + extra_data) * img->h());
f.write_c(";\n");
write_initializer(f, "Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, img->w(), img->h(), img->d(), img->ld());
}
/**
@ -132,126 +119,102 @@ void Fluid_Image::write_static_rgb(const char* idata_name) {
\param compressed write data in the original compressed file format
*/
void Fluid_Image::write_static(int compressed) {
void Fluid_Image::write_static(Fd_Code_Writer& f, int compressed) {
if (!img) return;
const char *idata_name = unique_id(this, "idata", fl_filename_name(name()), 0);
function_name_ = unique_id(this, "image", fl_filename_name(name()), 0);
const char *idata_name = f.unique_id(this, "idata", fl_filename_name(name()), 0);
function_name_ = f.unique_id(this, "image", fl_filename_name(name()), 0);
if (is_animated_gif_) {
// Write animated gif image data...
write_c("\n");
if (animated_gif_header_written != write_number) {
write_c("#include <FL/Fl_Anim_GIF_Image.H>\n");
animated_gif_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("AnimGIF");
write_c(";\n");
write_initializer("Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_Anim_GIF_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "AnimGIF");
f.write_c(";\n");
write_initializer(f, "Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".gif")==0) {
// Write gif image data...
write_c("\n");
if (gif_header_written != write_number) {
write_c("#include <FL/Fl_GIF_Image.H>\n");
gif_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("GIF");
write_c(";\n");
write_initializer("Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_GIF_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "GIF");
f.write_c(";\n");
write_initializer(f, "Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".bmp")==0) {
// Write bmp image data...
write_c("\n");
if (bmp_header_written != write_number) {
write_c("#include <FL/Fl_BMP_Image.H>\n");
bmp_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("BMP");
write_c(";\n");
write_initializer("Fl_BMP_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_BMP_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "BMP");
f.write_c(";\n");
write_initializer(f, "Fl_BMP_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (img->count() > 1) {
// Write Pixmap data...
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 const char *%s[] = {\n", idata_name);
write_cstring(img->data()[0], (int)strlen(img->data()[0]));
f.write_c("\n");
f.write_c_once("#include <FL/Fl_Pixmap.H>\n");
f.write_c("static const char *%s[] = {\n", idata_name);
f.write_cstring(img->data()[0], (int)strlen(img->data()[0]));
int i;
int ncolors, chars_per_color;
sscanf(img->data()[0], "%*d%*d%d%d", &ncolors, &chars_per_color);
if (ncolors < 0) {
write_c(",\n");
write_cstring(img->data()[1], ncolors * -4);
f.write_c(",\n");
f.write_cstring(img->data()[1], ncolors * -4);
i = 2;
} else {
for (i = 1; i <= ncolors; i ++) {
write_c(",\n");
write_cstring(img->data()[i], (int)strlen(img->data()[i]));
f.write_c(",\n");
f.write_cstring(img->data()[i], (int)strlen(img->data()[i]));
}
}
for (; i < img->count(); i ++) {
write_c(",\n");
write_cstring(img->data()[i], img->w() * chars_per_color);
f.write_c(",\n");
f.write_cstring(img->data()[i], img->w() * chars_per_color);
}
write_c("\n};\n");
write_initializer("Fl_Pixmap", "%s", idata_name);
f.write_c("\n};\n");
write_initializer(f, "Fl_Pixmap", "%s", idata_name);
} else if (img->d() == 0) {
// Write Bitmap data...
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 const unsigned char %s[] =\n", idata_name);
write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h());
write_c(";\n");
write_initializer( "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h());
f.write_c("\n");
f.write_c_once("#include <FL/Fl_Bitmap.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
f.write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h());
f.write_c(";\n");
write_initializer(f, "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h());
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".jpg")==0) {
// Write jpeg image data...
write_c("\n");
if (jpeg_header_written != write_number) {
write_c("#include <FL/Fl_JPEG_Image.H>\n");
jpeg_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("JPEG");
write_c(";\n");
write_initializer("Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_JPEG_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "JPEG");
f.write_c(";\n");
write_initializer(f, "Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".png")==0) {
// Write png image data...
write_c("\n");
if (png_header_written != write_number) {
write_c("#include <FL/Fl_PNG_Image.H>\n");
png_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("PNG");
write_c(";\n");
write_initializer("Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
f.write_c("\n");
f.write_c_once("#include <FL/Fl_PNG_Image.H>\n");
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "PNG");
f.write_c(";\n");
write_initializer(f, "Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (fl_ascii_strcasecmp(fl_filename_ext(name()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(name()), ".svgz")==0) {
bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0);
// Write svg image data...
if (compressed) {
write_c("\n");
if (svg_header_written != write_number) {
write_c("#include <FL/Fl_SVG_Image.H>\n");
svg_header_written = write_number;
}
f.write_c("\n");
f.write_c_once("#include <FL/Fl_SVG_Image.H>\n");
if (gzipped) {
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("SVGZ");
write_c(";\n");
write_initializer("Fl_SVG_Image", "\"%s\", %s, %ld", fl_filename_name(name()), idata_name, nData);
f.write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary(f, "SVGZ");
f.write_c(";\n");
write_initializer(f, "Fl_SVG_Image", "\"%s\", %s, %ld", fl_filename_name(name()), idata_name, nData);
} else {
write_c("static const char %s[] =\n", idata_name);
write_static_text("SVG");
write_c(";\n");
write_initializer("Fl_SVG_Image", "\"%s\", %s", fl_filename_name(name()), idata_name);
f.write_c("static const char %s[] =\n", idata_name);
write_static_text(f, "SVG");
f.write_c(";\n");
write_initializer(f, "Fl_SVG_Image", "\"%s\", %s", fl_filename_name(name()), idata_name);
}
} else {
// if FLUID runs from the command line, make sure that the image is not
@ -264,24 +227,24 @@ void Fluid_Image::write_static(int compressed) {
svg_image = rgb_image->as_svg_image();
if (svg_image) {
svg_image->resize(svg_image->w(), svg_image->h());
write_static_rgb(idata_name);
write_static_rgb(f, idata_name);
} else {
write_file_error("RGB_from_SVG");
write_file_error(f, "RGB_from_SVG");
}
}
} else {
write_static_rgb(idata_name);
write_static_rgb(f, idata_name);
}
}
void Fluid_Image::write_file_error(const char *fmt) {
write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno));
void Fluid_Image::write_file_error(Fd_Code_Writer& f, const char *fmt) {
f.write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno));
enter_project_dir();
write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX));
f.write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX));
leave_project_dir();
}
void Fluid_Image::write_initializer(const char *type_name, const char *format, ...) {
void Fluid_Image::write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...) {
/* Outputs code that returns (and initializes if needed) an Fl_Image as follows:
static Fl_Image *'function_name_'() {
static Fl_Image *image = NULL;
@ -291,32 +254,32 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
} */
va_list ap;
va_start(ap, format);
write_c("static Fl_Image *%s() {\n", function_name_);
f.write_c("static Fl_Image *%s() {\n", function_name_);
if (is_animated_gif_)
write_c("%sFl_GIF_Image::animate = true;\n", indent(1));
write_c("%sstatic Fl_Image *image = NULL;\n", indent(1));
write_c("%sif (!image)\n", indent(1));
write_c("%simage = new %s(", indent(2), type_name);
vwrite_c(format, ap);
write_c(");\n");
write_c("%sreturn image;\n", indent(1));
write_c("}\n");
f.write_c("%sFl_GIF_Image::animate = true;\n", f.indent(1));
f.write_c("%sstatic Fl_Image *image = NULL;\n", f.indent(1));
f.write_c("%sif (!image)\n", f.indent(1));
f.write_c("%simage = new %s(", f.indent(2), type_name);
f.vwrite_c(format, ap);
f.write_c(");\n");
f.write_c("%sreturn image;\n", f.indent(1));
f.write_c("}\n");
va_end(ap);
}
void Fluid_Image::write_code(int bind, const char *var, int inactive) {
void Fluid_Image::write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive) {
/* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item.
This code calls a function output before by Fluid_Image::write_initializer() */
if (img) {
write_c("%s%s->%s%s( %s() );\n", indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
f.write_c("%s%s->%s%s( %s() );\n", f.indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
if (is_animated_gif_)
write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", indent(), function_name_, var);
f.write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", f.indent(), function_name_, var);
}
}
void Fluid_Image::write_inline(int inactive) {
void Fluid_Image::write_inline(Fd_Code_Writer& f, int inactive) {
if (img)
write_c("%s()", function_name_);
f.write_c("%s()", function_name_);
}
@ -345,7 +308,10 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
enter_project_dir();
FILE *f = fl_fopen(iname,"rb");
if (!f) {
read_error("%s : %s",iname,strerror(errno));
if (batch_mode)
fprintf(stderr, "Can't open image file:\n%s\n%s",iname,strerror(errno));
else
fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno));
leave_project_dir();
return 0;
}
@ -356,7 +322,10 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
if (!ret->img || !ret->img->w() || !ret->img->h()) {
delete ret;
ret = 0;
read_error("%s : unrecognized image format", iname);
if (batch_mode)
fprintf(stderr, "Can't read image file:\n%s\nunrecognized image format",iname);
else
fl_message("Can't read image file:\n%s\nunrecognized image format",iname);
}
leave_project_dir();
if (!ret) return 0;

View File

@ -23,6 +23,8 @@
#include <FL/Fl_Shared_Image.H>
#include "code.h"
class Fluid_Image {
bool is_animated_gif_;
const char *name_;
@ -32,9 +34,9 @@ class Fluid_Image {
protected:
Fluid_Image(const char *name); // no public constructor
~Fluid_Image(); // no public destructor
size_t write_static_binary(const char* fmt);
size_t write_static_text(const char* fmt);
void write_static_rgb(const char* idata_name);
size_t write_static_binary(Fd_Code_Writer& f, const char* fmt);
size_t write_static_text(Fd_Code_Writer& f, const char* fmt);
void write_static_rgb(Fd_Code_Writer& f, const char* idata_name);
public:
int written;
static Fluid_Image* find(const char *);
@ -42,11 +44,11 @@ public:
void increment();
void image(Fl_Widget *); // set the image of this widget
void deimage(Fl_Widget *); // set the deimage of this widget
void write_static(int compressed);
void write_initializer(const char *type_name, const char *format, ...);
void write_code(int bind, const char *var, int inactive = 0);
void write_inline(int inactive = 0);
void write_file_error(const char *fmt);
void write_static(Fd_Code_Writer& f, int compressed);
void write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...);
void write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive = 0);
void write_inline(Fd_Code_Writer& f, int inactive = 0);
void write_file_error(Fd_Code_Writer& f, const char *fmt);
const char *name() const {return name_;}
};

View File

@ -22,6 +22,7 @@ void show_help(const char *name);
Fl_Double_Window *about_panel=(Fl_Double_Window *)0;
#include <FL/Fl_Anim_GIF_Image.H>
static const unsigned char idata_fluid[] =
{71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80,
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,

View File

@ -34,15 +34,6 @@
/// \defgroup cfile C Code File Operations
/// \{
static FILE *code_file = NULL;
static FILE *header_file = NULL;
/// Store the current indentation level for the C source code.
int indentation = 0;
int write_number = 0;
int write_sourceview = 0;
/**
Return true if c can be in a C identifier.
@ -52,40 +43,177 @@ int is_id(char c) {
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
}
/**
Write a file that contains all label and tooltip strings for internationalisation.
*/
int write_strings(const char *sfile) {
FILE *fp = fl_fopen(sfile, "w");
Fl_Type *p;
Fl_Widget_Type *w;
int i;
if (!fp) return 1;
switch (g_project.i18n_type) {
case 0 : /* None, just put static text out */
fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
for (p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
for (const char *s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
putc('\n', fp);
}
if (w->tooltip()) {
for (const char *s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
putc('\n', fp);
}
}
}
break;
case 1 : /* GNU gettext, put a .po file out */
fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
for (p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
const char *s;
fputs("msgid \"", fp);
for (s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
fputs("msgstr \"", fp);
for (s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
if (w->tooltip()) {
const char *s;
fputs("msgid \"", fp);
for (s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
fputs("msgstr \"", fp);
for (s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
}
}
break;
case 2 : /* POSIX catgets, put a .msg file out */
fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
fprintf(fp, "$set %s\n", g_project.i18n_set.value());
fputs("$quote \"\n", fp);
for (i = 1, p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
fprintf(fp, "%d \"", i ++);
for (const char *s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
if (w->tooltip()) {
fprintf(fp, "%d \"", i ++);
for (const char *s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
}
}
break;
}
return fclose(fp);
}
////////////////////////////////////////////////////////////////
// Generate unique but human-readable identifiers:
struct id {
struct Fd_Identifier_Tree {
char* text;
void* object;
id *left, *right;
id (const char* t, void* o) : text(fl_strdup(t)), object(o) {left = right = 0;}
~id();
Fd_Identifier_Tree *left, *right;
Fd_Identifier_Tree (const char* t, void* o) : text(fl_strdup(t)), object(o) {left = right = 0;}
~Fd_Identifier_Tree();
};
id::~id() {
Fd_Identifier_Tree::~Fd_Identifier_Tree() {
delete left;
free((void *)text);
delete right;
}
static id* id_root;
/** \brief Return a unique name for the given object.
// TODO: document me
const char* unique_id(void* o, const char* type, const char* name, const char* label) {
This function combines the anem and label into an identifier. It then checks
if that id was already taken by another object, and if so, appends a
hexadecimal value which is incremented until the id is unique in this file.
If a new id was created, it is stored in the id tree.
\param[in] o create an ID for this object
\param[in] type is the first word of the ID
\param[in] name if name is set, it is appended to the ID
\param[in] label else if label is set, it is appended, skipping non-keyword characters
\return buffer to a unique identifier, managed by Fd_Code_Writer, so caller must NOT free() it
*/
const char* Fd_Code_Writer::unique_id(void* o, const char* type, const char* name, const char* label) {
char buffer[128];
char* q = buffer;
char* q_end = q + 128 - 8 - 1; // room for hex number and NUL
while (*type) *q++ = *type++;
*q++ = '_';
const char* n = name;
if (!n || !*n) n = label;
if (n && *n) {
while (*n && !is_id(*n)) n++;
while (is_id(*n)) *q++ = *n++;
while (is_id(*n) && (q < q_end)) *q++ = *n++;
}
*q = 0;
// okay, search the tree and see if the name was already used:
id** p = &id_root;
Fd_Identifier_Tree** p = &id_root;
int which = 0;
while (*p) {
int i = strcmp(buffer, (*p)->text);
@ -99,7 +227,7 @@ const char* unique_id(void* o, const char* type, const char* name, const char* l
else if (i < 0) p = &((*p)->left);
else p = &((*p)->right);
}
*p = new id(buffer, o);
*p = new Fd_Identifier_Tree(buffer, o);
return (*p)->text;
}
@ -121,7 +249,7 @@ const char* unique_id(void* o, const char* type, const char* name, const char* l
\param[in] set generate this indent depth
\return pointer to a static string
*/
const char *indent(int set) {
const char *Fd_Code_Writer::indent(int set) {
static const char* spaces = " ";
int i = set * 2;
if (i>32) i = 32;
@ -133,7 +261,7 @@ const char *indent(int set) {
Return a C string that indents code to the current source file depth.
\return pointer to a static string
*/
const char *indent() {
const char *Fd_Code_Writer::indent() {
return indent(indentation);
}
@ -143,45 +271,59 @@ const char *indent() {
change the `indentation` variable; offset can be negative
\return pointer to a static string
*/
const char *indent_plus(int offset) {
const char *Fd_Code_Writer::indent_plus(int offset) {
return indent(indentation+offset);
}
////////////////////////////////////////////////////////////////
// declarations/include files:
// Each string generated by write_declare is written only once to
// Each string generated by write_h_once is written only once to
// the header file. This is done by keeping a binary tree of all
// the calls so far and not printing it if it is in the tree.
struct included {
struct Fd_Text_Tree {
char *text;
included *left, *right;
included(const char *t) {
Fd_Text_Tree *left, *right;
Fd_Text_Tree(const char *t) {
text = fl_strdup(t);
left = right = 0;
}
~included();
~Fd_Text_Tree();
};
included::~included() {
Fd_Text_Tree::~Fd_Text_Tree() {
delete left;
free((void *)text);
delete right;
}
static included *included_root;
struct Fd_Pointer_Tree {
void *ptr;
Fd_Pointer_Tree *left, *right;
Fd_Pointer_Tree(void *p) {
ptr = p;
left = right = 0;
}
~Fd_Pointer_Tree();
};
Fd_Pointer_Tree::~Fd_Pointer_Tree() {
delete left;
delete right;
}
/**
Print a formatted line to the header file, unless the same line was produced before.
Print a formatted line to the header file, unless the same line was produced before in this header file.
\param[in] format printf-style formatting text, followed by a vararg list
*/
int write_declare(const char *format, ...) {
int Fd_Code_Writer::write_h_once(const char *format, ...) {
va_list args;
char buf[1024];
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
included **p = &included_root;
Fd_Text_Tree **p = &text_in_header;
while (*p) {
int i = strcmp(buf,(*p)->text);
if (!i) return 0;
@ -189,17 +331,53 @@ int write_declare(const char *format, ...) {
else p = &((*p)->right);
}
fprintf(header_file,"%s\n",buf);
*p = new included(buf);
*p = new Fd_Text_Tree(buf);
return 1;
}
////////////////////////////////////////////////////////////////
/**
Print a formatted line to the source file, unless the same line was produced before in this code file.
\param[in] format printf-style formatting text, followed by a vararg list
*/
int Fd_Code_Writer::write_c_once(const char *format, ...) {
va_list args;
char buf[1024];
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
Fd_Text_Tree **p = &text_in_header;
while (*p) {
int i = strcmp(buf,(*p)->text);
if (!i) return 0;
else if (i < 0) p = &((*p)->left);
else p = &((*p)->right);
}
p = &text_in_code;
while (*p) {
int i = strcmp(buf,(*p)->text);
if (!i) return 0;
else if (i < 0) p = &((*p)->left);
else p = &((*p)->right);
}
fprintf(code_file,"%s\n",buf);
*p = new Fd_Text_Tree(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 variable "o" is used:
int varused_test;
int varused;
/**
Return true if this pointer was already included in the code file.
If it was not, add it to the list and return false.
*/
bool Fd_Code_Writer::c_contains(void *pp) {
Fd_Pointer_Tree **p = &ptr_in_code;
while (*p) {
if ((*p)->ptr == pp) return true;
else if ((*p)->ptr < pp) p = &((*p)->left);
else p = &((*p)->right);
}
*p = new Fd_Pointer_Tree(pp);
return false;
}
/**
Write a C string to the code file, escaping non-ASCII characters.
@ -215,9 +393,9 @@ int varused;
\param[in] s write this string
\param[in] length write so many bytes in this string
\see write_cstring(const char*)
\see f.write_cstring(const char*)
*/
void write_cstring(const char *s, int length) {
void Fd_Code_Writer::write_cstring(const char *s, int length) {
if (varused_test) {
varused = 1;
return;
@ -314,9 +492,9 @@ void write_cstring(const char *s, int length) {
/**
Write a C string, escaping non-ASCII characters.
\param[in] s write this string
\see write_cstring(const char*, int)
\see f.write_cstring(const char*, int)
*/
void write_cstring(const char *s) {
void Fd_Code_Writer::write_cstring(const char *s) {
write_cstring(s, (int)strlen(s));
}
@ -325,7 +503,7 @@ void write_cstring(const char *s) {
The output is bracketed in { and }. The content is written
as decimal bytes, i.e. `{ 1, 2, 200 }`
*/
void write_cdata(const char *s, int length) {
void Fd_Code_Writer::write_cdata(const char *s, int length) {
if (varused_test) {
varused = 1;
return;
@ -363,7 +541,7 @@ void write_cdata(const char *s, int length) {
\param[in] format printf-style formatting text
\param[in] args list of arguments
*/
void vwrite_c(const char* format, va_list args) {
void Fd_Code_Writer::vwrite_c(const char* format, va_list args) {
if (varused_test) {
varused = 1;
return;
@ -375,7 +553,7 @@ void vwrite_c(const char* format, va_list args) {
Print a formatted line to the source file.
\param[in] format printf-style formatting text, followed by a vararg list
*/
void write_c(const char* format,...) {
void Fd_Code_Writer::write_c(const char* format,...) {
va_list args;
va_start(args, format);
vwrite_c(format, args);
@ -390,7 +568,7 @@ void write_c(const char* format,...) {
\param[in] c line of code
\param[in] com optional commentary
*/
void write_cc(const char *indent, int n, const char *c, const char *com) {
void Fd_Code_Writer::write_cc(const char *indent, int n, const char *c, const char *com) {
write_c("%s%.*s", indent, n, c);
char cc = c[n-1];
if (cc!='}' && cc!=';')
@ -404,7 +582,7 @@ void write_cc(const char *indent, int n, const char *c, const char *com) {
Print a formatted line to the header file.
\param[in] format printf-style formatting text, followed by a vararg list
*/
void write_h(const char* format,...) {
void Fd_Code_Writer::write_h(const char* format,...) {
if (varused_test) return;
va_list args;
va_start(args, format);
@ -420,7 +598,7 @@ void write_h(const char* format,...) {
\param[in] c line of code
\param[in] com optional commentary
*/
void write_hc(const char *indent, int n, const char* c, const char *com) {
void Fd_Code_Writer::write_hc(const char *indent, int n, const char* c, const char *com) {
write_h("%s%.*s", indent, n, c);
char cc = c[n-1];
if (cc!='}' && cc!=';')
@ -434,7 +612,7 @@ void write_hc(const char *indent, int n, const char* c, const char *com) {
Write one or more lines of code, indenting each one of them.
\param[in] textlines one or more lines of text, seperated by \\n
*/
void write_c_indented(const char *textlines, int inIndent, char inTrailwWith) {
void Fd_Code_Writer::write_c_indented(const char *textlines, int inIndent, char inTrailwWith) {
if (textlines) {
indentation += inIndent;
for (;;) {
@ -470,7 +648,7 @@ void write_c_indented(const char *textlines, int inIndent, char inTrailwWith) {
/**
Recursively dump code, putting children between the two parts of the parent code.
*/
static Fl_Type* write_code(Fl_Type* p) {
Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) {
if (write_sourceview) {
p->code_position = (int)ftell(code_file);
if (p->header_position_end==-1)
@ -479,7 +657,7 @@ static Fl_Type* write_code(Fl_Type* p) {
// write all code that come before the children code
// (but don't write the last comment until the very end)
if (!(p==Fl_Type::last && p->is_comment()))
p->write_code1();
p->write_code1(*this);
// recursively write the code of all children
Fl_Type* q;
if (p->is_widget() && p->is_class()) {
@ -495,7 +673,7 @@ static Fl_Type* write_code(Fl_Type* p) {
}
// write all code that come after the children
p->write_code2();
p->write_code2(*this);
for (q = p->next; q && q->level > p->level;) {
if (!strcmp(q->type_name(), "Function")) q = write_code(q);
@ -512,7 +690,7 @@ static Fl_Type* write_code(Fl_Type* p) {
} else {
for (q = p->next; q && q->level > p->level;) q = write_code(q);
// write all code that come after the children
p->write_code2();
p->write_code2(*this);
}
if (write_sourceview) {
p->code_position_end = (int)ftell(code_file);
@ -531,11 +709,11 @@ static Fl_Type* write_code(Fl_Type* p) {
\param[in] t filename of the header file
\return 0 if the operation failed, 1 if it was successful
*/
int write_code(const char *s, const char *t) {
int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) {
write_sourceview = to_sourceview;
const char *filemode = "w";
if (write_sourceview)
filemode = "wb";
write_number++;
delete id_root; id_root = 0;
indentation = 0;
current_class = 0L;
@ -561,7 +739,7 @@ int write_code(const char *s, const char *t) {
first_type->header_position = (int)ftell(header_file);
}
// it is ok to write non-recusive code here, because comments have no children or code2 blocks
first_type->write_code1();
first_type->write_code1(*this);
if (write_sourceview) {
first_type->code_position_end = (int)ftell(code_file);
first_type->header_position_end = (int)ftell(header_file);
@ -585,10 +763,12 @@ int write_code(const char *s, const char *t) {
}
if (g_project.avoid_early_includes==0) {
write_declare("#include <FL/Fl.H>");
write_h_once("#include <FL/Fl.H>");
}
if (t && g_project.include_H_from_C) {
if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name, '/') == NULL) {
if (to_sourceview) {
write_c("#include \"CodeView.h\"\n");
} else if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name, '/') == NULL) {
write_c("#include \"%s\"\n", fl_filename_name(t));
} else {
write_c("#include \"%s\"\n", t);
@ -641,14 +821,14 @@ int write_code(const char *s, const char *t) {
for (Fl_Type* p = first_type; p;) {
// write all static data for this & all children first
if (write_sourceview) p->header_position = (int)ftell(header_file);
p->write_static();
p->write_static(*this);
if (write_sourceview) {
p->header_position_end = (int)ftell(header_file);
if (p->header_position==p->header_position_end) p->header_position_end = -1;
}
for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) {
if (write_sourceview) q->header_position = (int)ftell(header_file);
q->write_static();
q->write_static(*this);
if (write_sourceview) {
q->header_position_end = (int)ftell(header_file);
if (q->header_position==q->header_position_end) q->header_position_end = -1;
@ -658,8 +838,6 @@ int write_code(const char *s, const char *t) {
p = write_code(p);
}
delete included_root; included_root = 0;
if (!s) return 1;
fprintf(header_file, "#endif\n");
@ -670,147 +848,29 @@ int write_code(const char *s, const char *t) {
last_type->code_position = (int)ftell(code_file);
last_type->header_position = (int)ftell(header_file);
}
last_type->write_code1();
last_type->write_code1(*this);
if (write_sourceview) {
last_type->code_position_end = (int)ftell(code_file);
last_type->header_position_end = (int)ftell(header_file);
}
}
int x = 0, y = 0;
int x = fclose(code_file);
if (code_file != stdout)
x = fclose(code_file);
code_file = 0;
int y = fclose(header_file);
if (header_file != stdout)
y = fclose(header_file);
header_file = 0;
return x >= 0 && y >= 0;
}
int write_strings(const char *sfile) {
FILE *fp = fl_fopen(sfile, "w");
Fl_Type *p;
Fl_Widget_Type *w;
int i;
if (!fp) return 1;
switch (g_project.i18n_type) {
case 0 : /* None, just put static text out */
fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
for (p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
for (const char *s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
putc('\n', fp);
}
if (w->tooltip()) {
for (const char *s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
putc('\n', fp);
}
}
}
break;
case 1 : /* GNU gettext, put a .po file out */
fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
for (p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
const char *s;
fputs("msgid \"", fp);
for (s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
fputs("msgstr \"", fp);
for (s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
if (w->tooltip()) {
const char *s;
fputs("msgid \"", fp);
for (s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
fputs("msgstr \"", fp);
for (s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
}
}
break;
case 2 : /* POSIX catgets, put a .msg file out */
fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n",
FL_VERSION);
fprintf(fp, "$set %s\n", g_project.i18n_set.value());
fputs("$quote \"\n", fp);
for (i = 1, p = Fl_Type::first; p; p = p->next) {
if (p->is_widget()) {
w = (Fl_Widget_Type *)p;
if (w->label()) {
fprintf(fp, "%d \"", i ++);
for (const char *s = w->label(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
if (w->tooltip()) {
fprintf(fp, "%d \"", i ++);
for (const char *s = w->tooltip(); *s; s ++)
if (*s < 32 || *s > 126 || *s == '\"')
fprintf(fp, "\\%03o", *s);
else
putc(*s, fp);
fputs("\"\n", fp);
}
}
}
break;
}
return fclose(fp);
}
/**
Write the public/private/protected keywords inside the class.
This avoids repeating these words if the mode is already set.
*/
void write_public(int state) {
void Fd_Code_Writer::write_public(int state) {
if (!current_class && !current_widget_class) return;
if (current_class && current_class->write_public_state == state) return;
if (current_widget_class && current_widget_class->write_public_state == state) return;
@ -823,5 +883,27 @@ void write_public(int state) {
}
}
Fd_Code_Writer::Fd_Code_Writer()
: code_file(NULL),
header_file(NULL),
id_root(NULL),
text_in_header(NULL),
text_in_code(NULL),
ptr_in_code(NULL),
indentation(0),
write_sourceview(false),
varused_test(0),
varused(0)
{
}
Fd_Code_Writer::~Fd_Code_Writer()
{
delete ptr_in_code;
delete text_in_code;
delete text_in_header;
}
/// \}

View File

@ -20,28 +20,59 @@
#include <FL/fl_attr.h>
#include <stdarg.h>
#include <stdio.h>
extern int indentation;
extern int write_number;
extern int write_sourceview;
class Fl_Type;
struct Fd_Identifier_Tree;
struct Fd_Text_Tree;
struct Fd_Pointer_Tree;
int is_id(char c);
const char* unique_id(void* o, const char*, const char*, const char*);
const char *indent();
const char *indent(int set);
const char *indent_plus(int offset);
int write_declare(const char *, ...) __fl_attr((__format__ (__printf__, 1, 2)));
void write_cstring(const char *,int length);
void write_cstring(const char *);
void write_cdata(const char *,int length);
void vwrite_c(const char* format, va_list args);
void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
void write_cc(const char *, int, const char*, const char*);
void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
void write_hc(const char *, int, const char*, const char*);
void write_c_indented(const char *textlines, int inIndent, char inTrailwWith);
int write_code(const char *cfile, const char *hfile);
int write_strings(const char *sfile);
void write_public(int state); // writes pubic:/private: as needed
class Fd_Code_Writer
{
protected:
FILE *code_file;
FILE *header_file;
Fd_Identifier_Tree* id_root;
Fd_Text_Tree *text_in_header;
Fd_Text_Tree *text_in_code;
Fd_Pointer_Tree *ptr_in_code;
public:
int indentation;
bool write_sourceview;
// 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 variable "o" is used:
int varused_test;
int varused;
public:
Fd_Code_Writer();
~Fd_Code_Writer();
const char* unique_id(void* o, const char*, const char*, const char*);
void indent_more() { indentation++; }
void indent_less() { indentation--; }
const char *indent();
const char *indent(int set);
const char *indent_plus(int offset);
int write_h_once(const char *, ...) __fl_attr((__format__ (__printf__, 2, 3)));
int write_c_once(const char *, ...) __fl_attr((__format__ (__printf__, 2, 3)));
bool c_contains(void* ptr);
void write_cstring(const char *,int length);
void write_cstring(const char *);
void write_cdata(const char *,int length);
void vwrite_c(const char* format, va_list args);
void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 2, 3)));
void write_cc(const char *, int, const char*, const char*);
void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 2, 3)));
void write_hc(const char *, int, const char*, const char*);
void write_c_indented(const char *textlines, int inIndent, char inTrailwWith);
Fl_Type* write_code(Fl_Type* p);
int write_code(const char *cfile, const char *hfile, bool to_sourceview=false);
void write_public(int state); // writes pubic:/private: as needed
};
#endif // _FLUID_CODE_H

View File

@ -6,7 +6,7 @@
// They are somewhat similar to tcl, using matching { and }
// to quote strings.
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -30,6 +30,7 @@
#include "widget_browser.h"
#include "shell_command.h"
#include "code.h"
#include "undo.h"
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
@ -41,182 +42,40 @@
#include <stdlib.h>
#include <stdarg.h>
/// \defgroup flfile .fl Design File Operations
/// \defgroup flfile .fl Project File Operations
/// \{
// This file contains code to read and write .fl files.
// TODO: there is a name confusion with routines that write to the C and Header
// TODO: files vs. those that write to the .fl file which should be fixed.
static FILE *fout;
static FILE *fin;
int fdesign_flip = 0;
static int needspace;
static int lineno;
static const char *fname;
/** \brief Read a .fl project file.
int fdesign_flip;
int fdesign_magic;
The .fl file format is documented in `fluid/README_fl.txt`.
double read_version;
////////////////////////////////////////////////////////////////
// BASIC FILE WRITING:
/**
Open the .fl design file for writing.
If the filename is NULL, associate stdout instead.
\param[in] s the filename or NULL for stdout
\return 1 if successful. 0 if the operation failed
*/
static int open_write(const char *s) {
if (!s) {fout = stdout; return 1;}
FILE *f = fl_fopen(s,"w");
if (!f) return 0;
fout = f;
return 1;
}
/**
Close the .fl design file.
Don't close, if data was sent to stdout.
*/
static int close_write() {
if (fout != stdout) {
int x = fclose(fout);
fout = stdout;
return x >= 0;
}
return 1;
}
/**
Write a string to the .fl file, 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 to the .fl file, or a comment, etc .
If needspace is set, then one space is written before the string
unless the format starts with a newline character \\n.
*/
void write_string(const char *format, ...) {
va_list args;
va_start(args, format);
if (needspace && *format != '\n') fputc(' ',fout);
vfprintf(fout, format, args);
va_end(args);
needspace = !isspace(format[strlen(format)-1] & 255);
}
/**
Start a new line in the .fl file 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 '{' to the .fl file at the given indenting level.
*/
void write_open(int) {
if (needspace) fputc(' ',fout);
fputc('{',fout);
needspace = 0;
}
/**
Write a '}' to the .fl file at the given indenting level.
*/
void write_close(int n) {
if (needspace) write_indent(n);
fputc('}',fout);
needspace = 1;
}
////////////////////////////////////////////////////////////////
// BASIC FILE READING:
/**
Open an .fl file for reading.
\param[in] s filename, if NULL, read from stdin instead
\param[in] filename read this file
\param[in] merge if this is set, merge the file into an existing project
at Fl_Type::current
\param[in] strategy add new nodes after current or as last child
\return 0 if the operation failed, 1 if it succeeded
*/
static int open_read(const char *s) {
lineno = 1;
if (!s) {fin = stdin; fname = "stdin"; return 1;}
FILE *f = fl_fopen(s,"r");
if (!f) return 0;
fin = f;
fname = s;
return 1;
int read_file(const char *filename, int merge, Strategy strategy) {
Fd_Project_Reader f;
return f.read_project(filename, merge, strategy);
}
/**
Close the .fl file.
/** \brief Write an .fl design description file.
The .fl file format is documented in `fluid/README_fl.txt`.
\param[in] filename create this file, and if it exists, overwrite it
\param[in] selected_only write only the selected nodes in the widget_tree. This
is used to implement copy and paste.
\return 0 if the operation failed, 1 if it succeeded
*/
static int close_read() {
if (fin != stdin) {
int x = fclose(fin);
fin = 0;
return x >= 0;
}
return 1;
}
/**
Display an error while reading the file.
If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise
print to stdout.
\note Matt: I am not sure why it is done this way. Shouldn;t this depend on \c batch_mode?
*/
void read_error(const char *format, ...) {
va_list args;
va_start(args, format);
if (!fin) {
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), format, args);
fl_message("%s", buffer);
} else {
fprintf(stderr, "%s:%d: ", fname, lineno);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
}
va_end(args);
int write_file(const char *filename, int selected_only) {
Fd_Project_Writer out;
return out.write_project(filename, selected_only);
}
/**
@ -229,52 +88,13 @@ static int hexdigit(int x) {
return 20;
}
/**
Convert an ASCII sequence form the \.fl file that starts with a \\ into a single character.
Conversion includes the common C style \\ characters like \\n, \\x## hex
values, and \\o### octal values.
*/
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);
}
static char *buffer;
static int buflen;
// ---- Fd_Project_Reader ---------------------------------------------- MARK: -
/**
A simple growing buffer.
Oh how I wish sometimes we would upgrade to modern C++.
*/
static void expand_buffer(int length) {
void Fd_Project_Reader::expand_buffer(int length) {
if (length >= buflen) {
if (!buflen) {
buflen = length+1;
@ -287,161 +107,92 @@ static void expand_buffer(int length) {
}
}
/** \brief Construct local project reader. */
Fd_Project_Reader::Fd_Project_Reader()
: fin(NULL),
lineno(0),
fname(NULL),
buffer(NULL),
buflen(0),
read_version(0.0)
{
}
/** \brief Release project reader resources. */
Fd_Project_Reader::~Fd_Project_Reader()
{
}
/**
Return a word read from the .fl 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 '}'
Open an .fl file for reading.
\param[in] s filename, if NULL, read from stdin instead
\return 0 if the operation failed, 1 if it succeeded
*/
const char *read_word(int wantbrace) {
int x;
// skip all the whitespace before it:
for (;;) {
x = getc(fin);
if (x < 0 && feof(fin)) { // 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 & 255)) {
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;
int Fd_Project_Reader::open_read(const char *s) {
lineno = 1;
if (!s) {
fin = stdin;
fname = "stdin";
} 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 & 255) || x=='{' || x=='}' || x=='#') break;
buffer[length++] = x;
expand_buffer(length);
x = getc(fin);
}
ungetc(x, fin);
buffer[length] = 0;
return buffer;
FILE *f = fl_fopen(s,"r");
if (!f)
return 0;
fin = f;
fname = s;
}
return 1;
}
////////////////////////////////////////////////////////////////
/**
Write an .fl design description file.
\param[in] filename create this file, and if it exists, overwrite it
\param[in] selected_only write only the selected nodes in the widget_tree. This
is used to implement copy and paste.
Close the .fl file.
\return 0 if the operation failed, 1 if it succeeded
*/
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 %.4f",FL_VERSION);
if(!g_project.include_H_from_C)
write_string("\ndo_not_include_H_from_C");
if(g_project.use_FL_COMMAND)
write_string("\nuse_FL_COMMAND");
if (g_project.utf8_in_src)
write_string("\nutf8_in_src");
if (g_project.avoid_early_includes)
write_string("\navoid_early_includes");
if (g_project.i18n_type) {
write_string("\ni18n_type %d", g_project.i18n_type);
write_string("\ni18n_include"); write_word(g_project.i18n_include);
write_string("\ni18n_conditional"); write_word(g_project.i18n_conditional);
switch (g_project.i18n_type) {
case 1 : /* GNU gettext */
write_string("\ni18n_function"); write_word(g_project.i18n_function);
write_string("\ni18n_static_function"); write_word(g_project.i18n_static_function);
break;
case 2 : /* POSIX catgets */
if (g_project.i18n_file[0]) {
write_string("\ni18n_file");
write_word(g_project.i18n_file);
}
write_string("\ni18n_set"); write_word(g_project.i18n_set);
break;
}
int Fd_Project_Reader::close_read() {
if (fin != stdin) {
int x = fclose(fin);
fin = 0;
return x >= 0;
}
if (!selected_only) {
write_string("\nheader_name"); write_word(g_project.header_file_name);
write_string("\ncode_name"); write_word(g_project.code_file_name);
#if 0
// https://github.com/fltk/fltk/issues/328
// Project wide settings require a redesign.
shell_settings_write();
if (shell_settings_windows.command) {
write_string("\nwin_shell_cmd"); write_word(shell_settings_windows.command);
write_string("\nwin_shell_flags"); write_string("%d", shell_settings_windows.flags);
}
if (shell_settings_linux.command) {
write_string("\nlinux_shell_cmd"); write_word(shell_settings_linux.command);
write_string("\nlinux_shell_flags"); write_string("%d", shell_settings_linux.flags);
}
if (shell_settings_macos.command) {
write_string("\nmac_shell_cmd"); write_word(shell_settings_macos.command);
write_string("\nmac_shell_flags"); write_string("%d", shell_settings_macos.flags);
}
#endif
}
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) {/*empty*/}
} else {
p = p->next;
}
}
return close_write();
return 1;
}
////////////////////////////////////////////////////////////////
// read all the objects out of the input file:
/**
Convert an ASCII sequence form the \.fl file that starts with a \\ into a single character.
Conversion includes the common C style \\ characters like \\n, \\x## hex
values, and \\o### octal values.
*/
int Fd_Project_Reader::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);
}
/**
Recursively read child nodes in the .fl design file.
@ -452,9 +203,9 @@ int write_file(const char *filename, int selected_only) {
\param[in] paste if set, merge into existing design, else replace design
\param[in] strategy add nodes after current or as last child
\param[in] skip_options this is set if the options were already found in
a previous call, and there is no need to waste time searchingg for them.
a previous call, and there is no need to waste time searchingg for them.
*/
static void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options=0) {
void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options) {
Fl_Type::current = p;
for (;;) {
const char *c = read_word();
@ -614,7 +365,7 @@ static void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_op
for (;;) {
const char *cc = read_word();
if (!cc || !strcmp(cc,"}")) break;
t->read_property(cc);
t->read_property(*this, cc);
}
if (!t->is_parent()) continue;
@ -633,19 +384,21 @@ static void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_op
}
}
/**
Read a .fl design file.
/** \brief Read a .fl project file.
\param[in] filename read this file
\param[in] merge if this is set, merge the file into an existing design
at Fl_Type::current
\param[in] merge if this is set, merge the file into an existing project
at Fl_Type::current
\param[in] strategy add new nodes after current or as last child
\return 0 if the operation failed, 1 if it succeeded
*/
int read_file(const char *filename, int merge, Strategy strategy) {
int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) {
Fl_Type *o;
undo_suspend();
read_version = 0.0;
if (!open_read(filename))
if (!open_read(filename)) {
undo_resume();
return 0;
}
if (merge)
deselect();
else
@ -663,13 +416,111 @@ int read_file(const char *filename, int merge, Strategy strategy) {
}
selection_changed(Fl_Type::current);
shell_settings_read();
return close_read();
int ret = close_read();
undo_resume();
return ret;
}
////////////////////////////////////////////////////////////////
// Read Forms and XForms fdesign files:
/**
Display an error while reading the file.
If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise
print to stdout.
\note Matt: I am not sure why it is done this way. Shouldn't this depend on \c batch_mode?
*/
void Fd_Project_Reader::read_error(const char *format, ...) {
va_list args;
va_start(args, format);
if (!fin) {
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), format, args);
fl_message("%s", buffer);
} else {
fprintf(stderr, "%s:%d: ", fname, lineno);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
}
va_end(args);
}
static int read_fdesign_line(const char*& name, const char*& value) {
/**
Return a word read from the .fl 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 '}'
*/
const char *Fd_Project_Reader::read_word(int wantbrace) {
int x;
// skip all the whitespace before it:
for (;;) {
x = getc(fin);
if (x < 0 && feof(fin)) { // 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 & 255)) {
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 & 255) || x=='{' || x=='}' || x=='#') break;
buffer[length++] = x;
expand_buffer(length);
x = getc(fin);
}
ungetc(x, fin);
buffer[length] = 0;
return buffer;
}
}
int Fd_Project_Reader::read_fdesign_line(const char*& name, const char*& value) {
int length = 0;
int x;
// find a colon:
@ -707,53 +558,53 @@ static int read_fdesign_line(const char*& name, const char*& value) {
}
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};
"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};
/**
Finish a group of widgets and optionally transform its children's coordinates.
Finish a group of widgets and optionally transform its children's coordinates.
Implements the same functionality as Fl_Group::forms_end() from the forms
compatibility library would have done:
Implements the same functionality as Fl_Group::forms_end() from the forms
compatibility library would have done:
- resize the group to surround its children if the group's w() == 0
- optionally flip the \p y coordinates of all children relative to the group's window
- Fl_Group::end() the group
- resize the group to surround its children if the group's w() == 0
- optionally flip the \p y coordinates of all children relative to the group's window
- Fl_Group::end() the group
\note Copied from forms_compatibility.cxx and modified as a static fluid
function so we don't have to link to fltk_forms.
\note Copied from forms_compatibility.cxx and modified as a static fluid
function so we don't have to link to fltk_forms.
\param[in] g the Fl_Group widget
\param[in] flip flip children's \p y coordinates if true (non-zero)
*/
\param[in] g the Fl_Group widget
\param[in] flip flip children's \p y coordinates if true (non-zero)
*/
static void forms_end(Fl_Group *g, int flip) {
// set the dimensions of a group to surround its contents
const int nc = g->children();
@ -794,8 +645,8 @@ static void forms_end(Fl_Group *g, int flip) {
FLTK widgets.
\see http://xforms-toolkit.org
*/
void read_fdesign() {
fdesign_magic = atoi(read_word());
void Fd_Project_Reader::read_fdesign() {
int fdesign_magic = atoi(read_word());
fdesign_flip = (fdesign_magic < 13000);
Fl_Widget_Type *window = 0;
Fl_Widget_Type *group = 0;
@ -849,4 +700,203 @@ void read_fdesign() {
}
}
// ---- Fd_Project_Writer ---------------------------------------------- MARK: -
/** \brief Construct local project writer. */
Fd_Project_Writer::Fd_Project_Writer()
: fout(NULL),
needspace(0)
{
}
/** \brief Release project writer resources. */
Fd_Project_Writer::~Fd_Project_Writer()
{
}
/**
Open the .fl design file for writing.
If the filename is NULL, associate stdout instead.
\param[in] s the filename or NULL for stdout
\return 1 if successful. 0 if the operation failed
*/
int Fd_Project_Writer::open_write(const char *s) {
if (!s) {
fout = stdout;
} else {
FILE *f = fl_fopen(s,"w");
if (!f) return 0;
fout = f;
}
return 1;
}
/**
Close the .fl design file.
Don't close, if data was sent to stdout.
*/
int Fd_Project_Writer::close_write() {
if (fout != stdout) {
int x = fclose(fout);
fout = stdout;
return x >= 0;
}
return 1;
}
/** \brief Write an .fl design description file.
\param[in] filename create this file, and if it exists, overwrite it
\param[in] selected_only write only the selected nodes in the widget_tree. This
is used to implement copy and paste.
\return 0 if the operation failed, 1 if it succeeded
*/
int Fd_Project_Writer::write_project(const char *filename, int selected_only) {
undo_suspend();
if (!open_write(filename)) {
undo_resume();
return 0;
}
write_string("# data file for the Fltk User Interface Designer (fluid)\n"
"version %.4f",FL_VERSION);
if(!g_project.include_H_from_C)
write_string("\ndo_not_include_H_from_C");
if(g_project.use_FL_COMMAND)
write_string("\nuse_FL_COMMAND");
if (g_project.utf8_in_src)
write_string("\nutf8_in_src");
if (g_project.avoid_early_includes)
write_string("\navoid_early_includes");
if (g_project.i18n_type) {
write_string("\ni18n_type %d", g_project.i18n_type);
write_string("\ni18n_include"); write_word(g_project.i18n_include);
write_string("\ni18n_conditional"); write_word(g_project.i18n_conditional);
switch (g_project.i18n_type) {
case 1 : /* GNU gettext */
write_string("\ni18n_function"); write_word(g_project.i18n_function);
write_string("\ni18n_static_function"); write_word(g_project.i18n_static_function);
break;
case 2 : /* POSIX catgets */
if (g_project.i18n_file[0]) {
write_string("\ni18n_file");
write_word(g_project.i18n_file);
}
write_string("\ni18n_set"); write_word(g_project.i18n_set);
break;
}
}
if (!selected_only) {
write_string("\nheader_name"); write_word(g_project.header_file_name);
write_string("\ncode_name"); write_word(g_project.code_file_name);
#if 0
// https://github.com/fltk/fltk/issues/328
// Project wide settings require a redesign.
shell_settings_write();
if (shell_settings_windows.command) {
write_string("\nwin_shell_cmd"); write_word(shell_settings_windows.command);
write_string("\nwin_shell_flags"); write_string("%d", shell_settings_windows.flags);
}
if (shell_settings_linux.command) {
write_string("\nlinux_shell_cmd"); write_word(shell_settings_linux.command);
write_string("\nlinux_shell_flags"); write_string("%d", shell_settings_linux.flags);
}
if (shell_settings_macos.command) {
write_string("\nmac_shell_cmd"); write_word(shell_settings_macos.command);
write_string("\nmac_shell_flags"); write_string("%d", shell_settings_macos.flags);
}
#endif
}
for (Fl_Type *p = Fl_Type::first; p;) {
if (!selected_only || p->selected) {
p->write(*this);
write_string("\n");
int q = p->level;
for (p = p->next; p && p->level > q; p = p->next) {/*empty*/}
} else {
p = p->next;
}
}
int ret = close_write();
undo_resume();
return ret;
}
/**
Write a string to the .fl file, quoting characters if necessary.
*/
void Fd_Project_Writer::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 to the .fl file, or a comment, etc .
If needspace is set, then one space is written before the string
unless the format starts with a newline character \\n.
*/
void Fd_Project_Writer::write_string(const char *format, ...) {
va_list args;
va_start(args, format);
if (needspace && *format != '\n') fputc(' ',fout);
vfprintf(fout, format, args);
va_end(args);
needspace = !isspace(format[strlen(format)-1] & 255);
}
/**
Start a new line in the .fl file and indent it for a given nesting level.
*/
void Fd_Project_Writer::write_indent(int n) {
fputc('\n',fout);
while (n--) {fputc(' ',fout); fputc(' ',fout);}
needspace = 0;
}
/**
Write a '{' to the .fl file at the given indenting level.
*/
void Fd_Project_Writer::write_open(int) {
if (needspace) fputc(' ',fout);
fputc('{',fout);
needspace = 0;
}
/**
Write a '}' to the .fl file at the given indenting level.
*/
void Fd_Project_Writer::write_close(int n) {
if (needspace) write_indent(n);
fputc('}',fout);
needspace = 1;
}
/// \}

View File

@ -1,7 +1,7 @@
//
// Fluid file routines for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -21,22 +21,57 @@
#include <FL/fl_attr.h>
extern double read_version;
class Fl_Type;
extern int fdesign_flip;
extern int fdesign_magic;
void write_word(const char *);
void write_string(const char *,...) __fl_attr((__format__ (__printf__, 1, 2)));
void write_indent(int n);
void write_open(int);
void write_close(int n);
void read_error(const char *format, ...);
const char *read_word(int wantbrace = 0);
int write_file(const char *, int selected_only = 0);
int read_file(const char *, int merge, Strategy strategy=kAddAsLastChild);
void read_fdesign();
int write_file(const char *, int selected_only = 0);
class Fd_Project_Reader
{
protected:
FILE *fin;
int lineno;
const char *fname;
char *buffer;
int buflen;
void expand_buffer(int length);
public:
double read_version;
public:
Fd_Project_Reader();
~Fd_Project_Reader();
int open_read(const char *s);
int close_read();
int read_quoted();
void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options=0);
int read_project(const char *, int merge, Strategy strategy=kAddAsLastChild);
void read_error(const char *format, ...);
const char *read_word(int wantbrace = 0);
int read_fdesign_line(const char*& name, const char*& value);
void read_fdesign();
};
class Fd_Project_Writer
{
protected:
FILE *fout;
int needspace;
public:
Fd_Project_Writer();
~Fd_Project_Writer();
int open_write(const char *s);
int close_write();
int write_project(const char *filename, int selected_only);
void write_word(const char *);
void write_string(const char *,...) __fl_attr((__format__ (__printf__, 2, 3)));
void write_indent(int n);
void write_open(int);
void write_close(int n);
};
#endif // _FLUID_FILE_H

View File

@ -981,11 +981,14 @@ void new_from_template_cb(Fl_Widget *w, void *v) {
with the extension \c code_file_name which are both
settable by the user.
In batch_mode, the function will either be silent, or write an error message
to \c stderr and exit with exit code 1.
If the code filename has not been set yet, a "save file as" dialog will be
presented to the user.
In interactive mode, we will pop up an error message, or, if the user
hasn't isabled that, pop up a confirmation message.
In batch_mode, the function will either be silent, or, if opening or writing
the files fails, write an error message to \c stderr and exit with exit code 1.
In interactive mode, it will pop up an error message, or, if the user
hasn't disabled that, pop up a confirmation message.
\return 1 if the operation failed, 0 if it succeeded
*/
@ -1013,7 +1016,8 @@ int write_code_files() {
strlcpy(hname, g_project.header_file_name, FL_PATH_MAX);
}
if (!batch_mode) enter_project_dir();
int x = write_code(cname,hname);
Fd_Code_Writer f;
int x = f.write_code(cname, hname);
if (!batch_mode) leave_project_dir();
strlcat(cname, " and ", FL_PATH_MAX);
strlcat(cname, hname, FL_PATH_MAX);
@ -1931,9 +1935,9 @@ void update_sourceview_cb(Fl_Button*, void*)
g_project.header_file_name = sv_header_filename;
// generate the code and load the files
write_sourceview = 1;
Fd_Code_Writer f;
// generate files
if (write_code(sv_source_filename, sv_header_filename))
if (f.write_code(sv_source_filename, sv_header_filename, true))
{
// load file into source editor
int pos = sv_source->top_line();
@ -1946,7 +1950,6 @@ void update_sourceview_cb(Fl_Button*, void*)
// update the source code highlighting
update_sourceview_position();
}
write_sourceview = 0;
g_project.code_file_name = code_file_name_bak;
g_project.header_file_name = header_file_name_bak;

View File

@ -1,7 +1,7 @@
//
// Code dialogs for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this

View File

@ -5,7 +5,7 @@ code_name {.cxx}
comment {//
// Code dialogs for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -17,7 +17,7 @@ comment {//
//
// https://www.fltk.org/bugs.php
//
} {in_source in_header
} {selected in_source in_header
}
decl {\#include "fluid.h"} {private local
@ -483,7 +483,7 @@ Function {make_comment_panel()} {open
xywh {780 296 550 280} type Double labelsize 11 resizable
code0 {o->size_range(320, 180);} modal visible
} {
Fl_Text_Editor comment_input {selected
Fl_Text_Editor comment_input {
xywh {110 10 430 230} box DOWN_BOX labelsize 11 textfont 4 textsize 11 textcolor 58 resizable
code0 {o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE);}
code1 {o->buffer(new Fl_Text_Buffer());}

View File

@ -1,7 +1,7 @@
//
// Code dialogs for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this

View File

@ -112,6 +112,7 @@ Fl_Menu_Item menu_print_page_size[] = {
};
#include <FL/Fl_Pixmap.H>
static const char *idata_print_color[] = {
"24 24 17 1",
" \tc None",
@ -157,7 +158,9 @@ static const char *idata_print_color[] = {
" %%%%%% ****** "
};
static Fl_Image *image_print_color() {
static Fl_Image *image = new Fl_Pixmap(idata_print_color);
static Fl_Image *image = NULL;
if (!image)
image = new Fl_Pixmap(idata_print_color);
return image;
}
@ -206,7 +209,9 @@ static const char *idata_print_gray[] = {
" %%%%%% ****** "
};
static Fl_Image *image_print_gray() {
static Fl_Image *image = new Fl_Pixmap(idata_print_gray);
static Fl_Image *image = NULL;
if (!image)
image = new Fl_Pixmap(idata_print_gray);
return image;
}

View File

@ -26,7 +26,7 @@ decl {\#include "fluid.h"} {private local
decl {\#include <FL/fl_string_functions.h>} {private local
}
decl {\#include "../src/flstring.h"} {private local
decl {\#include "../src/flstring.h"} {selected private local
}
decl {\#include <stdlib.h>} {private local
@ -39,7 +39,7 @@ Function {make_print_panel()} {open
} {
Fl_Window print_panel {
label Print
xywh {465 222 465 235} type Double hide modal
xywh {465 222 465 235} type Double modal visible
} {
Fl_Group print_panel_controls {open
xywh {10 10 447 216}
@ -213,7 +213,7 @@ print_collate_group[1 - i]->hide();}
label {Printer Properties}
callback {print_properties_panel->hide();
print_update_status();}
xywh {462 486 290 130} type Double hide modal
xywh {462 486 290 130} type Double modal visible
} {
Fl_Choice print_page_size {
label {Page Size:}
@ -233,16 +233,16 @@ print_update_status();}
xywh {110 45 170 40} labelfont 1 labelsize 12 align 4
} {
Fl_Button {print_output_mode[0]} {
image {pixmaps/print_color.xpm} xywh {110 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX value 1 color 7 selection_color 0
image {pixmaps/print_color.xpm} compress_image 0 xywh {110 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX value 1 color 7 selection_color 0
}
Fl_Button {print_output_mode[1]} {
image {pixmaps/print_color.xpm} xywh {150 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
image {pixmaps/print_color.xpm} compress_image 0 xywh {150 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
}
Fl_Button {print_output_mode[2]} {
image {pixmaps/print_gray.xpm} xywh {200 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
image {pixmaps/print_gray.xpm} compress_image 0 xywh {200 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
}
Fl_Button {print_output_mode[3]} {
image {pixmaps/print_gray.xpm} xywh {240 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
image {pixmaps/print_gray.xpm} compress_image 0 xywh {240 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0
}
}
Fl_Return_Button {} {
@ -328,7 +328,7 @@ if (defname[0]) {
print_update_status();} {}
}
Function {print_update_status()} {open selected return_type void
Function {print_update_status()} {open return_type void
} {
code {FILE *lpstat;
char command[1024];

View File

@ -138,7 +138,7 @@ Fl_Double_Window* make_template_panel() {
template_browser->labelfont(1);
template_browser->callback((Fl_Callback*)cb_template_browser);
template_browser->align(Fl_Align(FL_ALIGN_TOP_LEFT));
template_browser->when(3);
template_browser->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED);
} // Fl_Browser* template_browser
{ template_preview = new Fl_Box(200, 28, 250, 250);
template_preview->box(FL_THIN_DOWN_BOX);
@ -149,7 +149,7 @@ Fl_Double_Window* make_template_panel() {
template_name->labelfont(1);
template_name->textfont(4);
template_name->callback((Fl_Callback*)cb_template_name);
template_name->when(3);
template_name->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED);
} // Fl_Input* template_name
{ template_instance = new Fl_Input(198, 288, 252, 25, "Instance Name:");
template_instance->labelfont(1);

View File

@ -299,7 +299,7 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
if (show_comments && l->comment()) {
copy_trunc(buf, l->comment(), 80, 0);
comment_incr = textsize()-1;
Fl_Color comment_color = fl_color_average(FL_DARK_GREEN, FL_BLACK, 0.9);
Fl_Color comment_color = fl_color_average(FL_DARK_GREEN, FL_BLACK, 0.9f);
if (l->new_selected) fl_color(fl_contrast(comment_color, FL_SELECTION_COLOR));
else fl_color(fl_contrast(comment_color, color()));
fl_font(textfont()+FL_ITALIC, textsize()-2);

View File

@ -49,7 +49,7 @@ Function {make_widget_panel()} {
xywh {95 40 309 20} labelfont 1 labelsize 11 align 4
} {
Fl_Input {} {
callback label_cb
callback label_cb selected
tooltip {The label text for the widget.
Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 15 textsize 11 resizable
}
@ -110,7 +110,7 @@ or compressed in the original file format} xywh {364 90 20 20} type Toggle
code3 {\#include "pixmaps.h"}
}
Fl_Button {} {
callback bind_deimage_cb selected
callback bind_deimage_cb
tooltip {bind the image to the widget, so it will be deleted automatically} xywh {384 90 20 20} type Toggle
code0 {o->image(bind_pixmap);}
code3 {\#include "pixmaps.h"}

View File

@ -1271,6 +1271,7 @@ double Fl_Cairo_Graphics_Driver::width(unsigned int utf32) {
double Fl_Cairo_Graphics_Driver::width(const char* str, int n) {
if (!font_descriptor()) return -1;
if ((str == NULL) || (n == 0)) return 0.;
if (n == fl_utf8len(*str)) { // str contains a single unicode character
int l;
unsigned c = fl_utf8decode(str, str+n, &l);

View File

@ -1273,6 +1273,7 @@ double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int utf32) {
}
double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
if ((str == NULL) || (n == 0)) return 0.;
if (n == fl_utf8len(*str)) { // str contains a single unicode character
int l;
unsigned c = fl_utf8decode(str, str+n, &l);

View File

@ -18,7 +18,7 @@
#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Scheme_Choice.H>
#include <FL/fl_draw.H>
@ -82,7 +82,8 @@ void bt(const char *name, Fl_Boxtype type, int square=0) {
N++;
x = x*W+10;
y = y*H+10;
Fl_Box *b = new Fl_Box(type,x,y,square ? H-20 : W-20,H-20,name);
Fl_Button *b = new Fl_Button(x,y,square ? H-20 : W-20,H-20,name);
b->box(type);
b->labelsize(11);
if (inactive) {
b->color(FL_GREEN);

View File

@ -37,7 +37,7 @@ Function {} {open
Fl_Slider {} {
label FL_HORIZONTAL
user_data {"Fl_Slider FL_HORIZONTAL"}
callback callback
callback callback selected
xywh {140 80 130 20} type Horizontal selection_color 1 labelsize 8
}
Fl_Slider {} {
@ -125,7 +125,7 @@ Function {} {open
Fl_Scrollbar {} {
label {FL_VERTICAL (0) ->}
user_data {"Fl_Scrollbar FL_VERTICAL"}
callback callback selected
callback callback
tooltip {Vertical Scrollbar} xywh {405 30 20 90} labelsize 8 align 13 maximum 100 value 20
}
Fl_Box {} {