1 /** \file
2 * Parameters for extensions.
3 */
5 /*
6 * Authors:
7 * Ted Gould <ted@gould.cx>
8 *
9 * Copyright (C) 2005 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
19 #include <gtkmm/adjustment.h>
20 #include <gtkmm/box.h>
21 #include <gtkmm/spinbutton.h>
23 #include <glibmm/i18n.h>
25 #include "extension.h"
26 #include "prefs-utils.h"
28 #include "parameter.h"
30 /** \brief The root directory in the preferences database for extension
31 related parameters. */
32 #define PREF_DIR "extensions"
34 namespace Inkscape {
35 namespace Extension {
37 /** \brief A boolean parameter */
38 class ParamBool : public Parameter {
39 private:
40 /** \brief Internal value. */
41 bool _value;
42 public:
43 ParamBool(const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
44 /** \brief Returns \c _value */
45 bool get (const Inkscape::XML::Document * doc) { return _value; }
46 bool set (bool in, Inkscape::XML::Document * doc);
47 Gtk::Widget * get_widget(void);
48 Glib::ustring * string (void);
49 };
51 /** \brief Use the superclass' allocator and set the \c _value */
52 ParamBool::ParamBool (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
53 Parameter(name, guitext, ext), _value(false)
54 {
55 const char * defaultval = NULL;
56 if (sp_repr_children(xml) != NULL)
57 defaultval = sp_repr_children(xml)->content();
59 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
60 _value = true;
61 } else {
62 _value = false;
63 }
65 gchar * pref_name = this->pref_name();
66 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
67 g_free(pref_name);
69 return;
70 }
72 class ParamInt : public Parameter {
73 private:
74 /** \brief Internal value. */
75 int _value;
76 int _min;
77 int _max;
78 public:
79 ParamInt (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
80 /** \brief Returns \c _value */
81 int get (const Inkscape::XML::Document * doc) { return _value; }
82 int set (int in, Inkscape::XML::Document * doc);
83 int max (void) { return _max; }
84 int min (void) { return _min; }
85 Gtk::Widget * get_widget(void);
86 Glib::ustring * string (void);
87 };
89 /** \brief Use the superclass' allocator and set the \c _value */
90 ParamInt::ParamInt (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
91 Parameter(name, guitext, ext), _value(0), _min(0), _max(10)
92 {
93 const char * defaultval = NULL;
94 if (sp_repr_children(xml) != NULL)
95 defaultval = sp_repr_children(xml)->content();
96 if (defaultval != NULL) {
97 _value = atoi(defaultval);
98 }
100 const char * maxval = xml->attribute("max");
101 if (maxval != NULL)
102 _max = atoi(maxval);
104 const char * minval = xml->attribute("min");
105 if (minval != NULL)
106 _min = atoi(minval);
108 /* We're handling this by just killing both values */
109 if (_max < _min) {
110 _max = 10;
111 _min = 0;
112 }
114 gchar * pref_name = this->pref_name();
115 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
116 g_free(pref_name);
118 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
120 if (_value > _max) _value = _max;
121 if (_value < _min) _value = _min;
123 return;
124 }
126 class ParamFloat : public Parameter {
127 private:
128 /** \brief Internal value. */
129 float _value;
130 float _min;
131 float _max;
132 public:
133 ParamFloat (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
134 /** \brief Returns \c _value */
135 float get (const Inkscape::XML::Document * doc) { return _value; }
136 float set (float in, Inkscape::XML::Document * doc);
137 float max (void) { return _max; }
138 float min (void) { return _min; }
139 Gtk::Widget * get_widget(void);
140 Glib::ustring * string (void);
141 };
143 /** \brief Use the superclass' allocator and set the \c _value */
144 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
145 Parameter(name, guitext, ext), _value(0.0), _min(0.0), _max(10.0)
146 {
147 const char * defaultval = NULL;
148 if (sp_repr_children(xml) != NULL)
149 defaultval = sp_repr_children(xml)->content();
150 if (defaultval != NULL) {
151 _value = atof(defaultval);
152 }
154 const char * maxval = xml->attribute("max");
155 if (maxval != NULL)
156 _max = atof(maxval);
158 const char * minval = xml->attribute("min");
159 if (minval != NULL)
160 _min = atof(minval);
162 /* We're handling this by just killing both values */
163 if (_max < _min) {
164 _max = 10.0;
165 _min = 0.0;
166 }
168 gchar * pref_name = this->pref_name();
169 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
170 g_free(pref_name);
172 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
174 if (_value > _max) _value = _max;
175 if (_value < _min) _value = _min;
177 return;
178 }
180 class ParamString : public Parameter {
181 private:
182 /** \brief Internal value. This should point to a string that has
183 been allocated in memory. And should be free'd. */
184 gchar * _value;
185 public:
186 ParamString(const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
187 ~ParamString(void);
188 /** \brief Returns \c _value, with a \i const to protect it. */
189 const gchar * get (const Inkscape::XML::Document * doc) { return _value; }
190 const gchar * set (const gchar * in, Inkscape::XML::Document * doc);
191 Gtk::Widget * get_widget(void);
192 Glib::ustring * string (void);
193 };
195 /**
196 \return None
197 \brief This function creates a parameter that can be used later. This
198 is typically done in the creation of the extension and defined
199 in the XML file describing the extension (it's private so people
200 have to use the system) :)
201 \param in_repr The XML describing the parameter
203 This function first grabs all of the data out of the Repr and puts
204 it into local variables. Actually, these are just pointers, and the
205 data is not duplicated so we need to be careful with it. If there
206 isn't a name or a type in the XML, then no parameter is created as
207 the function just returns.
209 From this point on, we're pretty committed as we've allocated an
210 object and we're starting to fill it. The name is set first, and
211 is created with a strdup to actually allocate memory for it. Then
212 there is a case statement (roughly because strcmp requires 'ifs')
213 based on what type of parameter this is. Depending which type it
214 is, the value is interpreted differently, but they are relatively
215 straight forward. In all cases the value is set to the default
216 value from the XML and the type is set to the interpreted type.
217 */
218 Parameter *
219 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
220 {
221 const char * name;
222 const char * type;
223 const char * guitext;
225 name = in_repr->attribute("name");
226 type = in_repr->attribute("type");
227 guitext = in_repr->attribute("gui-text");
228 if (guitext == NULL)
229 guitext = in_repr->attribute("_gui-text");
231 /* In this case we just don't have enough information */
232 if (name == NULL || type == NULL) {
233 return NULL;
234 }
236 Parameter * param = NULL;
237 if (!strcmp(type, "boolean")) {
238 param = new ParamBool(name, guitext, in_ext, in_repr);
239 } else if (!strcmp(type, "int")) {
240 param = new ParamInt(name, guitext, in_ext, in_repr);
241 } else if (!strcmp(type, "float")) {
242 param = new ParamFloat(name, guitext, in_ext, in_repr);
243 } else if (!strcmp(type, "string")) {
244 param = new ParamString(name, guitext, in_ext, in_repr);
245 }
247 /* Note: param could equal NULL */
248 return param;
249 }
251 /** \brief A function to set the \c _value
252 \param in The value to set to
253 \param doc A document that should be used to set the value.
255 This function sets the internal value, but it also sets the value
256 in the preferences structure. To put it in the right place, \c PREF_DIR
257 and \c pref_name() are used.
258 */
259 bool
260 ParamBool::set (bool in, Inkscape::XML::Document * doc)
261 {
262 _value = in;
264 gchar * prefname = this->pref_name();
265 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
266 g_free(prefname);
268 return _value;
269 }
271 /** \brief A function to set the \c _value
272 \param in The value to set to
273 \param doc A document that should be used to set the value.
275 This function sets the internal value, but it also sets the value
276 in the preferences structure. To put it in the right place, \c PREF_DIR
277 and \c pref_name() are used.
278 */
279 int
280 ParamInt::set (int in, Inkscape::XML::Document * doc)
281 {
282 _value = in;
283 if (_value > _max) _value = _max;
284 if (_value < _min) _value = _min;
286 gchar * prefname = this->pref_name();
287 prefs_set_int_attribute(PREF_DIR, prefname, _value);
288 g_free(prefname);
290 return _value;
291 }
293 /** \brief A function to set the \c _value
294 \param in The value to set to
295 \param doc A document that should be used to set the value.
297 This function sets the internal value, but it also sets the value
298 in the preferences structure. To put it in the right place, \c PREF_DIR
299 and \c pref_name() are used.
300 */
301 float
302 ParamFloat::set (float in, Inkscape::XML::Document * doc)
303 {
304 _value = in;
305 if (_value > _max) _value = _max;
306 if (_value < _min) _value = _min;
308 gchar * prefname = this->pref_name();
309 prefs_set_double_attribute(PREF_DIR, prefname, _value);
310 g_free(prefname);
312 return _value;
313 }
315 /** \brief A function to set the \c _value
316 \param in The value to set to
317 \param doc A document that should be used to set the value.
319 This function sets the internal value, but it also sets the value
320 in the preferences structure. To put it in the right place, \c PREF_DIR
321 and \c pref_name() are used.
323 To copy the data into _value the old memory must be free'd first.
324 It is important to note that \c g_free handles \c NULL just fine. Then
325 the passed in value is duplicated using \c g_strdup().
326 */
327 const gchar *
328 ParamString::set (const gchar * in, Inkscape::XML::Document * doc)
329 {
330 if (in == NULL) return NULL; /* Can't have NULL string */
332 if (_value != NULL)
333 g_free(_value);
334 _value = g_strdup(in);
336 gchar * prefname = this->pref_name();
337 prefs_set_string_attribute(PREF_DIR, prefname, _value);
338 g_free(prefname);
340 return _value;
341 }
343 /** \brief Wrapper to cast to the object and use it's function. */
344 bool
345 Parameter::get_bool (const Inkscape::XML::Document * doc)
346 {
347 ParamBool * boolpntr;
348 boolpntr = dynamic_cast<ParamBool *>(this);
349 if (boolpntr == NULL)
350 throw Extension::param_wrong_type();
351 return boolpntr->get(doc);
352 }
354 /** \brief Wrapper to cast to the object and use it's function. */
355 int
356 Parameter::get_int (const Inkscape::XML::Document * doc)
357 {
358 ParamInt * intpntr;
359 intpntr = dynamic_cast<ParamInt *>(this);
360 if (intpntr == NULL)
361 throw Extension::param_wrong_type();
362 return intpntr->get(doc);
363 }
365 /** \brief Wrapper to cast to the object and use it's function. */
366 float
367 Parameter::get_float (const Inkscape::XML::Document * doc)
368 {
369 ParamFloat * floatpntr;
370 floatpntr = dynamic_cast<ParamFloat *>(this);
371 if (floatpntr == NULL)
372 throw Extension::param_wrong_type();
373 return floatpntr->get(doc);
374 }
376 /** \brief Wrapper to cast to the object and use it's function. */
377 const gchar *
378 Parameter::get_string (const Inkscape::XML::Document * doc)
379 {
380 ParamString * stringpntr;
381 stringpntr = dynamic_cast<ParamString *>(this);
382 if (stringpntr == NULL)
383 throw Extension::param_wrong_type();
384 return stringpntr->get(doc);
385 }
387 /** \brief Wrapper to cast to the object and use it's function. */
388 bool
389 Parameter::set_bool (bool in, Inkscape::XML::Document * doc)
390 {
391 ParamBool * boolpntr;
392 boolpntr = dynamic_cast<ParamBool *>(this);
393 if (boolpntr == NULL)
394 throw Extension::param_wrong_type();
395 return boolpntr->set(in, doc);
396 }
398 /** \brief Wrapper to cast to the object and use it's function. */
399 int
400 Parameter::set_int (int in, Inkscape::XML::Document * doc)
401 {
402 ParamInt * intpntr;
403 intpntr = dynamic_cast<ParamInt *>(this);
404 if (intpntr == NULL)
405 throw Extension::param_wrong_type();
406 return intpntr->set(in, doc);
407 }
409 /** \brief Wrapper to cast to the object and use it's function. */
410 float
411 Parameter::set_float (float in, Inkscape::XML::Document * doc)
412 {
413 ParamFloat * floatpntr;
414 floatpntr = dynamic_cast<ParamFloat *>(this);
415 if (floatpntr == NULL)
416 throw Extension::param_wrong_type();
417 return floatpntr->set(in, doc);
418 }
420 /** \brief Wrapper to cast to the object and use it's function. */
421 const gchar *
422 Parameter::set_string (const gchar * in, Inkscape::XML::Document * doc)
423 {
424 ParamString * stringpntr;
425 stringpntr = dynamic_cast<ParamString *>(this);
426 if (stringpntr == NULL)
427 throw Extension::param_wrong_type();
428 return stringpntr->set(in, doc);
429 }
431 /** \brief Initialize the object, to do that, copy the data. */
432 ParamString::ParamString (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
433 Parameter(name, guitext, ext), _value(NULL)
434 {
435 const char * defaultval = NULL;
436 if (sp_repr_children(xml) != NULL)
437 defaultval = sp_repr_children(xml)->content();
439 gchar * pref_name = this->pref_name();
440 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
441 g_free(pref_name);
443 if (paramval != NULL)
444 defaultval = paramval;
445 if (defaultval != NULL)
446 _value = g_strdup(defaultval);
448 return;
449 }
451 /** \brief Free the allocated data. */
452 ParamString::~ParamString(void)
453 {
454 g_free(_value);
455 }
457 /** \brief Oop, now that we need a parameter, we need it's name. */
458 Parameter::Parameter (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext) :
459 extension(ext), _name(NULL), _text(NULL)
460 {
461 _name = g_strdup(name);
462 if (guitext != NULL)
463 _text = g_strdup(guitext);
464 else
465 _text = g_strdup(name);
466 }
468 /** \brief Just free the allocated name. */
469 Parameter::~Parameter (void)
470 {
471 g_free(_name);
472 g_free(_text);
473 }
475 /** \brief Build the name to write the parameter from the extension's
476 ID and the name of this parameter. */
477 gchar *
478 Parameter::pref_name (void)
479 {
480 return g_strdup_printf("%s.%s", extension->get_id(), _name);
481 }
483 /** \brief Basically, if there is no widget pass a NULL. */
484 Gtk::Widget *
485 Parameter::get_widget (void)
486 {
487 return NULL;
488 }
490 /** \brief If I'm not sure which it is, just don't return a value. */
491 Glib::ustring *
492 Parameter::string (void)
493 {
494 Glib::ustring * mystring = new Glib::ustring("");
495 return mystring;
496 }
498 /** \brief A class to make an adjustment that uses Extension params */
499 class ParamFloatAdjustment : public Gtk::Adjustment {
500 /** The parameter to adjust */
501 ParamFloat * _pref;
502 public:
503 /** \brief Make the adjustment using an extension and the string
504 describing the parameter. */
505 ParamFloatAdjustment (ParamFloat * param) :
506 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
507 this->set_value(_pref->get(NULL) /* \todo fix */);
508 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
509 return;
510 };
512 void val_changed (void);
513 }; /* class ParamFloatAdjustment */
515 /** \brief A function to respond to the value_changed signal from the
516 adjustment.
518 This function just grabs the value from the adjustment and writes
519 it to the parameter. Very simple, but yet beautiful.
520 */
521 void
522 ParamFloatAdjustment::val_changed (void)
523 {
524 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
525 _pref->set(this->get_value(), NULL /* \todo fix */);
526 return;
527 }
529 /** \brief A class to make an adjustment that uses Extension params */
530 class ParamIntAdjustment : public Gtk::Adjustment {
531 /** The parameter to adjust */
532 ParamInt * _pref;
533 public:
534 /** \brief Make the adjustment using an extension and the string
535 describing the parameter. */
536 ParamIntAdjustment (ParamInt * param) :
537 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
538 this->set_value(_pref->get(NULL) /* \todo fix */);
539 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
540 return;
541 };
543 void val_changed (void);
544 }; /* class ParamIntAdjustment */
546 /** \brief A function to respond to the value_changed signal from the
547 adjustment.
549 This function just grabs the value from the adjustment and writes
550 it to the parameter. Very simple, but yet beautiful.
551 */
552 void
553 ParamIntAdjustment::val_changed (void)
554 {
555 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
556 _pref->set((int)this->get_value(), NULL /* \todo fix */);
557 return;
558 }
560 /**
561 \brief Creates a Float Adjustment for a float parameter
563 Builds a hbox with a label and a float adjustment in it.
564 */
565 Gtk::Widget *
566 ParamFloat::get_widget (void)
567 {
568 Gtk::HBox * hbox = new Gtk::HBox();
570 Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
571 label->show();
572 hbox->pack_start(*label, true, true);
574 ParamFloatAdjustment * fadjust = new ParamFloatAdjustment(this);
575 Gtk::SpinButton * spin = new Gtk::SpinButton(*fadjust, 0.1, 1);
576 spin->show();
577 hbox->pack_start(*spin, false, false);
579 hbox->show();
581 return dynamic_cast<Gtk::Widget *>(hbox);
582 }
584 /**
585 \brief Creates a Int Adjustment for a int parameter
587 Builds a hbox with a label and a int adjustment in it.
588 */
589 Gtk::Widget *
590 ParamInt::get_widget (void)
591 {
592 Gtk::HBox * hbox = new Gtk::HBox();
594 Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
595 label->show();
596 hbox->pack_start(*label, true, true);
598 ParamIntAdjustment * fadjust = new ParamIntAdjustment(this);
599 Gtk::SpinButton * spin = new Gtk::SpinButton(*fadjust, 1.0, 0);
600 spin->show();
601 hbox->pack_start(*spin, false, false);
603 hbox->show();
605 return dynamic_cast<Gtk::Widget *>(hbox);
606 }
608 /** \brief A check button which is Param aware. It works with the
609 parameter to change it's value as the check button changes
610 value. */
611 class ParamBoolCheckButton : public Gtk::CheckButton {
612 private:
613 /** \brief Param to change */
614 ParamBool * _pref;
615 public:
616 /** \brief Initialize the check button
617 \param param Which parameter to adjust on changing the check button
619 This function sets the value of the checkbox to be that of the
620 parameter, and then sets up a callback to \c on_toggle.
621 */
622 ParamBoolCheckButton (ParamBool * param) :
623 Gtk::CheckButton(), _pref(param) {
624 this->set_active(_pref->get(NULL) /**\todo fix */);
625 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
626 return;
627 }
628 void on_toggle (void);
629 };
631 /**
632 \brief A function to respond to the check box changing
634 Adjusts the value of the preference to match that in the check box.
635 */
636 void
637 ParamBoolCheckButton::on_toggle (void)
638 {
639 _pref->set(this->get_active(), NULL /**\todo fix this */);
640 return;
641 }
643 /**
644 \brief Creates a bool check button for a bool parameter
646 Builds a hbox with a label and a check button in it.
647 */
648 Gtk::Widget *
649 ParamBool::get_widget (void)
650 {
651 Gtk::HBox * hbox = new Gtk::HBox();
653 Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
654 label->show();
655 hbox->pack_start(*label, true, true);
657 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
658 checkbox->show();
659 hbox->pack_start(*checkbox, false, false);
661 hbox->show();
663 return dynamic_cast<Gtk::Widget *>(hbox);
664 }
666 /** \brief A special category of Gtk::Entry to handle string parameteres */
667 class ParamStringEntry : public Gtk::Entry {
668 private:
669 ParamString * _pref;
670 public:
671 /** \brief Build a string preference for the given parameter
672 \param pref Where to get the string from, and where to put it
673 when it changes.
674 */
675 ParamStringEntry (ParamString * pref) :
676 Gtk::Entry(), _pref(pref) {
677 if (_pref->get(NULL) != NULL)
678 this->set_text(Glib::ustring(_pref->get(NULL)));
679 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
680 };
681 void changed_text (void);
682 };
684 /** \brief Respond to the text box changing
686 This function responds to the box changing by grabbing the value
687 from the text box and putting it in the parameter.
688 */
689 void
690 ParamStringEntry::changed_text (void)
691 {
692 Glib::ustring data = this->get_text();
693 _pref->set(data.c_str(), NULL);
694 return;
695 }
697 /**
698 \brief Creates a text box for the string parameter
700 Builds a hbox with a label and a text box in it.
701 */
702 Gtk::Widget *
703 ParamString::get_widget (void)
704 {
705 Gtk::HBox * hbox = new Gtk::HBox();
707 Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
708 label->show();
709 hbox->pack_start(*label, true, true);
711 ParamStringEntry * textbox = new ParamStringEntry(this);
712 textbox->show();
713 hbox->pack_start(*textbox, false, false);
715 hbox->show();
717 return dynamic_cast<Gtk::Widget *>(hbox);
718 }
720 /** \brief Return 'true' or 'false' */
721 Glib::ustring *
722 ParamBool::string (void)
723 {
724 Glib::ustring * mystring;
726 if (_value)
727 mystring = new Glib::ustring("true");
728 else
729 mystring = new Glib::ustring("false");
731 return mystring;
732 }
734 /** \brief Return the value as a string */
735 Glib::ustring *
736 ParamInt::string (void)
737 {
738 char startstring[32];
739 sprintf(startstring, "%d", _value);
740 Glib::ustring * mystring = new Glib::ustring(startstring);
741 return mystring;
742 }
744 /** \brief Return the value as a string */
745 Glib::ustring *
746 ParamFloat::string (void)
747 {
748 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
749 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
750 Glib::ustring * mystring = new Glib::ustring(startstring);
751 return mystring;
752 }
754 /** \brief Return the value as a string */
755 Glib::ustring *
756 ParamString::string (void)
757 {
758 Glib::ustring * mystring = new Glib::ustring("");
759 *mystring += "\"";
760 *mystring += _value;
761 *mystring += "\"";
762 return mystring;
763 }
766 } /* namespace Extension */
767 } /* namespace Inkscape */
769 /*
770 Local Variables:
771 mode:c++
772 c-file-style:"stroustrup"
773 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
774 indent-tabs-mode:nil
775 fill-column:99
776 End:
777 */
778 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :