Reviewed by Chris Blumenberg.
[WebKit-https.git] / WebCore / khtml / html / html_formimpl.h
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2000 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2004 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  *
24  */
25 #ifndef HTML_FORMIMPL_H
26 #define HTML_FORMIMPL_H
27
28 #include "html/html_elementimpl.h"
29 #include "dom/html_element.h"
30 #include "html/html_miscimpl.h"
31
32 #include <qptrvector.h>
33 #include <qmemarray.h>
34
35 class KHTMLView;
36 class QTextCodec;
37
38 namespace khtml
39 {
40     class FormData;
41     class RenderFormElement;
42     class RenderTextArea;
43     class RenderSelect;
44     class RenderLineEdit;
45     class RenderRadioButton;
46     class RenderFileButton;
47 #if APPLE_CHANGES
48     class RenderSlider;
49 #endif
50 }
51
52 namespace DOM {
53
54 class DOMString;
55 class FormDataList;
56 class HTMLFormElement;
57 class HTMLGenericFormElementImpl;
58 class HTMLImageElementImpl;
59 class HTMLImageLoader;
60 class HTMLOptionElementImpl;
61 class HTMLOptionsCollectionImpl;
62
63 // -------------------------------------------------------------------------
64
65 class HTMLFormElementImpl : public HTMLElementImpl
66 {
67 public:
68     HTMLFormElementImpl(DocumentPtr *doc);
69     virtual ~HTMLFormElementImpl();
70
71     virtual Id id() const;
72
73     virtual void attach();
74     virtual void detach();
75
76     SharedPtr<HTMLCollectionImpl> elements();
77     long length() const;
78
79     DOMString enctype() const { return m_enctype; }
80     void setEnctype(const DOMString &);
81
82     DOMString boundary() const { return m_boundary; }
83     void setBoundary(const DOMString &);
84
85     bool autoComplete() const { return m_autocomplete; }
86
87     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
88
89     void radioClicked( HTMLGenericFormElementImpl *caller );
90
91     void registerFormElement(HTMLGenericFormElementImpl *);
92     void removeFormElement(HTMLGenericFormElementImpl *);
93     void makeFormElementDormant(HTMLGenericFormElementImpl *);
94     void registerImgElement(HTMLImageElementImpl *);
95     void removeImgElement(HTMLImageElementImpl *);
96
97     bool prepareSubmit();
98     void submit(bool activateSubmitButton = false);
99     void reset();
100
101     void setMalformed(bool malformed) { m_malformed = malformed; }
102     virtual bool isMalformed() { return m_malformed; }
103     
104     virtual bool isURLAttribute(AttributeImpl *attr) const;
105     
106     void submitClick();
107     bool formWouldHaveSecureSubmission(const DOMString &url);
108
109     DOMString name() const;
110     void setName(const DOMString &);
111
112     DOMString acceptCharset() const;
113     void setAcceptCharset(const DOMString &);
114
115     DOMString action() const;
116     void setAction(const DOMString &);
117
118     DOMString method() const;
119     void setMethod(const DOMString &);
120
121     DOMString target() const;
122     void setTarget(const DOMString &);
123
124     static void i18nData();
125
126     friend class HTMLFormElement;
127     friend class HTMLFormCollectionImpl;
128
129     HTMLCollectionImpl::CollectionInfo *collectionInfo;
130
131     QPtrVector<HTMLGenericFormElementImpl> formElements;
132     QPtrVector<HTMLGenericFormElementImpl> dormantFormElements;
133     QPtrVector<HTMLImageElementImpl> imgElements;
134     DOMString m_url;
135     DOMString m_target;
136     DOMString m_enctype;
137     DOMString m_boundary;
138     DOMString m_acceptcharset;
139     bool m_post : 1;
140     bool m_multipart : 1;
141     bool m_autocomplete : 1;
142     bool m_insubmit : 1;
143     bool m_doingsubmit : 1;
144     bool m_inreset : 1;
145     bool m_malformed : 1;
146
147  private:
148     void parseEnctype(const DOMString &);
149     bool formData(khtml::FormData &) const;
150
151     QString oldIdAttr;
152     QString oldNameAttr;
153 };
154
155 // -------------------------------------------------------------------------
156
157 class HTMLGenericFormElementImpl : public HTMLElementImpl
158 {
159     friend class HTMLFormElementImpl;
160     friend class khtml::RenderFormElement;
161
162 public:
163     HTMLGenericFormElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
164     virtual ~HTMLGenericFormElementImpl();
165
166     HTMLFormElementImpl *form() { return m_form; }
167
168     virtual DOMString type() const = 0;
169
170     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
171     virtual void attach();
172     virtual void insertedIntoDocument();
173     virtual void removedFromDocument();
174
175     virtual void reset() {}
176
177     void onSelect();
178     void onChange();
179
180     bool disabled() const;
181     void setDisabled(bool _disabled);
182
183     virtual bool isFocusable() const;
184     virtual bool isKeyboardFocusable() const;
185     virtual bool isMouseFocusable() const;
186     virtual bool isEnumeratable() const { return false; }
187
188     bool readOnly() const { return m_readOnly; }
189     void setReadOnly(bool _readOnly);
190
191     virtual void recalcStyle( StyleChange );
192
193     DOMString name() const;
194     void setName(const DOMString& name);
195
196     void setOverrideName(const DOMString& name);
197
198     virtual bool isGenericFormElement() const { return true; }
199
200     /*
201      * override in derived classes to get the encoded name=value pair
202      * for submitting
203      * return true for a successful control (see HTML4-17.13.2)
204      */
205     virtual bool appendFormData(FormDataList&, bool) { return false; }
206
207     virtual void defaultEventHandler(EventImpl *evt);
208     virtual bool isEditable();
209
210     virtual QString state();
211     QString findMatchingState(QStringList &states);
212
213     virtual bool isSuccessfulSubmitButton() const { return false; }
214     virtual bool isActivatedSubmit() const { return false; }
215     virtual void setActivatedSubmit(bool flag) { }
216
217     long tabIndex() const;
218     void setTabIndex(long);
219
220 protected:
221     HTMLFormElementImpl *getForm() const;
222
223     DOMString m_overrideName;
224     HTMLFormElementImpl *m_form;
225     bool m_disabled, m_readOnly;
226
227     bool m_inited : 1;
228     bool m_dormant : 1;
229 };
230
231 // -------------------------------------------------------------------------
232
233 class HTMLButtonElementImpl : public HTMLGenericFormElementImpl
234 {
235 public:
236     HTMLButtonElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
237
238     virtual ~HTMLButtonElementImpl();
239
240     enum typeEnum {
241         SUBMIT,
242         RESET,
243         BUTTON
244     };
245
246     virtual Id id() const;
247     DOMString type() const;
248
249     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
250     virtual void defaultEventHandler(EventImpl *evt);
251     virtual bool appendFormData(FormDataList&, bool);
252
253     virtual bool isSuccessfulSubmitButton() const;
254     virtual bool isActivatedSubmit() const;
255     virtual void setActivatedSubmit(bool flag);
256
257     virtual void click(bool sendMouseEvents);
258     virtual void accessKeyAction(bool sendToAnyElement);
259
260     DOMString accessKey() const;
261     void setAccessKey(const DOMString &);
262
263     DOMString value() const;
264     void setValue(const DOMString &);
265
266     void blur();
267     void focus();
268     
269 protected:
270     DOMString m_value;
271     DOMString m_currValue;
272     typeEnum  m_type : 2;
273     bool      m_dirty : 1;
274     bool      m_activeSubmit : 1;
275 };
276
277 // -------------------------------------------------------------------------
278
279 class HTMLFieldSetElementImpl : public HTMLGenericFormElementImpl
280 {
281 public:
282     HTMLFieldSetElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
283
284     virtual ~HTMLFieldSetElementImpl();
285
286     virtual Id id() const;
287     
288     virtual bool isFocusable() const;
289     
290     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
291
292     virtual DOMString type() const;
293 };
294
295 // -------------------------------------------------------------------------
296
297 class HTMLInputElementImpl : public HTMLGenericFormElementImpl
298 {
299     friend class khtml::RenderLineEdit;
300     friend class khtml::RenderRadioButton;
301     friend class khtml::RenderFileButton;
302
303 #if APPLE_CHANGES
304     friend class HTMLSelectElementImpl;
305     friend class khtml::RenderSlider;
306 #endif
307
308 public:
309     // do not change the order!
310     enum typeEnum {
311         TEXT,
312         PASSWORD,
313         ISINDEX,
314         CHECKBOX,
315         RADIO,
316         SUBMIT,
317         RESET,
318         FILE,
319         HIDDEN,
320         IMAGE,
321         BUTTON
322 #if APPLE_CHANGES
323         ,SEARCH,
324         RANGE
325 #endif
326     };
327
328     HTMLInputElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
329     virtual ~HTMLInputElementImpl();
330
331     virtual Id id() const;
332
333     virtual bool isEnumeratable() const { return inputType() != IMAGE; }
334
335     bool autoComplete() const { return m_autocomplete; }
336
337     bool checked() const { return m_checked; }
338     void setChecked(bool);
339     long maxLength() const { return m_maxLen; }
340     int size() const { return m_size; }
341     DOMString type() const;
342     void setType(const DOMString& t);
343
344     DOMString value() const;
345     void setValue(const DOMString &);
346
347     DOMString valueWithDefault() const;
348
349     void setValueFromRenderer(const DOMString &);
350     bool valueMatchesRenderer() const { return m_valueMatchesRenderer; }
351     void setValueMatchesRenderer() { m_valueMatchesRenderer = true; }
352
353     void blur();
354     void focus();
355
356     virtual bool maintainsState() { return m_type != PASSWORD; }
357     virtual QString state();
358     virtual void restoreState(QStringList &);
359
360     void select();
361     
362     virtual void click(bool sendMouseEvents = false);
363     virtual void accessKeyAction(bool sendToAnyElement);
364
365     virtual bool mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const;
366     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
367
368     virtual void attach();
369     virtual bool rendererIsNeeded(khtml::RenderStyle *);
370     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
371     virtual void detach();
372     virtual bool appendFormData(FormDataList&, bool);
373
374     virtual bool isSuccessfulSubmitButton() const;
375     virtual bool isActivatedSubmit() const;
376     virtual void setActivatedSubmit(bool flag);
377
378     typeEnum inputType() const { return m_type; }
379     virtual void reset();
380
381     // used in case input type=image was clicked.
382     int clickX() const { return xPos; }
383     int clickY() const { return yPos; }
384
385     virtual void defaultEventHandler(EventImpl *evt);
386     virtual bool isEditable();
387
388     DOMString altText() const;
389     
390     virtual bool isURLAttribute(AttributeImpl *attr) const;
391
392     long maxResults() const { return m_maxResults; }
393
394     DOMString defaultValue() const;
395     void setDefaultValue(const DOMString &);
396     
397     bool defaultChecked() const;
398     void setDefaultChecked(bool);
399
400     DOMString accept() const;
401     void setAccept(const DOMString &);
402
403     DOMString accessKey() const;
404     void setAccessKey(const DOMString &);
405
406     DOMString align() const;
407     void setAlign(const DOMString &);
408
409     DOMString alt() const;
410     void setAlt(const DOMString &);
411
412     DOMString sizeDOM() const; // FIXME: rename to size after renaming existing size attribute
413     void setSize(const DOMString &);
414
415     DOMString src() const;
416     void setSrc(const DOMString &);
417
418     void setMaxLength(long);
419
420     DOMString useMap() const;
421     void setUseMap(const DOMString &);
422
423 protected:
424     bool storesValueSeparateFromAttribute() const;
425
426     DOMString m_value;
427     int       xPos;
428     short     m_maxLen;
429     short     m_size;
430     short     yPos;
431
432     short     m_maxResults;
433
434     HTMLImageLoader* m_imageLoader;
435
436     typeEnum m_type : 4;
437     bool m_checked : 1;
438     bool m_defaultChecked : 1;
439     bool m_useDefaultChecked : 1;
440     bool m_haveType : 1;
441     bool m_activeSubmit : 1;
442     bool m_autocomplete : 1;
443     bool m_valueMatchesRenderer : 1;
444 };
445
446 // -------------------------------------------------------------------------
447
448 class HTMLLabelElementImpl : public HTMLElementImpl
449 {
450 public:
451     HTMLLabelElementImpl(DocumentPtr *doc);
452     virtual ~HTMLLabelElementImpl();
453
454     virtual bool isFocusable() const;
455     
456     virtual Id id() const;
457
458     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
459
460     virtual void accessKeyAction(bool sendToAnyElement);
461
462     /**
463      * the form element this label is associated to.
464      */
465     ElementImpl *formElement();
466
467     HTMLFormElementImpl *form();
468
469     DOMString accessKey() const;
470     void setAccessKey(const DOMString &);
471
472     DOMString htmlFor() const;
473     void setHtmlFor(const DOMString &);
474
475  private:
476     DOMString m_formElementID;
477 };
478
479 // -------------------------------------------------------------------------
480
481 class HTMLLegendElementImpl : public HTMLGenericFormElementImpl
482 {
483 public:
484     HTMLLegendElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
485     virtual ~HTMLLegendElementImpl();
486
487     virtual bool isFocusable() const;
488     
489     virtual Id id() const;
490     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
491
492     virtual DOMString type() const;
493
494     DOMString accessKey() const;
495     void setAccessKey(const DOMString &);
496
497     DOMString align() const;
498     void setAlign(const DOMString &);
499 };
500
501 // -------------------------------------------------------------------------
502
503 class HTMLSelectElementImpl : public HTMLGenericFormElementImpl
504 {
505     friend class khtml::RenderSelect;
506
507 public:
508     HTMLSelectElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
509     ~HTMLSelectElementImpl();
510
511     virtual Id id() const;
512     DOMString type() const;
513
514     virtual void recalcStyle( StyleChange );
515
516     long selectedIndex() const;
517     void setSelectedIndex( long index );
518
519     virtual bool isEnumeratable() const { return true; }
520
521     long length() const;
522
523     long minWidth() const { return m_minwidth; }
524
525     long size() const { return m_size; }
526
527     bool multiple() const { return m_multiple; }
528
529     void add ( HTMLElementImpl *element, HTMLElementImpl *before );
530     void remove ( long index );
531     void blur();
532     void focus();
533
534     DOMString value();
535     void setValue(const DOMString &);
536     
537     HTMLOptionsCollectionImpl *options();
538     SharedPtr<HTMLCollectionImpl> optionsHTMLCollection(); // FIXME: Remove this and migrate to options().
539
540     virtual bool maintainsState() { return true; }
541     virtual QString state();
542     virtual void restoreState(QStringList &);
543
544     virtual NodeImpl *insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode );
545     virtual NodeImpl *replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode );
546     virtual NodeImpl *removeChild ( NodeImpl *oldChild, int &exceptioncode );
547     virtual NodeImpl *appendChild ( NodeImpl *newChild, int &exceptioncode );
548     virtual NodeImpl *addChild( NodeImpl* newChild );
549
550     virtual void childrenChanged();
551
552     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
553
554     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
555     virtual bool appendFormData(FormDataList&, bool);
556
557     // get the actual listbox index of the optionIndexth option
558     int optionToListIndex(int optionIndex) const;
559     // reverse of optionToListIndex - get optionIndex from listboxIndex
560     int listToOptionIndex(int listIndex) const;
561
562     void setRecalcListItems();
563
564     QMemArray<HTMLGenericFormElementImpl*> listItems() const
565      {
566          if (m_recalcListItems) const_cast<HTMLSelectElementImpl*>(this)->recalcListItems();
567          return m_listItems;
568      }
569     virtual void reset();
570     void notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected);
571
572     virtual void defaultEventHandler(EventImpl *evt);
573     virtual void accessKeyAction(bool sendToAnyElement);
574
575     void setMultiple(bool);
576
577     void setSize(long);
578
579 private:
580     void recalcListItems();
581
582 protected:
583     mutable QMemArray<HTMLGenericFormElementImpl*> m_listItems;
584     HTMLOptionsCollectionImpl *m_options;
585     short m_minwidth;
586     short m_size;
587     bool m_multiple;
588     bool m_recalcListItems;
589 };
590
591 // -------------------------------------------------------------------------
592
593 class HTMLKeygenElementImpl : public HTMLSelectElementImpl
594 {
595 public:
596     HTMLKeygenElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
597
598     virtual Id id() const;
599
600     DOMString type() const;
601
602     // ### this is just a rough guess
603     virtual bool isEnumeratable() const { return false; }
604
605     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
606     virtual bool appendFormData(FormDataList&, bool);
607 protected:
608     AtomicString m_challenge;
609     AtomicString m_keyType;
610 };
611
612 // -------------------------------------------------------------------------
613
614 class HTMLOptGroupElementImpl : public HTMLGenericFormElementImpl
615 {
616 public:
617     HTMLOptGroupElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
618     virtual ~HTMLOptGroupElementImpl();
619
620     virtual Id id() const;
621     DOMString type() const;
622
623     virtual bool isFocusable() const;
624     
625     virtual NodeImpl *insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode );
626     virtual NodeImpl *replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode );
627     virtual NodeImpl *removeChild ( NodeImpl *oldChild, int &exceptioncode );
628     virtual NodeImpl *appendChild ( NodeImpl *newChild, int &exceptioncode );
629     virtual NodeImpl *addChild( NodeImpl* newChild );
630     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
631     void recalcSelectOptions();
632
633     DOMString label() const;
634     void setLabel(const DOMString &);
635 };
636
637
638 // ---------------------------------------------------------------------------
639
640 class HTMLOptionElementImpl : public HTMLGenericFormElementImpl
641 {
642     friend class khtml::RenderSelect;
643     friend class DOM::HTMLSelectElementImpl;
644
645 public:
646     HTMLOptionElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
647
648     virtual bool isFocusable() const;
649     
650     virtual Id id() const;
651     DOMString type() const;
652
653     DOMString text() const;
654     void setText(const DOMString &, int &exception);
655
656     long index() const;
657     void setIndex(long, int &exception);
658     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
659     DOMString value() const;
660     void setValue(const DOMString &);
661
662     bool selected() const { return m_selected; }
663     void setSelected(bool _selected);
664
665     HTMLSelectElementImpl *getSelect() const;
666
667     virtual void childrenChanged();
668
669     bool defaultSelected() const;
670     void setDefaultSelected( bool );
671
672     DOMString label() const;
673     void setLabel( const DOMString & );
674
675 protected:
676     DOMString m_value;
677     bool m_selected;
678 };
679
680
681 // -------------------------------------------------------------------------
682
683 class HTMLTextAreaElementImpl : public HTMLGenericFormElementImpl
684 {
685     friend class khtml::RenderTextArea;
686
687 public:
688     enum WrapMethod {
689         ta_NoWrap,
690         ta_Virtual,
691         ta_Physical
692     };
693
694     HTMLTextAreaElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
695     ~HTMLTextAreaElementImpl();
696
697     virtual Id id() const;
698
699     long cols() const { return m_cols; }
700
701     long rows() const { return m_rows; }
702
703     WrapMethod wrap() const { return m_wrap; }
704
705     virtual bool isEnumeratable() const { return true; }
706
707     DOMString type() const;
708
709     virtual bool maintainsState() { return true; }
710     virtual QString state();
711     virtual void restoreState(QStringList &);
712
713     void select (  );
714
715     virtual void childrenChanged();
716     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
717     virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
718     virtual void detach();
719     virtual bool appendFormData(FormDataList&, bool);
720     virtual void reset();
721     DOMString value();
722     void setValue(const DOMString &value);
723     DOMString defaultValue();
724     void setDefaultValue(const DOMString &value);
725     void blur();
726     void focus();
727
728     void invalidateValue() { m_valueIsValid = false; }
729     void updateValue();
730
731     bool valueMatchesRenderer() const { return m_valueMatchesRenderer; }
732     void setValueMatchesRenderer() { m_valueMatchesRenderer = true; }
733
734     virtual bool isEditable();
735     
736     virtual void accessKeyAction(bool sendToAnyElement);
737     
738     DOMString accessKey() const;
739     void setAccessKey(const DOMString &);
740
741     void setCols(long);
742
743     void setRows(long);
744
745 protected:
746     int m_rows;
747     int m_cols;
748     WrapMethod m_wrap;
749     QString m_value;
750     bool m_valueIsValid;
751     bool m_valueMatchesRenderer;
752 };
753
754 // -------------------------------------------------------------------------
755
756 class HTMLIsIndexElementImpl : public HTMLInputElementImpl
757 {
758 public:
759     HTMLIsIndexElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f = 0);
760
761     virtual Id id() const;
762     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
763
764     DOMString prompt() const;
765     void setPrompt(const DOMString &);
766
767 protected:
768     DOMString m_prompt;
769 };
770
771 // -------------------------------------------------------------------------
772
773 class HTMLOptionsCollectionImpl : public khtml::Shared<HTMLOptionsCollectionImpl>
774 {
775 public:
776     HTMLOptionsCollectionImpl(HTMLSelectElementImpl *impl) : m_select(impl) { }
777
778     unsigned long length() const;
779     void setLength(unsigned long);
780     NodeImpl *item(unsigned long index) const;
781     NodeImpl *namedItem(const DOMString &name) const;
782
783     void detach() { m_select = 0; }
784
785 private:
786     HTMLSelectElementImpl *m_select;
787 };
788
789 } //namespace
790
791 #endif