fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Function_Type.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Function_Type.cxx 8063 2010-12-19 21:20:10Z matt $"
00003 //
00004 // C function type code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 #include <FL/Fl.H>
00029 #include <FL/Fl_Preferences.H>
00030 #include <FL/Fl_File_Chooser.H>
00031 #include "Fl_Type.h"
00032 #include <FL/fl_show_input.H>
00033 #include <FL/Fl_File_Chooser.H>
00034 #include "../src/flstring.h"
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 
00038 extern int i18n_type;
00039 extern const char* i18n_include;
00040 extern const char* i18n_function;
00041 extern const char* i18n_file;
00042 extern const char* i18n_set;
00043 extern char i18n_program[];
00044 
00045 extern int compile_only;
00046 
00047 extern void redraw_browser();
00048 extern void goto_source_dir();
00049 extern void leave_source_dir();
00050 
00052 // quick check of any C code for legality, returns an error message
00053 
00054 static char buffer[128]; // for error messages
00055 
00056 // check a quoted string ending in either " or ' or >:
00057 const char *_q_check(const char * & c, int type) {
00058   for (;;) switch (*c++) {
00059     case '\0':
00060       sprintf(buffer,"missing %c",type);
00061       return buffer;
00062     case '\\':
00063       if (*c) c++;
00064       break;
00065     default:
00066       if (*(c-1) == type) return 0;
00067   }
00068 }
00069 
00070 // check normal code, match braces and parenthesis:
00071 const char *_c_check(const char * & c, int type) {
00072   const char *d;
00073   for (;;) switch (*c++) {
00074     case 0:
00075       if (!type) return 0;
00076       sprintf(buffer, "missing %c", type);
00077       return buffer;
00078     case '/':
00079       // Skip comments as needed...
00080       if (*c == '/') {
00081         while (*c != '\n' && *c) c++;
00082       } else if (*c == '*') {
00083         c++;
00084         while ((*c != '*' || c[1] != '/') && *c) c++;
00085         if (*c == '*') c+=2;
00086         else {
00087           return "missing '*/'";
00088         }
00089       }
00090       break;
00091     case '#':
00092       // treat cpp directives as a comment:
00093       while (*c != '\n' && *c) c++;
00094       break;
00095     case '{':
00096       if (type==')') goto UNEXPECTED;
00097       d = _c_check(c,'}');
00098       if (d) return d;
00099       break;
00100     case '(':
00101       d = _c_check(c,')');
00102       if (d) return d;
00103       break;
00104     case '\"':
00105       d = _q_check(c,'\"');
00106       if (d) return d;
00107       break;
00108     case '\'':
00109       d = _q_check(c,'\'');
00110       if (d) return d;
00111       break;
00112     case '}':
00113     case ')':
00114     UNEXPECTED:
00115       if (type == *(c-1)) return 0;
00116       sprintf(buffer, "unexpected %c", *(c-1));
00117       return buffer;
00118   }
00119 }
00120 
00121 const char *c_check(const char *c, int type) {
00122   return _c_check(c,type);
00123 }
00124 
00126 
00127 int Fl_Function_Type::is_public() const {return public_;}
00128 
00129 Fl_Type *Fl_Function_Type::make() {
00130   Fl_Type *p = Fl_Type::current;
00131   while (p && !p->is_decl_block()) p = p->parent;
00132   Fl_Function_Type *o = new Fl_Function_Type();
00133   o->name("make_window()");
00134   o->return_type = 0;
00135   o->add(p);
00136   o->factory = this;
00137   o->public_ = 1;
00138   o->cdecl_ = 0;
00139   return o;
00140 }
00141 
00142 void Fl_Function_Type::write_properties() {
00143   Fl_Type::write_properties();
00144   switch (public_) {
00145     case 0: write_string("private"); break;
00146     case 2: write_string("protected"); break;
00147   }
00148   if (cdecl_) write_string("C");
00149   if (return_type) {
00150     write_string("return_type");
00151     write_word(return_type);
00152   }
00153 }
00154 
00155 void Fl_Function_Type::read_property(const char *c) {
00156   if (!strcmp(c,"private")) {
00157     public_ = 0;
00158   } else if (!strcmp(c,"protected")) {
00159     public_ = 2;
00160   } else if (!strcmp(c,"C")) {
00161     cdecl_ = 1;
00162   } else if (!strcmp(c,"return_type")) {
00163     storestring(read_word(),return_type);
00164   } else {
00165     Fl_Type::read_property(c);
00166   }
00167 }
00168 
00169 #include "function_panel.h"
00170 #include <FL/fl_ask.H>
00171 
00172 void Fl_Function_Type::open() {
00173   if (!function_panel) make_function_panel();
00174   f_return_type_input->static_value(return_type);
00175   f_name_input->static_value(name());
00176   if (is_in_class()) {
00177     f_public_member_choice->value(public_);
00178     f_public_member_choice->show();
00179     f_public_choice->hide();
00180   } else {
00181     f_public_choice->value(public_>0);
00182     f_public_choice->show();
00183     f_public_member_choice->hide();
00184   }
00185   f_c_button->value(cdecl_);
00186   const char *c = comment();
00187   f_comment_input->buffer()->text(c?c:"");
00188   function_panel->show();
00189   const char* message = 0;
00190   for (;;) { // repeat as long as there are errors
00191     if (message) fl_alert("%s", message);
00192     for (;;) {
00193       Fl_Widget* w = Fl::readqueue();
00194       if (w == f_panel_cancel) goto BREAK2;
00195       else if (w == f_panel_ok) break;
00196       else if (!w) Fl::wait();
00197     }
00198     const char*c = f_name_input->value();
00199     while (isspace(*c)) c++;
00200     message = c_check(c); if (message) continue;
00201     const char *d = c;
00202     for (; *d != '('; d++) if (isspace(*d) || !*d) break;
00203     if (*c && *d != '(') {
00204       message = "must be name(arguments), try again:"; continue;
00205     }
00206     int mod = 0;
00207     c = f_return_type_input->value();
00208     message = c_check(c); if (message) continue;
00209     name(f_name_input->value());
00210     storestring(c, return_type);
00211     if (is_in_class()) {
00212       if (public_ != f_public_member_choice->value()) {
00213         mod = 1;
00214         public_ = f_public_member_choice->value();
00215         redraw_browser();
00216       }
00217     } else {
00218       if (public_ != f_public_choice->value()) {
00219         mod = 1;
00220         public_ = f_public_choice->value();
00221         redraw_browser();
00222       }
00223     }
00224     if (cdecl_ != f_c_button->value()) {
00225       mod = 1;
00226       cdecl_ = f_c_button->value();
00227     }
00228     c = f_comment_input->buffer()->text();
00229     if (c && *c) {
00230       if (!comment() || strcmp(c, comment())) redraw_browser();
00231       comment(c);
00232     } else {
00233       if (comment()) redraw_browser();
00234       comment(0);
00235     }
00236     if (c) free((void*)c);
00237     if (mod) set_modflag(1);
00238     break;
00239   }
00240 BREAK2:
00241   function_panel->hide();
00242 }
00243 
00244 Fl_Function_Type Fl_Function_type;
00245 
00246 extern const char* subclassname(Fl_Type*);
00247 
00248 void Fl_Function_Type::write_code1() {
00249   constructor=0;
00250   havewidgets = 0;
00251   Fl_Type *child;
00252   // if the function has no children (hence no body), Fluid will not generate
00253   // the function either. This is great if you decide to implement that function
00254   // inside another module
00255   char havechildren = 0;
00256   for (child = next; child && child->level > level; child = child->next) {
00257     havechildren = 1;
00258     if (child->is_widget()) {
00259       havewidgets = 1;
00260       break;
00261     }
00262   }
00263   if (havechildren)
00264     write_c("\n");
00265   if (ismain()) {
00266     if (havechildren)
00267       write_c("int main(int argc, char **argv) {\n");
00268   } else {
00269     const char* rtype = return_type;
00270     const char* star = "";
00271     // from matt: let the user type "static " at the start of type
00272     // in order to declare a static method;
00273     int is_static = 0;
00274     int is_virtual = 0;
00275     if (rtype) {
00276       if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;}
00277       else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;}
00278       if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;}
00279       else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;}
00280     }
00281     if (!rtype) {
00282       if (havewidgets) {
00283         rtype = subclassname(child);
00284         star = "*";
00285       } else rtype = "void";
00286     }
00287     
00288     const char* k = class_name(0);
00289     if (k) {
00290       if (havechildren)
00291         write_comment_c();
00292       write_public(public_);
00293       if (name()[0] == '~')
00294         constructor = 1;
00295       else {
00296         size_t n = strlen(k);
00297         if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1;
00298       }
00299       write_h("  ");
00300       if (is_static) write_h("static ");
00301       if (is_virtual) write_h("virtual ");
00302       if (!constructor) {
00303         write_h("%s%s ", rtype, star);
00304         if (havechildren)
00305           write_c("%s%s ", rtype, star);
00306       }
00307       
00308       // if this is a subclass, only write_h() the part before the ':'
00309       char s[1024], *sptr = s;
00310       char *nptr = (char *)name();
00311       
00312       while (*nptr) {
00313         if (*nptr == ':') {
00314           if (nptr[1] != ':') break;
00315           // Copy extra ":" for "class::member"...
00316           *sptr++ = *nptr++;
00317         }         
00318         *sptr++ = *nptr++;
00319       }
00320       *sptr = '\0';
00321       
00322       write_h("%s;\n", s);
00323       // skip all function default param. init in body:
00324       int skips=0,skipc=0;
00325       int nc=0,plevel=0;
00326       for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
00327         if (!skips && *nptr=='(') plevel++;
00328         else if (!skips && *nptr==')') plevel--;
00329         if ( *nptr=='"' &&  !(nc &&  *(nptr-1)=='\\') ) 
00330           skips = skips ? 0 : 1;
00331         else if(!skips && *nptr=='\'' &&  !(nc &&  *(nptr-1)=='\\'))
00332           skipc = skipc ? 0 : 1;
00333         if(!skips && !skipc && plevel==1 && *nptr =='=' && 
00334            !(nc && *(nptr-1)=='\'') ) // ignore '=' case 
00335           while(*++nptr  && (skips || skipc || ( (*nptr!=',' && *nptr!=')') || plevel!=1) )) {
00336             if ( *nptr=='"' &&  *(nptr-1)!='\\' ) 
00337               skips = skips ? 0 : 1;
00338             else if(!skips && *nptr=='\'' &&  *(nptr-1)!='\\')
00339               skipc = skipc ? 0 : 1;
00340             if (!skips && !skipc && *nptr=='(') plevel++;
00341             else if (!skips && *nptr==')') plevel--;
00342           }
00343         
00344         if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
00345       }
00346       *sptr = '\0';
00347       
00348       if (havechildren)
00349         write_c("%s::%s {\n", k, s);
00350     } else {
00351       if (havechildren)
00352         write_comment_c();
00353       if (public_) {
00354         if (cdecl_)
00355           write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name());
00356         else
00357           write_h("%s%s %s;\n", rtype, star, name());
00358       } else {
00359         if (havechildren)
00360           write_c("static ");
00361       }
00362       
00363       // write everything but the default parameters (if any)
00364       char s[1024], *sptr;
00365       char *nptr;
00366       int skips=0,skipc=0;
00367       int nc=0,plevel=0;
00368       for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
00369         if (!skips && *nptr=='(') plevel++;
00370         else if (!skips && *nptr==')') plevel--;
00371         if ( *nptr=='"' &&  !(nc &&  *(nptr-1)=='\\') ) 
00372           skips = skips ? 0 : 1;
00373         else if(!skips && *nptr=='\'' &&  !(nc &&  *(nptr-1)=='\\'))
00374           skipc = skipc ? 0 : 1;
00375         if(!skips && !skipc && plevel==1 && *nptr =='=' && 
00376            !(nc && *(nptr-1)=='\'') ) // ignore '=' case 
00377           while(*++nptr  && (skips || skipc || ( (*nptr!=',' && *nptr!=')') || plevel!=1) )) {
00378             if ( *nptr=='"' &&  *(nptr-1)!='\\' ) 
00379               skips = skips ? 0 : 1;
00380             else if(!skips && *nptr=='\'' &&  *(nptr-1)!='\\')
00381               skipc = skipc ? 0 : 1;
00382             if (!skips && !skipc && *nptr=='(') plevel++;
00383             else if (!skips && *nptr==')') plevel--;
00384           }
00385         
00386         if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
00387       }
00388       *sptr = '\0';
00389       
00390       if (havechildren)
00391         write_c("%s%s %s {\n", rtype, star, s);
00392     }
00393   }
00394   
00395   if (havewidgets && !child->name()) write_c("  %s* w;\n", subclassname(child));
00396   indentation += 2;
00397 }
00398 
00399 void Fl_Function_Type::write_code2() {
00400   Fl_Type *child;
00401   const char *var = "w";
00402   char havechildren = 0;
00403   for (child = next; child && child->level > level; child = child->next) {
00404     havechildren = 1;
00405     if (child->is_window() && child->name()) var = child->name();
00406   }
00407   
00408   if (ismain()) {
00409     if (havewidgets) write_c("  %s->show(argc, argv);\n", var);
00410     if (havechildren) write_c("  return Fl::run();\n");
00411   } else if (havewidgets && !constructor && !return_type) {
00412     write_c("  return %s;\n", var);
00413   }
00414   if (havechildren)
00415     write_c("}\n");
00416   indentation = 0;
00417 }
00418 
00419 int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const {
00420   if (rtype && !return_type) return 0;
00421   if (!name()) return 0;
00422   if ( (rtype==0L || strcmp(return_type, rtype)==0) 
00423       && fl_filename_match(name(), sig)) {
00424     return 1;
00425   }
00426   return 0;
00427 }
00428 
00430 
00431 Fl_Type *Fl_Code_Type::make() {
00432   Fl_Type *p = Fl_Type::current;
00433   while (p && !p->is_code_block()) p = p->parent;
00434   if (!p) {
00435     fl_message("Please select a function");
00436     return 0;
00437   }
00438   Fl_Code_Type *o = new Fl_Code_Type();
00439   o->name("printf(\"Hello, World!\\n\");");
00440   o->add(p);
00441   o->factory = this;
00442   return o;
00443 }
00444 
00445 void Fl_Code_Type::open() {
00446   if (!code_panel) make_code_panel();
00447   const char *text = name();
00448   code_input->buffer()->text( text ? text : "" );
00449   code_panel->show();
00450   const char* message = 0;
00451   for (;;) { // repeat as long as there are errors
00452     if (message) fl_alert("%s", message);
00453     for (;;) {
00454       Fl_Widget* w = Fl::readqueue();
00455       if (w == code_panel_cancel) goto BREAK2;
00456       else if (w == code_panel_ok) break;
00457       else if (!w) Fl::wait();
00458     }
00459     char*c = code_input->buffer()->text();
00460     message = c_check(c); if (message) continue;
00461     name(c);
00462     free(c);
00463     break;
00464   }
00465 BREAK2:
00466   code_panel->hide();
00467 }
00468 
00469 Fl_Code_Type Fl_Code_type;
00470 
00471 void Fl_Code_Type::write_code1() {
00472   const char* c = name();
00473   if (!c) return;
00474   const char *pch;
00475   const char *ind = indent();
00476   while( (pch=strchr(c,'\n')) )
00477   {
00478     int line_len = pch - c;
00479     write_c("%s%.*s\n", ind, line_len, c);
00480     c = pch+1;
00481   }
00482   write_c("%s%s\n", ind, c);
00483 }
00484 
00485 void Fl_Code_Type::write_code2() {}
00486 
00488 
00489 Fl_Type *Fl_CodeBlock_Type::make() {
00490   Fl_Type *p = Fl_Type::current;
00491   while (p && !p->is_code_block()) p = p->parent;
00492   if (!p) {
00493     fl_message("Please select a function");
00494     return 0;
00495   }
00496   Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
00497   o->name("if (test())");
00498   o->after = 0;
00499   o->add(p);
00500   o->factory = this;
00501   return o;
00502 }
00503 
00504 void Fl_CodeBlock_Type::write_properties() {
00505   Fl_Type::write_properties();
00506   if (after) {
00507     write_string("after");
00508     write_word(after);
00509   }
00510 }
00511 
00512 void Fl_CodeBlock_Type::read_property(const char *c) {
00513   if (!strcmp(c,"after")) {
00514     storestring(read_word(),after);
00515   } else {
00516     Fl_Type::read_property(c);
00517   }
00518 }
00519 
00520 void Fl_CodeBlock_Type::open() {
00521   if (!codeblock_panel) make_codeblock_panel();
00522   code_before_input->static_value(name());
00523   code_after_input->static_value(after);
00524   codeblock_panel->show();
00525   const char* message = 0;
00526   for (;;) { // repeat as long as there are errors
00527     if (message) fl_alert("%s", message);
00528     for (;;) {
00529       Fl_Widget* w = Fl::readqueue();
00530       if (w == codeblock_panel_cancel) goto BREAK2;
00531       else if (w == codeblock_panel_ok) break;
00532       else if (!w) Fl::wait();
00533     }
00534     const char*c = code_before_input->value();
00535     message = c_check(c); if (message) continue;
00536     name(c);
00537     c = code_after_input->value();
00538     message = c_check(c); if (message) continue;
00539     storestring(c, after);
00540     break;
00541   }
00542 BREAK2:
00543   codeblock_panel->hide();
00544 }
00545 
00546 Fl_CodeBlock_Type Fl_CodeBlock_type;
00547 
00548 void Fl_CodeBlock_Type::write_code1() {
00549   const char* c = name();
00550   write_c("%s%s {\n", indent(), c ? c : "");
00551   indentation += 2;
00552 }
00553 
00554 void Fl_CodeBlock_Type::write_code2() {
00555   indentation += 2;
00556   if (after) write_c("%s} %s\n", indent(), after);
00557   else write_c("%s}\n", indent());
00558 }
00559 
00561 
00562 int Fl_Decl_Type::is_public() const 
00563 {
00564   Fl_Type *p = parent;
00565   while (p && !p->is_decl_block()) p = p->parent;
00566   if(p && p->is_public() && public_)
00567     return public_;
00568   else if(!p)
00569     return public_;
00570   return 0;
00571 }
00572 
00573 Fl_Type *Fl_Decl_Type::make() {
00574   Fl_Type *p = Fl_Type::current;
00575   while (p && !p->is_decl_block()) p = p->parent;
00576   Fl_Decl_Type *o = new Fl_Decl_Type();
00577   o->public_ = 0;
00578   o->static_ = 1;
00579   o->name("int x;");
00580   o->add(p);
00581   o->factory = this;
00582   return o;
00583 }
00584 
00585 void Fl_Decl_Type::write_properties() {
00586   Fl_Type::write_properties();
00587   switch (public_) {
00588     case 0: write_string("private"); break;
00589     case 1: write_string("public"); break;
00590     case 2: write_string("protected"); break;
00591   }
00592   if (static_) 
00593     write_string("local");
00594   else
00595     write_string("global");
00596 }
00597 
00598 void Fl_Decl_Type::read_property(const char *c) {
00599   if (!strcmp(c,"public")) {
00600     public_ = 1;
00601   } else if (!strcmp(c,"private")) {
00602     public_ = 0;
00603   } else if (!strcmp(c,"protected")) {
00604     public_ = 2;
00605   } else if (!strcmp(c,"local")) {
00606     static_ = 1;
00607   } else if (!strcmp(c,"global")) {
00608     static_ = 0;
00609   } else {
00610     Fl_Type::read_property(c);
00611   }
00612 }
00613 
00614 void Fl_Decl_Type::open() {
00615   if (!decl_panel) make_decl_panel();
00616   decl_input->static_value(name());
00617   if (is_in_class()) {
00618     decl_class_choice->value(public_);
00619     decl_class_choice->show();
00620     decl_choice->hide();
00621   } else {
00622     decl_choice->value((public_&1)|((static_&1)<<1));
00623     decl_choice->show();
00624     decl_class_choice->hide();
00625   }
00626   const char *c = comment();
00627   decl_comment_input->buffer()->text(c?c:"");
00628   decl_panel->show();
00629   const char* message = 0;
00630   for (;;) { // repeat as long as there are errors
00631     if (message) fl_alert("%s", message);
00632     for (;;) {
00633       Fl_Widget* w = Fl::readqueue();
00634       if (w == decl_panel_cancel) goto BREAK2;
00635       else if (w == decl_panel_ok) break;
00636       else if (!w) Fl::wait();
00637     }
00638     const char*c = decl_input->value();
00639     while (isspace(*c)) c++;
00640     message = c_check(c&&c[0]=='#' ? c+1 : c);
00641     if (message) continue;
00642     name(c);
00643     if (is_in_class()) {
00644       if (public_!=decl_class_choice->value()) {
00645         set_modflag(1);
00646         public_ = decl_class_choice->value();
00647       }
00648     } else {
00649       if (public_!=(decl_choice->value()&1)) {
00650         set_modflag(1);
00651         public_ = (decl_choice->value()&1);
00652       }
00653       if (static_!=((decl_choice->value()>>1)&1)) {
00654         set_modflag(1);
00655         static_ = ((decl_choice->value()>>1)&1);
00656       }
00657     }
00658     c = decl_comment_input->buffer()->text();
00659     if (c && *c) {
00660       if (!comment() || strcmp(c, comment())) redraw_browser();
00661       comment(c);
00662     } else {
00663       if (comment()) redraw_browser();
00664       comment(0);
00665     }
00666     if (c) free((void*)c);
00667     break;
00668   }
00669 BREAK2:
00670   decl_panel->hide();
00671 }
00672 
00673 Fl_Decl_Type Fl_Decl_type;
00674 
00675 void Fl_Decl_Type::write_code1() {
00676   const char* c = name();
00677   if (!c) return;
00678   // handle a few keywords differently if inside a class
00679   if (is_in_class() && (   (!strncmp(c,"class",5) && isspace(c[5]))
00680                         || (!strncmp(c,"typedef",7) && isspace(c[7]))
00681                         || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9]))
00682                         || (!strncmp(c,"struct",6) && isspace(c[6]))
00683                         ) ) {
00684     write_public(public_);
00685     write_comment_h("  ");
00686     write_h("  %s\n", c);
00687     return;
00688   }
00689   // handle putting #include, extern, using or typedef into decl:
00690   if (   (!isalpha(*c) && *c != '~')
00691       || (!strncmp(c,"extern",6) && isspace(c[6]))
00692       || (!strncmp(c,"class",5) && isspace(c[5]))
00693       || (!strncmp(c,"typedef",7) && isspace(c[7]))
00694       || (!strncmp(c,"using",5) && isspace(c[5]))
00695       || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9]))
00696       //    || !strncmp(c,"struct",6) && isspace(c[6])
00697       ) {
00698     if (public_) {
00699       write_comment_h();
00700       write_h("%s\n", c);
00701     } else {
00702       write_comment_c();
00703       write_c("%s\n", c);
00704     }
00705     return;
00706   }
00707   // find the first C++ style comment
00708   const char* e = c+strlen(c), *csc = c;
00709   while (csc<e && (csc[0]!='/' || csc[1]!='/')) csc++;
00710   if (csc!=e) e = csc; // comment found
00711                        // lose all trailing semicolons so I can add one:
00712   while (e>c && e[-1]==' ') e--;
00713   while (e>c && e[-1]==';') e--;
00714   if (class_name(1)) {
00715     write_public(public_);
00716     write_comment_h("  ");
00717     write_h("  %.*s; %s\n", (int)(e-c), c, csc);
00718   } else {
00719     if (public_) {
00720       if (static_) 
00721         write_h("extern ");
00722       else
00723         write_comment_h();
00724       write_h("%.*s; %s\n", (int)(e-c), c, csc);
00725       if (static_) {
00726         write_comment_c();
00727         write_c("%.*s; %s\n", (int)(e-c), c, csc);
00728       }
00729     } else {
00730       write_comment_c();
00731       if (static_) 
00732         write_c("static ");
00733       write_c("%.*s; %s\n", (int)(e-c), c, csc);
00734     }
00735   }
00736 }
00737 
00738 void Fl_Decl_Type::write_code2() {}
00739 
00741 
00742 Fl_Type *Fl_Data_Type::make() {
00743   Fl_Type *p = Fl_Type::current;
00744   while (p && !p->is_decl_block()) p = p->parent;
00745   Fl_Data_Type *o = new Fl_Data_Type();
00746   o->public_ = 1;
00747   o->static_ = 1;
00748   o->filename_ = 0;
00749   o->name("myBinaryData");
00750   o->add(p);
00751   o->factory = this;
00752   return o;
00753 }
00754 
00755 void Fl_Data_Type::write_properties() {
00756   Fl_Decl_Type::write_properties();
00757   if (filename_) {
00758     write_string("filename");
00759     write_word(filename_);
00760   }
00761 }
00762 
00763 void Fl_Data_Type::read_property(const char *c) {
00764   if (!strcmp(c,"filename")) {
00765     storestring(read_word(), filename_, 1);
00766   } else {
00767     Fl_Decl_Type::read_property(c);
00768   }
00769 }
00770 
00771 void Fl_Data_Type::open() {
00772   if (!data_panel) make_data_panel();
00773   data_input->static_value(name());
00774   if (is_in_class()) {
00775     data_class_choice->value(public_);
00776     data_class_choice->show();
00777     data_choice->hide();
00778   } else {
00779     data_choice->value((public_&1)|((static_&1)<<1));
00780     data_choice->show();
00781     data_class_choice->hide();
00782   }
00783   data_filename->value(filename_?filename_:"");
00784   const char *c = comment();
00785   data_comment_input->buffer()->text(c?c:"");
00786   data_panel->show();
00787   const char* message = 0;
00788   for (;;) { // repeat as long as there are errors
00789     if (message) fl_alert("%s", message);
00790     for (;;) {
00791       Fl_Widget* w = Fl::readqueue();
00792       if (w == data_panel_cancel) goto BREAK2;
00793       else if (w == data_panel_ok) break;
00794       else if (w == data_filebrowser) {
00795         goto_source_dir();
00796         const char *fn = fl_file_chooser("Load Binary Data", 0L, data_filename->value(), 1);
00797         leave_source_dir();
00798         if (fn) {
00799           if (strcmp(fn, data_filename->value()))
00800             set_modflag(1); 
00801           data_filename->value(fn);
00802         }
00803       }
00804       else if (!w) Fl::wait();
00805     }
00806     // store the variable name:
00807     const char*c = data_input->value();
00808     char *s = strdup(c), *p = s, *q, *n;
00809     for (;;++p) {
00810       if (!isspace((unsigned char)(*p))) break;
00811     }
00812     n = p;
00813     if ( (!isalpha((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) goto OOPS;
00814     ++p;
00815     for (;;++p) {
00816       if ( (!isalnum((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) break;
00817     }
00818     q = p;
00819     for (;;++q) {
00820       if (!*q) break;
00821       if (!isspace((unsigned char)(*q))) goto OOPS;
00822     }           
00823     if (n==q) {
00824     OOPS: message = "variable name must be a C identifier";
00825       free((void*)s);
00826       continue;
00827     }
00828     *p = 0;
00829     name(n);
00830     free(s);
00831     // store flags
00832     if (is_in_class()) {
00833       if (public_!=data_class_choice->value()) {
00834         set_modflag(1);
00835         public_ = data_class_choice->value();
00836       }
00837     } else {
00838       if (public_!=(data_choice->value()&1)) {
00839         set_modflag(1);
00840         public_ = (data_choice->value()&1);
00841       }
00842       if (static_!=((data_choice->value()>>1)&1)) {
00843         set_modflag(1);
00844         static_ = ((data_choice->value()>>1)&1);
00845       }
00846     }
00847     // store the filename
00848     c = data_filename->value();
00849     if (filename_ && strcmp(filename_, data_filename->value()))
00850       set_modflag(1); 
00851     else if (!filename_ && *c)
00852       set_modflag(1);
00853     if (filename_) { free((void*)filename_); filename_ = 0L; }
00854     if (c && *c) filename_ = strdup(c);
00855     // store the comment
00856     c = data_comment_input->buffer()->text();
00857     if (c && *c) {
00858       if (!comment() || strcmp(c, comment())) redraw_browser();
00859       comment(c);
00860     } else {
00861       if (comment()) redraw_browser();
00862       comment(0);
00863     }
00864     if (c) free((void*)c);
00865     break;
00866   }
00867 BREAK2:
00868   data_panel->hide();
00869 }
00870 
00871 Fl_Data_Type Fl_Data_type;
00872 
00873 void Fl_Data_Type::write_code1() {
00874   const char *message = 0;
00875   const char *c = name();
00876   if (!c) return;
00877   const char *fn = filename_;
00878   char *data = 0;
00879   int nData = -1;
00880   // path should be set correctly already
00881   if (filename_ && !write_sourceview) {
00882     FILE *f = fl_fopen(filename_, "rb");
00883     if (!f) {
00884       message = "Can't include binary file. Can't open";
00885     } else {
00886       fseek(f, 0, SEEK_END);
00887       nData = ftell(f);
00888       fseek(f, 0, SEEK_SET);
00889       if (nData) {
00890         data = (char*)calloc(nData, 1);
00891         if (fread(data, nData, 1, f)==0) { /* use default */ }
00892       }
00893       fclose(f);
00894     }
00895   } else {
00896     fn = "<no filename>";
00897   }
00898   if (is_in_class()) {
00899     write_public(public_);
00900     write_comment_h("  ");
00901     write_h("  static unsigned char %s[];\n", c);
00902     write_c("unsigned char %s::%s[] = /* binary data included from %s */\n", class_name(1), c, fn);
00903     if (message) write_c("#error %s %s\n", message, fn);
00904     write_cdata(data, nData);
00905     write_c(";\n");
00906   } else {
00907     // the "header only" option does not apply here!
00908     if (public_) {
00909       if (static_) {
00910         write_h("extern unsigned char %s[];\n", c);
00911         write_comment_c();
00912         write_c("unsigned char %s[] = /* binary data included from %s */\n", c, fn);
00913         if (message) write_c("#error %s %s\n", message, fn);
00914         write_cdata(data, nData);
00915         write_c(";\n");
00916       } else {
00917         write_comment_h();
00918         write_h("#error Unsupported declaration loading binary data %s\n", fn);
00919         write_h("unsigned char %s[] = { 1, 2, 3 };\n", c);
00920       }
00921     } else {
00922       write_comment_c();
00923       if (static_) 
00924         write_c("static ");
00925       write_c("unsigned char %s[] = /* binary data included from %s */\n", c, fn);
00926       if (message) write_c("#error %s %s\n", message, fn);
00927       write_cdata(data, nData);
00928       write_c(";\n");
00929     }
00930   }
00931   // if we are in interactive mode, we pop up a warning dialog 
00932   // giving the error: (compile_only && !write_sourceview)
00933   if (message && !write_sourceview) {
00934     if (compile_only)
00935       fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn);
00936     else
00937       fl_alert("%s\n%s\n", message, fn);
00938   }
00939   if (data) free(data);
00940 }
00941 
00942 void Fl_Data_Type::write_code2() {}
00943 
00945 
00946 int Fl_DeclBlock_Type::is_public() const {return public_;}
00947 
00948 Fl_Type *Fl_DeclBlock_Type::make() {
00949   Fl_Type *p = Fl_Type::current;
00950   while (p && !p->is_decl_block()) p = p->parent;
00951   Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
00952   o->name("#if 1");
00953   o->public_ = 0;
00954   o->after = strdup("#endif");
00955   o->add(p);
00956   o->factory = this;
00957   return o;
00958 }
00959 
00960 void Fl_DeclBlock_Type::write_properties() {
00961   Fl_Type::write_properties();
00962   switch (public_) {
00963     case 1: write_string("public"); break;
00964     case 2: write_string("protected"); break;
00965   }
00966   write_string("after");
00967   write_word(after);
00968 }
00969 
00970 void Fl_DeclBlock_Type::read_property(const char *c) {
00971   if(!strcmp(c,"public")) {
00972     public_ = 1;
00973   } else if(!strcmp(c,"protected")) {
00974     public_ = 2;
00975   } else  if (!strcmp(c,"after")) {
00976     storestring(read_word(),after);
00977   } else {
00978     Fl_Type::read_property(c);
00979   }
00980 }
00981 
00982 void Fl_DeclBlock_Type::open() {
00983   if (!declblock_panel) make_declblock_panel();
00984   decl_before_input->static_value(name());
00985   declblock_public_choice->value((public_>0));
00986   decl_after_input->static_value(after);
00987   declblock_panel->show();
00988   const char* message = 0;
00989   for (;;) { // repeat as long as there are errors
00990     if (message) fl_alert("%s", message);
00991     for (;;) {
00992       Fl_Widget* w = Fl::readqueue();
00993       if (w == declblock_panel_cancel) goto BREAK2;
00994       else if (w == declblock_panel_ok) break;
00995       else if (!w) Fl::wait();
00996     }
00997     const char*c = decl_before_input->value();
00998     while (isspace(*c)) c++;
00999     message = c_check(c&&c[0]=='#' ? c+1 : c);
01000     if (message) continue;
01001     name(c);
01002     c = decl_after_input->value();
01003     while (isspace(*c)) c++;
01004     message = c_check(c&&c[0]=='#' ? c+1 : c);
01005     if (message) continue;
01006     storestring(c,after);
01007     if (public_ != declblock_public_choice->value()) {
01008       set_modflag(1);
01009       public_ = declblock_public_choice->value();
01010       redraw_browser();
01011     }
01012     break;
01013   }
01014 BREAK2:
01015   declblock_panel->hide();
01016 }
01017 
01018 Fl_DeclBlock_Type Fl_DeclBlock_type;
01019 
01020 void Fl_DeclBlock_Type::write_code1() {
01021   const char* c = name();
01022   if (public_)
01023     write_h("%s\n", c);
01024   write_c("%s\n", c);
01025 }
01026 
01027 void Fl_DeclBlock_Type::write_code2() {
01028   const char* c = after;
01029   if (public_)
01030     write_h("%s\n", c);
01031   write_c("%s\n", c);
01032 }
01033 
01035 
01036 Fl_Type *Fl_Comment_Type::make() {
01037   Fl_Type *p = Fl_Type::current;
01038   while (p && !p->is_code_block()) p = p->parent;
01039   Fl_Comment_Type *o = new Fl_Comment_Type();
01040   o->in_c_ = 1;
01041   o->in_h_ = 1;
01042   o->style_ = 0;
01043   o->name("my comment");
01044   o->add(p);
01045   o->factory = this;
01046   o->title_buf[0] = 0;
01047   return o;
01048 }
01049 
01050 void Fl_Comment_Type::write_properties() {
01051   Fl_Type::write_properties();
01052   if (in_c_) write_string("in_source"); else write_string("not_in_source"); 
01053   if (in_h_) write_string("in_header"); else write_string("not_in_header");
01054 }
01055 
01056 void Fl_Comment_Type::read_property(const char *c) {
01057   if (!strcmp(c,"in_source")) {
01058     in_c_ = 1;
01059   } else if (!strcmp(c,"not_in_source")) {
01060     in_c_ = 0;
01061   } else if (!strcmp(c,"in_header")) {
01062     in_h_ = 1;
01063   } else if (!strcmp(c,"not_in_header")) {
01064     in_h_ = 0;
01065   } else {
01066     Fl_Type::read_property(c);
01067   }
01068 }
01069 
01070 #include "comments.h"
01071 
01072 static void load_comments_preset(Fl_Preferences &menu) {
01073   static const char * const predefined_comment[] = {
01074     "GNU Public License/GPL Header",  "GNU Public License/GPL Footer",
01075     "GNU Public License/LGPL Header", "GNU Public License/LGPL Footer",
01076     "FLTK/Header", "FLTK/Footer" };
01077   int i;
01078   menu.set("n", 6);
01079   Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
01080   for (i=0; i<6; i++) {
01081     menu.set(Fl_Preferences::Name(i), predefined_comment[i]);
01082     db.set(predefined_comment[i], comment_text[i]);
01083   }
01084 }
01085 
01086 void Fl_Comment_Type::open() {
01087   if (!comment_panel) make_comment_panel();
01088   const char *text = name();
01089   {
01090     int i=0, n=0;
01091     Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
01092     comment_predefined->clear();
01093     comment_predefined->add("_Edit/Add current comment...");
01094     comment_predefined->add("_Edit/Remove last selection...");
01095     menu.get("n", n, -1);
01096     if (n==-1) load_comments_preset(menu);
01097     menu.get("n", n, 0);
01098     for (i=0;i<n;i++) {
01099       char *text;
01100       menu.get(Fl_Preferences::Name(i), text, "");
01101       comment_predefined->add(text);
01102       free(text);
01103     }
01104   }
01105   comment_input->buffer()->text( text ? text : "" );
01106   comment_in_source->value(in_c_);
01107   comment_in_header->value(in_h_);
01108   comment_panel->show();
01109   const char* message = 0;
01110   char itempath[FL_PATH_MAX]; itempath[0] = 0;
01111   int last_selected_item = 0;
01112   for (;;) { // repeat as long as there are errors
01113     if (message) fl_alert("%s", message);
01114     for (;;) {
01115       Fl_Widget* w = Fl::readqueue();
01116       if (w == comment_panel_cancel) goto BREAK2;
01117       else if (w == comment_panel_ok) break;
01118       else if (w == comment_predefined) {
01119         if (comment_predefined->value()==1) {
01120           // add the current comment to the database
01121           const char *xname = fl_input(
01122                                        "Please enter a name to reference the current\ncomment in your database.\n\n"
01123                                        "Use forward slashes '/' to create submenus.", 
01124                                        "My Comment");
01125           if (xname) {
01126             char *name = strdup(xname);
01127             for (char*s=name;*s;s++) if (*s==':') *s = ';';
01128             int n;
01129             Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
01130             db.set(name, comment_input->buffer()->text());
01131             Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
01132             menu.get("n", n, 0);
01133             menu.set(Fl_Preferences::Name(n), name);
01134             menu.set("n", ++n);
01135             comment_predefined->add(name);
01136             free(name);
01137           }
01138         } else if (comment_predefined->value()==2) {
01139           // remove the last selected comment from the database
01140           if (itempath[0]==0 || last_selected_item==0) {
01141             fl_message("Please select an entry form this menu first.");
01142           } else if (fl_choice("Are you sure that you want to delete the entry\n"
01143                                "\"%s\"\nfrom the database?", "Cancel", "Delete",
01144                                NULL, itempath)) {
01145             Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
01146             db.deleteEntry(itempath);
01147             comment_predefined->remove(last_selected_item);
01148             Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
01149             int i, n;
01150             for (i=4, n=0; i<comment_predefined->size(); i++) {
01151               const Fl_Menu_Item *mi = comment_predefined->menu()+i;
01152               if (comment_predefined->item_pathname(itempath, 255, mi)==0) {
01153                 if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
01154                 if (itempath[0]) menu.set(Fl_Preferences::Name(n++), itempath);
01155               }
01156             }
01157             menu.set("n", n);
01158           }
01159         } else {
01160           // load the selected comment from the database
01161           if (comment_predefined->item_pathname(itempath, 255)==0) {
01162             if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
01163             Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
01164             char *text; 
01165             db.get(itempath, text, "(no text found in data base)");
01166             comment_input->buffer()->text(text);
01167             free(text);
01168             last_selected_item = comment_predefined->value();
01169           }
01170         }
01171       }
01172       else if (w == comment_load) {
01173         // load a comment from disk
01174         fl_file_chooser_ok_label("Use File");
01175         const char *fname = fl_file_chooser("Pick a comment", 0L, 0L);
01176         fl_file_chooser_ok_label(NULL);
01177         if (fname) {
01178           if (comment_input->buffer()->loadfile(fname)) {
01179             fl_alert("Error loading file\n%s", fname);
01180           }
01181         }
01182       }
01183       else if (!w) Fl::wait();
01184     }
01185     char*c = comment_input->buffer()->text();
01186     name(c);
01187     free(c);
01188     int mod = 0;
01189     if (in_c_ != comment_in_source->value()) {
01190       in_c_ = comment_in_source->value();
01191       mod = 1;
01192     }
01193     if (in_h_ != comment_in_header->value()) {
01194       in_h_ = comment_in_header->value();
01195       mod = 1;
01196     }
01197     if (mod) set_modflag(1);
01198     break;
01199   }
01200 BREAK2:
01201   title_buf[0] = 0;
01202   comment_panel->hide();
01203 }
01204 
01205 const char *Fl_Comment_Type::title() {
01206   const char* n = name(); 
01207   if (!n || !*n) return type_name();
01208   if (title_buf[0]==0) {
01209     const char *s = n;
01210     char *d = title_buf;
01211     int i = 50;
01212     while (--i > 0) {
01213       char n = *s++;
01214       if (n==0) break;
01215       if (n=='\r') { *d++ = '\\'; *d++ = 'r'; i--; }
01216       else if (n=='\n') { *d++ = '\\'; *d++ = 'n'; i--; }
01217       else if (n<32) { *d++ = '^'; *d++ = 'A'+n; i--; }
01218       else *d++ = n;
01219     }
01220     if (i<=0) { *d++ = '.'; *d++ = '.'; *d++ = '.'; }
01221     *d++ = 0;
01222   }
01223   return title_buf;
01224 }
01225 
01226 Fl_Comment_Type Fl_Comment_type;
01227 
01228 void Fl_Comment_Type::write_code1() {
01229   const char* c = name();
01230   if (!c) return;
01231   if (!in_c_ && !in_h_) return;
01232   // find out if there is already a valid comment:
01233   const char *s = c;
01234   while (isspace(*s)) s++;
01235   // if this seems to be a C style comment, copy the block as is
01236   // (it's up to the user to correctly close the comment)
01237   if (s[0]=='/' && s[1]=='*') {
01238     if (in_h_) write_h("%s\n", c);
01239     if (in_c_) write_c("%s\n", c);
01240     return;
01241   }
01242   // copy the comment line by line, add the double slash if needed
01243   char *txt = strdup(c);
01244   char *b = txt, *e = txt;
01245   for (;;) {
01246     // find the end of the line and set it to NUL
01247     while (*e && *e!='\n') e++;
01248     char eol = *e;
01249     *e = 0;
01250     // check if there is a C++ style comment at the beginning of the line
01251     char *s = b;
01252     while (isspace(*s)) s++;
01253     if (s!=e && ( s[0]!='/' || s[1]!='/') ) {
01254       // if no comment marker was found, we add one ourselves
01255       if (in_h_) write_h("// ");
01256       if (in_c_) write_c("// ");
01257     }
01258     // now copy the rest of the line
01259     if (in_h_) write_h("%s\n", b);
01260     if (in_c_) write_c("%s\n", b);
01261     if (eol==0) break;
01262     *e++ = eol;
01263     b = e;
01264   }
01265 }
01266 
01267 void Fl_Comment_Type::write_code2() {}
01268 
01270 
01271 const char* Fl_Type::class_name(const int need_nest) const {
01272   Fl_Type* p = parent;
01273   while (p) {
01274     if (p->is_class()) {
01275       // see if we are nested in another class, we must fully-qualify name:
01276       // this is lame but works...
01277       const char* q = 0;
01278       if(need_nest) q=p->class_name(need_nest);
01279       if (q) {
01280         static char s[256];
01281         if (q != s) strlcpy(s, q, sizeof(s));
01282         strlcat(s, "::", sizeof(s));
01283         strlcat(s, p->name(), sizeof(s));
01284         return s;
01285       }
01286       return p->name();
01287     }
01288     p = p->parent;
01289   }
01290   return 0;
01291 }
01292 
01296 const Fl_Class_Type *Fl_Type::is_in_class() const {
01297   Fl_Type* p = parent;
01298   while (p) {
01299     if (p->is_class()) {
01300       return (Fl_Class_Type*)p;
01301     }
01302     p = p->parent;
01303   }
01304   return 0;
01305 }
01306 
01307 int Fl_Class_Type::is_public() const {return public_;}
01308 
01309 void Fl_Class_Type::prefix(const char*p) {
01310   free((void*) class_prefix);
01311   class_prefix=strdup(p ? p : "" );
01312 }
01313 
01314 Fl_Type *Fl_Class_Type::make() {
01315   Fl_Type *p = Fl_Type::current;
01316   while (p && !p->is_decl_block()) p = p->parent;
01317   Fl_Class_Type *o = new Fl_Class_Type();
01318   o->name("UserInterface");
01319   o->class_prefix=0;
01320   o->subclass_of = 0;
01321   o->public_ = 1;
01322   o->add(p);
01323   o->factory = this;
01324   return o;
01325 }
01326 
01327 void Fl_Class_Type::write_properties() {
01328   Fl_Type::write_properties();
01329   if (subclass_of) {
01330     write_string(":");
01331     write_word(subclass_of);
01332   }
01333   switch (public_) {
01334     case 0: write_string("private"); break;
01335     case 2: write_string("protected"); break;
01336   }
01337 }
01338 
01339 void Fl_Class_Type::read_property(const char *c) {
01340   if (!strcmp(c,"private")) {
01341     public_ = 0;
01342   } else if (!strcmp(c,"protected")) {
01343     public_ = 2;
01344   } else if (!strcmp(c,":")) {
01345     storestring(read_word(), subclass_of);
01346   } else {
01347     Fl_Type::read_property(c);
01348   }
01349 }
01350 
01351 void Fl_Class_Type::open() {
01352   if (!class_panel) make_class_panel();
01353   char fullname[FL_PATH_MAX]="";
01354   if (prefix() && strlen(prefix())) 
01355     sprintf(fullname,"%s %s",prefix(),name());
01356   else 
01357     strcpy(fullname, name());
01358   c_name_input->static_value(fullname);
01359   c_subclass_input->static_value(subclass_of);
01360   c_public_button->value(public_);
01361   const char *c = comment();
01362   c_comment_input->buffer()->text(c?c:"");
01363   class_panel->show();
01364   const char* message = 0;
01365   
01366   char *na=0,*pr=0,*p=0; // name and prefix substrings
01367   
01368   for (;;) { // repeat as long as there are errors
01369     if (message) fl_alert("%s", message);
01370     for (;;) {
01371       Fl_Widget* w = Fl::readqueue();
01372       if (w == c_panel_cancel) goto BREAK2;
01373       else if (w == c_panel_ok) break;
01374       else if (!w) Fl::wait();
01375     }
01376     const char*c = c_name_input->value();
01377     char *s = strdup(c);
01378     size_t len = strlen(s);
01379     if (!*s) goto OOPS;
01380     p = (char*) (s+len-1);
01381     while (p>=s && isspace(*p)) *(p--)='\0';
01382     if (p<s) goto OOPS;
01383     while (p>=s && is_id(*p)) p--;
01384     if ( (p<s && !is_id(*(p+1))) || !*(p+1) ) {
01385     OOPS: message = "class name must be C++ identifier";
01386       free((void*)s);
01387       continue;
01388     }
01389     na=p+1; // now we have the name
01390     if(p>s) *p--='\0';
01391     while (p>=s && isspace(*p)) *(p--)='\0';
01392     while (p>=s && is_id(*p))   p--;
01393     if (p<s)                    p++;
01394     if (is_id(*p) && p<na)      pr=p; // prefix detected
01395     c = c_subclass_input->value();
01396     message = c_check(c); 
01397     if (message) { free((void*)s);continue;}
01398     name(na);
01399     prefix(pr);
01400     free((void*)s);
01401     storestring(c, subclass_of);
01402     if (public_ != c_public_button->value()) {
01403       public_ = c_public_button->value();
01404       set_modflag(1);
01405     }
01406     c = c_comment_input->buffer()->text();
01407     if (c && *c) {
01408       if (!comment() || strcmp(c, comment())) redraw_browser();
01409       comment(c);
01410     } else {
01411       if (comment()) redraw_browser();
01412       comment(0);
01413     }
01414     if (c) free((void*)c);
01415     break;
01416   }
01417 BREAK2:
01418   class_panel->hide();
01419 }
01420 
01421 Fl_Class_Type Fl_Class_type;
01422 
01423 Fl_Class_Type *current_class;
01424 extern Fl_Widget_Class_Type *current_widget_class;
01425 void write_public(int state) {
01426   if (!current_class && !current_widget_class) return;
01427   if (current_class && current_class->write_public_state == state) return;
01428   if (current_widget_class && current_widget_class->write_public_state == state) return;
01429   if (current_class) current_class->write_public_state = state;
01430   if (current_widget_class) current_widget_class->write_public_state = state;
01431   switch (state) {
01432     case 0: write_h("private:\n"); break;
01433     case 1: write_h("public:\n"); break;
01434     case 2: write_h("protected:\n"); break;
01435   }
01436 }
01437 
01438 void Fl_Class_Type::write_code1() {
01439   parent_class = current_class;
01440   current_class = this;
01441   write_public_state = 0;
01442   write_h("\n");
01443   write_comment_h();
01444   if (prefix() && strlen(prefix()))
01445     write_h("class %s %s ", prefix(), name());
01446   else
01447     write_h("class %s ", name());
01448   if (subclass_of) write_h(": %s ", subclass_of);
01449   write_h("{\n");
01450 }
01451 
01452 void Fl_Class_Type::write_code2() {
01453   write_h("};\n");
01454   current_class = parent_class;
01455 }
01456 
01460 int Fl_Class_Type::has_function(const char *rtype, const char *sig) const {
01461   Fl_Type *child;
01462   for (child = next; child && child->level > level; child = child->next) {
01463     if (child->level == level+1 && strcmp(child->type_name(), "Function")==0) {
01464       const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
01465       if (fn->has_signature(rtype, sig))
01466         return 1;
01467     }
01468   }
01469   return 0;
01470 }
01471 
01472 //
01473 // End of "$Id: Fl_Function_Type.cxx 8063 2010-12-19 21:20:10Z matt $".
01474 //