PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/Utilities/FLTK/fluid/Fl_Function_Type.cxx

https://bitbucket.org/olahlou/otb
C++ | 1184 lines | 1020 code | 91 blank | 73 comment | 472 complexity | c91fc914622d62540b24223be56093ac MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, LGPL-2.0, CC-BY-SA-3.0, BSD-3-Clause, LGPL-2.1
  1. //
  2. // "$Id$"
  3. //
  4. // C function type code for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2006 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 "../src/flstring.h"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. extern int i18n_type;
  36. extern const char* i18n_include;
  37. extern const char* i18n_function;
  38. extern const char* i18n_file;
  39. extern const char* i18n_set;
  40. extern char i18n_program[];
  41. extern void redraw_browser();
  42. ////////////////////////////////////////////////////////////////
  43. // quick check of any C code for legality, returns an error message
  44. static char buffer[128]; // for error messages
  45. // check a quoted string ending in either " or ' or >:
  46. const char *_q_check(const char * & c, int type) {
  47. for (;;) switch (*c++) {
  48. case '\0':
  49. sprintf(buffer,"missing %c",type);
  50. return buffer;
  51. case '\\':
  52. if (*c) c++;
  53. break;
  54. default:
  55. if (*(c-1) == type) return 0;
  56. }
  57. }
  58. // check normal code, match braces and parenthesis:
  59. const char *_c_check(const char * & c, int type) {
  60. const char *d;
  61. for (;;) switch (*c++) {
  62. case 0:
  63. if (!type) return 0;
  64. sprintf(buffer, "missing %c", type);
  65. return buffer;
  66. case '/':
  67. // Skip comments as needed...
  68. if (*c == '/') {
  69. while (*c != '\n' && *c) c++;
  70. } else if (*c == '*') {
  71. c++;
  72. while ((*c != '*' || c[1] != '/') && *c) c++;
  73. if (*c == '*') c+=2;
  74. else {
  75. return "missing '*/'";
  76. }
  77. }
  78. break;
  79. case '#':
  80. // treat cpp directives as a comment:
  81. while (*c != '\n' && *c) c++;
  82. break;
  83. case '{':
  84. if (type==')') goto UNEXPECTED;
  85. d = _c_check(c,'}');
  86. if (d) return d;
  87. break;
  88. case '(':
  89. d = _c_check(c,')');
  90. if (d) return d;
  91. break;
  92. case '\"':
  93. d = _q_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. case ')':
  102. UNEXPECTED:
  103. if (type == *(c-1)) return 0;
  104. sprintf(buffer, "unexpected %c", *(c-1));
  105. return buffer;
  106. }
  107. }
  108. const char *c_check(const char *c, int type) {
  109. return _c_check(c,type);
  110. }
  111. ////////////////////////////////////////////////////////////////
  112. int Fl_Function_Type::is_public() const {return public_;}
  113. Fl_Type *Fl_Function_Type::make() {
  114. Fl_Type *p = Fl_Type::current;
  115. while (p && !p->is_decl_block()) p = p->parent;
  116. Fl_Function_Type *o = new Fl_Function_Type();
  117. o->name("make_window()");
  118. o->return_type = 0;
  119. o->add(p);
  120. o->factory = this;
  121. o->public_ = 1;
  122. o->cdecl_ = 0;
  123. return o;
  124. }
  125. void Fl_Function_Type::write_properties() {
  126. Fl_Type::write_properties();
  127. switch (public_) {
  128. case 0: write_string("private"); break;
  129. case 2: write_string("protected"); break;
  130. }
  131. if (cdecl_) write_string("C");
  132. if (return_type) {
  133. write_string("return_type");
  134. write_word(return_type);
  135. }
  136. }
  137. void Fl_Function_Type::read_property(const char *c) {
  138. if (!strcmp(c,"private")) {
  139. public_ = 0;
  140. } else if (!strcmp(c,"protected")) {
  141. public_ = 2;
  142. } else if (!strcmp(c,"C")) {
  143. cdecl_ = 1;
  144. } else if (!strcmp(c,"return_type")) {
  145. storestring(read_word(),return_type);
  146. } else {
  147. Fl_Type::read_property(c);
  148. }
  149. }
  150. #include "function_panel.h"
  151. #include <FL/fl_ask.H>
  152. void Fl_Function_Type::open() {
  153. if (!function_panel) make_function_panel();
  154. f_return_type_input->static_value(return_type);
  155. f_name_input->static_value(name());
  156. if (is_in_class()) {
  157. f_public_member_choice->value(public_);
  158. f_public_member_choice->show();
  159. f_public_choice->hide();
  160. } else {
  161. f_public_choice->value(public_>0);
  162. f_public_choice->show();
  163. f_public_member_choice->hide();
  164. }
  165. f_c_button->value(cdecl_);
  166. function_panel->show();
  167. const char* message = 0;
  168. for (;;) { // repeat as long as there are errors
  169. if (message) fl_alert(message);
  170. for (;;) {
  171. Fl_Widget* w = Fl::readqueue();
  172. if (w == f_panel_cancel) goto BREAK2;
  173. else if (w == f_panel_ok) break;
  174. else if (!w) Fl::wait();
  175. }
  176. const char*c = f_name_input->value();
  177. while (isspace(*c)) c++;
  178. message = c_check(c); if (message) continue;
  179. const char *d = c;
  180. for (; *d != '('; d++) if (isspace(*d) || !*d) break;
  181. if (*c && *d != '(') {
  182. message = "must be name(arguments), try again:"; continue;
  183. }
  184. int mod = 0;
  185. c = f_return_type_input->value();
  186. message = c_check(c); if (message) continue;
  187. name(f_name_input->value());
  188. storestring(c, return_type);
  189. if (is_in_class()) {
  190. if (public_ != f_public_member_choice->value()) {
  191. mod = 1;
  192. public_ = f_public_member_choice->value();
  193. redraw_browser();
  194. }
  195. } else {
  196. if (public_ != f_public_choice->value()) {
  197. mod = 1;
  198. public_ = f_public_choice->value();
  199. redraw_browser();
  200. }
  201. }
  202. if (cdecl_ != f_c_button->value()) {
  203. mod = 1;
  204. cdecl_ = f_c_button->value();
  205. }
  206. if (mod) set_modflag(1);
  207. break;
  208. }
  209. BREAK2:
  210. function_panel->hide();
  211. }
  212. Fl_Function_Type Fl_Function_type;
  213. extern const char* subclassname(Fl_Type*);
  214. void Fl_Function_Type::write_code1() {
  215. constructor=0;
  216. havewidgets = 0;
  217. Fl_Type *child;
  218. for (child = next; child && child->level > level; child = child->next)
  219. if (child->is_widget()) {
  220. havewidgets = 1;
  221. break;
  222. }
  223. write_c("\n");
  224. if (ismain())
  225. write_c("int main(int argc, char **argv) {\n");
  226. else {
  227. const char* rtype = return_type;
  228. const char* star = "";
  229. // from matt: let the user type "static " at the start of type
  230. // in order to declare a static method;
  231. int is_static = 0;
  232. int is_virtual = 0;
  233. if (rtype) {
  234. if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;}
  235. else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;}
  236. if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;}
  237. else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;}
  238. }
  239. if (!rtype) {
  240. if (havewidgets) {
  241. rtype = subclassname(child);
  242. star = "*";
  243. } else rtype = "void";
  244. }
  245. const char* k = class_name(0);
  246. if (k) {
  247. write_public(public_);
  248. if (name()[0] == '~')
  249. constructor = 1;
  250. else {
  251. size_t n = strlen(k);
  252. if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1;
  253. }
  254. write_h(" ");
  255. if (is_static) write_h("static ");
  256. if (is_virtual) write_h("virtual ");
  257. if (!constructor) {
  258. write_h("%s%s ", rtype, star);
  259. write_c("%s%s ", rtype, star);
  260. }
  261. // if this is a subclass, only write_h() the part before the ':'
  262. char s[1024], *sptr = s;
  263. char *nptr = (char *)name();
  264. while (*nptr) {
  265. if (*nptr == ':') {
  266. if (nptr[1] != ':') break;
  267. // Copy extra ":" for "class::member"...
  268. *sptr++ = *nptr++;
  269. }
  270. *sptr++ = *nptr++;
  271. }
  272. *sptr = '\0';
  273. write_h("%s;\n", s);
  274. // skip all function default param. init in body:
  275. int skips=0,skipc=0;
  276. int nc=0,plevel=0;
  277. for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
  278. if (!skips && *nptr=='(') plevel++;
  279. else if (!skips && *nptr==')') plevel--;
  280. if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') )
  281. skips = skips ? 0 : 1;
  282. else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\'))
  283. skipc = skipc ? 0 : 1;
  284. if(!skips && !skipc && plevel==1 && *nptr =='=' &&
  285. !(nc && *(nptr-1)=='\'') ) // ignore '=' case
  286. while(*++nptr && (skips || skipc || (*nptr!=',' && *nptr!=')' || plevel!=1) )) {
  287. if ( *nptr=='"' && *(nptr-1)!='\\' )
  288. skips = skips ? 0 : 1;
  289. else if(!skips && *nptr=='\'' && *(nptr-1)!='\\')
  290. skipc = skipc ? 0 : 1;
  291. if (!skips && !skipc && *nptr=='(') plevel++;
  292. else if (!skips && *nptr==')') plevel--;
  293. }
  294. if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
  295. }
  296. *sptr = '\0';
  297. write_c("%s::%s {\n", k, s);
  298. } else {
  299. if (public_) {
  300. if (cdecl_)
  301. write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name());
  302. else
  303. write_h("%s%s %s;\n", rtype, star, name());
  304. }
  305. else write_c("static ");
  306. // write everything but the default parameters (if any)
  307. char s[1024], *sptr;
  308. char *nptr;
  309. int skips=0,skipc=0;
  310. int nc=0,plevel=0;
  311. for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) {
  312. if (!skips && *nptr=='(') plevel++;
  313. else if (!skips && *nptr==')') plevel--;
  314. if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') )
  315. skips = skips ? 0 : 1;
  316. else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\'))
  317. skipc = skipc ? 0 : 1;
  318. if(!skips && !skipc && plevel==1 && *nptr =='=' &&
  319. !(nc && *(nptr-1)=='\'') ) // ignore '=' case
  320. while(*++nptr && (skips || skipc || (*nptr!=',' && *nptr!=')' || plevel!=1) )) {
  321. if ( *nptr=='"' && *(nptr-1)!='\\' )
  322. skips = skips ? 0 : 1;
  323. else if(!skips && *nptr=='\'' && *(nptr-1)!='\\')
  324. skipc = skipc ? 0 : 1;
  325. if (!skips && !skipc && *nptr=='(') plevel++;
  326. else if (!skips && *nptr==')') plevel--;
  327. }
  328. if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr;
  329. }
  330. *sptr = '\0';
  331. write_c("%s%s %s {\n", rtype, star, s);
  332. }
  333. }
  334. if (havewidgets && !child->name()) write_c(" %s* w;\n", subclassname(child));
  335. indentation += 2;
  336. }
  337. void Fl_Function_Type::write_code2() {
  338. Fl_Type *child;
  339. const char *var = "w";
  340. for (child = next; child && child->level > level; child = child->next)
  341. if (child->is_window() && child->name()) var = child->name();
  342. if (ismain()) {
  343. if (havewidgets) write_c(" %s->show(argc, argv);\n", var);
  344. write_c(" return Fl::run();\n");
  345. } else if (havewidgets && !constructor && !return_type) {
  346. write_c(" return %s;\n", var);
  347. }
  348. write_c("}\n");
  349. indentation = 0;
  350. }
  351. int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const {
  352. if (rtype && !return_type) return 0;
  353. if (!name()) return 0;
  354. if ( (rtype==0L || strcmp(return_type, rtype)==0)
  355. && fl_filename_match(name(), sig)) {
  356. return 1;
  357. }
  358. return 0;
  359. }
  360. ////////////////////////////////////////////////////////////////
  361. Fl_Type *Fl_Code_Type::make() {
  362. Fl_Type *p = Fl_Type::current;
  363. while (p && !p->is_code_block()) p = p->parent;
  364. if (!p) {
  365. fl_message("Please select a function");
  366. return 0;
  367. }
  368. Fl_Code_Type *o = new Fl_Code_Type();
  369. o->name("printf(\"Hello, World!\\n\");");
  370. o->add(p);
  371. o->factory = this;
  372. return o;
  373. }
  374. void Fl_Code_Type::open() {
  375. if (!code_panel) make_code_panel();
  376. const char *text = name();
  377. code_input->buffer()->text( text ? text : "" );
  378. code_panel->show();
  379. const char* message = 0;
  380. for (;;) { // repeat as long as there are errors
  381. if (message) fl_alert(message);
  382. for (;;) {
  383. Fl_Widget* w = Fl::readqueue();
  384. if (w == code_panel_cancel) goto BREAK2;
  385. else if (w == code_panel_ok) break;
  386. else if (!w) Fl::wait();
  387. }
  388. char*c = code_input->buffer()->text();
  389. message = c_check(c); if (message) continue;
  390. name(c);
  391. free(c);
  392. break;
  393. }
  394. BREAK2:
  395. code_panel->hide();
  396. }
  397. Fl_Code_Type Fl_Code_type;
  398. void Fl_Code_Type::write_code1() {
  399. const char* c = name();
  400. if (!c) return;
  401. write_c("%s%s\n", indent(), c);
  402. }
  403. void Fl_Code_Type::write_code2() {}
  404. ////////////////////////////////////////////////////////////////
  405. Fl_Type *Fl_CodeBlock_Type::make() {
  406. Fl_Type *p = Fl_Type::current;
  407. while (p && !p->is_code_block()) p = p->parent;
  408. if (!p) {
  409. fl_message("Please select a function");
  410. return 0;
  411. }
  412. Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
  413. o->name("if (test())");
  414. o->after = 0;
  415. o->add(p);
  416. o->factory = this;
  417. return o;
  418. }
  419. void Fl_CodeBlock_Type::write_properties() {
  420. Fl_Type::write_properties();
  421. if (after) {
  422. write_string("after");
  423. write_word(after);
  424. }
  425. }
  426. void Fl_CodeBlock_Type::read_property(const char *c) {
  427. if (!strcmp(c,"after")) {
  428. storestring(read_word(),after);
  429. } else {
  430. Fl_Type::read_property(c);
  431. }
  432. }
  433. void Fl_CodeBlock_Type::open() {
  434. if (!codeblock_panel) make_codeblock_panel();
  435. code_before_input->static_value(name());
  436. code_after_input->static_value(after);
  437. codeblock_panel->show();
  438. const char* message = 0;
  439. for (;;) { // repeat as long as there are errors
  440. if (message) fl_alert(message);
  441. for (;;) {
  442. Fl_Widget* w = Fl::readqueue();
  443. if (w == codeblock_panel_cancel) goto BREAK2;
  444. else if (w == codeblock_panel_ok) break;
  445. else if (!w) Fl::wait();
  446. }
  447. const char*c = code_before_input->value();
  448. message = c_check(c); if (message) continue;
  449. name(c);
  450. c = code_after_input->value();
  451. message = c_check(c); if (message) continue;
  452. storestring(c, after);
  453. break;
  454. }
  455. BREAK2:
  456. codeblock_panel->hide();
  457. }
  458. Fl_CodeBlock_Type Fl_CodeBlock_type;
  459. void Fl_CodeBlock_Type::write_code1() {
  460. const char* c = name();
  461. write_c("%s%s {\n", indent(), c ? c : "");
  462. indentation += 2;
  463. }
  464. void Fl_CodeBlock_Type::write_code2() {
  465. indentation += 2;
  466. if (after) write_c("%s} %s\n", indent(), after);
  467. else write_c("%s}\n", indent());
  468. }
  469. ////////////////////////////////////////////////////////////////
  470. int Fl_Decl_Type::is_public() const
  471. {
  472. Fl_Type *p = parent;
  473. while (p && !p->is_decl_block()) p = p->parent;
  474. if(p && p->is_public() && public_)
  475. return public_;
  476. else if(!p)
  477. return public_;
  478. return 0;
  479. }
  480. Fl_Type *Fl_Decl_Type::make() {
  481. Fl_Type *p = Fl_Type::current;
  482. while (p && !p->is_decl_block()) p = p->parent;
  483. Fl_Decl_Type *o = new Fl_Decl_Type();
  484. o->public_ = 0;
  485. o->static_ = 1;
  486. o->name("int x;");
  487. o->add(p);
  488. o->factory = this;
  489. return o;
  490. }
  491. void Fl_Decl_Type::write_properties() {
  492. Fl_Type::write_properties();
  493. switch (public_) {
  494. case 1: write_string("public"); break;
  495. case 2: write_string("protected"); break;
  496. }
  497. if (!static_) write_string("global");
  498. }
  499. void Fl_Decl_Type::read_property(const char *c) {
  500. if (!strcmp(c,"public")) {
  501. public_ = 1;
  502. } else if (!strcmp(c,"protected")) {
  503. public_ = 2;
  504. } else if (!strcmp(c,"global")) {
  505. static_ = 0;
  506. } else {
  507. Fl_Type::read_property(c);
  508. }
  509. }
  510. void Fl_Decl_Type::open() {
  511. if (!decl_panel) make_decl_panel();
  512. decl_input->static_value(name());
  513. if (is_in_class()) {
  514. decl_class_choice->value(public_);
  515. decl_class_choice->show();
  516. decl_choice->hide();
  517. } else {
  518. decl_choice->value((public_&1)|((static_&1)<<1));
  519. decl_choice->show();
  520. decl_class_choice->hide();
  521. }
  522. decl_panel->show();
  523. const char* message = 0;
  524. for (;;) { // repeat as long as there are errors
  525. if (message) fl_alert(message);
  526. for (;;) {
  527. Fl_Widget* w = Fl::readqueue();
  528. if (w == decl_panel_cancel) goto BREAK2;
  529. else if (w == decl_panel_ok) break;
  530. else if (!w) Fl::wait();
  531. }
  532. const char*c = decl_input->value();
  533. while (isspace(*c)) c++;
  534. message = c_check(c&&c[0]=='#' ? c+1 : c);
  535. if (message) continue;
  536. name(c);
  537. if (is_in_class()) {
  538. if (public_!=decl_class_choice->value()) {
  539. set_modflag(1);
  540. public_ = decl_class_choice->value();
  541. }
  542. } else {
  543. if (public_!=(decl_choice->value()&1)) {
  544. set_modflag(1);
  545. public_ = (decl_choice->value()&1);
  546. }
  547. if (static_!=((decl_choice->value()>>1)&1)) {
  548. set_modflag(1);
  549. static_ = ((decl_choice->value()>>1)&1);
  550. }
  551. }
  552. break;
  553. }
  554. BREAK2:
  555. decl_panel->hide();
  556. }
  557. Fl_Decl_Type Fl_Decl_type;
  558. void Fl_Decl_Type::write_code1() {
  559. const char* c = name();
  560. if (!c) return;
  561. // handle a few keywords differently if inside a class
  562. if (is_in_class() && (
  563. !strncmp(c,"class",5) && isspace(c[5])
  564. || !strncmp(c,"typedef",7) && isspace(c[7])
  565. || !strncmp(c,"FL_EXPORT",9) && isspace(c[9])
  566. || !strncmp(c,"struct",6) && isspace(c[6])
  567. ) ) {
  568. write_public(public_);
  569. write_h(" %s\n", c);
  570. return;
  571. }
  572. // handle putting #include, extern, using or typedef into decl:
  573. if (!isalpha(*c) && *c != '~'
  574. || !strncmp(c,"extern",6) && isspace(c[6])
  575. || !strncmp(c,"class",5) && isspace(c[5])
  576. || !strncmp(c,"typedef",7) && isspace(c[7])
  577. || !strncmp(c,"using",5) && isspace(c[5])
  578. || !strncmp(c,"FL_EXPORT",9) && isspace(c[9])
  579. // || !strncmp(c,"struct",6) && isspace(c[6])
  580. ) {
  581. if (public_)
  582. write_h("%s\n", c);
  583. else
  584. write_c("%s\n", c);
  585. return;
  586. }
  587. // find the first C++ style comment
  588. const char* e = c+strlen(c), *csc = c;
  589. while (csc<e && (csc[0]!='/' || csc[1]!='/')) csc++;
  590. if (csc!=e) e = csc; // comment found
  591. // lose all trailing semicolons so I can add one:
  592. while (e>c && e[-1]==' ') e--;
  593. while (e>c && e[-1]==';') e--;
  594. if (class_name(1)) {
  595. write_public(public_);
  596. write_h(" %.*s; %s\n", (int)(e-c), c, csc);
  597. } else {
  598. if (public_) {
  599. if (static_)
  600. write_h("extern ");
  601. write_h("%.*s; %s\n", (int)(e-c), c, csc);
  602. if (static_)
  603. write_c("%.*s; %s\n", (int)(e-c), c, csc);
  604. } else {
  605. if (static_)
  606. write_c("static ");
  607. write_c("%.*s; %s\n", (int)(e-c), c, csc);
  608. }
  609. }
  610. }
  611. void Fl_Decl_Type::write_code2() {}
  612. ////////////////////////////////////////////////////////////////
  613. int Fl_DeclBlock_Type::is_public() const {return public_;}
  614. Fl_Type *Fl_DeclBlock_Type::make() {
  615. Fl_Type *p = Fl_Type::current;
  616. while (p && !p->is_decl_block()) p = p->parent;
  617. Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
  618. o->name("#if 1");
  619. o->public_ = 0;
  620. o->after = strdup("#endif");
  621. o->add(p);
  622. o->factory = this;
  623. return o;
  624. }
  625. void Fl_DeclBlock_Type::write_properties() {
  626. Fl_Type::write_properties();
  627. switch (public_) {
  628. case 1: write_string("public"); break;
  629. case 2: write_string("protected"); break;
  630. }
  631. write_string("after");
  632. write_word(after);
  633. }
  634. void Fl_DeclBlock_Type::read_property(const char *c) {
  635. if(!strcmp(c,"public")) {
  636. public_ = 1;
  637. } else if(!strcmp(c,"protected")) {
  638. public_ = 2;
  639. } else if (!strcmp(c,"after")) {
  640. storestring(read_word(),after);
  641. } else {
  642. Fl_Type::read_property(c);
  643. }
  644. }
  645. void Fl_DeclBlock_Type::open() {
  646. if (!declblock_panel) make_declblock_panel();
  647. decl_before_input->static_value(name());
  648. declblock_public_choice->value((public_>0));
  649. decl_after_input->static_value(after);
  650. declblock_panel->show();
  651. const char* message = 0;
  652. for (;;) { // repeat as long as there are errors
  653. if (message) fl_alert(message);
  654. for (;;) {
  655. Fl_Widget* w = Fl::readqueue();
  656. if (w == declblock_panel_cancel) goto BREAK2;
  657. else if (w == declblock_panel_ok) break;
  658. else if (!w) Fl::wait();
  659. }
  660. const char*c = decl_before_input->value();
  661. while (isspace(*c)) c++;
  662. message = c_check(c&&c[0]=='#' ? c+1 : c);
  663. if (message) continue;
  664. name(c);
  665. c = decl_after_input->value();
  666. while (isspace(*c)) c++;
  667. message = c_check(c&&c[0]=='#' ? c+1 : c);
  668. if (message) continue;
  669. storestring(c,after);
  670. if (public_ != declblock_public_choice->value()) {
  671. set_modflag(1);
  672. public_ = declblock_public_choice->value();
  673. redraw_browser();
  674. }
  675. break;
  676. }
  677. BREAK2:
  678. declblock_panel->hide();
  679. }
  680. Fl_DeclBlock_Type Fl_DeclBlock_type;
  681. void Fl_DeclBlock_Type::write_code1() {
  682. const char* c = name();
  683. if (public_)
  684. write_h("%s\n", c);
  685. write_c("%s\n", c);
  686. }
  687. void Fl_DeclBlock_Type::write_code2() {
  688. const char* c = after;
  689. if (public_)
  690. write_h("%s\n", c);
  691. write_c("%s\n", c);
  692. }
  693. ////////////////////////////////////////////////////////////////
  694. Fl_Type *Fl_Comment_Type::make() {
  695. Fl_Type *p = Fl_Type::current;
  696. while (p && !p->is_code_block()) p = p->parent;
  697. Fl_Comment_Type *o = new Fl_Comment_Type();
  698. o->in_c_ = 1;
  699. o->in_h_ = 1;
  700. o->style_ = 0;
  701. o->name("my comment");
  702. o->add(p);
  703. o->factory = this;
  704. o->title_buf[0] = 0;
  705. return o;
  706. }
  707. void Fl_Comment_Type::write_properties() {
  708. Fl_Type::write_properties();
  709. if (in_c_) write_string("in_source"); else write_string("not_in_source");
  710. if (in_h_) write_string("in_header"); else write_string("not_in_header");
  711. }
  712. void Fl_Comment_Type::read_property(const char *c) {
  713. if (!strcmp(c,"in_source")) {
  714. in_c_ = 1;
  715. } else if (!strcmp(c,"not_in_source")) {
  716. in_c_ = 0;
  717. } else if (!strcmp(c,"in_header")) {
  718. in_h_ = 1;
  719. } else if (!strcmp(c,"not_in_header")) {
  720. in_h_ = 0;
  721. } else {
  722. Fl_Type::read_property(c);
  723. }
  724. }
  725. #include "comments.h"
  726. static void load_comments_preset(Fl_Preferences &menu) {
  727. static const char * const predefined_comment[] = {
  728. "GNU Public License/GPL Header", "GNU Public License/GPL Footer",
  729. "GNU Public License/LGPL Header", "GNU Public License/LGPL Footer",
  730. "FLTK/Header", "FLTK/Footer" };
  731. int i;
  732. menu.set("n", 6);
  733. Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
  734. for (i=0; i<6; i++) {
  735. menu.set(Fl_Preferences::Name(i), predefined_comment[i]);
  736. db.set(predefined_comment[i], comment_text[i]);
  737. }
  738. }
  739. void Fl_Comment_Type::open() {
  740. if (!comment_panel) make_comment_panel();
  741. const char *text = name();
  742. {
  743. int i=0, n=0;
  744. Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
  745. comment_predefined->clear();
  746. comment_predefined->add("_Edit/Add current comment...");
  747. comment_predefined->add("_Edit/Remove last selection...");
  748. menu.get("n", n, -1);
  749. if (n==-1) load_comments_preset(menu);
  750. menu.get("n", n, 0);
  751. for (i=0;i<n;i++) {
  752. char *text;
  753. menu.get(Fl_Preferences::Name(i), text, "");
  754. comment_predefined->add(text);
  755. free(text);
  756. }
  757. }
  758. comment_input->buffer()->text( text ? text : "" );
  759. comment_in_source->value(in_c_);
  760. comment_in_header->value(in_h_);
  761. comment_panel->show();
  762. const char* message = 0;
  763. char itempath[256]; itempath[0] = 0;
  764. int last_selected_item = 0;
  765. for (;;) { // repeat as long as there are errors
  766. if (message) fl_alert(message);
  767. for (;;) {
  768. Fl_Widget* w = Fl::readqueue();
  769. if (w == comment_panel_cancel) goto BREAK2;
  770. else if (w == comment_panel_ok) break;
  771. else if (w == comment_predefined) {
  772. if (comment_predefined->value()==1) {
  773. // add the current comment to the database
  774. const char *xname = fl_input(
  775. "Please enter a name to reference the current\ncomment in your database.\n\n"
  776. "Use forward slashes '/' to create submenus.",
  777. "My Comment");
  778. if (xname) {
  779. char *name = strdup(xname);
  780. for (char*s=name;*s;s++) if (*s==':') *s = ';';
  781. int n;
  782. Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
  783. db.set(name, comment_input->buffer()->text());
  784. Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
  785. menu.get("n", n, 0);
  786. menu.set(Fl_Preferences::Name(n), name);
  787. menu.set("n", ++n);
  788. comment_predefined->add(name);
  789. free(name);
  790. }
  791. } else if (comment_predefined->value()==2) {
  792. // remove the last selected comment from the database
  793. if (itempath[0]==0 || last_selected_item==0) {
  794. fl_message("Please select an entry form this menu first.");
  795. } else if (fl_choice("Are you sure that you want to delete the entry\n"
  796. "\"%s\"\nfrom the database?", "Cancel", "Delete",
  797. NULL, itempath)) {
  798. Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
  799. db.deleteEntry(itempath);
  800. comment_predefined->remove(last_selected_item);
  801. Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu");
  802. int i, n;
  803. for (i=4, n=0; i<comment_predefined->size(); i++) {
  804. const Fl_Menu_Item *mi = comment_predefined->menu()+i;
  805. if (comment_predefined->item_pathname(itempath, 255, mi)==0) {
  806. if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
  807. if (itempath[0]) menu.set(Fl_Preferences::Name(n++), itempath);
  808. }
  809. }
  810. menu.set("n", n);
  811. }
  812. } else {
  813. // load the selected comment from the database
  814. if (comment_predefined->item_pathname(itempath, 255)==0) {
  815. if (itempath[0]=='/') memmove(itempath, itempath+1, 255);
  816. Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
  817. char *text;
  818. db.get(itempath, text, "(no text found in data base)");
  819. comment_input->buffer()->text(text);
  820. free(text);
  821. last_selected_item = comment_predefined->value();
  822. }
  823. }
  824. }
  825. else if (w == comment_load) {
  826. // load a comment from disk
  827. fl_file_chooser_ok_label("Use File");
  828. const char *fname = fl_file_chooser("Pick a comment", 0L, 0L);
  829. fl_file_chooser_ok_label(NULL);
  830. if (fname) {
  831. if (comment_input->buffer()->loadfile(fname)) {
  832. fl_alert("Error loading file\n%s", fname);
  833. }
  834. }
  835. }
  836. else if (!w) Fl::wait();
  837. }
  838. char*c = comment_input->buffer()->text();
  839. name(c);
  840. free(c);
  841. int mod = 0;
  842. if (in_c_ != comment_in_source->value()) {
  843. in_c_ = comment_in_source->value();
  844. mod = 1;
  845. }
  846. if (in_h_ != comment_in_header->value()) {
  847. in_h_ = comment_in_header->value();
  848. mod = 1;
  849. }
  850. if (mod) set_modflag(1);
  851. break;
  852. }
  853. BREAK2:
  854. title_buf[0] = 0;
  855. comment_panel->hide();
  856. }
  857. const char *Fl_Comment_Type::title() {
  858. const char* n = name();
  859. if (!n || !*n) return type_name();
  860. if (title_buf[0]==0) {
  861. const char *s = n;
  862. char *d = title_buf;
  863. int i = 50;
  864. while (--i > 0) {
  865. char n = *s++;
  866. if (n==0) break;
  867. if (n=='\r') { *d++ = '\\'; *d++ = 'r'; i--; }
  868. else if (n=='\n') { *d++ = '\\'; *d++ = 'n'; i--; }
  869. else if (n<32) { *d++ = '^'; *d++ = 'A'+n; i--; }
  870. else *d++ = n;
  871. }
  872. if (i<=0) { *d++ = '.'; *d++ = '.'; *d++ = '.'; }
  873. *d++ = 0;
  874. }
  875. return title_buf;
  876. }
  877. Fl_Comment_Type Fl_Comment_type;
  878. void Fl_Comment_Type::write_code1() {
  879. const char* c = name();
  880. if (!c) return;
  881. if (!in_c_ && !in_h_) return;
  882. // find out if there is already a valid comment:
  883. const char *s = c;
  884. while (isspace(*s)) s++;
  885. // if this seems to be a C style comment, copy the block as is
  886. // (it's up to the user to correctly close the comment)
  887. if (s[0]=='/' && s[1]=='*') {
  888. if (in_h_) write_h("%s\n", c);
  889. if (in_c_) write_c("%s\n", c);
  890. return;
  891. }
  892. // copy the comment line by line, add the double slash if needed
  893. char *txt = strdup(c);
  894. char *b = txt, *e = txt;
  895. for (;;) {
  896. // find the end of the line and set it to NUL
  897. while (*e && *e!='\n') e++;
  898. char eol = *e;
  899. *e = 0;
  900. // check if there is a C++ style comment at the beginning of the line
  901. char *s = b;
  902. while (isspace(*s)) s++;
  903. if (s!=e && ( s[0]!='/' || s[1]!='/') ) {
  904. // if no comment marker was found, we add one ourselves
  905. if (in_h_) write_h("// ");
  906. if (in_c_) write_c("// ");
  907. }
  908. // now copy the rest of the line
  909. if (in_h_) write_h("%s\n", b);
  910. if (in_c_) write_c("%s\n", b);
  911. if (eol==0) break;
  912. *e++ = eol;
  913. b = e;
  914. }
  915. }
  916. void Fl_Comment_Type::write_code2() {}
  917. ////////////////////////////////////////////////////////////////
  918. const char* Fl_Type::class_name(const int need_nest) const {
  919. Fl_Type* p = parent;
  920. while (p) {
  921. if (p->is_class()) {
  922. // see if we are nested in another class, we must fully-qualify name:
  923. // this is lame but works...
  924. const char* q = 0;
  925. if(need_nest) q=p->class_name(need_nest);
  926. if (q) {
  927. static char s[256];
  928. if (q != s) strlcpy(s, q, sizeof(s));
  929. strlcat(s, "::", sizeof(s));
  930. strlcat(s, p->name(), sizeof(s));
  931. return s;
  932. }
  933. return p->name();
  934. }
  935. p = p->parent;
  936. }
  937. return 0;
  938. }
  939. /**
  940. * If this Type resides inside a class, this function returns the class type, or null.
  941. */
  942. const Fl_Class_Type *Fl_Type::is_in_class() const {
  943. Fl_Type* p = parent;
  944. while (p) {
  945. if (p->is_class()) {
  946. return (Fl_Class_Type*)p;
  947. }
  948. p = p->parent;
  949. }
  950. return 0;
  951. }
  952. int Fl_Class_Type::is_public() const {return public_;}
  953. void Fl_Class_Type::prefix(const char*p) {
  954. free((void*) class_prefix);
  955. class_prefix=strdup(p ? p : "" );
  956. }
  957. Fl_Type *Fl_Class_Type::make() {
  958. Fl_Type *p = Fl_Type::current;
  959. while (p && !p->is_decl_block()) p = p->parent;
  960. Fl_Class_Type *o = new Fl_Class_Type();
  961. o->name("UserInterface");
  962. o->class_prefix=0;
  963. o->subclass_of = 0;
  964. o->public_ = 1;
  965. o->add(p);
  966. o->factory = this;
  967. return o;
  968. }
  969. void Fl_Class_Type::write_properties() {
  970. Fl_Type::write_properties();
  971. if (subclass_of) {
  972. write_string(":");
  973. write_word(subclass_of);
  974. }
  975. switch (public_) {
  976. case 0: write_string("private"); break;
  977. case 2: write_string("protected"); break;
  978. }
  979. }
  980. void Fl_Class_Type::read_property(const char *c) {
  981. if (!strcmp(c,"private")) {
  982. public_ = 0;
  983. } else if (!strcmp(c,"protected")) {
  984. public_ = 2;
  985. } else if (!strcmp(c,":")) {
  986. storestring(read_word(), subclass_of);
  987. } else {
  988. Fl_Type::read_property(c);
  989. }
  990. }
  991. void Fl_Class_Type::open() {
  992. if (!class_panel) make_class_panel();
  993. char fullname[1024]="";
  994. if (prefix() && strlen(prefix()))
  995. sprintf(fullname,"%s %s",prefix(),name());
  996. else
  997. strcpy(fullname, name());
  998. c_name_input->static_value(fullname);
  999. c_subclass_input->static_value(subclass_of);
  1000. c_public_button->value(public_);
  1001. class_panel->show();
  1002. const char* message = 0;
  1003. char *na=0,*pr=0,*p=0; // name and prefix substrings
  1004. for (;;) { // repeat as long as there are errors
  1005. if (message) fl_alert(message);
  1006. for (;;) {
  1007. Fl_Widget* w = Fl::readqueue();
  1008. if (w == c_panel_cancel) goto BREAK2;
  1009. else if (w == c_panel_ok) break;
  1010. else if (!w) Fl::wait();
  1011. }
  1012. const char*c = c_name_input->value();
  1013. char *s = strdup(c);
  1014. size_t len = strlen(s);
  1015. if (!*s) goto OOPS;
  1016. p = (char*) (s+len-1);
  1017. while (p>=s && isspace(*p)) *(p--)='\0';
  1018. if (p<s) goto OOPS;
  1019. while (p>=s && is_id(*p)) p--;
  1020. if ( (p<s && !is_id(*(p+1))) || !*(p+1) ) {
  1021. OOPS: message = "class name must be C++ identifier";
  1022. free((void*)s);
  1023. continue;
  1024. }
  1025. na=p+1; // now we have the name
  1026. if(p>s) *p--='\0';
  1027. while (p>=s && isspace(*p)) *(p--)='\0';
  1028. while (p>=s && is_id(*p)) p--;
  1029. if (p<s) p++;
  1030. if (is_id(*p) && p<na) pr=p; // prefix detected
  1031. c = c_subclass_input->value();
  1032. message = c_check(c);
  1033. if (message) { free((void*)s);continue;}
  1034. name(na);
  1035. prefix(pr);
  1036. free((void*)s);
  1037. storestring(c, subclass_of);
  1038. if (public_ != c_public_button->value()) {
  1039. public_ = c_public_button->value();
  1040. set_modflag(1);
  1041. }
  1042. break;
  1043. }
  1044. BREAK2:
  1045. class_panel->hide();
  1046. }
  1047. Fl_Class_Type Fl_Class_type;
  1048. Fl_Class_Type *current_class;
  1049. extern Fl_Widget_Class_Type *current_widget_class;
  1050. void write_public(int state) {
  1051. if (!current_class && !current_widget_class) return;
  1052. if (current_class && current_class->write_public_state == state) return;
  1053. if (current_widget_class && current_widget_class->write_public_state == state) return;
  1054. if (current_class) current_class->write_public_state = state;
  1055. if (current_widget_class) current_widget_class->write_public_state = state;
  1056. switch (state) {
  1057. case 0: write_h("private:\n"); break;
  1058. case 1: write_h("public:\n"); break;
  1059. case 2: write_h("protected:\n"); break;
  1060. }
  1061. }
  1062. void Fl_Class_Type::write_code1() {
  1063. parent_class = current_class;
  1064. current_class = this;
  1065. write_public_state = 0;
  1066. if (prefix() && strlen(prefix()))
  1067. write_h("\nclass %s %s ", prefix(), name());
  1068. else
  1069. write_h("\nclass %s ", name());
  1070. if (subclass_of) write_h(": %s ", subclass_of);
  1071. write_h("{\n");
  1072. }
  1073. void Fl_Class_Type::write_code2() {
  1074. write_h("};\n");
  1075. current_class = parent_class;
  1076. }
  1077. /**
  1078. * Return 1 if this class contains a function with the given signature.
  1079. */
  1080. int Fl_Class_Type::has_function(const char *rtype, const char *sig) const {
  1081. Fl_Type *child;
  1082. for (child = next; child && child->level > level; child = child->next) {
  1083. if (child->level == level+1 && strcmp(child->type_name(), "Function")==0) {
  1084. const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
  1085. if (fn->has_signature(rtype, sig))
  1086. return 1;
  1087. }
  1088. }
  1089. return 0;
  1090. }
  1091. //
  1092. // End of "$Id$".
  1093. //