|
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) ![]() |
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 //