1 //
2 // "$Id: Fl_Function_Type.cxx 8786 2011-06-07 11:41:36Z manolo $"
3 //
4 // C function type code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2011 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
22 //
23 // Please report all bugs and problems on the following page:
24 //
25 // http://www.fltk.org/str.php
26 //
27
28 #include <FL/Fl.H>
29 #include <FL/Fl_Preferences.H>
30 #include <FL/Fl_File_Chooser.H>
31 #include "Fl_Type.h"
32 #include <FL/fl_show_input.H>
33 #include <FL/Fl_File_Chooser.H>
34 #include "../src/flstring.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 extern int i18n_type;
39 extern const char* i18n_include;
40 extern const char* i18n_function;
41 extern const char* i18n_file;
42 extern const char* i18n_set;
43 extern char i18n_program[];
44
45 extern int compile_only;
46
47 extern void redraw_browser();
48 extern void goto_source_dir();
49 extern void leave_source_dir();
50
51 ////////////////////////////////////////////////////////////////
52 // quick check of any C code for legality, returns an error message
53
54 static char buffer[128]; // for error messages
55
56 // check a quoted string ending in either " or ' or >:
_q_check(const char * & c,int type)57 const char *_q_check(const char * & c, int type) {
58 for (;;) switch (*c++) {
59 case '\0':
60 sprintf(buffer,"missing %c",type);
61 return buffer;
62 case '\\':
63 if (*c) c++;
64 break;
65 default:
66 if (*(c-1) == type) return 0;
67 }
68 }
69
70 // check normal code, match braces and parenthesis:
_c_check(const char * & c,int type)71 const char *_c_check(const char * & c, int type) {
72 const char *d;
73 for (;;) switch (*c++) {
74 case 0:
75 if (!type) return 0;
76 sprintf(buffer, "missing %c", type);
77 return buffer;
78 case '/':
79 // Skip comments as needed...
80 if (*c == '/') {
81 while (*c != '\n' && *c) c++;
82 } else if (*c == '*') {
83 c++;
84 while ((*c != '*' || c[1] != '/') && *c) c++;
85 if (*c == '*') c+=2;
86 else {
87 return "missing '*/'";
88 }
89 }
90 break;
91 case '#':
92 // treat cpp directives as a comment:
93 while (*c != '\n' && *c) c++;
94 break;
95 case '{':
96 if (type==')') goto UNEXPECTED;
97 d = _c_check(c,'}');
98 if (d) return d;
99 break;
100 case '(':
101 d = _c_check(c,')');
102 if (d) return d;
103 break;
104 case '\"':
105 d = _q_check(c,'\"');
106 if (d) return d;
107 break;
108 case '\'':
109 d = _q_check(c,'\'');
110 if (d) return d;
111 break;
112 case '}':
113 case ')':
114 UNEXPECTED:
115 if (type == *(c-1)) return 0;
116 sprintf(buffer, "unexpected %c", *(c-1));
117 return buffer;
118 }
119 }
120
c_check(const char * c,int type)121 const char *c_check(const char *c, int type) {
122 return _c_check(c,type);
123 }
124
125 ////////////////////////////////////////////////////////////////
126
is_public() const127 int Fl_Function_Type::is_public() const {return public_;}
128
make()129 Fl_Type *Fl_Function_Type::make() {
130 Fl_Type *p = Fl_Type::current;
131 while (p && !p->is_decl_block()) p = p->parent;
132 Fl_Function_Type *o = new Fl_Function_Type();
133 o->name("make_window()");
134 o->return_type = 0;
135 o->add(p);
136 o->factory = this;
137 o->public_ = 1;
138 o->cdecl_ = 0;
139 return o;
140 }
141
write_properties()142 void Fl_Function_Type::write_properties() {
143 Fl_Type::write_properties();
144 switch (public_) {
145 case 0: write_string("private"); break;
146 case 2: write_string("protected"); break;
147 }
148 if (cdecl_) write_string("C");
149 if (return_type) {
150 write_string("return_type");
151 write_word(return_type);
152 }
153 }
154
read_property(const char * c)155 void Fl_Function_Type::read_property(const char *c) {
156 if (!strcmp(c,"private")) {
157 public_ = 0;
158 } else if (!strcmp(c,"protected")) {
159 public_ = 2;
160 } else if (!strcmp(c,"C")) {
161 cdecl_ = 1;
162 } else if (!strcmp(c,"return_type")) {
163 storestring(read_word(),return_type);
164 } else {
165 Fl_Type::read_property(c);
166 }
167 }
168
169 #include "function_panel.h"
170 #include <FL/fl_ask.H>
171
open()172 void Fl_Function_Type::open() {
173 if (!function_panel) make_function_panel();
174 f_return_type_input->static_value(return_type);
175 f_name_input->static_value(name());
176 if (is_in_class()) {
177 f_public_member_choice->value(public_);
178 f_public_member_choice->show();
179 f_public_choice->hide();
180 } else {
181 f_public_choice->value(public_>0);
182 f_public_choice->show();
183 f_public_member_choice->hide();
184 }
185 f_c_button->value(cdecl_);
186 const char *c = comment();
187 f_comment_input->buffer()->text(c?c:"");
188 function_panel->show();
189 const char* message = 0;
190 for (;;) { // repeat as long as there are errors
191 if (message) fl_alert("%s", message);
192 for (;;) {
193 Fl_Widget* w = Fl::readqueue();
194 if (w == f_panel_cancel) goto BREAK2;
195 else if (w == f_panel_ok) break;
196 else if (!w) Fl::wait();
197 }
198 const char*c = f_name_input->value();
199 while (isspace(*c)) c++;
200 message = c_check(c); if (message) continue;
201 const char *d = c;
202 for (; *d != '('; d++) if (isspace(*d) || !*d) break;
203 if (*c && *d != '(') {
204 message = "must be name(arguments), try again:"; continue;
205 }
206 int mod = 0;
207 c = f_return_type_input->value();
208 message = c_check(c); if (message) continue;
209 name(f_name_input->value());
210 storestring(c, return_type);
211 if (is_in_class()) {
212 if (public_ != f_public_member_choice->value()) {
213 mod = 1;
214 public_ = f_public_member_choice->value();
215 redraw_browser();
216 }
217 } else {
218 if (public_ != f_public_choice->value()) {
219 mod = 1;
220 public_ = f_public_choice->value();
221 redraw_browser();
222 }
223 }
224 if (cdecl_ != f_c_button->value()) {
225 mod = 1;
226 cdecl_ = f_c_button->value();
227 }
228 c = f_comment_input->buffer()->text();
229 if (c && *c) {
230 if (!comment() || strcmp(c, comment())) redraw_browser();
231 comment(c);
232 } else {
233 if (comment()) redraw_browser();
234 comment(0);
235 }
236 if (c) free((void*)c);
237 if (mod) set_modflag(1);
238 break;
239 }
240 BREAK2:
241 function_panel->hide();
242 }
243
244 Fl_Function_Type Fl_Function_type;
245
246 extern const char* subclassname(Fl_Type*);
247
write_code1()248 void Fl_Function_Type::write_code1() {
249 constructor=0;
250 havewidgets = 0;
251 Fl_Type *child;
252 // if the function has no children (hence no body), Fluid will not generate
253 // the function either. This is great if you decide to implement that function
254 // inside another module
255 char havechildren = 0;
256 for (child = next; child && child->level > level; child = child->next) {
257 havechildren = 1;
258 if (child->is_widget()) {
259 havewidgets = 1;
260 break;
261 }
262 }
263 if (havechildren)
264 write_c("\n");
265 if (ismain()) {
266 if (havechildren)
267 write_c("int main(int argc, char **argv) {\n");
268 } else {
269 const char* rtype = return_type;
270 const char* star = "";
271 // from matt: let the user type "static " at the start of type
272 // in order to declare a static method;
273 int is_static = 0;
274 int is_virtual = 0;
275 if (rtype) {
276 if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;}
277 else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;}
278 if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;}
279 else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;}
280 }
281 if (!rtype) {
282 if (havewidgets) {
283 rtype = subclassname(child);
284 star = "*";
285 } else rtype = "void";
286 }
287
288 const char* k = class_name(0);
289 if (k) {
290 if (havechildren)
291 write_comment_c();
292 write_public(public_);
293 if (name()[0] == '~')
294 constructor = 1;
295 else {
296 size_t n = strlen(k);
297 if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1;
298 }
299 write_h(" ");
300 if (is_static) write_h("static ");
301 if (is_virtual) write_h("virtual ");
302 if (!constructor) {
303 write_h("%s%s ", rtype, star);
304 if (havechildren)
305 write_c("%s%s ", rtype, star);
306 }
307
308 // if this is a subclass, only write_h() the part before the ':'
309 char s[1024], *sptr = s;
310 char *nptr = (char *)name();
311
312 while (*nptr) {
313 if (*nptr == ':') {
314 if (nptr[1] != ':') break;
315 // Copy extra ":" for "class::member"...
316 *sptr++ = *nptr++;
317 }
318 *sptr++ = *nptr++;
319 }
320 *sptr = '\0';
321
322 write_h("%s;\n", s);
323 // skip all function default param. init in body:
324 int skips=0,skipc=0;
325 int nc=0,plevel=0;
326 for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
327 if (!skips && *nptr=='(') plevel++;
328 else if (!skips && *nptr==')') plevel--;
329 if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') )
330 skips = skips ? 0 : 1;
331 else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\'))
332 skipc = skipc ? 0 : 1;
333 if(!skips && !skipc && plevel==1 && *nptr =='=' &&
334 !(nc && *(nptr-1)=='\'') ) // ignore '=' case
335 while(*++nptr && (skips || skipc || ( (*nptr!=',' && *nptr!=')') || plevel!=1) )) {
336 if ( *nptr=='"' && *(nptr-1)!='\\' )
337 skips = skips ? 0 : 1;
338 else if(!skips && *nptr=='\'' && *(nptr-1)!='\\')
339 skipc = skipc ? 0 : 1;
340 if (!skips && !skipc && *nptr=='(') plevel++;
341 else if (!skips && *nptr==')') plevel--;
342 }
343
344 if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
345 }
346 *sptr = '\0';
347
348 if (havechildren)
349 write_c("%s::%s {\n", k, s);
350 } else {
351 if (havechildren)
352 write_comment_c();
353 if (public_) {
354 if (cdecl_)
355 write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name());
356 else
357 write_h("%s%s %s;\n", rtype, star, name());
358 } else {
359 if (havechildren)
360 write_c("static ");
361 }
362
363 // write everything but the default parameters (if any)
364 char s[1024], *sptr;
365 char *nptr;
366 int skips=0,skipc=0;
367 int nc=0,plevel=0;
368 for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
369 if (!skips && *nptr=='(') plevel++;
370 else if (!skips && *nptr==')') plevel--;
371 if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') )
372 skips = skips ? 0 : 1;
373 else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\'))
374 skipc = skipc ? 0 : 1;
375 if(!skips && !skipc && plevel==1 && *nptr =='=' &&
376 !(nc && *(nptr-1)=='\'') ) // ignore '=' case
377 while(*++nptr && (skips || skipc || ( (*nptr!=',' && *nptr!=')') || plevel!=1) )) {
378 if ( *nptr=='"' && *(nptr-1)!='\\' )
379 skips = skips ? 0 : 1;
380 else if(!skips && *nptr=='\'' && *(nptr-1)!='\\')
381 skipc = skipc ? 0 : 1;
382 if (!skips && !skipc && *nptr=='(') plevel++;
383 else if (!skips && *nptr==')') plevel--;
384 }
385
386 if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
387 }
388 *sptr = '\0';
389
390 if (havechildren)
391 write_c("%s%s %s {\n", rtype, star, s);
392 }
393 }
394
395 if (havewidgets && !child->name()) write_c(" %s* w;\n", subclassname(child));
396 indentation += 2;
397 }
398
write_code2()399 void Fl_Function_Type::write_code2() {
400 Fl_Type *child;
401 const char *var = "w";
402 char havechildren = 0;
403 for (child = next; child && child->level > level; child = child->next) {
404 havechildren = 1;
405 if (child->is_window() && child->name()) var = child->name();
406 }
407
408 if (ismain()) {
409 if (havewidgets) write_c(" %s->show(argc, argv);\n", var);
410 if (havechildren) write_c(" return Fl::run();\n");
411 } else if (havewidgets && !constructor && !return_type) {
412 write_c(" return %s;\n", var);
413 }
414 if (havechildren)
415 write_c("}\n");
416 indentation = 0;
417 }
418
has_signature(const char * rtype,const char * sig) const419 int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const {
420 if (rtype && !return_type) return 0;
421 if (!name()) return 0;
422 if ( (rtype==0L || strcmp(return_type, rtype)==0)
423 && fl_filename_match(name(), sig)) {
424 return 1;
425 }
426 return 0;
427 }
428
429 ////////////////////////////////////////////////////////////////
430
make()431 Fl_Type *Fl_Code_Type::make() {
432 Fl_Type *p = Fl_Type::current;
433 while (p && !p->is_code_block()) p = p->parent;
434 if (!p) {
435 fl_message("Please select a function");
436 return 0;
437 }
438 Fl_Code_Type *o = new Fl_Code_Type();
439 o->name("printf(\"Hello, World!\\n\");");
440 o->add(p);
441 o->factory = this;
442 return o;
443 }
444
open()445 void Fl_Code_Type::open() {
446 if (!code_panel) make_code_panel();
447 const char *text = name();
448 code_input->buffer()->text( text ? text : "" );
449 code_panel->show();
450 const char* message = 0;
451 for (;;) { // repeat as long as there are errors
452 if (message) fl_alert("%s", message);
453 for (;;) {
454 Fl_Widget* w = Fl::readqueue();
455 if (w == code_panel_cancel) goto BREAK2;
456 else if (w == code_panel_ok) break;
457 else if (!w) Fl::wait();
458 }
459 char*c = code_input->buffer()->text();
460 message = c_check(c); if (message) continue;
461 name(c);
462 free(c);
463 break;
464 }
465 BREAK2:
466 code_panel->hide();
467 }
468
469 Fl_Code_Type Fl_Code_type;
470
write_code1()471 void Fl_Code_Type::write_code1() {
472 const char* c = name();
473 if (!c) return;
474 const char *pch;
475 const char *ind = indent();
476 while( (pch=strchr(c,'\n')) )
477 {
478 int line_len = pch - c;
479 write_c("%s%.*s\n", ind, line_len, c);
480 c = pch+1;
481 }
482 write_c("%s%s\n", ind, c);
483 }
484
write_code2()485 void Fl_Code_Type::write_code2() {}
486
487 ////////////////////////////////////////////////////////////////
488
make()489 Fl_Type *Fl_CodeBlock_Type::make() {
490 Fl_Type *p = Fl_Type::current;
491 while (p && !p->is_code_block()) p = p->parent;
492 if (!p) {
493 fl_message("Please select a function");
494 return 0;
495 }
496 Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
497 o->name("if (test())");
498 o->after = 0;
499 o->add(p);
500 o->factory = this;
501 return o;
502 }
503
write_properties()504 void Fl_CodeBlock_Type::write_properties() {
505 Fl_Type::write_properties();
506 if (after) {
507 write_string("after");
508 write_word(after);
509 }
510 }
511
read_property(const char * c)512 void Fl_CodeBlock_Type::read_property(const char *c) {
513 if (!strcmp(c,"after")) {
514 storestring(read_word(),after);
515 } else {
516 Fl_Type::read_property(c);
517 }
518 }
519
open()520 void Fl_CodeBlock_Type::open() {
521 if (!codeblock_panel) make_codeblock_panel();
522 code_before_input->static_value(name());
523 code_after_input->static_value(after);
524 codeblock_panel->show();
525 const char* message = 0;
526 for (;;) { // repeat as long as there are errors
527 if (message) fl_alert("%s", message);
528 for (;;) {
529 Fl_Widget* w = Fl::readqueue();
530 if (w == codeblock_panel_cancel) goto BREAK2;
531 else if (w == codeblock_panel_ok) break;
532 else if (!w) Fl::wait();
533 }
534 const char*c = code_before_input->value();
535 message = c_check(c); if (message) continue;
536 name(c);
537 c = code_after_input->value();
538 message = c_check(c); if (message) continue;
539 storestring(c, after);
540 break;
541 }
542 BREAK2:
543 codeblock_panel->hide();
544 }
545
546 Fl_CodeBlock_Type Fl_CodeBlock_type;
547
write_code1()548 void Fl_CodeBlock_Type::write_code1() {
549 const char* c = name();
550 write_c("%s%s {\n", indent(), c ? c : "");
551 indentation += 2;
552 }
553
write_code2()554 void Fl_CodeBlock_Type::write_code2() {
555 indentation -= 2;
556 if (after) write_c("%s} %s\n", indent(), after);
557 else write_c("%s}\n", indent());
558 }
559
560 ////////////////////////////////////////////////////////////////
561
is_public() const562 int Fl_Decl_Type::is_public() const
563 {
564 Fl_Type *p = parent;
565 while (p && !p->is_decl_block()) p = p->parent;
566 if(p && p->is_public() && public_)
567 return public_;
568 else if(!p)
569 return public_;
570 return 0;
571 }
572
make()573 Fl_Type *Fl_Decl_Type::make() {
574 Fl_Type *p = Fl_Type::current;
575 while (p && !p->is_decl_block()) p = p->parent;
576 Fl_Decl_Type *o = new Fl_Decl_Type();
577 o->public_ = 0;
578 o->static_ = 1;
579 o->name("int x;");
580 o->add(p);
581 o->factory = this;
582 return o;
583 }
584
write_properties()585 void Fl_Decl_Type::write_properties() {
586 Fl_Type::write_properties();
587 switch (public_) {
588 case 0: write_string("private"); break;
589 case 1: write_string("public"); break;
590 case 2: write_string("protected"); break;
591 }
592 if (static_)
593 write_string("local");
594 else
595 write_string("global");
596 }
597
read_property(const char * c)598 void Fl_Decl_Type::read_property(const char *c) {
599 if (!strcmp(c,"public")) {
600 public_ = 1;
601 } else if (!strcmp(c,"private")) {
602 public_ = 0;
603 } else if (!strcmp(c,"protected")) {
604 public_ = 2;
605 } else if (!strcmp(c,"local")) {
606 static_ = 1;
607 } else if (!strcmp(c,"global")) {
608 static_ = 0;
609 } else {
610 Fl_Type::read_property(c);
611 }
612 }
613
open()614 void Fl_Decl_Type::open() {
615 if (!decl_panel) make_decl_panel();
616 decl_input->static_value(name());
617 if (is_in_class()) {
618 decl_class_choice->value(public_);
619 decl_class_choice->show();
620 decl_choice->hide();
621 } else {
622 decl_choice->value((public_&1)|((static_&1)<<1));
623 decl_choice->show();
624 decl_class_choice->hide();
625 }
626 const char *c = comment();
627 decl_comment_input->buffer()->text(c?c:"");
628 decl_panel->show();
629 const char* message = 0;
630 for (;;) { // repeat as long as there are errors
631 if (message) fl_alert("%s", message);
632 for (;;) {
633 Fl_Widget* w = Fl::readqueue();
634 if (w == decl_panel_cancel) goto BREAK2;
635 else if (w == decl_panel_ok) break;
636 else if (!w) Fl::wait();
637 }
638 const char*c = decl_input->value();
639 while (isspace(*c)) c++;
640 message = c_check(c&&c[0]=='#' ? c+1 : c);
641 if (message) continue;
642 name(c);
643 if (is_in_class()) {
644 if (public_!=decl_class_choice->value()) {
645 set_modflag(1);
646 public_ = decl_class_choice->value();
647 }
648 } else {
649 if (public_!=(decl_choice->value()&1)) {
650 set_modflag(1);
651 public_ = (decl_choice->value()&1);
652 }
653 if (static_!=((decl_choice->value()>>1)&1)) {
654 set_modflag(1);
655 static_ = ((decl_choice->value()>>1)&1);
656 }
657 }
658 c = decl_comment_input->buffer()->text();
659 if (c && *c) {
660 if (!comment() || strcmp(c, comment())) redraw_browser();
661 comment(c);
662 } else {
663 if (comment()) redraw_browser();
664 comment(0);
665 }
666 if (c) free((void*)c);
667 break;
668 }
669 BREAK2:
670 decl_panel->hide();
671 }
672
673 Fl_Decl_Type Fl_Decl_type;
674
write_code1()675 void Fl_Decl_Type::write_code1() {
676 const char* c = name();
677 if (!c) return;
678 // handle a few keywords differently if inside a class
679 if (is_in_class() && ( (!strncmp(c,"class",5) && isspace(c[5]))
680 || (!strncmp(c,"typedef",7) && isspace(c[7]))
681 || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9]))
682 || (!strncmp(c,"struct",6) && isspace(c[6]))
683 ) ) {
684 write_public(public_);
685 write_comment_h(" ");
686 write_h(" %s\n", c);
687 return;
688 }
689 // handle putting #include, extern, using or typedef into decl:
690 if ( (!isalpha(*c) && *c != '~')
691 || (!strncmp(c,"extern",6) && isspace(c[6]))
692 || (!strncmp(c,"class",5) && isspace(c[5]))
693 || (!strncmp(c,"typedef",7) && isspace(c[7]))
694 || (!strncmp(c,"using",5) && isspace(c[5]))
695 || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9]))
696 // || !strncmp(c,"struct",6) && isspace(c[6])
697 ) {
698 if (public_) {
699 write_comment_h();
700 write_h("%s\n", c);
701 } else {
702 write_comment_c();
703 write_c("%s\n", c);
704 }
705 return;
706 }
707 // find the first C++ style comment
708 const char* e = c+strlen(c), *csc = c;
709 while (csc<e && (csc[0]!='/' || csc[1]!='/')) csc++;
710 if (csc!=e) e = csc; // comment found
711 // lose all trailing semicolons so I can add one:
712 while (e>c && e[-1]==' ') e--;
713 while (e>c && e[-1]==';') e--;
714 if (class_name(1)) {
715 write_public(public_);
716 write_comment_h(" ");
717 write_h(" %.*s; %s\n", (int)(e-c), c, csc);
718 } else {
719 if (public_) {
720 if (static_)
721 write_h("extern ");
722 else
723 write_comment_h();
724 write_h("%.*s; %s\n", (int)(e-c), c, csc);
725 if (static_) {
726 write_comment_c();
727 write_c("%.*s; %s\n", (int)(e-c), c, csc);
728 }
729 } else {
730 write_comment_c();
731 if (static_)
732 write_c("static ");
733 write_c("%.*s; %s\n", (int)(e-c), c, csc);
734 }
735 }
736 }
737
write_code2()738 void Fl_Decl_Type::write_code2() {}
739
740 ////////////////////////////////////////////////////////////////
741
make()742 Fl_Type *Fl_Data_Type::make() {
743 Fl_Type *p = Fl_Type::current;
744 while (p && !p->is_decl_block()) p = p->parent;
745 Fl_Data_Type *o = new Fl_Data_Type();
746 o->public_ = 1;
747 o->static_ = 1;
748 o->filename_ = 0;
749 o->name("myBinaryData");
750 o->add(p);
751 o->factory = this;
752 return o;
753 }
754
write_properties()755 void Fl_Data_Type::write_properties() {
756 Fl_Decl_Type::write_properties();
757 if (filename_) {
758 write_string("filename");
759 write_word(filename_);
760 }
761 }
762
read_property(const char * c)763 void Fl_Data_Type::read_property(const char *c) {
764 if (!strcmp(c,"filename")) {
765 storestring(read_word(), filename_, 1);
766 } else {
767 Fl_Decl_Type::read_property(c);
768 }
769 }
770
open()771 void Fl_Data_Type::open() {
772 if (!data_panel) make_data_panel();
773 data_input->static_value(name());
774 if (is_in_class()) {
775 data_class_choice->value(public_);
776 data_class_choice->show();
777 data_choice->hide();
778 } else {
779 data_choice->value((public_&1)|((static_&1)<<1));
780 data_choice->show();
781 data_class_choice->hide();
782 }
783 data_filename->value(filename_?filename_:"");
784 const char *c = comment();
785 data_comment_input->buffer()->text(c?c:"");
786 data_panel->show();
787 const char* message = 0;
788 for (;;) { // repeat as long as there are errors
789 if (message) fl_alert("%s", message);
790 for (;;) {
791 Fl_Widget* w = Fl::readqueue();
792 if (w == data_panel_cancel) goto BREAK2;
793 else if (w == data_panel_ok) break;
794 else if (w == data_filebrowser) {
795 goto_source_dir();
796 const char *fn = fl_file_chooser("Load Binary Data", 0L, data_filename->value(), 1);
797 leave_source_dir();
798 if (fn) {
799 if (strcmp(fn, data_filename->value()))
800 set_modflag(1);
801 data_filename->value(fn);
802 }
803 }
804 else if (!w) Fl::wait();
805 }
806 // store the variable name:
807 const char*c = data_input->value();
808 char *s = strdup(c), *p = s, *q, *n;
809 for (;;++p) {
810 if (!isspace((unsigned char)(*p))) break;
811 }
812 n = p;
813 if ( (!isalpha((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) goto OOPS;
814 ++p;
815 for (;;++p) {
816 if ( (!isalnum((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) break;
817 }
818 q = p;
819 for (;;++q) {
820 if (!*q) break;
821 if (!isspace((unsigned char)(*q))) goto OOPS;
822 }
823 if (n==q) {
824 OOPS: message = "variable name must be a C identifier";
825 free((void*)s);
826 continue;
827 }
828 *p = 0;
829 name(n);
830 free(s);
831 // store flags
832 if (is_in_class()) {
833 if (public_!=data_class_choice->value()) {
834 set_modflag(1);
835 public_ = data_class_choice->value();
836 }
837 } else {
838 if (public_!=(data_choice->value()&1)) {
839 set_modflag(1);
840 public_ = (data_choice->value()&1);
841 }
842 if (static_!=((data_choice->value()>>1)&1)) {
843 set_modflag(1);
844 static_ = ((data_choice->value()>>1)&1);
845 }
846 }
847 // store the filename
848 c = data_filename->value();
849 if (filename_ && strcmp(filename_, data_filename->value()))
850 set_modflag(1);
851 else if (!filename_ && *c)
852 set_modflag(1);
853 if (filename_) { free((void*)filename_); filename_ = 0L; }
854 if (c && *c) filename_ = strdup(c);
855 // store the comment
856 c = data_comment_input->buffer()->text();
857 if (c && *c) {
858 if (!comment() || strcmp(c, comment())) redraw_browser();
859 comment(c);
860 } else {
861 if (comment()) redraw_browser();
862 comment(0);
863 }
864 if (c) free((void*)c);
865 break;
866 }
867 BREAK2:
868 data_panel->hide();
869 }
870
871 Fl_Data_Type Fl_Data_type;
872
write_code1()873 void Fl_Data_Type::write_code1() {
874 const char *message = 0;
875 const char *c = name();
876 if (!c) return;
877 const char *fn = filename_;
878 char *data = 0;
879 int nData = -1;
880 // path should be set correctly already
881 if (filename_ && !write_sourceview) {
882 FILE *f = fl_fopen(filename_, "rb");
883 if (!f) {
884 message = "Can't include binary file. Can't open";
885 } else {
886 fseek(f, 0, SEEK_END);
887 nData = ftell(f);
888 fseek(f, 0, SEEK_SET);
889 if (nData) {
890 data = (char*)calloc(nData, 1);
891 if (fread(data, nData, 1, f)==0) { /* use default */ }
892 }
893 fclose(f);
894 }
895 } else {
896 fn = "<no filename>";
897 }
898 if (is_in_class()) {
899 write_public(public_);
900 write_comment_h(" ");
901 write_h(" static unsigned char %s[%d];\n", c, nData);
902 write_c("unsigned char %s::%s[%d] = /* binary data included from %s */\n", class_name(1), c, nData, fn);
903 if (message) write_c("#error %s %s\n", message, fn);
904 write_cdata(data, nData);
905 write_c(";\n");
906 } else {
907 // the "header only" option does not apply here!
908 if (public_) {
909 if (static_) {
910 write_h("extern unsigned char %s[%d];\n", c, nData);
911 write_comment_c();
912 write_c("unsigned char %s[%d] = /* binary data included from %s */\n", c, nData, fn);
913 if (message) write_c("#error %s %s\n", message, fn);
914 write_cdata(data, nData);
915 write_c(";\n");
916 } else {
917 write_comment_h();
918 write_h("#error Unsupported declaration loading binary data %s\n", fn);
919 write_h("unsigned char %s[3] = { 1, 2, 3 };\n", c);
920 }
921 } else {
922 write_comment_c();
923 if (static_)
924 write_c("static ");
925 write_c("unsigned char %s[%d] = /* binary data included from %s */\n", c, nData, fn);
926 if (message) write_c("#error %s %s\n", message, fn);
927 write_cdata(data, nData);
928 write_c(";\n");
929 }
930 }
931 // if we are in interactive mode, we pop up a warning dialog
932 // giving the error: (compile_only && !write_sourceview)
933 if (message && !write_sourceview) {
934 if (compile_only)
935 fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn);
936 else
937 fl_alert("%s\n%s\n", message, fn);
938 }
939 if (data) free(data);
940 }
941
write_code2()942 void Fl_Data_Type::write_code2() {}
943
944 ////////////////////////////////////////////////////////////////
945
is_public() const946 int Fl_DeclBlock_Type::is_public() const {return public_;}
947
make()948 Fl_Type *Fl_DeclBlock_Type::make() {
949 Fl_Type *p = Fl_Type::current;
950 while (p && !p->is_decl_block()) p = p->parent;
951 Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
952 o->name("#if 1");
953 o->public_ = 0;
954 o->after = strdup("#endif");
955 o->add(p);
956 o->factory = this;
957 return o;
958 }
959
write_properties()960 void Fl_DeclBlock_Type::write_properties() {
961 Fl_Type::write_properties();
962 switch (public_) {
963 case 1: write_string("public"); break;
964 case 2: write_string("protected"); break;
965 }
966 write_string("after");
967 write_word(after);
968 }
969
read_property(const char * c)970 void Fl_DeclBlock_Type::read_property(const char *c) {
971 if(!strcmp(c,"public")) {
972 public_ = 1;
973 } else if(!strcmp(c,"protected")) {
974 public_ = 2;
975 } else if (!strcmp(c,"after")) {
976 storestring(read_word(),after);
977 } else {
978 Fl_Type::read_property(c);
979 }
980 }
981
open()982 void Fl_DeclBlock_Type::open() {
983 if (!declblock_panel) make_declblock_panel();
984 decl_before_input->static_value(name());
985 declblock_public_choice->value((public_>0));
986 decl_after_input->static_value(after);
987 declblock_panel->show();
988 const char* message = 0;
989 for (;;) { // repeat as long as there are errors
990 if (message) fl_alert("%s", message);
991 for (;;) {
992 Fl_Widget* w = Fl::readqueue();
993 if (w == declblock_panel_cancel) goto BREAK2;
994 else if (w == declblock_panel_ok) break;
995 else if (!w) Fl::wait();
996 }
997 const char*c = decl_before_input->value();
998 while (isspace(*c)) c++;
999 message = c_check(c&&c[0]=='#' ? c+1 : c);
1000 if (message) continue;
1001 name(c);
1002 c = decl_after_input->value();
1003 while (isspace(*c)) c++;
1004 message = c_check(c&&c[0]=='#' ? c+1 : c);
1005 if (message) continue;
1006 storestring(c,after);
1007 if (public_ != declblock_public_choice->value()) {
1008 set_modflag(1);
1009 public_ = declblock_public_choice->value();
1010 redraw_browser();
1011 }
1012 break;
1013 }
1014 BREAK2:
1015 declblock_panel->hide();
1016 }
1017
1018 Fl_DeclBlock_Type Fl_DeclBlock_type;
1019
write_code1()1020 void Fl_DeclBlock_Type::write_code1() {
1021 const char* c = name();
1022 if (public_)
1023 write_h("%s\n", c);
1024 write_c("%s\n", c);
1025 }
1026
write_code2()1027 void Fl_DeclBlock_Type::write_code2() {
1028 const char* c = after;
1029 if (public_)
1030 write_h("%s\n", c);
1031 write_c("%s\n", c);
1032 }
1033
1034 ////////////////////////////////////////////////////////////////
1035
make()1036 Fl_Type *Fl_Comment_Type::make() {
1037 Fl_Type *p = Fl_Type::current;
1038 while (p && !p->is_code_block()) p = p->parent;
1039 Fl_Comment_Type *o = new Fl_Comment_Type();
1040 o->in_c_ = 1;
1041 o->in_h_ = 1;
1042 o->style_ = 0;
1043 o->name("my comment");
1044 o->add(p);
1045 o->factory = this;
1046 o->title_buf[0] = 0;
1047 return o;
1048 }
1049
write_properties()1050 void Fl_Comment_Type::write_properties() {
1051 Fl_Type::write_properties();
1052 if (in_c_) write_string("in_source"); else write_string("not_in_source");
1053 if (in_h_) write_string("in_header"); else write_string("not_in_header");
1054 }
1055
read_property(const char * c)1056 void Fl_Comment_Type::read_property(const char *c) {
1057 if (!strcmp(c,"in_source")) {
1058 in_c_ = 1;
1059 } else if (!strcmp(c,"not_in_source")) {
1060 in_c_ = 0;
1061 } else if (!strcmp(c,"in_header")) {
1062 in_h_ = 1;
1063 } else if (!strcmp(c,"not_in_header")) {
1064 in_h_ = 0;
1065 } else {
1066 Fl_Type::read_property(c);
1067 }
1068 }
1069
1070 #include "comments.h"
1071
load_comments_preset(Fl_Preferences & menu)1072 static void load_comments_preset(Fl_Preferences &menu) {
1073 static const char * const predefined_comment[] = {
1074 "GNU Public License/GPL Header", "GNU Public License/GPL Footer",
1075 "GNU Public License/LGPL Header", "GNU Public License/LGPL Footer",
1076 "FLTK/Header", "FLTK/Footer" };
1077 int i;
1078 menu.set("n", 6);
1079 Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
1080 for (i=0; i<6; i++) {
1081 menu.set(Fl_Preferences::Name(i), predefined_comment[i]);
1082 db.set(predefined_comment[i], comment_text[i]);
1083 }
1084 }
1085
open()1086 void Fl_Comment_Type::open() {
1087 if (!comment_panel) make_comment_panel();
1088 const char *text = name();
1089 {
1090 int i=0, n=0;
1091 Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
1092 comment_predefined->clear();
1093 comment_predefined->add("_Edit/Add current comment...");
1094 comment_predefined->add("_Edit/Remove last selection...");
1095 menu.get("n", n, -1);
1096 if (n==-1) load_comments_preset(menu);
1097 menu.get("n", n, 0);
1098 for (i=0;i<n;i++) {
1099 char *text;
1100 menu.get(Fl_Preferences::Name(i), text, "");
1101 comment_predefined->add(text);
1102 free(text);
1103 }
1104 }
1105 comment_input->buffer()->text( text ? text : "" );
1106 comment_in_source->value(in_c_);
1107 comment_in_header->value(in_h_);
1108 comment_panel->show();
1109 const char* message = 0;
1110 char itempath[FL_PATH_MAX]; itempath[0] = 0;
1111 int last_selected_item = 0;
1112 for (;;) { // repeat as long as there are errors
1113 if (message) fl_alert("%s", message);
1114 for (;;) {
1115 Fl_Widget* w = Fl::readqueue();
1116 if (w == comment_panel_cancel) goto BREAK2;
1117 else if (w == comment_panel_ok) break;
1118 else if (w == comment_predefined) {
1119 if (comment_predefined->value()==1) {
1120 // add the current comment to the database
1121 const char *xname = fl_input(
1122 "Please enter a name to reference the current\ncomment in your database.\n\n"
1123 "Use forward slashes '/' to create submenus.",
1124 "My Comment");
1125 if (xname) {
1126 char *name = strdup(xname);
1127 for (char*s=name;*s;s++) if (*s==':') *s = ';';
1128 int n;
1129 Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
1130 db.set(name, comment_input->buffer()->text());
1131 Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
1132 menu.get("n", n, 0);
1133 menu.set(Fl_Preferences::Name(n), name);
1134 menu.set("n", ++n);
1135 comment_predefined->add(name);
1136 free(name);
1137 }
1138 } else if (comment_predefined->value()==2) {
1139 // remove the last selected comment from the database
1140 if (itempath[0]==0 || last_selected_item==0) {
1141 fl_message("Please select an entry form this menu first.");
1142 } else if (fl_choice("Are you sure that you want to delete the entry\n"
1143 "\"%s\"\nfrom the database?", "Cancel", "Delete",
1144 NULL, itempath)) {
1145 Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
1146 db.deleteEntry(itempath);
1147 comment_predefined->remove(last_selected_item);
1148 Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
1149 int i, n;
1150 for (i=4, n=0; i<comment_predefined->size(); i++) {
1151 const Fl_Menu_Item *mi = comment_predefined->menu()+i;
1152 if (comment_predefined->item_pathname(itempath, 255, mi)==0) {
1153 if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
1154 if (itempath[0]) menu.set(Fl_Preferences::Name(n++), itempath);
1155 }
1156 }
1157 menu.set("n", n);
1158 }
1159 } else {
1160 // load the selected comment from the database
1161 if (comment_predefined->item_pathname(itempath, 255)==0) {
1162 if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
1163 Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
1164 char *text;
1165 db.get(itempath, text, "(no text found in data base)");
1166 comment_input->buffer()->text(text);
1167 free(text);
1168 last_selected_item = comment_predefined->value();
1169 }
1170 }
1171 }
1172 else if (w == comment_load) {
1173 // load a comment from disk
1174 fl_file_chooser_ok_label("Use File");
1175 const char *fname = fl_file_chooser("Pick a comment", 0L, 0L);
1176 fl_file_chooser_ok_label(NULL);
1177 if (fname) {
1178 if (comment_input->buffer()->loadfile(fname)) {
1179 fl_alert("Error loading file\n%s", fname);
1180 }
1181 }
1182 }
1183 else if (!w) Fl::wait();
1184 }
1185 char*c = comment_input->buffer()->text();
1186 name(c);
1187 free(c);
1188 int mod = 0;
1189 if (in_c_ != comment_in_source->value()) {
1190 in_c_ = comment_in_source->value();
1191 mod = 1;
1192 }
1193 if (in_h_ != comment_in_header->value()) {
1194 in_h_ = comment_in_header->value();
1195 mod = 1;
1196 }
1197 if (mod) set_modflag(1);
1198 break;
1199 }
1200 BREAK2:
1201 title_buf[0] = 0;
1202 comment_panel->hide();
1203 }
1204
title()1205 const char *Fl_Comment_Type::title() {
1206 const char* n = name();
1207 if (!n || !*n) return type_name();
1208 if (title_buf[0]==0) {
1209 const char *s = n;
1210 char *d = title_buf;
1211 int i = 50;
1212 while (--i > 0) {
1213 char n = *s++;
1214 if (n==0) break;
1215 if (n=='\r') { *d++ = '\\'; *d++ = 'r'; i--; }
1216 else if (n=='\n') { *d++ = '\\'; *d++ = 'n'; i--; }
1217 else if (n<32) { *d++ = '^'; *d++ = 'A'+n; i--; }
1218 else *d++ = n;
1219 }
1220 if (i<=0) { *d++ = '.'; *d++ = '.'; *d++ = '.'; }
1221 *d++ = 0;
1222 }
1223 return title_buf;
1224 }
1225
1226 Fl_Comment_Type Fl_Comment_type;
1227
write_code1()1228 void Fl_Comment_Type::write_code1() {
1229 const char* c = name();
1230 if (!c) return;
1231 if (!in_c_ && !in_h_) return;
1232 // find out if there is already a valid comment:
1233 const char *s = c;
1234 while (isspace(*s)) s++;
1235 // if this seems to be a C style comment, copy the block as is
1236 // (it's up to the user to correctly close the comment)
1237 if (s[0]=='/' && s[1]=='*') {
1238 if (in_h_) write_h("%s\n", c);
1239 if (in_c_) write_c("%s\n", c);
1240 return;
1241 }
1242 // copy the comment line by line, add the double slash if needed
1243 char *txt = strdup(c);
1244 char *b = txt, *e = txt;
1245 for (;;) {
1246 // find the end of the line and set it to NUL
1247 while (*e && *e!='\n') e++;
1248 char eol = *e;
1249 *e = 0;
1250 // check if there is a C++ style comment at the beginning of the line
1251 char *s = b;
1252 while (isspace(*s)) s++;
1253 if (s!=e && ( s[0]!='/' || s[1]!='/') ) {
1254 // if no comment marker was found, we add one ourselves
1255 if (in_h_) write_h("// ");
1256 if (in_c_) write_c("// ");
1257 }
1258 // now copy the rest of the line
1259 if (in_h_) write_h("%s\n", b);
1260 if (in_c_) write_c("%s\n", b);
1261 if (eol==0) break;
1262 *e++ = eol;
1263 b = e;
1264 }
1265 }
1266
write_code2()1267 void Fl_Comment_Type::write_code2() {}
1268
1269 ////////////////////////////////////////////////////////////////
1270
class_name(const int need_nest) const1271 const char* Fl_Type::class_name(const int need_nest) const {
1272 Fl_Type* p = parent;
1273 while (p) {
1274 if (p->is_class()) {
1275 // see if we are nested in another class, we must fully-qualify name:
1276 // this is lame but works...
1277 const char* q = 0;
1278 if(need_nest) q=p->class_name(need_nest);
1279 if (q) {
1280 static char s[256];
1281 if (q != s) strlcpy(s, q, sizeof(s));
1282 strlcat(s, "::", sizeof(s));
1283 strlcat(s, p->name(), sizeof(s));
1284 return s;
1285 }
1286 return p->name();
1287 }
1288 p = p->parent;
1289 }
1290 return 0;
1291 }
1292
1293 /**
1294 * If this Type resides inside a class, this function returns the class type, or null.
1295 */
is_in_class() const1296 const Fl_Class_Type *Fl_Type::is_in_class() const {
1297 Fl_Type* p = parent;
1298 while (p) {
1299 if (p->is_class()) {
1300 return (Fl_Class_Type*)p;
1301 }
1302 p = p->parent;
1303 }
1304 return 0;
1305 }
1306
is_public() const1307 int Fl_Class_Type::is_public() const {return public_;}
1308
prefix(const char * p)1309 void Fl_Class_Type::prefix(const char*p) {
1310 free((void*) class_prefix);
1311 class_prefix=strdup(p ? p : "" );
1312 }
1313
make()1314 Fl_Type *Fl_Class_Type::make() {
1315 Fl_Type *p = Fl_Type::current;
1316 while (p && !p->is_decl_block()) p = p->parent;
1317 Fl_Class_Type *o = new Fl_Class_Type();
1318 o->name("UserInterface");
1319 o->class_prefix=0;
1320 o->subclass_of = 0;
1321 o->public_ = 1;
1322 o->add(p);
1323 o->factory = this;
1324 return o;
1325 }
1326
write_properties()1327 void Fl_Class_Type::write_properties() {
1328 Fl_Type::write_properties();
1329 if (subclass_of) {
1330 write_string(":");
1331 write_word(subclass_of);
1332 }
1333 switch (public_) {
1334 case 0: write_string("private"); break;
1335 case 2: write_string("protected"); break;
1336 }
1337 }
1338
read_property(const char * c)1339 void Fl_Class_Type::read_property(const char *c) {
1340 if (!strcmp(c,"private")) {
1341 public_ = 0;
1342 } else if (!strcmp(c,"protected")) {
1343 public_ = 2;
1344 } else if (!strcmp(c,":")) {
1345 storestring(read_word(), subclass_of);
1346 } else {
1347 Fl_Type::read_property(c);
1348 }
1349 }
1350
open()1351 void Fl_Class_Type::open() {
1352 if (!class_panel) make_class_panel();
1353 char fullname[FL_PATH_MAX]="";
1354 if (prefix() && strlen(prefix()))
1355 sprintf(fullname,"%s %s",prefix(),name());
1356 else
1357 strcpy(fullname, name());
1358 c_name_input->static_value(fullname);
1359 c_subclass_input->static_value(subclass_of);
1360 c_public_button->value(public_);
1361 const char *c = comment();
1362 c_comment_input->buffer()->text(c?c:"");
1363 class_panel->show();
1364 const char* message = 0;
1365
1366 char *na=0,*pr=0,*p=0; // name and prefix substrings
1367
1368 for (;;) { // repeat as long as there are errors
1369 if (message) fl_alert("%s", message);
1370 for (;;) {
1371 Fl_Widget* w = Fl::readqueue();
1372 if (w == c_panel_cancel) goto BREAK2;
1373 else if (w == c_panel_ok) break;
1374 else if (!w) Fl::wait();
1375 }
1376 const char*c = c_name_input->value();
1377 char *s = strdup(c);
1378 size_t len = strlen(s);
1379 if (!*s) goto OOPS;
1380 p = (char*) (s+len-1);
1381 while (p>=s && isspace(*p)) *(p--)='\0';
1382 if (p<s) goto OOPS;
1383 while (p>=s && is_id(*p)) p--;
1384 if ( (p<s && !is_id(*(p+1))) || !*(p+1) ) {
1385 OOPS: message = "class name must be C++ identifier";
1386 free((void*)s);
1387 continue;
1388 }
1389 na=p+1; // now we have the name
1390 if(p>s) *p--='\0';
1391 while (p>=s && isspace(*p)) *(p--)='\0';
1392 while (p>=s && is_id(*p)) p--;
1393 if (p<s) p++;
1394 if (is_id(*p) && p<na) pr=p; // prefix detected
1395 c = c_subclass_input->value();
1396 message = c_check(c);
1397 if (message) { free((void*)s);continue;}
1398 name(na);
1399 prefix(pr);
1400 free((void*)s);
1401 storestring(c, subclass_of);
1402 if (public_ != c_public_button->value()) {
1403 public_ = c_public_button->value();
1404 set_modflag(1);
1405 }
1406 c = c_comment_input->buffer()->text();
1407 if (c && *c) {
1408 if (!comment() || strcmp(c, comment())) redraw_browser();
1409 comment(c);
1410 } else {
1411 if (comment()) redraw_browser();
1412 comment(0);
1413 }
1414 if (c) free((void*)c);
1415 break;
1416 }
1417 BREAK2:
1418 class_panel->hide();
1419 }
1420
1421 Fl_Class_Type Fl_Class_type;
1422
1423 Fl_Class_Type *current_class;
1424 extern Fl_Widget_Class_Type *current_widget_class;
write_public(int state)1425 void write_public(int state) {
1426 if (!current_class && !current_widget_class) return;
1427 if (current_class && current_class->write_public_state == state) return;
1428 if (current_widget_class && current_widget_class->write_public_state == state) return;
1429 if (current_class) current_class->write_public_state = state;
1430 if (current_widget_class) current_widget_class->write_public_state = state;
1431 switch (state) {
1432 case 0: write_h("private:\n"); break;
1433 case 1: write_h("public:\n"); break;
1434 case 2: write_h("protected:\n"); break;
1435 }
1436 }
1437
write_code1()1438 void Fl_Class_Type::write_code1() {
1439 parent_class = current_class;
1440 current_class = this;
1441 write_public_state = 0;
1442 write_h("\n");
1443 write_comment_h();
1444 if (prefix() && strlen(prefix()))
1445 write_h("class %s %s ", prefix(), name());
1446 else
1447 write_h("class %s ", name());
1448 if (subclass_of) write_h(": %s ", subclass_of);
1449 write_h("{\n");
1450 }
1451
write_code2()1452 void Fl_Class_Type::write_code2() {
1453 write_h("};\n");
1454 current_class = parent_class;
1455 }
1456
1457 /**
1458 * Return 1 if this class contains a function with the given signature.
1459 */
has_function(const char * rtype,const char * sig) const1460 int Fl_Class_Type::has_function(const char *rtype, const char *sig) const {
1461 Fl_Type *child;
1462 for (child = next; child && child->level > level; child = child->next) {
1463 if (child->level == level+1 && strcmp(child->type_name(), "Function")==0) {
1464 const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
1465 if (fn->has_signature(rtype, sig))
1466 return 1;
1467 }
1468 }
1469 return 0;
1470 }
1471
1472 //
1473 // End of "$Id: Fl_Function_Type.cxx 8786 2011-06-07 11:41:36Z manolo $".
1474 //
1475