add new sigc++2 directory
[ardour.git] / libs / glibmm2 / glib / glibmm / optiongroup.cc
1 // Generated by gtkmmproc -- DO NOT MODIFY!
2
3
4 #include <glibmm/optiongroup.h>
5 #include <glibmm/private/optiongroup_p.h>
6
7 // -*- c++ -*-
8 /* $Id: optiongroup.ccg,v 1.15.4.3 2006/03/30 12:19:58 murrayc Exp $ */
9
10 /* Copyright (C) 2002 The gtkmm Development Team
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the Free
24  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #include <glibmm/optionentry.h>
28 #include <glibmm/optioncontext.h>
29 #include <glibmm/utility.h>
30 //#include <glibmm/containers.h>
31 #include <glib/gmem.h> // g_malloc
32 #include <glib/goption.h>
33
34 namespace Glib
35 {
36
37 namespace //anonymous
38 {
39
40 extern "C"
41 {
42
43 static gboolean g_callback_pre_parse(GOptionContext* context, GOptionGroup* /* group */, gpointer data, GError** /* TODO error */)
44 {
45   OptionContext cppContext(context, false /* take_ownership */);
46   //OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
47
48   OptionGroup* option_group = static_cast<OptionGroup*>(data);
49   if(option_group)
50     return option_group->on_pre_parse(cppContext, *option_group);
51   else
52     return false;
53 }
54
55 static gboolean g_callback_post_parse(GOptionContext* context, GOptionGroup* /* group */, gpointer data, GError** /* TODO error */)
56 {
57   OptionContext cppContext(context, false /* take_ownership */);
58   //OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
59
60   OptionGroup* option_group = static_cast<OptionGroup*>(data);
61   if(option_group)
62   {
63     return option_group->on_post_parse(cppContext, *option_group);
64   }
65   else
66     return false;
67 }
68
69 static void g_callback_error(GOptionContext* context, GOptionGroup* /* group */, gpointer data, GError** /* TODO error*/)
70 {
71   OptionContext cppContext(context, false /* take_ownership */);
72   //OptionGroup cppGroup(group); //Maybe this should be option_group.
73
74   OptionGroup* option_group = static_cast<OptionGroup*>(data);
75   if(option_group)
76     return option_group->on_error(cppContext, *option_group);
77 }
78
79 } /* extern "C" */
80
81 } //anonymous namespace
82
83
84 OptionGroup::OptionGroup(const Glib::ustring& name, const Glib::ustring& description, const Glib::ustring& help_description)
85 : gobject_( g_option_group_new(name.c_str(), description.c_str(), help_description.c_str(), this, 0 /* destroy_func */) ),
86   has_ownership_(true)
87 {
88   //Connect callbacks, so that derived classes can override the virtual methods:
89   g_option_group_set_parse_hooks(gobj(), &g_callback_pre_parse, &g_callback_post_parse);
90   g_option_group_set_error_hook(gobj(), &g_callback_error);
91 }
92
93 OptionGroup::OptionGroup(GOptionGroup* castitem)
94 : gobject_(castitem),
95   has_ownership_(true)
96 {
97   //Always takes ownership - never takes copy.
98 }
99
100
101 OptionGroup::~OptionGroup()
102 {
103   //Free any C types that were allocated during add_entry():
104   for(type_map_entries::iterator iter = map_entries_.begin(); iter != map_entries_.end(); ++iter)
105   {
106     CppOptionEntry& cpp_entry = iter->second;
107     cpp_entry.release_c_arg();
108   }
109
110   if(has_ownership_)
111   {
112     g_option_group_free(gobj());
113     gobject_ = 0;
114   }
115 }
116
117 void OptionGroup::add_entry(const OptionEntry& entry)
118 {
119   //It does not copy the entry, so it needs to live as long as the group.
120
121   //g_option_group_add_entries takes an array, with the last item in the array having a null long_name.
122   //Hopefully this will be properly documented eventually - see bug #
123
124   //Create a temporary array, just so we can give the correct thing to g_option_group_add_entries:
125   GOptionEntry array[2];
126   array[0] = *(entry.gobj()); //Copy contents.
127   GLIBMM_INITIALIZE_STRUCT(array[1], GOptionEntry);
128
129   g_option_group_add_entries(gobj(), array);
130 }
131
132 void OptionGroup::add_entry(const OptionEntry& entry, bool& arg)
133 {
134   add_entry_with_wrapper(entry, G_OPTION_ARG_NONE /* Actually a boolean on/off, depending on whether the argument name was given, without argument parameters. */, &arg);
135 }
136
137 void OptionGroup::add_entry(const OptionEntry& entry, int& arg)
138 {
139   add_entry_with_wrapper(entry, G_OPTION_ARG_INT, &arg);
140 }
141
142 void OptionGroup::add_entry(const OptionEntry& entry, Glib::ustring& arg)
143 {
144   add_entry_with_wrapper(entry, G_OPTION_ARG_STRING, &arg);
145 }
146
147 void OptionGroup::add_entry(const OptionEntry& entry, vecustrings& arg)
148 {
149   add_entry_with_wrapper(entry, G_OPTION_ARG_STRING_ARRAY, &arg);
150 }
151
152 void OptionGroup::add_entry_filename(const OptionEntry& entry, std::string& arg)
153 {
154   add_entry_with_wrapper(entry, G_OPTION_ARG_FILENAME, &arg);
155 }
156
157 void OptionGroup::add_entry_filename(const OptionEntry& entry, vecstrings& arg)
158 {
159   add_entry_with_wrapper(entry, G_OPTION_ARG_FILENAME_ARRAY, &arg);
160 }
161  
162 void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg arg_type, void* cpp_arg)
163 {
164   const Glib::ustring name = entry.get_long_name();
165   type_map_entries::iterator iterFind = map_entries_.find(name);
166   if( iterFind == map_entries_.end() ) //If we have not added this entry already
167   {
168     CppOptionEntry cppEntry;
169     cppEntry.carg_type_ = arg_type;
170     cppEntry.allocate_c_arg();
171     cppEntry.set_c_arg_default(cpp_arg);
172
173     cppEntry.cpparg_ = cpp_arg;
174
175     //Give the information to the C API:
176
177     cppEntry.entry_ = new OptionEntry(entry); //g_option_group_add_entry() does not take its own copy, so we must keep the instance alive. */
178     //cppEntry.entry_ is deleted in release_c_arg(), via the destructor.
179
180     cppEntry.entry_->gobj()->arg = arg_type;
181     cppEntry.entry_->gobj()->arg_data = cppEntry.carg_;
182
183     //Remember the C++/C mapping so that we can use it later:
184     map_entries_[name] = cppEntry;
185
186     add_entry(*(cppEntry.entry_));
187   }
188 }
189
190
191 bool OptionGroup::on_pre_parse(OptionContext& /* context */, OptionGroup& /* group */)
192 {
193   return true;
194 }
195
196 bool OptionGroup::on_post_parse(OptionContext& /* context */, OptionGroup& /* group */)
197 {
198   //Call this at the start of overrides.
199
200   //TODO: Maybe put this in the C callback:
201
202   //The C args have now been given values by GOption.
203   //Convert C values to C++ values:
204
205   for(type_map_entries::iterator iter = map_entries_.begin(); iter != map_entries_.end(); ++iter)
206   {
207     CppOptionEntry& cpp_entry = iter->second;
208     cpp_entry.convert_c_to_cpp();
209   }
210
211   return true;
212 }
213
214 void OptionGroup::on_error(OptionContext& /* context */, OptionGroup& /* group */)
215 {
216 }
217
218
219 OptionGroup::CppOptionEntry::CppOptionEntry()
220 : carg_type_(G_OPTION_ARG_NONE), carg_(0), cpparg_(0), entry_(0)
221 {}
222
223 void OptionGroup::CppOptionEntry::allocate_c_arg()
224 {
225   //Create an instance of the appropriate C type.
226   //This will be destroyed in the OptionGroup destructor.
227   //
228   //We must also call set_c_arg_default() to give these C types the specified defaults based on the C++-typed arguments.
229   switch(carg_type_)
230   {
231     case G_OPTION_ARG_STRING: //The char* will be for UTF8 strins.
232     case G_OPTION_ARG_FILENAME: //The char* will be for strings in the current locale's encoding.
233     {
234       char** typed_arg = new char*;
235       //The C code will allocate a char* and put it here, for us to g_free() later.
236       //Alternatively, set_c_arg_default() might allocate a char*, and the C code might or might not free and replace that.
237       *typed_arg = 0;
238       carg_ = typed_arg;
239
240       break;
241     }
242     case G_OPTION_ARG_INT:
243     {
244       int* typed_arg = new int;
245       *typed_arg = 0;
246       carg_ = typed_arg;
247
248       break;
249     }
250     case G_OPTION_ARG_STRING_ARRAY:
251     case G_OPTION_ARG_FILENAME_ARRAY:
252     {
253       char*** typed_arg = new char**;
254       *typed_arg = 0;
255       carg_ = typed_arg;
256
257       break;
258     }
259     case G_OPTION_ARG_NONE: /* Actually a boolean. */
260     {
261       gboolean* typed_arg = new gboolean;
262       *typed_arg = 0;
263       carg_ = typed_arg;
264
265       break;
266     }
267     default:
268     {
269       break;
270     }
271   }
272 }
273
274 void OptionGroup::CppOptionEntry::set_c_arg_default(void* cpp_arg)
275 {
276   switch(carg_type_)
277   {
278     case G_OPTION_ARG_INT:
279     {
280       *static_cast<int*>(carg_) = *static_cast<int*>(cpp_arg);
281       break;
282     }
283     case G_OPTION_ARG_NONE:
284     {
285       *static_cast<gboolean*>(carg_) = *static_cast<bool*>(cpp_arg);
286       break;
287     }
288     case G_OPTION_ARG_STRING:
289     {
290       Glib::ustring* typed_cpp_arg = static_cast<Glib::ustring*>(cpp_arg);
291       if(typed_cpp_arg && !typed_cpp_arg->empty())
292       {
293         const char** typed_c_arg = static_cast<const char**>(carg_);
294         *typed_c_arg = g_strdup(typed_cpp_arg->c_str()); //Freed in release_c_arg().
295       }
296       break;
297     }
298     case G_OPTION_ARG_FILENAME:
299     {
300       std::string* typed_cpp_arg = static_cast<std::string*>(cpp_arg);
301       if(typed_cpp_arg && !typed_cpp_arg->empty())
302       {
303         const char** typed_c_arg = static_cast<const char**>(carg_);
304         *typed_c_arg = g_strdup(typed_cpp_arg->c_str()); //Freed in release_c_arg().
305       }
306       break;
307     }
308     case G_OPTION_ARG_STRING_ARRAY:
309     {
310       std::vector<Glib::ustring>* typed_cpp_arg = static_cast<std::vector<Glib::ustring>*>(cpp_arg);
311       if(typed_cpp_arg)
312       {
313         std::vector<Glib::ustring>& vec = *typed_cpp_arg;
314         const char** array = static_cast<const char**>( g_malloc(sizeof(gchar*) * (vec.size() + 1)) );
315
316         for(std::vector<Glib::ustring>::size_type i = 0; i < vec.size(); ++i)
317         {
318           array[i] = g_strdup( vec[i].c_str() );
319         }
320
321         array[vec.size()] = 0;
322
323         const char*** typed_c_arg = static_cast<const char***>(carg_);
324         *typed_c_arg = array;
325       }
326       break;
327     }
328     case G_OPTION_ARG_FILENAME_ARRAY:
329     {
330       std::vector<std::string>* typed_cpp_arg = static_cast<std::vector<std::string>*>(cpp_arg);
331       if(typed_cpp_arg)
332       {
333         std::vector<std::string>& vec = *typed_cpp_arg;
334         const char** array = static_cast<const char**>( g_malloc(sizeof(gchar*) * (vec.size() + 1)) );
335
336         for(std::vector<Glib::ustring>::size_type i = 0; i < vec.size(); ++i)
337         {
338           array[i] = g_strdup( vec[i].c_str() );
339         }
340
341         array[vec.size()] = 0;
342
343         const char*** typed_c_arg = static_cast<const char***>(carg_);
344         *typed_c_arg = array;
345       }
346       break;
347     }
348     default:
349     {
350       break;
351     }
352   }
353 }
354
355 void OptionGroup::CppOptionEntry::release_c_arg()
356 {
357   //Delete the instances that we created in allocate_c_arg().
358   //Notice that we delete the type that we created, but not the value to which it points.
359   if(carg_)
360   {
361     switch(carg_type_)
362     {
363       case G_OPTION_ARG_STRING:
364       case G_OPTION_ARG_FILENAME:
365       {
366         char** typed_arg = static_cast<char**>(carg_);
367         g_free(*typed_arg); //Free the char* string at type_arg, which was allocated by the C code.
368         delete typed_arg; //Delete the char** that we allocated in allocate_c_arg;
369
370         break;
371       }
372       case G_OPTION_ARG_INT:
373       {
374         int* typed_arg = static_cast<int*>(carg_);
375         delete typed_arg;
376
377         break;
378       }
379       case G_OPTION_ARG_STRING_ARRAY:
380       case G_OPTION_ARG_FILENAME_ARRAY:
381       {
382         delete (char**)carg_;
383         break;
384       }
385       case G_OPTION_ARG_NONE: /* Actually a boolean. */
386       {
387         gboolean* typed_arg = static_cast<gboolean*>(carg_);
388         delete typed_arg;
389
390         break;
391       }
392       default:
393       {
394         /* TODO:
395         G_OPTION_ARG_CALLBACK,
396         */
397         break;
398       }
399     }
400
401     carg_ = 0;
402   }
403
404   if(entry_)
405     delete entry_;
406 }
407
408 void OptionGroup::CppOptionEntry::convert_c_to_cpp()
409 {
410   switch(carg_type_)
411   {
412     case G_OPTION_ARG_STRING:
413     {
414       char** typed_arg = static_cast<char**>(carg_);
415       Glib::ustring* typed_cpp_arg = static_cast<Glib::ustring*>(cpparg_);
416       if(typed_arg && typed_cpp_arg)
417       {
418         char* pch = *typed_arg;
419         (*typed_cpp_arg) = Glib::convert_const_gchar_ptr_to_ustring(pch);
420
421         break;
422       }
423     }
424     case G_OPTION_ARG_FILENAME:
425     {
426       char** typed_arg = static_cast<char**>(carg_);
427       std::string* typed_cpp_arg = static_cast<std::string*>(cpparg_);
428       if(typed_arg && typed_cpp_arg)
429       {
430         char* pch = *typed_arg;
431         (*typed_cpp_arg) = Glib::convert_const_gchar_ptr_to_stdstring(pch);
432
433         break;
434       }
435     }
436     case G_OPTION_ARG_INT:
437     {
438       *((int*)cpparg_) = *(static_cast<int*>(carg_));
439       break;
440     }
441         case G_OPTION_ARG_STRING_ARRAY:
442     {
443       char*** typed_arg = static_cast<char***>(carg_);
444       vecustrings* typed_cpp_arg = static_cast<vecustrings*>(cpparg_);
445       if(typed_arg && typed_cpp_arg)
446       {
447         typed_cpp_arg->clear();
448
449         //The C array seems to be null-terminated.
450         //Glib::StringArrayHandle array_handle(*typed_arg,  Glib::OWNERSHIP_NONE);
451
452         //The SUN Forte compiler complains about this:
453         // "optiongroup.cc", line 354: Error: Cannot assign Glib::ArrayHandle<Glib::ustring, 
454         // Glib::Container_Helpers::TypeTraits<Glib::ustring>> to std::vector<Glib::ustring> without 
455         // "std::vector<Glib::ustring>::operator=(const std::vector<Glib::ustring>&)";.
456         //
457         //(*typed_cpp_arg) = array_handle;
458         //
459         //And the Tru64 compiler does not even like us to instantiate the StringArrayHandle:
460         //
461         // cxx: Error: ../../glib/glibmm/containerhandle_shared.h, line 149: the operand
462         //     of a pointer dynamic_cast must be a pointer to a complete class type
463         //   return dynamic_cast<CppType>(Glib::wrap_auto(cobj, false /* take_copy */));
464
465         //for(Glib::StringArrayHandle::iterator iter = array_handle.begin(); iter != array_handle.end(); ++iter)
466         //{
467         //  typed_cpp_arg->push_back(*iter);
468         //}
469
470         //So we do this:
471
472         char** char_array_next = *typed_arg;
473         while(char_array_next && *char_array_next)
474         {
475           typed_cpp_arg->push_back(*char_array_next);
476           ++char_array_next;
477         }
478       }
479
480       break;
481     }
482     case G_OPTION_ARG_FILENAME_ARRAY:
483     {
484       char*** typed_arg = static_cast<char***>(carg_);
485       vecustrings* typed_cpp_arg = static_cast<vecustrings*>(cpparg_);
486       if(typed_arg && typed_cpp_arg)
487       { 
488         typed_cpp_arg->clear();
489
490         //See comments above about the SUN Forte and Tru64 compilers.
491
492         char** char_array_next = *typed_arg;
493         while(char_array_next && *char_array_next)
494         {
495           typed_cpp_arg->push_back(*char_array_next);
496           ++char_array_next;
497         }
498       }
499
500       break;
501     }
502     case G_OPTION_ARG_NONE: /* Actually a boolean. */
503     {
504       *(static_cast<bool*>(cpparg_)) = *(static_cast<gboolean*>(carg_));
505       break;
506     }
507     default:
508     {
509       /* TODO:
510       G_OPTION_ARG_CALLBACK,
511       */
512       break;
513     }
514   }
515
516
517 GOptionGroup* OptionGroup::gobj_give_ownership()
518 {
519   has_ownership_ = false;
520   return gobj();
521 }
522
523 } // namespace Glib
524
525
526 namespace
527 {
528 } // anonymous namespace
529
530
531 namespace Glib
532 {
533
534
535 void OptionGroup::set_translation_domain(const Glib::ustring& domain)
536 {
537 g_option_group_set_translation_domain(gobj(), domain.c_str()); 
538 }
539
540
541 } // namespace Glib
542
543