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

code.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Code output routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2015 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include "../src/flstring.h"
22 #include <stdarg.h>
23 
24 #include <FL/Fl.H>
25 #include "Fl_Type.h"
26 #include "alignment_panel.h"
27 
28 static FILE *code_file;
29 static FILE *header_file;
30 
31 extern char i18n_program[];
32 extern int i18n_type;
33 extern const char* i18n_include;
34 extern const char* i18n_function;
35 extern const char* i18n_file;
36 extern const char* i18n_set;
37 
38 // return true if c can be in a C identifier. I needed this so
39 // it is not messed up by locale settings:
40 int is_id(char c) {
41  return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
42 }
43 
45 // Generate unique but human-readable identifiers:
46 
47 struct id {
48  char* text;
49  void* object;
50  id *left, *right;
51  id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
52  ~id();
53 };
54 
56  delete left;
57  free((void *)text);
58  delete right;
59 }
60 
61 static id* id_root;
62 
63 const char* unique_id(void* o, const char* type, const char* name, const char* label) {
64  char buffer[128];
65  char* q = buffer;
66  while (*type) *q++ = *type++;
67  *q++ = '_';
68  const char* n = name;
69  if (!n || !*n) n = label;
70  if (n && *n) {
71  while (*n && !is_id(*n)) n++;
72  while (is_id(*n)) *q++ = *n++;
73  }
74  *q = 0;
75  // okay, search the tree and see if the name was already used:
76  id** p = &id_root;
77  int which = 0;
78  while (*p) {
79  int i = strcmp(buffer, (*p)->text);
80  if (!i) {
81  if ((*p)->object == o) return (*p)->text;
82  // already used, we need to pick a new name:
83  sprintf(q,"%x",++which);
84  p = &id_root;
85  continue;
86  }
87  else if (i < 0) p = &((*p)->left);
88  else p = &((*p)->right);
89  }
90  *p = new id(buffer, o);
91  return (*p)->text;
92 }
93 
95 // return current indentation:
96 
97 static const char* spaces = " ";
99 const char* indent() {
100  int i = indentation; if (i>16) i = 16;
101  return spaces+16-i;
102 }
103 
105 // declarations/include files:
106 // Each string generated by write_declare is written only once to
107 // the header file. This is done by keeping a binary tree of all
108 // the calls so far and not printing it if it is in the tree.
109 
110 struct included {
111  char *text;
113  included(const char *t) {
114  text = strdup(t);
115  left = right = 0;
116  }
117  ~included();
118 };
119 
121  delete left;
122  free((void *)text);
123  delete right;
124 }
126 
127 int write_declare(const char *format, ...) {
128  va_list args;
129  char buf[1024];
130  va_start(args, format);
131  vsnprintf(buf, sizeof(buf), format, args);
132  va_end(args);
133  included **p = &included_root;
134  while (*p) {
135  int i = strcmp(buf,(*p)->text);
136  if (!i) return 0;
137  else if (i < 0) p = &((*p)->left);
138  else p = &((*p)->right);
139  }
140  fprintf(header_file,"%s\n",buf);
141  *p = new included(buf);
142  return 1;
143 }
144 
146 
147 // silly thing to prevent declaring unused variables:
148 // When this symbol is on, all attempts to write code don't write
149 // anything, but set a variable if it looks like the variable "o" is used:
152 
153 // write an array of C characters (adds a null):
154 void write_cstring(const char *s, int length) {
155  if (varused_test) {
156  varused = 1;
157  return;
158  }
159  const char *p = s;
160  const char *e = s+length;
161  int linelength = 1;
162  putc('\"', code_file);
163  for (; p < e;) {
164  int c = *p++;
165  switch (c) {
166  case '\b': c = 'b'; goto QUOTED;
167  case '\t': c = 't'; goto QUOTED;
168  case '\n': c = 'n'; goto QUOTED;
169  case '\f': c = 'f'; goto QUOTED;
170  case '\r': c = 'r'; goto QUOTED;
171  case '\"':
172  case '\'':
173  case '\\':
174  QUOTED:
175  if (linelength >= 77) {fputs("\\\n",code_file); linelength = 0;}
176  putc('\\', code_file);
177  putc(c, code_file);
178  linelength += 2;
179  break;
180  case '?': // prevent trigraphs by writing ?? as ?\?
181  if (p-2 >= s && *(p-2) == '?') goto QUOTED;
182  // else fall through:
183  default:
184  if (c >= ' ' && c < 127) {
185  // a legal ASCII character
186  if (linelength >= 78) {fputs("\\\n",code_file); linelength = 0;}
187  putc(c, code_file);
188  linelength++;
189  break;
190  }
191  // otherwise we must print it as an octal constant:
192  c &= 255;
193  if (c < 8) {
194  if (linelength >= 76) {fputs("\\\n",code_file); linelength = 0;}
195  fprintf(code_file, "\\%o",c);
196  linelength += 2;
197  } else if (c < 64) {
198  if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;}
199  fprintf(code_file, "\\%o",c);
200  linelength += 3;
201  } else {
202  if (linelength >= 74) {fputs("\\\n",code_file); linelength = 0;}
203  fprintf(code_file, "\\%o",c);
204  linelength += 4;
205  }
206  // We must not put more numbers after it, because some C compilers
207  // consume them as part of the quoted sequence. Use string constant
208  // pasting to avoid this:
209  c = *p;
210  if (p < e && ( (c>='0'&&c<='9') || (c>='a'&&c<='f') || (c>='A'&&c<='F') )) {
211  putc('\"', code_file); linelength++;
212  if (linelength >= 79) {fputs("\n",code_file); linelength = 0;}
213  putc('\"', code_file); linelength++;
214  }
215  break;
216  }
217  }
218  putc('\"', code_file);
219 }
220 
221 // write a C string, quoting characters if necessary:
222 void write_cstring(const char *s) {write_cstring(s,strlen(s));}
223 
224 // write an array of C binary data (does not add a null):
225 void write_cdata(const char *s, int length) {
226  if (varused_test) {
227  varused = 1;
228  return;
229  }
230  if (write_sourceview) {
231  if (length>=0)
232  fprintf(code_file, "{ /* ... %d bytes of binary data... */ }", length);
233  else
234  fprintf(code_file, "{ /* ... binary data... */ }");
235  return;
236  }
237  if (length==-1) {
238  fprintf(code_file, "{ /* ... undefined size binary data... */ }");
239  return;
240  }
241  const unsigned char *w = (const unsigned char *)s;
242  const unsigned char *e = w+length;
243  int linelength = 1;
244  putc('{', code_file);
245  for (; w < e;) {
246  unsigned char c = *w++;
247  if (c>99) linelength += 4;
248  else if (c>9) linelength += 3;
249  else linelength += 2;
250  if (linelength >= 77) {fputs("\n",code_file); linelength = 0;}
251  fprintf(code_file, "%d", c);
252  if (w<e) putc(',', code_file);
253  }
254  putc('}', code_file);
255 }
256 
257 void vwrite_c(const char* format, va_list args) {
258  if (varused_test) {
259  varused = 1;
260  return;
261  }
262  vfprintf(code_file, format, args);
263 }
264 
265 void write_c(const char* format,...) {
266  va_list args;
267  va_start(args, format);
268  vwrite_c(format, args);
269  va_end(args);
270 }
271 
272 void write_h(const char* format,...) {
273  if (varused_test) return;
274  va_list args;
275  va_start(args, format);
276  vfprintf(header_file, format, args);
277  va_end(args);
278 }
279 
280 #include <FL/filename.H>
284 
285 // recursively dump code, putting children between the two parts
286 // of the parent code:
288  if (write_sourceview) {
289  p->code_position = (int)ftell(code_file);
290  if (p->header_position_end==-1)
291  p->header_position = (int)ftell(header_file);
292  }
293  // write all code that come before the children code
294  // (but don't write the last comment until the very end)
295  if (!(p==Fl_Type::last && p->is_comment()))
296  p->write_code1();
297  // recursively write the code of all children
298  Fl_Type* q;
299  if (p->is_widget() && p->is_class()) {
300  // Handle widget classes specially
301  for (q = p->next; q && q->level > p->level;) {
302  if (strcmp(q->type_name(), "Function")) q = write_code(q);
303  else {
304  int level = q->level;
305  do {
306  q = q->next;
307  } while (q && q->level > level);
308  }
309  }
310 
311  // write all code that come after the children
312  p->write_code2();
313 
314  for (q = p->next; q && q->level > p->level;) {
315  if (!strcmp(q->type_name(), "Function")) q = write_code(q);
316  else {
317  int level = q->level;
318  do {
319  q = q->next;
320  } while (q && q->level > level);
321  }
322  }
323 
324  write_h("};\n");
326  } else {
327  for (q = p->next; q && q->level > p->level;) q = write_code(q);
328  // write all code that come after the children
329  p->write_code2();
330  }
331  if (write_sourceview) {
332  p->code_position_end = (int)ftell(code_file);
333  if (p->header_position_end==-1)
334  p->header_position_end = (int)ftell(header_file);
335  }
336  return q;
337 }
338 
339 extern const char* header_file_name;
341 
342 int write_code(const char *s, const char *t) {
343  const char *filemode = "w";
344  if (write_sourceview)
345  filemode = "wb";
346  write_number++;
347  delete id_root; id_root = 0;
348  indentation = 0;
349  current_class = 0L;
351  if (!s) code_file = stdout;
352  else {
353  FILE *f = fl_fopen(s, filemode);
354  if (!f) return 0;
355  code_file = f;
356  }
357  if (!t) header_file = stdout;
358  else {
359  FILE *f = fl_fopen(t, filemode);
360  if (!f) {fclose(code_file); return 0;}
361  header_file = f;
362  }
363  // if the first entry in the Type tree is a comment, then it is probably
364  // a copyright notice. We print that before anything else in the file!
365  Fl_Type* first_type = Fl_Type::first;
366  if (first_type && first_type->is_comment()) {
367  if (write_sourceview) {
368  first_type->code_position = (int)ftell(code_file);
369  first_type->header_position = (int)ftell(header_file);
370  }
371  // it is ok to write non-recusive code here, because comments have no children or code2 blocks
372  first_type->write_code1();
373  if (write_sourceview) {
374  first_type->code_position_end = (int)ftell(code_file);
375  first_type->header_position_end = (int)ftell(header_file);
376  }
377  first_type = first_type->next;
378  }
379 
380  const char *hdr = "\
381 // generated by Fast Light User Interface Designer (fluid) version %.4f\n\n";
382  fprintf(header_file, hdr, FL_VERSION);
383  fprintf(code_file, hdr, FL_VERSION);
384 
385  {char define_name[102];
386  const char* a = fl_filename_name(t);
387  char* b = define_name;
388  if (!isalpha(*a)) {*b++ = '_';}
389  while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;}
390  *b = 0;
391  fprintf(header_file, "#ifndef %s\n", define_name);
392  fprintf(header_file, "#define %s\n", define_name);
393  }
394 
395  write_declare("#include <FL/Fl.H>");
396  if (i18n_type && i18n_include[0]) {
397  if (i18n_include[0] != '<' &&
398  i18n_include[0] != '\"')
399  write_c("#include \"%s\"\n", i18n_include);
400  else
401  write_c("#include %s\n", i18n_include);
402  if (i18n_type == 2) {
403  if (i18n_file[0]) write_c("extern nl_catd %s;\n", i18n_file);
404  else {
405  write_c("// Initialize I18N stuff now for menus...\n");
406  write_c("#include <locale.h>\n");
407  write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n");
408  write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n",
409  i18n_program);
410  }
411  }
412  }
413  if (t && include_H_from_C) {
414  if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) {
415  write_c("#include \"%s\"\n", fl_filename_name(t));
416  } else {
417  write_c("#include \"%s\"\n", t);
418  }
419  }
420  for (Fl_Type* p = first_type; p;) {
421  // write all static data for this & all children first
422  if (write_sourceview) p->header_position = (int)ftell(header_file);
423  p->write_static();
424  if (write_sourceview) {
425  p->header_position_end = (int)ftell(header_file);
426  if (p->header_position==p->header_position_end) p->header_position_end = -1;
427  }
428  for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) {
429  if (write_sourceview) q->header_position = (int)ftell(header_file);
430  q->write_static();
431  if (write_sourceview) {
432  q->header_position_end = (int)ftell(header_file);
433  if (q->header_position==q->header_position_end) q->header_position_end = -1;
434  }
435  }
436  // then write the nested code:
437  p = write_code(p);
438  }
439 
440  delete included_root; included_root = 0;
441 
442  if (!s) return 1;
443 
444  fprintf(header_file, "#endif\n");
445 
446  Fl_Type* last_type = Fl_Type::last;
447  if (last_type && last_type->is_comment()) {
448  if (write_sourceview) {
449  last_type->code_position = (int)ftell(code_file);
450  last_type->header_position = (int)ftell(header_file);
451  }
452  last_type->write_code1();
453  if (write_sourceview) {
454  last_type->code_position_end = (int)ftell(code_file);
455  last_type->header_position_end = (int)ftell(header_file);
456  }
457  }
458 
459  int x = fclose(code_file);
460  code_file = 0;
461  int y = fclose(header_file);
462  header_file = 0;
463  return x >= 0 && y >= 0;
464 }
465 
466 int write_strings(const char *sfile) {
467  FILE *fp = fl_fopen(sfile, "w");
468  Fl_Type *p;
469  Fl_Widget_Type *w;
470  int i;
471 
472  if (!fp) return 1;
473 
474  switch (i18n_type) {
475  case 0 : /* None, just put static text out */
476  fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
477  FL_VERSION);
478  for (p = Fl_Type::first; p; p = p->next) {
479  if (p->is_widget()) {
480  w = (Fl_Widget_Type *)p;
481 
482  if (w->label()) {
483  for (const char *s = w->label(); *s; s ++)
484  if (*s < 32 || *s > 126 || *s == '\"')
485  fprintf(fp, "\\%03o", *s);
486  else
487  putc(*s, fp);
488  putc('\n', fp);
489  }
490 
491  if (w->tooltip()) {
492  for (const char *s = w->tooltip(); *s; s ++)
493  if (*s < 32 || *s > 126 || *s == '\"')
494  fprintf(fp, "\\%03o", *s);
495  else
496  putc(*s, fp);
497  putc('\n', fp);
498  }
499  }
500  }
501  break;
502  case 1 : /* GNU gettext, put a .po file out */
503  fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
504  FL_VERSION);
505  for (p = Fl_Type::first; p; p = p->next) {
506  if (p->is_widget()) {
507  w = (Fl_Widget_Type *)p;
508 
509  if (w->label()) {
510  const char *s;
511 
512  fputs("msgid \"", fp);
513  for (s = w->label(); *s; s ++)
514  if (*s < 32 || *s > 126 || *s == '\"')
515  fprintf(fp, "\\%03o", *s);
516  else
517  putc(*s, fp);
518  fputs("\"\n", fp);
519 
520  fputs("msgstr \"", fp);
521  for (s = w->label(); *s; s ++)
522  if (*s < 32 || *s > 126 || *s == '\"')
523  fprintf(fp, "\\%03o", *s);
524  else
525  putc(*s, fp);
526  fputs("\"\n", fp);
527  }
528 
529  if (w->tooltip()) {
530  const char *s;
531 
532  fputs("msgid \"", fp);
533  for (s = w->tooltip(); *s; s ++)
534  if (*s < 32 || *s > 126 || *s == '\"')
535  fprintf(fp, "\\%03o", *s);
536  else
537  putc(*s, fp);
538  fputs("\"\n", fp);
539 
540  fputs("msgstr \"", fp);
541  for (s = w->tooltip(); *s; s ++)
542  if (*s < 32 || *s > 126 || *s == '\"')
543  fprintf(fp, "\\%03o", *s);
544  else
545  putc(*s, fp);
546  fputs("\"\n", fp);
547  }
548  }
549  }
550  break;
551  case 2 : /* POSIX catgets, put a .msg file out */
552  fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n",
553  FL_VERSION);
554  fprintf(fp, "$set %s\n", i18n_set);
555  fputs("$quote \"\n", fp);
556 
557  for (i = 1, p = Fl_Type::first; p; p = p->next) {
558  if (p->is_widget()) {
559  w = (Fl_Widget_Type *)p;
560 
561  if (w->label()) {
562  fprintf(fp, "%d \"", i ++);
563  for (const char *s = w->label(); *s; s ++)
564  if (*s < 32 || *s > 126 || *s == '\"')
565  fprintf(fp, "\\%03o", *s);
566  else
567  putc(*s, fp);
568  fputs("\"\n", fp);
569  }
570 
571  if (w->tooltip()) {
572  fprintf(fp, "%d \"", i ++);
573  for (const char *s = w->tooltip(); *s; s ++)
574  if (*s < 32 || *s > 126 || *s == '\"')
575  fprintf(fp, "\\%03o", *s);
576  else
577  putc(*s, fp);
578  fputs("\"\n", fp);
579  }
580  }
581  }
582  break;
583  }
584 
585  return fclose(fp);
586 }
587 
589 
592  write_h("// Header for %s\n", title());
593  write_c("// Code for %s\n", title());
594 }
596 
597 //
598 // End of "$Id$".
599 //
Fl_Type::write_static
virtual void write_static()
Definition: code.cxx:590
include_H_from_C
int include_H_from_C
Definition: Fl_Window_Type.cxx:42
Fl_Type::title
virtual const char * title()
Definition: Fl_Type.cxx:294
Fl_Type::write_code1
virtual void write_code1()
Definition: code.cxx:591
Fl.H
i18n_type
int i18n_type
Definition: fluid.cxx:702
Fl_Widget_Class_Type
Definition: Fl_Type.h:644
buf
static char * buf
Definition: fl_encoding_mac_roman.cxx:76
Fl_Widget_Type
Definition: Fl_Type.h:374
included
Definition: code.cxx:110
header_file
static FILE * header_file
Definition: code.cxx:29
Fl_Type::next
Fl_Type * next
Definition: Fl_Type.h:71
id_root
static id * id_root
Definition: code.cxx:61
header_file_name
const char * header_file_name
Definition: fluid.cxx:700
write_code
static Fl_Type * write_code(Fl_Type *p)
Definition: code.cxx:287
spaces
static const char * spaces
Definition: code.cxx:97
vsnprintf
#define vsnprintf
Definition: flstring.h:69
id::text
char * text
Definition: code.cxx:48
current_class
Fl_Class_Type * current_class
Definition: Fl_Function_Type.cxx:1445
Fl_Widget_Type::tooltip
const char * tooltip() const
Definition: Fl_Type.h:417
id::right
id * right
Definition: code.cxx:50
id::left
id * left
Definition: code.cxx:50
filename.H
varused_test
int varused_test
Definition: code.cxx:150
Fl_Type::level
int level
Definition: Fl_Type.h:69
free
void free()
NULL
#define NULL
Definition: forms.H:34
write_declare
int write_declare(const char *format,...)
Definition: code.cxx:127
varused
int varused
Definition: code.cxx:151
write_c
void write_c(const char *format,...)
Definition: code.cxx:265
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
b
long b
Definition: jpegint.h:397
Fl_Type::first
static Fl_Type * first
Definition: Fl_Type.h:70
id::id
id(const char *t, void *o)
Definition: code.cxx:51
Fl_Type::is_comment
virtual int is_comment() const
Definition: Fl_Type.cxx:763
Fl_Type::write_code2
virtual void write_code2()
Definition: code.cxx:595
write_cstring
void write_cstring(const char *s, int length)
Definition: code.cxx:154
Fl_Type.h
buffer
static char * buffer
Definition: file.cxx:215
Fl_Type::header_position_end
int header_position_end
Definition: Fl_Type.h:77
vwrite_c
void vwrite_c(const char *format, va_list args)
Definition: code.cxx:257
p
static menustate * p
Definition: Fl_Menu.cxx:606
i18n_program
char i18n_program[]
Definition: fluid.cxx:707
id::~id
~id()
Definition: code.cxx:55
write_strings
int write_strings(const char *sfile)
Definition: code.cxx:466
included::right
included * right
Definition: code.cxx:112
fl_filename_name
const char * fl_filename_name(const char *filename)
Definition: Fl_win32.cxx:2179
id::object
void * object
Definition: code.cxx:49
Fl_Type::type_name
virtual const char * type_name()=0
i18n_include
const char * i18n_include
Definition: fluid.cxx:703
id
Definition: code.cxx:47
indentation
int indentation
Definition: code.cxx:98
code_file
static FILE * code_file
Definition: code.cxx:28
Fl_Type
Definition: Fl_Type.h:43
indent
const char * indent()
Definition: code.cxx:99
included::included
included(const char *t)
Definition: code.cxx:113
alignment_panel.h
included::text
char * text
Definition: code.cxx:111
write_h
void write_h(const char *format,...)
Definition: code.cxx:272
included_root
static included * included_root
Definition: code.cxx:125
Fl_Type::last
static Fl_Type * last
Definition: Fl_Type.h:70
x
int x
Definition: test.c:73
current_widget_class
Fl_Widget_Class_Type * current_widget_class
Definition: Fl_Window_Type.cxx:1435
Fl_Type::code_position_end
int code_position_end
Definition: Fl_Type.h:77
unique_id
const char * unique_id(void *o, const char *type, const char *name, const char *label)
Definition: code.cxx:63
Fl_Type::label
const char * label() const
Definition: Fl_Type.h:98
write_number
int write_number
Definition: code.cxx:281
y
int y
Definition: test.c:74
Fl_Type::code_position
int code_position
Definition: Fl_Type.h:76
is_id
int is_id(char c)
Definition: code.cxx:40
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
write_sourceview
int write_sourceview
Definition: code.cxx:282
included::~included
~included()
Definition: code.cxx:120
FL_VERSION
#define FL_VERSION
Definition: Enumerations.H:101
length
png_uint_32 length
Definition: png.c:2173
i18n_file
const char * i18n_file
Definition: fluid.cxx:705
name
static const char * name
Definition: Fl_arg.cxx:53
i18n_set
const char * i18n_set
Definition: fluid.cxx:706
write_cdata
void write_cdata(const char *s, int length)
Definition: code.cxx:225
included::left
included * left
Definition: code.cxx:112
Fl_Class_Type
Definition: Fl_Type.h:338
i18n_function
const char * i18n_function
Definition: fluid.cxx:704
Fl_Type::header_position
int header_position
Definition: Fl_Type.h:76