PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/fltk/fluid/Fl_Function_Type.cxx

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