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