source: rtems-graphics-toolkit/fltk-1.1.10/fluid/code.cxx @ 513eea1

Last change on this file since 513eea1 was 513eea1, checked in by Joel Sherrill <joel.sherrill@…>, on 01/09/10 at 22:43:24

2010-01-08 Joel Sherrill <joel.sherrill@…>

fltk 1.1.10. imported

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