| 
							- //
 - // "$Id: code.cxx 7903 2010-11-28 21:06:39Z matt $"
 - //
 - // Code output routines for the Fast Light Tool Kit (FLTK).
 - //
 - // Copyright 1998-2010 by Bill Spitzak and others.
 - //
 - // This library is free software; you can redistribute it and/or
 - // modify it under the terms of the GNU Library General Public
 - // License as published by the Free Software Foundation; either
 - // version 2 of the License, or (at your option) any later version.
 - //
 - // This library is distributed in the hope that it will be useful,
 - // but WITHOUT ANY WARRANTY; without even the implied warranty of
 - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - // Library General Public License for more details.
 - //
 - // You should have received a copy of the GNU Library General Public
 - // License along with this library; if not, write to the Free Software
 - // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 - // USA.
 - //
 - // 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;
 - 
 - 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 7903 2010-11-28 21:06:39Z matt $".
 - //
 
 
  |