| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 |
- //
- // "$Id: code.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $"
- //
- // Code output routines for the Fast Light Tool Kit (FLTK).
- //
- // Copyright 1998-2010 by Bill Spitzak and others.
- //
- // This library is free software. Distribution and use rights are outlined in
- // the file "COPYING" which should have been included with this file. If this
- // file is missing or damaged, see the license at:
- //
- // http://www.fltk.org/COPYING.php
- //
- // Please report all bugs and problems on the following page:
- //
- // http://www.fltk.org/str.php
- //
- #include <stdio.h>
- #include <stdlib.h>
- #include "../src/flstring.h"
- #include <stdarg.h>
- #include <FL/Fl.H>
- #include "Fl_Type.h"
- #include "alignment_panel.h"
- static FILE *code_file;
- static FILE *header_file;
- extern char i18n_program[];
- extern int i18n_type;
- extern const char* i18n_include;
- extern const char* i18n_function;
- extern const char* i18n_file;
- extern const char* i18n_set;
- // return true if c can be in a C identifier. I needed this so
- // it is not messed up by locale settings:
- int is_id(char c) {
- return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
- }
- ////////////////////////////////////////////////////////////////
- // Generate unique but human-readable identifiers:
- struct id {
- char* text;
- void* object;
- id *left, *right;
- id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
- ~id();
- };
- id::~id() {
- delete left;
- free((void *)text);
- delete right;
- }
- static id* id_root;
- const char* unique_id(void* o, const char* type, const char* name, const char* label) {
- char buffer[128];
- char* q = buffer;
- while (*type) *q++ = *type++;
- *q++ = '_';
- const char* n = name;
- if (!n || !*n) n = label;
- if (n && *n) {
- while (*n && !is_id(*n)) n++;
- while (is_id(*n)) *q++ = *n++;
- }
- *q = 0;
- // okay, search the tree and see if the name was already used:
- id** p = &id_root;
- int which = 0;
- while (*p) {
- int i = strcmp(buffer, (*p)->text);
- if (!i) {
- if ((*p)->object == o) return (*p)->text;
- // already used, we need to pick a new name:
- sprintf(q,"%x",++which);
- p = &id_root;
- continue;
- }
- else if (i < 0) p = &((*p)->left);
- else p = &((*p)->right);
- }
- *p = new id(buffer, o);
- return (*p)->text;
- }
- ////////////////////////////////////////////////////////////////
- // return current indentation:
- static const char* spaces = " ";
- int indentation;
- const char* indent() {
- int i = indentation; if (i>16) i = 16;
- return spaces+16-i;
- }
- ////////////////////////////////////////////////////////////////
- // declarations/include files:
- // Each string generated by write_declare is written only once to
- // the header file. This is done by keeping a binary tree of all
- // the calls so far and not printing it if it is in the tree.
- struct included {
- char *text;
- included *left, *right;
- included(const char *t) {
- text = strdup(t);
- left = right = 0;
- }
- ~included();
- };
- included::~included() {
- delete left;
- free((void *)text);
- delete right;
- }
- static included *included_root;
- int write_declare(const char *format, ...) {
- va_list args;
- char buf[1024];
- va_start(args, format);
- vsnprintf(buf, sizeof(buf), format, args);
- va_end(args);
- included **p = &included_root;
- while (*p) {
- int i = strcmp(buf,(*p)->text);
- if (!i) return 0;
- else if (i < 0) p = &((*p)->left);
- else p = &((*p)->right);
- }
- fprintf(header_file,"%s\n",buf);
- *p = new included(buf);
- return 1;
- }
- ////////////////////////////////////////////////////////////////
- // silly thing to prevent declaring unused variables:
- // When this symbol is on, all attempts to write code don't write
- // anything, but set a variable if it looks like the variable "o" is used:
- int varused_test;
- int varused;
- // write an array of C characters (adds a null):
- void write_cstring(const char *w, int length) {
- if (varused_test) {
- varused = 1;
- return;
- }
- const char *e = w+length;
- int linelength = 1;
- putc('\"', code_file);
- for (; w < e;) {
- int c = *w++;
- switch (c) {
- case '\b': c = 'b'; goto QUOTED;
- case '\t': c = 't'; goto QUOTED;
- case '\n': c = 'n'; goto QUOTED;
- case '\f': c = 'f'; goto QUOTED;
- case '\r': c = 'r'; goto QUOTED;
- case '\"':
- case '\'':
- case '\\':
- QUOTED:
- if (linelength >= 77) {fputs("\\\n",code_file); linelength = 0;}
- putc('\\', code_file);
- putc(c, code_file);
- linelength += 2;
- break;
- case '?': // prevent trigraphs by writing ?? as ?\?
- if (*(w-2) == '?') goto QUOTED;
- // else fall through:
- default:
- if (c >= ' ' && c < 127) {
- // a legal ASCII character
- if (linelength >= 78) {fputs("\\\n",code_file); linelength = 0;}
- putc(c, code_file);
- linelength++;
- break;
- }
- // otherwise we must print it as an octal constant:
- c &= 255;
- if (c < 8) {
- if (linelength >= 76) {fputs("\\\n",code_file); linelength = 0;}
- fprintf(code_file, "\\%o",c);
- linelength += 2;
- } else if (c < 64) {
- if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;}
- fprintf(code_file, "\\%o",c);
- linelength += 3;
- } else {
- if (linelength >= 74) {fputs("\\\n",code_file); linelength = 0;}
- fprintf(code_file, "\\%o",c);
- linelength += 4;
- }
- // We must not put more numbers after it, because some C compilers
- // consume them as part of the quoted sequence. Use string constant
- // pasting to avoid this:
- c = *w;
- if (w < e && ( (c>='0'&&c<='9') || (c>='a'&&c<='f') || (c>='A'&&c<='F') )) {
- putc('\"', code_file); linelength++;
- if (linelength >= 79) {fputs("\n",code_file); linelength = 0;}
- putc('\"', code_file); linelength++;
- }
- break;
- }
- }
- putc('\"', code_file);
- }
- // write a C string, quoting characters if necessary:
- void write_cstring(const char *w) {write_cstring(w,strlen(w));}
- // write an array of C binary data (does not add a null):
- void write_cdata(const char *s, int length) {
- if (varused_test) {
- varused = 1;
- return;
- }
- if (write_sourceview) {
- if (length>=0)
- fprintf(code_file, "{ /* ... %d bytes of binary data... */ }", length);
- else
- fprintf(code_file, "{ /* ... binary data... */ }");
- return;
- }
- if (length==-1) {
- fprintf(code_file, "{ /* ... undefined size binary data... */ }");
- return;
- }
- const unsigned char *w = (const unsigned char *)s;
- const unsigned char *e = w+length;
- int linelength = 1;
- putc('{', code_file);
- for (; w < e;) {
- unsigned char c = *w++;
- if (c>99) linelength += 4;
- else if (c>9) linelength += 3;
- else linelength += 2;
- if (linelength >= 77) {fputs("\n",code_file); linelength = 0;}
- fprintf(code_file, "%d", c);
- if (w<e) putc(',', code_file);
- }
- putc('}', code_file);
- }
- void write_c(const char* format,...) {
- if (varused_test) {
- varused = 1;
- return;
- }
- va_list args;
- va_start(args, format);
- vfprintf(code_file, format, args);
- va_end(args);
- }
- void write_h(const char* format,...) {
- if (varused_test) return;
- va_list args;
- va_start(args, format);
- vfprintf(header_file, format, args);
- va_end(args);
- }
- #include <FL/filename.H>
- int write_number;
- int write_sourceview;
- extern Fl_Widget_Class_Type *current_widget_class;
- // recursively dump code, putting children between the two parts
- // of the parent code:
- static Fl_Type* write_code(Fl_Type* p) {
- if (write_sourceview) {
- p->code_position = (int)ftell(code_file);
- if (p->header_position_end==-1)
- p->header_position = (int)ftell(header_file);
- }
- // write all code that come before the children code
- // (but don't write the last comment until the very end)
- if (!(p==Fl_Type::last && p->is_comment()))
- p->write_code1();
- // recursively write the code of all children
- Fl_Type* q;
- if (p->is_widget() && p->is_class()) {
- // Handle widget classes specially
- for (q = p->next; q && q->level > p->level;) {
- if (strcmp(q->type_name(), "Function")) q = write_code(q);
- else {
- int level = q->level;
- do {
- q = q->next;
- } while (q && q->level > level);
- }
- }
- // write all code that come after the children
- p->write_code2();
- for (q = p->next; q && q->level > p->level;) {
- if (!strcmp(q->type_name(), "Function")) q = write_code(q);
- else {
- int level = q->level;
- do {
- q = q->next;
- } while (q && q->level > level);
- }
- }
- write_h("};\n");
- current_widget_class = 0L;
- } else {
- for (q = p->next; q && q->level > p->level;) q = write_code(q);
- // write all code that come after the children
- p->write_code2();
- }
- if (write_sourceview) {
- p->code_position_end = (int)ftell(code_file);
- if (p->header_position_end==-1)
- p->header_position_end = (int)ftell(header_file);
- }
- return q;
- }
- extern const char* header_file_name;
- extern Fl_Class_Type *current_class;
- extern const char *code_file_name;
- int write_code_block(Fl_Block_Type *block) {
- const char *filemode = "w";
- if (write_sourceview)
- filemode = "wb";
- write_number++;
- int x, y;
- Fl_Type* first_type;
- Fl_Type* last_type;
- const char *hdr;
- const char *file_name_base = block->get_file_name();
- char buf[1024];
- *buf = '\0';
- //return value
- int ret_value = 0;
- //save globals
- id *saved_id_root = id_root;
- int saved_indentation = indentation;
- Fl_Class_Type *saved_current_class = current_class;
- Fl_Widget_Class_Type *saved_current_widget_class = current_widget_class;
- FILE *saved_code_file = code_file;
- FILE *saved_header_file = header_file;
- included *saved_included_root = included_root;
- included_root = 0;
- id_root = 0;
- indentation = 0;
- current_class = 0L;
- current_widget_class = 0L;
- if (!file_name_base) code_file = stdout;
- else {
- snprintf(buf, sizeof(buf),"%s.%s", file_name_base,
- code_file_name ? code_file_name : "cpp");
- FILE *f = fopen(buf, filemode);
- if (!f){
- ret_value = 0;
- goto restore_on_return;
- }
- code_file = f;
- }
- if (!file_name_base) header_file = stdout;
- else {
- snprintf(buf, sizeof(buf),"%s.%s", file_name_base,
- header_file_name ? header_file_name : "h");
- FILE *f = fopen(buf, filemode);
- if (!f) {
- fclose(code_file);
- ret_value = 0;
- goto restore_on_return;
- }
- header_file = f;
- }
- // if the first entry in the Type tree is a comment, then it is probably
- // a copyright notice. We print that before anything else in the file!
- first_type = Fl_Type::last;
- if (first_type && first_type->is_comment()) {
- if (write_sourceview) {
- first_type->code_position = (int)ftell(code_file);
- first_type->header_position = (int)ftell(header_file);
- }
- // it is ok to write non-recusive code here, because comments have no children or code2 blocks
- first_type->write_code1();
- if (write_sourceview) {
- first_type->code_position_end = (int)ftell(code_file);
- first_type->header_position_end = (int)ftell(header_file);
- }
- }
- first_type = block;
- hdr = "\
- // generated by Fast Light User Interface Designer (fluid) version %.4f\n\n";
- fprintf(header_file, hdr, FL_VERSION);
- fprintf(code_file, hdr, FL_VERSION);
- {char define_name[102];
- const char* a = fl_filename_name(buf);
- char* b = define_name;
- if (!isalpha(*a)) {*b++ = '_';}
- while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;}
- *b = 0;
- fprintf(header_file, "#ifndef %s\n", define_name);
- fprintf(header_file, "#define %s\n", define_name);
- }
- write_declare("#include <FL/Fl.H>");
- if (i18n_type && i18n_include[0]) {
- if (i18n_include[0] != '<' &&
- i18n_include[0] != '\"')
- write_c("#include \"%s\"\n", i18n_include);
- else
- write_c("#include %s\n", i18n_include);
- if (i18n_type == 2) {
- if (i18n_file[0]) write_c("extern nl_catd %s;\n", i18n_file);
- else {
- write_c("// Initialize I18N stuff now for menus...\n");
- write_c("#include <locale.h>\n");
- write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n");
- write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n",
- i18n_program);
- }
- }
- }
- if (*buf && include_H_from_C) {
- if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) {
- write_c("#include \"%s\"\n", fl_filename_name(buf));
- } else {
- write_c("#include \"%s\"\n", buf);
- }
- }
- for (Fl_Type* p = first_type; p;) {
- // write all static data for this & all children first
- if (write_sourceview) p->header_position = (int)ftell(header_file);
- p->write_static();
- if (write_sourceview) {
- p->header_position_end = (int)ftell(header_file);
- if (p->header_position==p->header_position_end) p->header_position_end = -1;
- }
- for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) {
- if (write_sourceview) q->header_position = (int)ftell(header_file);
- q->write_static();
- if (write_sourceview) {
- q->header_position_end = (int)ftell(header_file);
- if (q->header_position==q->header_position_end) q->header_position_end = -1;
- }
- }
- // then write the nested code:
- p = write_code(p);
- }
- delete included_root; included_root = 0;
- if (!*buf) {
- ret_value = 1;
- goto restore_on_return;
- }
- fprintf(header_file, "#endif\n");
- last_type = Fl_Type::last;
- if (last_type && last_type->is_comment()) {
- if (write_sourceview) {
- last_type->code_position = (int)ftell(code_file);
- last_type->header_position = (int)ftell(header_file);
- }
- last_type->write_code1();
- if (write_sourceview) {
- last_type->code_position_end = (int)ftell(code_file);
- last_type->header_position_end = (int)ftell(header_file);
- }
- }
- x = fclose(code_file);
- code_file = 0;
- y = fclose(header_file);
- header_file = 0;
- ret_value = x >= 0 && y >= 0;
- restore_on_return:
- //restore globals
- id_root = saved_id_root;
- indentation = saved_indentation;
- current_class = saved_current_class;
- current_widget_class = saved_current_widget_class;
- code_file = saved_code_file;
- header_file = saved_header_file;
- included_root = saved_included_root;
- return ret_value;
- }
- int write_code(const char *s, const char *t) {
- const char *filemode = "w";
- if (write_sourceview)
- filemode = "wb";
- write_number++;
- delete id_root; id_root = 0;
- indentation = 0;
- current_class = 0L;
- current_widget_class = 0L;
- if (!s) code_file = stdout;
- else {
- FILE *f = fl_fopen(s, filemode);
- if (!f) return 0;
- code_file = f;
- }
- if (!t) header_file = stdout;
- else {
- FILE *f = fl_fopen(t, filemode);
- if (!f) {fclose(code_file); return 0;}
- header_file = f;
- }
- // if the first entry in the Type tree is a comment, then it is probably
- // a copyright notice. We print that before anything else in the file!
- Fl_Type* first_type = Fl_Type::first;
- if (first_type && first_type->is_comment()) {
- if (write_sourceview) {
- first_type->code_position = (int)ftell(code_file);
- first_type->header_position = (int)ftell(header_file);
- }
- // it is ok to write non-recusive code here, because comments have no children or code2 blocks
- first_type->write_code1();
- if (write_sourceview) {
- first_type->code_position_end = (int)ftell(code_file);
- first_type->header_position_end = (int)ftell(header_file);
- }
- first_type = first_type->next;
- }
- const char *hdr = "\
- // generated by Fast Light User Interface Designer (fluid) version %.4f\n\n";
- fprintf(header_file, hdr, FL_VERSION);
- fprintf(code_file, hdr, FL_VERSION);
- {char define_name[102];
- const char* a = fl_filename_name(t);
- char* b = define_name;
- if (!isalpha(*a)) {*b++ = '_';}
- while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;}
- *b = 0;
- fprintf(header_file, "#ifndef %s\n", define_name);
- fprintf(header_file, "#define %s\n", define_name);
- }
- write_declare("#include <FL/Fl.H>");
- if (i18n_type && i18n_include[0]) {
- if (i18n_include[0] != '<' &&
- i18n_include[0] != '\"')
- write_c("#include \"%s\"\n", i18n_include);
- else
- write_c("#include %s\n", i18n_include);
- if (i18n_type == 2) {
- if (i18n_file[0]) write_c("extern nl_catd %s;\n", i18n_file);
- else {
- write_c("// Initialize I18N stuff now for menus...\n");
- write_c("#include <locale.h>\n");
- write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n");
- write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n",
- i18n_program);
- }
- }
- }
- if (t && include_H_from_C) {
- if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) {
- write_c("#include \"%s\"\n", fl_filename_name(t));
- } else {
- write_c("#include \"%s\"\n", t);
- }
- }
- for (Fl_Type* p = first_type; p;) {
- // write all static data for this & all children first
- if (write_sourceview) p->header_position = (int)ftell(header_file);
- p->write_static();
- if (write_sourceview) {
- p->header_position_end = (int)ftell(header_file);
- if (p->header_position==p->header_position_end) p->header_position_end = -1;
- }
- for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) {
- if (write_sourceview) q->header_position = (int)ftell(header_file);
- q->write_static();
- if (write_sourceview) {
- q->header_position_end = (int)ftell(header_file);
- if (q->header_position==q->header_position_end) q->header_position_end = -1;
- }
- }
- // then write the nested code:
- p = write_code(p);
- }
- delete included_root; included_root = 0;
- if (!s) return 1;
- fprintf(header_file, "#endif\n");
- Fl_Type* last_type = Fl_Type::last;
- if (last_type && last_type->is_comment()) {
- if (write_sourceview) {
- last_type->code_position = (int)ftell(code_file);
- last_type->header_position = (int)ftell(header_file);
- }
- last_type->write_code1();
- if (write_sourceview) {
- last_type->code_position_end = (int)ftell(code_file);
- last_type->header_position_end = (int)ftell(header_file);
- }
- }
- int x = fclose(code_file);
- code_file = 0;
- int y = fclose(header_file);
- header_file = 0;
- return x >= 0 && y >= 0;
- }
- int write_strings(const char *sfile) {
- FILE *fp = fl_fopen(sfile, "w");
- Fl_Type *p;
- Fl_Widget_Type *w;
- int i;
- if (!fp) return 1;
- switch (i18n_type) {
- case 0 : /* None, just put static text out */
- fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
- FL_VERSION);
- for (p = Fl_Type::first; p; p = p->next) {
- if (p->is_widget()) {
- w = (Fl_Widget_Type *)p;
- if (w->label()) {
- for (const char *s = w->label(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- putc('\n', fp);
- }
- if (w->tooltip()) {
- for (const char *s = w->tooltip(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- putc('\n', fp);
- }
- }
- }
- break;
- case 1 : /* GNU gettext, put a .po file out */
- fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n",
- FL_VERSION);
- for (p = Fl_Type::first; p; p = p->next) {
- if (p->is_widget()) {
- w = (Fl_Widget_Type *)p;
- if (w->label()) {
- const char *s;
- fputs("msgid \"", fp);
- for (s = w->label(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- fputs("msgstr \"", fp);
- for (s = w->label(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- }
- if (w->tooltip()) {
- const char *s;
- fputs("msgid \"", fp);
- for (s = w->tooltip(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- fputs("msgstr \"", fp);
- for (s = w->tooltip(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- }
- }
- }
- break;
- case 2 : /* POSIX catgets, put a .msg file out */
- fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n",
- FL_VERSION);
- fprintf(fp, "$set %s\n", i18n_set);
- fputs("$quote \"\n", fp);
- for (i = 1, p = Fl_Type::first; p; p = p->next) {
- if (p->is_widget()) {
- w = (Fl_Widget_Type *)p;
- if (w->label()) {
- fprintf(fp, "%d \"", i ++);
- for (const char *s = w->label(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- }
- if (w->tooltip()) {
- fprintf(fp, "%d \"", i ++);
- for (const char *s = w->tooltip(); *s; s ++)
- if (*s < 32 || *s > 126 || *s == '\"')
- fprintf(fp, "\\%03o", *s);
- else
- putc(*s, fp);
- fputs("\"\n", fp);
- }
- }
- }
- break;
- }
- return fclose(fp);
- }
- ////////////////////////////////////////////////////////////////
- void Fl_Type::write_static() {}
- void Fl_Type::write_code1() {
- write_h("// Header for %s\n", title());
- write_c("// Code for %s\n", title());
- }
- void Fl_Type::write_code2() {}
- //
- // End of "$Id: code.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $".
- //
|