1 // $Id: glade--.cc,v 1.90 2004/05/10 06:33:15 christof Exp $
2 /*  glade--: C++ frontend for glade (Gtk+ User Interface Builder)
3  *  Copyright (C) 1998  Christof Petig
4  *  Copyright (C) 1999-2002 Adolf Petig GmbH & Co. KG, written by Christof Petig
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include "TagStream.hh"
25 #include "Cxx.hh"
26 #include "Configuration.hh"
27 #include <unistd.h>
28 #include <cstdlib>
29 #include <sys/stat.h> // for makedir
30 #include <cstdio>
31 
32 #ifndef HAVE_GETOPT_LONG
33 #include "./getopt.h"
34 #else
35 #include <getopt.h>
36 #endif
37 
38 #ifndef __MINGW32__
39 #include <pwd.h>
40 #include <sys/utsname.h>
41 #endif
42 
43 struct Configuration Configuration;
44 
45 enum longopts { GTKVERSION=0x100, GTKMMVERSION, AUTOCONF,
46 	GTK_OSTREAM,FORCE_ACCEL,FORCE_NOACCEL, TEMPL_POSTFIX, OM_STRINGS,
47 	OM_CREATE_ENUMS, CASE_CONV, UPPERCASE_ENUMS, MIXEDCASE_DEFINES,
48 	OM_NO_CREATE_ENUMS, AUTOMAKE15, EMBED_PICS, LOAD_PICS, BASE_CLASS,
49 	SHOW_OPTIONS, NON_VIRTUAL_CALLBACKS, LOOKUP_TABLE, FLAG_GNOME2,
50 	LIBGLADE_OPTION, IMAGE_PROVIDER, NOAUTORECONF, AUTORECONF };
51 
52 const static struct option options[]=
53 { { "directory",	required_argument, NULL, 'd' },
54   { "name",		required_argument, NULL, 'm' },
55   { "version",		no_argument,	   NULL, 'V' },
56   { "debug",		no_argument,	   NULL, 'g' },
57   { "samplecode",       no_argument,       NULL, 's' },
58   { "barebones",        no_argument,       NULL, 'r' },
59   { "gladeonly",        no_argument,       NULL, 'r' },
60   { "noautoconf",       no_argument,       NULL, 'A' },
61   { "autoconf",         no_argument,       NULL, AUTOCONF },
62   { "help",		no_argument,       NULL, '?' },
63   { "gtkversion",	required_argument, NULL, GTKVERSION },
64   { "gtkmmversion",	required_argument, NULL, GTKMMVERSION },
65   { "gtkostream",	no_argument,	   NULL, GTK_OSTREAM },
66   // compatibility with old versions
67   { "widgettable",      no_argument,       NULL, LOOKUP_TABLE },
68   { "fulltable",        no_argument,       NULL, 'w' },
69 
70   { "libglade",		no_argument,	   NULL, 'l' },
71   { "libglade-option",	no_argument,	   NULL, LIBGLADE_OPTION },
72   { "accelerators",	no_argument,	   NULL, FORCE_ACCEL },
73   { "noaccelerators",	no_argument,	   NULL, FORCE_NOACCEL },
74   { "template-postfix",	required_argument, NULL, TEMPL_POSTFIX },
75   { "optionmenu-strings", no_argument,	   NULL, OM_STRINGS },
76   { "optionmenu-no-create-enums", no_argument,NULL, OM_NO_CREATE_ENUMS },
77   { "optionmenu-create-enums", no_argument,NULL, OM_CREATE_ENUMS },
78   { "do-case-conversion", no_argument,	   NULL, CASE_CONV },
79   { "uppercase-enums",	no_argument,	   NULL, UPPERCASE_ENUMS },
80   { "mixedcase-defines", no_argument,	   NULL, MIXEDCASE_DEFINES },
81   { "automake-1-5",	no_argument,	   NULL, AUTOMAKE15 },
82   { "no-autoreconf",	no_argument,	   NULL, NOAUTORECONF },
83   { "autoreconf",	no_argument,	   NULL, AUTORECONF },
84   { "embed-images",	no_argument,	   NULL, EMBED_PICS },
85   { "load-images",	no_argument,	   NULL, LOAD_PICS },
86   { "baseclass",	no_argument,	   NULL, BASE_CLASS },
87   { "non-virtual-callbacks",	no_argument,	   NULL, NON_VIRTUAL_CALLBACKS },
88   { "gnome2",	no_argument,	   NULL, FLAG_GNOME2 },
89 
90   { "header-suffix",	required_argument, NULL, 'h' },
91   { "source_suffix",	required_argument, NULL, 'c' },
92 
93   { "verbose",		no_argument,	   NULL, 'v' },
94   { "show-options",	no_argument,	   NULL, SHOW_OPTIONS },
95   { "image-provider",	required_argument, NULL, IMAGE_PROVIDER },
96 
97   { NULL,		0,		   NULL, 0 }
98 };
99 
parse_version(const char * arg,Pkg_Version & v,Pkg_Version::Source s=Pkg_Version::Unknown,bool ignore_letters=false)100 static bool parse_version(const char *arg,Pkg_Version &v, Pkg_Version::Source s=Pkg_Version::Unknown, bool ignore_letters=false)
101 {  int mymajor=0,myminor=0,mymicro=0;
102    const char *nextp=arg;
103    if (ignore_letters)
104    {  while (*nextp && !isdigit((unsigned char)*nextp)) ++nextp;
105       arg=nextp;
106    }
107    else if (s==Pkg_Version::Gnome_Config)  // gnome-config prints 'gnomemm-1.2.2'
108    {  nextp=strrchr(arg,'-');
109       if (nextp) arg=nextp+1;
110    }
111    if (!*arg) return false;
112    mymajor=strtol(arg,const_cast<char **>(&nextp),10);
113    if (!*nextp) goto version_ok;
114    if (*nextp!='.' && *nextp!=',')
115    {  std::cerr << "error parsing version std::string '" << arg << "\n";
116       return false;
117    }
118    myminor=strtol(nextp+1,const_cast<char **>(&nextp),10);
119    if (!*nextp) goto version_ok;
120    if (*nextp!='.' && *nextp!=',')
121    {  if (ignore_letters) goto version_ok;
122       std::cerr << "error parsing version std::string '" << arg << "\n";
123       return false;
124    }
125    mymicro=strtol(nextp+1,const_cast<char **>(&nextp),10);
126    if (ignore_letters || !*nextp || *nextp=='.') // forget about nano version
127    {version_ok:
128       v=Pkg_Version(mymajor,myminor,mymicro,s); return true; }
129    std::cerr << "error parsing version std::string '" << arg << "\n";
130    return false;
131 }
132 
CheckVersion(const std::string & cmd,Pkg_Version & v,Pkg_Version::Source src=Pkg_Version::Unknown,bool ignore_letters=false)133 static bool CheckVersion(const std::string &cmd, Pkg_Version &v, Pkg_Version::Source src=Pkg_Version::Unknown, bool ignore_letters=false)
134 {  if (v.source==Pkg_Version::Command_Line) return true;
135    char buf[80];
136    bool result=false;
137    FILE *f=popen(cmd.c_str(),"r");
138    if (f)
139    {  if (fgets(buf,sizeof(buf),f))
140       {  if (!ignore_letters)
141            for (unsigned char *s=(unsigned char*)buf;*s;s++)
142             if (isspace(*s))
143             {  *s=0; break; }
144          // not installed/found
145          if (!strncmp(buf,"Package ",8) && strstr(buf," not ")) result=false;
146          else if (parse_version(buf,v,src,ignore_letters)) result=true;
147          else std::cerr << cmd << ": strange result '" << buf << "'\n";
148       }
149       pclose(f);
150    }
151    else perror(cmd.c_str());
152    return result;
153 }
154 
call_gtkmm_config()155 static void call_gtkmm_config()
156 {  CheckVersion("pkg-config --version",Configuration.pc_version,Pkg_Version::Pkg_Config);
157 
158    if (CheckVersion("automake-1.9 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
159       Configuration.automake_name="automake-1.9";
160    else if (CheckVersion("automake-1.8 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
161       Configuration.automake_name="automake-1.8";
162    else if (CheckVersion("automake-1.7 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
163       Configuration.automake_name="automake-1.7";
164    else if (CheckVersion("automake-1.6 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
165       Configuration.automake_name="automake-1.6";
166    else if (CheckVersion("automake --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
167       Configuration.automake_name="automake";
168    else if (CheckVersion("automake-1.5 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
169       Configuration.automake_name="automake-1.5";
170    else if (CheckVersion("automake-1.4 --version",Configuration.automake_version,Pkg_Version::MMVersion,true))
171       Configuration.automake_name="automake-1.4";
172 
173    if (CheckVersion("autoconf2.50 --version",Configuration.autoconf_version,Pkg_Version::MMVersion,true))
174       Configuration.autoconf_name="autoconf2.50";
175    else if (CheckVersion("autoconf --version",Configuration.autoconf_version,Pkg_Version::MMVersion,true))
176       Configuration.autoconf_name="autoconf";
177    else if (CheckVersion("autoconf2.13 --version",Configuration.autoconf_version,Pkg_Version::MMVersion,true))
178       Configuration.autoconf_name="autoconf2.13";
179 
180 //   if (Configuration.autoconf_version>=Pkg_Version(2,50,0))
181 //      Configuration.use_autoreconf=true;
182 
183    CheckVersion("gettext --version",Configuration.gettext_version,Pkg_Version::MMVersion,true);
184 
185    // Pkgconfig checks (Gnome 2)
186    if (Configuration.gnome2) {
187       if (!!Configuration.pc_version) {
188 	 CheckVersion("pkg-config --silence-errors --modversion gtk+-2.0",Configuration.gtk_version,Pkg_Version::Pkg_Config);
189 	 if (!CheckVersion("pkg-config --silence-errors --modversion gtkmm-2.4",Configuration.gtkmm_version,Pkg_Version::Pkg_Config))
190 	    CheckVersion("pkg-config --silence-errors --modversion gtkmm-2.0",Configuration.gtkmm_version,Pkg_Version::Pkg_Config);
191 	 CheckVersion("pkg-config --silence-errors --modversion libgnomemm-2.0",Configuration.libgnomemm_version,Pkg_Version::Pkg_Config);
192 	 CheckVersion("pkg-config --silence-errors --modversion libgnomeuimm-2.0",Configuration.libgnomeuimm_version,Pkg_Version::Pkg_Config);
193          CheckVersion("pkg-config --silence-errors --modversion libbonobomm-2.0",Configuration.libbonobomm_version,Pkg_Version::Pkg_Config);
194          CheckVersion("pkg-config --silence-errors --modversion libbonobouimm-2.0",Configuration.libbonobouimm_version,Pkg_Version::Pkg_Config);
195       }
196    }
197    else // old script checks
198    {  if (!Configuration.pc_version ||
199              !CheckVersion("pkg-config --silence-errors --modversion gtk+",Configuration.gtk_version,Pkg_Version::Pkg_Config))
200 	 CheckVersion("gtk-config --version",Configuration.gtk_version,Pkg_Version::Gtk_Config);
201        CheckVersion("gtkmm-config --version",Configuration.gtkmm_version,Pkg_Version::Gtkmm_Config);
202        CheckVersion("gnome-config --modversion gnomemm",Configuration.libgnomemm_version,Pkg_Version::Gnome_Config);
203    }
204 }
205 
206 #ifdef __MINGW32__
207 #define ONLY_UNIX(y,x)
208 #else
209 #define ONLY_UNIX(y,x) y,x
210 #endif
211 
ApplyProject(const Tag & t)212 static void ApplyProject(const Tag &t)
213 {
214    if (Configuration.main_filename.empty() && t.hasTag("program_name"))
215       Configuration.main_filename=t.getString("program_name","error");
216 
217    Configuration.source_directory="/"+t.getString("source_directory","src");
218    if (Configuration.source_directory[1]=='/')
219    {  std::cerr << "I can't handle an absolute source directory ("
220    	<< (Configuration.source_directory.c_str()+1) << ")\n";
221       exit(2);
222    }
223 
224    Configuration.destination_directory=t.getString("directory",".");
225    if (Configuration.destination_directory.empty())
226    	Configuration.destination_directory=".";
227    if (Configuration.destination_directory!=".")
228    {  std::cerr << "I'm confused about the directory to write to, \n"
229            "by default I'm writing relative to the .glade file.\n"
230            "\nPlease report this incident to christof@petig-baender.de for future fixing.\n\n";
231       Configuration.destination_directory=".";
232    }
233 
234    if (access(Configuration.destination_directory.c_str(),F_OK))
235       if (mkdir(Configuration.destination_directory.c_str() ONLY_UNIX(,0755)))
236       {  perror(Configuration.destination_directory.c_str());
237          exit(2);
238       }
239    const std::string srcdir(Configuration.destination_directory+Configuration.source_directory);
240    if (access(srcdir.c_str(),F_OK))
241       if (mkdir(srcdir.c_str() ONLY_UNIX(,0755)))
242       {  perror(srcdir.c_str());
243          exit(2);
244       }
245 
246    Configuration.pixmap_dir=t.getString("pixmaps_directory","pixmaps");
247    // XXX make pixmaps directory relative to source
248    if ((Configuration.pixmap_dir.empty() || Configuration.pixmap_dir[0]!='/'))
249       // blind guess, but better than nothing
250    {  if (Configuration.source_directory!="/" && Configuration.source_directory!="/.")
251          Configuration.pixmap_dir_relative_to_src="../"+Configuration.pixmap_dir;
252       else // src should be current (?)
253          Configuration.pixmap_dir_relative_to_src=Configuration.pixmap_dir;
254    }
255    else
256       Configuration.pixmap_dir_relative_to_src=Configuration.pixmap_dir;
257    if ((Configuration.pixmap_dir.empty() || Configuration.pixmap_dir[0]!='/'))
258    // relative
259    {  Configuration.pixmap_dir=Configuration.destination_directory+'/'+Configuration.pixmap_dir;
260    }
261 
262    // Latest glade (1.1.2) doesn't save "gnome+gettext_support" if it is true.
263    Configuration.gnome_support=t.getBool("gnome_support", Configuration.glade2);
264    Configuration.gettext_support=t.getBool("gettext_support", Configuration.glade2);
265    Configuration.widget_names=t.getBool("use_widget_names");
266 //   Configuration.output_main_file=t.getBool("output_main_file");
267 // ...
268    std::string podir(Configuration.destination_directory+"/po");
269    if (Configuration.destination_directory.empty()) podir="po";
270    if (Configuration.gettext_support && access(podir.c_str(),F_OK))
271       if (mkdir(podir.c_str() ONLY_UNIX(,0755)))
272       {  perror(podir.c_str());
273          exit(2);
274       }
275    Widget::const_contained_iterator::init();
276 
277 }
278 
279 struct xmloption
280 {  const char * const type;
281    const char * const tag;
282    const char * const description;
283    const char * const long_desc;
284    const char * const default_value;
285    const char * const values;
286 };
287 
show_options(std::ostream & o)288 static void show_options(std::ostream &o)
289 {  TagStream ts;
290    ts.setEncoding("UTF-8");
291 
292    Tag &options=ts.push_back(Tag("glademm-options"));
293 
294    Tag &project=options.push_back(Tag("project"));
295    static const struct xmloption pro_opts[] =
296    {  { "string", "program_name", "Name of the executable", 0, 0 ,0 },
297       { "string", "source_directory", "Source Directory", 0, "src" ,0 },
298       { "string", "pixmaps_directory", "Image Directory", 0, "pixmaps" ,0 },
299       { "bool", "gnome_support", "Gnome support", 0, "False" ,0 },
300       { "bool", "gettext_support", "Gettext support", 0, "False" ,0 },
301       { "bool", "use_widget_names", "Set widget names", 0, "True" ,0 },
302       { "bool", "use_widget_names", "Set widget names", 0, "True" ,0 },
303 //      { "bool", "sample_code", "Generate sample code", 0, "False" ,0 },
304 //      { "bool", "no_autoconf", "Generate raw Makefile", 0, "False" ,0 },
305       { "string", "gtk_version", "Target Gtk+ Version", 0, 0,0 },
306       { "string", "gtkmm_version", "Target Gtkmm Version", 0, 0,0 },
307 //      { "string", "gnomemm_version", "Target Gnomemm Version", 0, 0 ,0 },
308       { "bool", "libglade", "Generate libglademm skeleton", 0, "False" ,0 },
309       { "bool", "accelerators", "Project has accelerators", 0, "False" ,0 },
310       { "bool", "embed-images", "Embed images in the executable", 0, "True" ,0 },
311       { "bool", "baseclass", "Use a base class", 0, "False" ,0 },
312       { "string", "header-suffix", "Header file extension", 0, ".hh" ,0 },
313       { "string", "source-suffix", "Source file extension", 0, ".cc" ,0 },
314       { 0,0,0,0,0 ,0 },
315    };
316    for (const struct xmloption *i=pro_opts; i->type; ++i)
317    {  Tag &t=project.push_back(Tag(i->type));
318       t.setAttr("tag",i->tag);
319       t.setAttr("description",i->description);
320       if (i->long_desc) t.setAttr("long-description",i->long_desc);
321       if (i->default_value) t.setAttr("default",i->default_value);
322    }
323 
324    Tag &widget=options.push_back(Tag("widget"));
325    static const struct xmloption wdg_opts[] =
326    {  { "bool", CXX_SEPERATE_CLASS, "Separate Class", "Put Widget in a separate Class", "False" ,0 },
327       { "bool", CXX_SEPERATE_FILE, "Separate File", "Put Class in a separate File", "False" ,0 },
328       { "enum", "cxx_visibility", "Visibility", 0, "private" ,"private|protected|public" },
329       { 0,0,0,0,0 ,0 },
330    };
331    for (const struct xmloption *i=wdg_opts; i->type; ++i)
332    {  Tag &t=widget.push_back(Tag(i->type));
333       t.setAttr("tag",i->tag);
334       t.setAttr("description",i->description);
335       if (i->long_desc) t.setAttr("long-description",i->long_desc);
336       if (i->default_value) t.setAttr("default",i->default_value);
337       if (i->values) t.setAttr("values",i->values);
338    }
339 
340    Tag &signal=options.push_back(Tag("signal"));
341    static const struct xmloption sig_opts[] =
342    {  { "string", "data", "data", "Additional arguments to callback", "",0 },
343       { "string", "data_type", "type(s)", "Types of the arguments", "" ,0 },
344       { "bool", "connection", "save connection", "Save connection (SigC)", "False" ,0 },
345       { "bool", "const", "const callback", "Declare this callback as const (can not change class members)", "False" ,0 },
346 //      { "bool", "slot", "slot", "Save slot (SigC)", "False" ,0 },
347       { 0,0,0,0,0,0 },
348    };
349    for (const struct xmloption *i=sig_opts; i->type; ++i)
350    {  Tag &t=signal.push_back(Tag(i->type));
351       t.setAttr("tag",i->tag);
352       t.setAttr("description",i->description);
353       if (i->long_desc) t.setAttr("long-description",i->long_desc);
354       if (i->default_value) t.setAttr("default",i->default_value);
355    }
356 
357    ts.write(o);
358 }
359 
append_cs_args(const std::string & filename)360 static void append_cs_args(const std::string &filename)
361 {  try
362    {  TagStream ts(filename);
363       Tag &t=ts.getContent();
364       FOR_EACH_CONST_TAG(i,t)
365          Configuration.custom_signal_args.push_back(*i);
366    }
367    catch (...) {}
368 }
369 
read_custom_signal_args()370 static void read_custom_signal_args()
371 {  append_cs_args(".glademm-callbacks");
372    append_cs_args(getenv("HOME")+std::string("/.glademm-callbacks"));
373    append_cs_args(PREFIX "/share/glademm-callbacks");
374 }
375 
main(int argc,char ** argv)376 int main(int argc,char **argv)
377 {  int opt;
378    bool force_gnome2=false;
379    bool force_noaccel=false;
380    int depth=1;
381 
382    for (int i=0;i<argc;i++)
383    {  if (i) Configuration.commandline+=' ';
384       Configuration.commandline+=argv[i];
385    }
386    while ((opt=getopt_long(argc,argv,"d:m:h:c:Vgrs1AwlN",options,NULL))!=EOF)
387     switch(opt)
388    {  case 'd': Configuration.destination_directory=optarg;
389          break;
390       case 'm': Configuration.main_filename=optarg;
391          break;
392       case 'c': Configuration.source_suffix=optarg;
393       	 break;
394       case 'h': Configuration.header_suffix=optarg;
395          break;
396       case 'V': std::cout<< "glademm V" VERSION " (glade to Gtk-- converter)\n";
397          return 0;
398          break;
399       case 'v': Configuration.verbose++; break;
400       case 'g': Configuration.debug=true; ++depth;
401          break;
402       case 's': Configuration.sample_code=true;
403          break;
404       case 'r': Configuration.bare_bones=true;
405          break;
406       case 'A': Configuration.no_autoconf=true;
407          break;
408       case 'w': Configuration.lookup_table_compat=true;
409          Configuration.lookup_table=true;
410          break;
411       case LOOKUP_TABLE: Configuration.lookup_table=true;
412          break;
413       case 'l': Configuration.use_libglade=true;
414          Configuration.libglade_support=true;
415          break;
416       case LIBGLADE_OPTION: Configuration.libglade_support=true;
417          break;
418       case GTKVERSION:
419          {  Pkg_Version v;
420             if (parse_version(optarg,v,Pkg_Version::Command_Line))
421                Configuration.gtk_version=v;
422             else return 1;
423          }
424          break;
425       case GTKMMVERSION:
426          {  Pkg_Version v;
427             if (parse_version(optarg,v,Pkg_Version::Command_Line))
428                Configuration.gtkmm_version=v;
429             else return 1;
430          }
431          break;
432       case GTK_OSTREAM: Configuration.gtk_ostream=true;
433          break;
434       case FORCE_ACCEL: Configuration.has_accelerators=true;
435          break;
436       case FORCE_NOACCEL: Configuration.has_accelerators=false;
437          force_noaccel=true;
438          break;
439       case TEMPL_POSTFIX: Configuration.template_postfix=optarg;
440          break;
441       case OM_STRINGS: Configuration.optionmenu_strings=true;
442          break;
443       case OM_NO_CREATE_ENUMS: Configuration.optionmenu_create_enum=false;
444          break;
445       case OM_CREATE_ENUMS: Configuration.optionmenu_create_enum=true;
446          break;
447       case UPPERCASE_ENUMS: Configuration.uppercase_enums=true;
448          break;
449       case CASE_CONV: Configuration.do_case_conversion=true;
450          break;
451       case MIXEDCASE_DEFINES: Configuration.mixedcase_defines=true;
452          break;
453       case AUTOMAKE15: if (Configuration.automake_version<Pkg_Version(1,5,0))
454       	    Configuration.automake_version=Pkg_Version(1,5,0,Pkg_Version::Command_Line);
455          break;
456       case NOAUTORECONF: Configuration.use_autoreconf=false;
457          break;
458       case AUTORECONF: Configuration.use_autoreconf=true;
459          break;
460       case EMBED_PICS: Configuration.embed_images=true;
461          break;
462       case LOAD_PICS: Configuration.embed_images=false;
463          break;
464       case BASE_CLASS: Configuration.baseclass=true;
465          break;
466       case NON_VIRTUAL_CALLBACKS: Configuration.non_virtual_callbacks=true;
467          break;
468       case FLAG_GNOME2: Configuration.select_Gnome2();
469          force_gnome2=true;
470          break;
471       case SHOW_OPTIONS: show_options(std::cout);
472          exit(0);
473       case IMAGE_PROVIDER: Configuration.image_provider=optarg;
474          break;
475       case '?': usage: default:
476          std::cerr << "Since glade-- now honors glade's project settings, there should be no need\n"
477          	 "to pass any options. Simply create the code within glade.\n";
478          std::cerr << "\n"
479          	 "But if you plan to use experimental/compatibility features, the appropriate options are:\n"
480          	 "\t--[no]accelerators\tforce accelerator code support on/off\n"
481          	 "\t--gladeonly\tonly generate *_glade.?? files\n"
482          	 "\t--gtk[mm]version\tgenerate code for specific version\n"
483          	 "\t--gnome2\tgenerate gtk2/gnome2 code for a glade-1 project\n"
484          	 "\t--non-virtual-callbacks\trevert to old callback style\n"
485          	 "\t--template-postfix <extension>\tif you don't like 'foo.cc_new'\n"
486          	 "\t--load-images\tdo not embed images\n"
487 		 "\t--baseclass\tderive from base class (for class parameters)\n"
488          	 "\t--libglade\tgenerate code skeleton for a libglade-- application.\n"
489          	 "\t--libglade-option\tgenerate infrastructure for libglade without using it.\n"
490          	 "\t--version\tprints 'glademm V" VERSION "'\n";
491          return 1;
492    }
493    if (argc-optind!=1) goto usage;
494    Configuration.in_filename=argv[optind];
495    // there should be a way to do this with STL
496    {  char buf[10240];
497       strncpy(buf,argv[optind],sizeof buf);
498       buf[sizeof(buf)-1]=0;
499       char *s=strrchr(buf,'/');
500       if (s)
501       {  Configuration.in_filename=s+1;
502          *s=0;
503          if (*buf)
504          {  if (!chdir(buf)) std::cout << "Changed dir to "<<buf<<'\n';
505             else { perror(buf); exit(2); }
506          }
507       }
508    }
509 
510    // read custom signal arguments
511    TagStream::host_encoding="UTF-8"; // first default to gtk2
512 reopen:
513    TagStream ts(Configuration.in_filename);
514   try
515   {Tag &top=ts.getContent();
516    if (top.Type()=="glade-interface")
517    {  Configuration.glade2=true;
518       Configuration.select_Gnome2();
519       read_custom_signal_args(); // we should read them after the encoding is clear
520       TagStream ts2(Configuration.in_filename+'p');
521       try
522       {  const Tag &t=ts2.getContent();
523          if (t.Type()=="glade-project") ApplyProject(t);
524          else std::cerr << "Warning: strange project tag '" << t.Type() << "'\n";
525       }
526       catch (...)
527       {  std::cerr << "Warning: no or illegal project file.\n";
528          Tag t("glade-project","");
529          // Configuration.in_filename without path and .glade
530          std::string name=Configuration.in_filename;
531          std::string::size_type lastslash=name.rfind('/');
532          if (lastslash!=std::string::npos) name=name.substr(lastslash);
533          if (name.substr(name.size()-6,6)==".glade") name=name.substr(0,name.size()-6);
534          t.push_back(Tag("program_name",name));
535          t.push_back(Tag("gnome_support","false"));
536          t.push_back(Tag("gettext_support","false"));
537          ApplyProject(t);
538       }
539    }
540    else if (top.Type()=="glade-project")
541    {  Configuration.in_filename=Configuration.in_filename.substr
542    	(0,Configuration.in_filename.size()-1);
543       goto reopen;
544    }
545    else if (top.Type()=="GTK-Interface") // glade-1
546    {  if (!force_gnome2) Configuration.select_Gnome1();
547       if (TagStream::host_encoding=="UTF-8")
548       {  TagStream::host_encoding="ISO-8859-1";
549          goto reopen;
550       }
551       Tag::const_iterator t=top.begin();
552       read_custom_signal_args();
553       if (t->Type()!="project")
554       {  std::cerr << "Can't find project tag\n"; }
555       else ApplyProject(*t);
556    }
557    else
558    {  std::cerr << "Error: strange Tag '" << top.Type() << "'\n";
559       exit(1);
560    }
561 
562    if (Configuration.debug) top.debug(depth);
563    call_gtkmm_config();
564 
565    // Apply dependant preferences
566    if (Configuration.gettext_support)
567    {  if (Configuration.gtk_version>=Pkg_Version(2,4,0))
568          Configuration.gettext_source=Configuration::GT_GLIB;
569       else if (Configuration.gnome_support)
570          Configuration.gettext_source=Configuration::GT_GNOME;
571       else
572          Configuration.gettext_source=Configuration::GT_GNU;
573    }
574    if (Configuration.gettext_source==Configuration::GT_GNU
575    		&& !Configuration.gettext_version)
576    {  std::cerr << "gettext not found, disabled\n";
577       Configuration.gettext_support=false;
578       Configuration.gettext_source=Configuration::GT_NONE;
579    }
580 
581    if (!!Configuration.pc_version)
582       std::cout << "Found pkg-config version " << Configuration.pc_version
583       	 << '\n';
584    std::cout << "Generating code for gtk " << Configuration.gtk_version
585    	<< " (" << Configuration.gtk_version.getSource()
586    	<< "), gtkmm " << Configuration.gtkmm_version
587    	<< " (" << Configuration.gtkmm_version.getSource() << ')';
588    if (!!Configuration.libgnomemm_version)
589    {  std::cout << ", ";
590       if (!Configuration.gnome_support) std::cout << '[';
591       std::cout << "gnomemm " << Configuration.libgnomemm_version
592    	<< " (" << Configuration.libgnomemm_version.getSource()
593    	<< ')';
594       if (Configuration.Gnome2())
595       { if (!!Configuration.libgnomeuimm_version)
596          std::cout << "\n\tgnomeuimm " << Configuration.libgnomeuimm_version
597    	<< " (" << Configuration.libgnomeuimm_version.getSource()
598    	<< ')';
599    	if (!!Configuration.libbonobomm_version)
600          std::cout << " bonobomm " << Configuration.libbonobomm_version
601    	<< " (" << Configuration.libbonobomm_version.getSource()
602    	<< ')';
603    	if (!!Configuration.libbonobouimm_version)
604          std::cout << " bonobouimm " << Configuration.libbonobouimm_version
605    	<< " (" << Configuration.libbonobouimm_version.getSource()
606    	<< ')';
607       }
608       if (!Configuration.gnome_support) std::cout << ']';
609    }
610    std::cout << '\n';
611    if (!Configuration.no_autoconf)
612    { std::cout << "Using " << Configuration.autoconf_name << ' '
613    	<< Configuration.autoconf_version << ", "
614    	<< Configuration.automake_name << ' '
615    	<< Configuration.automake_version;
616      if (Configuration.gettext_source==Configuration::GT_GNU)
617      {  std::cout << ", gettext " << Configuration.gettext_version;
618      }
619      else if (Configuration.gettext_source==Configuration::GT_GNOME)
620      {  std::cout << ", gnome's gettext";
621      }
622      else if (Configuration.gettext_source==Configuration::GT_GLIB)
623      {  std::cout << ", glib's gettext";
624      }
625      std::cout << '\n';
626    }
627    if (Configuration.gnome_support && !Configuration.Gtkmm1())
628    {  std::cerr << "Gnome 2.x support is unmaintained - expect problems\n";
629    }
630 #if 0
631    if (Configuration.gettext_support && !Configuration.gnome_support
632    	&& Configuration.Gtkmm1())
633    {  std::cout << "Gettext support is not yet implemented without gnome.\n"
634         "Is there any standard way of accessing gettext?\n"
635    	"Disabling gettext for now.\n";
636       Configuration.gettext_support=false;
637    }
638 #endif
639 #ifndef __MINGW32__
640   {struct passwd *pwd=getpwuid(getuid());
641    struct utsname uts;
642    if (uname(&uts))
643    {  strcpy(uts.nodename,"(unknown)");
644 #ifdef HAS_DOMAINNAME
645       strcpy(uts.domainname,"(unknown)");
646 #endif
647    }
648    Configuration.author_email=std::string(pwd?pwd->pw_name:"(unknown)")
649    	+ "@" + uts.nodename
650 #ifdef HAS_DOMAINNAME
651         + "." + uts.domainname
652 #endif
653 	;
654 #ifdef HAS_REAL_NAME
655    Configuration.author_name= pwd->HAS_REAL_NAME;
656 #endif
657   }
658 #endif
659 
660    // now the generated project rejects to compile
661 //   if (Configuration.Gtkmm2())
662 //      std::cout << "WARNING: THIS PROGRAM WILL CRASH IF COMPILED WITH G++ 2.9x!!!\n";
663    if (force_noaccel && Configuration.has_accelerators) Configuration.has_accelerators=false;
664    Cxx *cxx=new Cxx(&top);
665    cxx->WriteTags();
666    if (Configuration.only_private_widgets)
667       std::cerr << "WARNING: All your widgets are declared as private members, so I made them all\n"
668          "\tpublic. Use \"visibilty\" to tell which widgets you need to access.\n";
669    delete cxx;
670    return 0;
671   }
672    catch (std::exception &e)
673    {  std::cerr << "Error "<< e.what()<<" loading .glade file, exiting.\n"; exit(1); }
674 }
675 
676 // ok, strictly this does not belong here ...
677 
operator <<(std::ostream & o,const Pkg_Version & v)678 std::ostream &operator<<(std::ostream &o, const Pkg_Version &v)
679 {  return o << v.mymajor << '.' << v.myminor << '.' << v.mymicro;
680 }
681 
operator <<(std::ostream & o,const Pkg_Version::Source s)682 std::ostream &operator<<(std::ostream &o, const Pkg_Version::Source s)
683 {  if (s==Pkg_Version::Not_Available) o << "n.a.";
684    else if (s==Pkg_Version::Unknown) o << "unknown";
685    else if (s==Pkg_Version::Glademm_Compile_Time) o << "compiled in";
686    else if (s==Pkg_Version::Command_Line) o << "specified";
687    else if (s==Pkg_Version::Gtk_Config) o << "gtk-config";
688    else if (s==Pkg_Version::Gtkmm_Config) o << "gtkmm-config";
689    else if (s==Pkg_Version::Gnome_Config) o << "gnome-config";
690    else if (s==Pkg_Version::Pkg_Config) o << "pkg-config";
691    else o << "<NULL>";
692    return o;
693 }
694