1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * xaml.cpp: xaml parser
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
30 #include "animation.h"
31 #include "bitmapimage.h"
33 #include "textblock.h"
41 #include "namescope.h"
48 #include "application.h"
49 #include "thickness.h"
50 #include "cornerradius.h"
51 #include "deployment.h"
53 #include "deepzoomimagetilesource.h"
56 class XamlElementInfo
;
57 class XamlElementInstance
;
60 class DefaultNamespace
;
63 class PrimitiveNamespace
;
64 class MCIgnorableNamespace
;
65 class XamlElementInfoNative
;
66 class XamlElementInstanceNative
;
67 class XamlElementInstanceValueType
;
68 class XamlElementInfoEnum
;
69 class XamlElementInstanceEnum
;
70 class XamlElementInfoManaged
;
71 class XamlElementInstanceManaged
;
72 class XamlElementInfoImportedManaged
;
73 class XamlElementInstanceTemplate
;
75 #define INTERNAL_IGNORABLE_ELEMENT "MoonlightInternalIgnorableElement"
77 #define IS_NULL_OR_EMPTY(str) (!str || (*str == 0))
79 static DefaultNamespace
*default_namespace
= NULL
;
80 static XNamespace
*x_namespace
= NULL
;
81 static XmlNamespace
*xml_namespace
= NULL
;
83 static const char* default_namespace_names
[] = {
84 "http://schemas.microsoft.com/winfx/2006/xaml/presentation",
85 "http://schemas.microsoft.com/client/2007",
86 "http://schemas.microsoft.com/xps/2005/06",
87 "http://schemas.microsoft.com/client/2007/deployment",
91 #define X_NAMESPACE_URI "http://schemas.microsoft.com/winfx/2006/xaml"
92 #define XML_NAMESPACE_URI "http://www.w3.org/XML/1998/namespace"
93 #define PRIMITIVE_NAMESPACE_URI "clr-namespace:System;assembly=mscorlib"
94 #define MC_IGNORABLE_NAMESPACE_URI "http://schemas.openxmlformats.org/markup-compatibility/2006"
97 static bool value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
);
98 static bool dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
);
99 static bool set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
);
100 static void dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
);
101 static void dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
102 static void value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
103 static bool element_begins_buffering (Type::Kind kind
);
104 static bool is_managed_kind (Type::Kind kind
);
105 static bool kind_requires_managed_load (Type::Kind kind
);
106 static bool is_legal_top_level_kind (Type::Kind kind
);
107 static Value
*lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
);
108 static void parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...);
109 static gboolean
namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
);
111 static XamlElementInfo
*create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
);
112 static void destroy_created_namespace (gpointer data
, gpointer user_data
);
115 BUFFER_MODE_TEMPLATE
,
120 class XamlNamespace
{
131 virtual ~XamlNamespace () { }
132 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
) = 0;
133 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
) = 0;
135 virtual const char* GetUri () = 0;
136 virtual const char* GetPrefix () = 0;
140 add_namespace_data (gpointer key
, gpointer value
, gpointer user_data
)
142 XamlNamespace
*ns
= (XamlNamespace
*) value
;
143 GHashTable
*table
= (GHashTable
*) user_data
;
145 if ((void *)ns
!= (void *)default_namespace
)
146 g_hash_table_insert (table
, g_strdup (ns
->GetPrefix ()), g_strdup (ns
->GetUri ()));
150 add_namespace_to_ignorable (gpointer key
, gpointer value
, gpointer user_data
)
152 char *prefix
= (char *) key
;
153 char *uri
= (char *) value
;
154 GString
*str
= (GString
*) user_data
;
156 g_string_append_printf (str
, "xmlns:%s=\"%s\" ", prefix
, uri
);
159 class XamlContextInternal
{
163 FrameworkTemplate
*template_parent
;
164 GHashTable
*imported_namespaces
;
166 XamlLoaderCallbacks callbacks
;
168 XamlContextInternal
*parent_context
;
170 DependencyObject
*source
;
172 XamlContextInternal (XamlLoaderCallbacks callbacks
, Value
*top_element
, FrameworkTemplate
*template_parent
, GHashTable
*namespaces
, GSList
*resources
, XamlContextInternal
*parent_context
)
174 this->callbacks
= callbacks
;
175 this->top_element
= new Value (*top_element
);
176 this->template_parent
= template_parent
;
177 this->surface
= template_parent
->GetSurface ();
178 this->resources
= resources
;
179 this->parent_context
= parent_context
;
181 if (this->callbacks
.create_gchandle
)
182 this->callbacks
.create_gchandle ();
183 imported_namespaces
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
184 g_hash_table_foreach (namespaces
, add_namespace_data
, imported_namespaces
);
188 ~XamlContextInternal ()
190 if (imported_namespaces
)
191 g_hash_table_destroy (imported_namespaces
);
193 g_slist_free (resources
);
197 char *CreateIgnorableTagOpen ()
199 GString
*str
= g_string_new ("<" INTERNAL_IGNORABLE_ELEMENT
" ");
200 g_hash_table_foreach (imported_namespaces
, add_namespace_to_ignorable
, str
);
202 str
= g_string_append (str
, ">");
204 char *res
= str
->str
;
205 g_string_free (str
, false);
210 char *CreateIgnorableTagClose ()
212 return g_strdup ("</" INTERNAL_IGNORABLE_ELEMENT
">");
215 bool LookupNamedItem (const char* name
, Value
**v
)
221 GSList
*walk
= resources
;
223 DependencyObject
*dob
= (DependencyObject
*)walk
->data
;
224 if (dob
->Is (Type::RESOURCE_DICTIONARY
))
225 *v
= lookup_resource_dictionary ((ResourceDictionary
*) walk
->data
, name
, &exists
);
226 else /* dob->Is (Type::FRAMEWORKELEMENT) */ {
227 ResourceDictionary
*rd
= dob
->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary();
228 *v
= lookup_resource_dictionary (rd
, name
, &exists
);
238 else if (!parent_context
)
241 return parent_context
->LookupNamedItem (name
, v
);
244 void SetTemplateBindingSource (DependencyObject
*source
)
246 this->source
= source
;
249 DependencyObject
* GetTemplateBindingSource ()
256 XamlContext::XamlContext (XamlContextInternal
*internal
)
258 this->internal
= internal
;
261 XamlContext::~XamlContext ()
267 XamlContext::SetTemplateBindingSource (DependencyObject
*source
)
269 internal
->SetTemplateBindingSource (source
);
273 XamlContext::GetTemplateBindingSource ()
275 return internal
->GetTemplateBindingSource ();
278 class XamlElementInfo
{
281 Type::Kind property_owner_kind
;
285 XamlElementInfo
*parent
;
289 XamlElementInfo (const char *xmlns
, const char *name
, Type::Kind kind
)
295 this->cdata_verbatim
= false;
297 this->property_owner_kind
= Type::INVALID
;
304 virtual Type::Kind
GetKind () { return kind
; }
306 virtual void SetPropertyOwnerKind (Type::Kind value
) { property_owner_kind
= value
; }
307 virtual Type::Kind
GetPropertyOwnerKind () { return property_owner_kind
; }
309 virtual const char *GetContentProperty (XamlParserInfo
*p
)
311 Type
*t
= Type::Find (kind
);
313 return t
->GetContentPropertyName ();
317 void SetIsCDataVerbatim (bool flag
)
319 cdata_verbatim
= flag
;
322 bool IsCDataVerbatim ()
324 return cdata_verbatim
;
327 virtual bool RequiresManagedSet () { return false; }
329 virtual XamlElementInstance
*CreateElementInstance (XamlParserInfo
*p
) = 0;
330 virtual XamlElementInstance
*CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
) = 0;
331 virtual XamlElementInstance
*CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) = 0;
335 struct DelayedProperty
{
340 DelayedProperty (const char *xmlns
, const char *name
, const Value
*value
)
342 this->xmlns
= g_strdup (xmlns
);
343 this->name
= g_strdup (name
);
344 this->value
= new Value (*value
);
356 free_property_list (GSList
*list
)
361 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
370 class XamlElementInstance
: public List::Node
{
373 DependencyObject
*item
;
376 GSList
*delayed_properties
;
379 const char *element_name
;
380 XamlElementInfo
*info
;
382 XamlElementInstance
*parent
;
392 bool requires_managed
;
396 GHashTable
*set_properties
;
398 XamlElementInstance (XamlElementInfo
*info
, const char* element_name
, ElementType type
, bool requires_managed
= false)
400 this->element_name
= element_name
;
401 this->set_properties
= NULL
;
402 this->element_type
= type
;
409 this->cleanup_value
= true;
410 this->requires_managed
= requires_managed
;
411 this->delayed_properties
= NULL
;
413 children
= new List ();
416 virtual ~XamlElementInstance ()
418 children
->Clear (true);
429 g_hash_table_destroy (set_properties
);
431 if (element_name
&& element_type
== PROPERTY
)
432 g_free ((void*) element_name
);
434 free_property_list (delayed_properties
);
437 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) = 0;
438 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
) = 0;
439 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) = 0;
440 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
) = 0;
442 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
443 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
446 char *GetKey () { return x_key
; }
447 char *GetName () { return x_name
; }
449 void SetName (XamlParserInfo
*p
, const char *name
)
451 this->x_name
= g_strdup (name
);
454 void SetKey (XamlParserInfo
*p
, const char *key
)
456 this->x_key
= g_strdup (key
);
459 virtual bool IsDependencyObject ()
464 virtual bool SetUnknownAttribute (XamlParserInfo
*p
, const char* name
, const char* value
);
466 void SetValue (Value
*v
)
468 if (value
&& cleanup_value
)
473 virtual Value
*GetAsValue ()
476 value
= new Value (item
);
481 virtual DependencyObject
*GetAsDependencyObject ()
486 virtual void SetDependencyObject (DependencyObject
*value
)
491 virtual void* GetManagedPointer ()
496 virtual Value
* GetParentPointer ()
498 XamlElementInstance
*walk
= parent
;
499 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
505 return walk
->GetAsValue ();
508 virtual bool IsTemplate ()
513 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
515 void SetDelayedProperties (XamlParserInfo
*p
);
517 void DelaySetProperty (const char *xmlns
, const char *name
, const Value
*value
)
519 DelayedProperty
*prop
= new DelayedProperty (xmlns
, name
, value
);
521 delayed_properties
= g_slist_append (delayed_properties
, prop
);
524 bool IsPropertySet (const char *name
)
529 return g_hash_table_lookup (set_properties
, name
) != NULL
;
532 void MarkPropertyAsSet (const char *name
)
535 set_properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
537 g_hash_table_insert (set_properties
, (void *) name
, GINT_TO_POINTER (TRUE
));
542 unref_xaml_element (gpointer data
, gpointer user_data
)
544 DependencyObject
* dob
= (DependencyObject
*) data
;
545 //printf ("unref_xaml_element: %i\n", dob->id);
550 class XamlParserInfo
{
554 const char *file_name
;
556 NameScope
*namescope
;
557 XamlElementInstance
*top_element
;
558 XamlNamespace
*current_namespace
;
559 XamlElementInstance
*current_element
;
560 const char *next_element
;
562 GHashTable
*namespace_map
;
566 bool implicit_default_namespace
;
568 ParserErrorEventArgs
*error_args
;
574 // If set, this is used to hydrate an existing object, not to create a new toplevel one
576 Value
*hydrate_expecting
;
579 char* buffer_until_element
;
581 BufferMode buffer_mode
;
583 bool validate_templates
;
586 GList
*created_elements
;
587 GList
*created_namespaces
;
588 const char* xml_buffer
;
589 int multi_buffer_offset
;
590 int xml_buffer_start_index
;
593 XamlParserInfo (XML_Parser parser
, const char *file_name
)
595 this->parser
= parser
;
596 this->file_name
= file_name
;
597 this->namescope
= new NameScope ();
600 current_namespace
= NULL
;
601 current_element
= NULL
;
602 cdata_content
= false;
604 implicit_default_namespace
= false;
607 created_elements
= NULL
;
608 created_namespaces
= NULL
;
609 hydrate_expecting
= NULL
;
612 buffer_until_element
= NULL
;
616 multi_buffer_offset
= 0;
617 validate_templates
= false;
619 namespace_map
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
622 void AddCreatedElement (DependencyObject
* element
)
624 // if we have a loader, set the surface and base resource location
626 element
->SetSurface (loader
->GetSurface());
627 element
->SetResourceBase (loader
->GetResourceBase());
630 // When instantiating a template, some elements are created which are not explicitly
631 // mentioned in the xaml. Therefore we need to keep walking up the tree until we find
632 // the last element which we set a value for Control::IsTemplateItem and propagate
634 XamlElementInstance
*instance
= current_element
;
636 if (!instance
->IsDependencyObject () || !instance
->GetAsDependencyObject ()) {
637 instance
= instance
->parent
;
640 if (!instance
->GetAsDependencyObject ()->ReadLocalValue (Control::IsTemplateItemProperty
)) {
641 instance
= instance
->parent
;
644 Control::SetIsTemplateItem (element
, Control::GetIsTemplateItem (instance
->GetAsDependencyObject ()));
648 if (instance
== NULL
)
649 Control::SetIsTemplateItem (element
, loader
->GetExpandingTemplate ());
651 if (Control::GetIsTemplateItem (element
))
652 NameScope::SetNameScope (element
, namescope
);
653 created_elements
= g_list_prepend (created_elements
, element
);
656 void AddCreatedNamespace (XamlNamespace
* ns
)
658 created_namespaces
= g_list_prepend (created_namespaces
, ns
);
661 void QueueBeginBuffering (char* buffer_until
, BufferMode mode
)
663 buffer_until_element
= buffer_until
;
667 xml_buffer_start_index
= -1;
670 void BeginBuffering ()
672 xml_buffer_start_index
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
673 buffer
= g_string_new (NULL
);
676 bool ShouldBeginBuffering ()
678 return InBufferingMode () && xml_buffer_start_index
== -1;
681 bool InBufferingMode ()
683 return buffer_until_element
!= NULL
;
686 void AppendCurrentXml ()
690 int pos
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
691 g_string_append_len (buffer
, xml_buffer
+ xml_buffer_start_index
, pos
- xml_buffer_start_index
);
699 buffer_until_element
= NULL
;
702 return g_strdup ("");
704 char* res
= buffer
->str
;
705 g_string_free (buffer
, FALSE
);
710 void SetXmlBuffer (const char* xml_buffer
)
712 if (InBufferingMode ())
715 if (this->xml_buffer
)
716 multi_buffer_offset
+= strlen (this->xml_buffer
);
718 this->xml_buffer
= xml_buffer
;
719 xml_buffer_start_index
= 0;
722 void ValidateTemplate (const char* buffer
, XamlContext
* context
, FrameworkTemplate
*binding_source
)
724 XamlLoader
*loader
= new XamlLoader (NULL
, buffer
, NULL
, context
);
727 context
->SetTemplateBindingSource (binding_source
);
729 loader
->SetImportDefaultXmlns (true);
732 Value
*result
= loader
->CreateFromStringWithError (buffer
, true, &dummy
, XamlLoader::IMPORT_DEFAULT_XMLNS
| XamlLoader::VALIDATE_TEMPLATES
, &error
);
737 if (error
.number
!= MoonError::NO_ERROR
) {
738 int line_number
= error
.line_number
+ XML_GetCurrentLineNumber (parser
);
739 error_args
= new ParserErrorEventArgs (error
.message
, file_name
, line_number
, error
.char_position
, error
.code
, NULL
, NULL
);
743 FrameworkTemplate
*GetTemplateParent (XamlElementInstance
*item
)
745 XamlElementInstance
*parent
= item
->parent
;
747 while (parent
&& !parent
->IsTemplate ())
748 parent
= parent
->parent
;
751 return (FrameworkTemplate
*) parent
->GetManagedPointer ();
756 XamlContext
*context
= loader
->GetContext ();
760 return context
->internal
->template_parent
;
763 Value
*GetTopElementPtr ()
765 XamlContext
*context
= loader
->GetContext ();
767 return context
->internal
->top_element
;
770 return top_element
->GetAsValue ();
777 created_elements
= g_list_reverse (created_elements
);
778 g_list_foreach (created_elements
, unref_xaml_element
, NULL
);
779 g_list_free (created_elements
);
781 g_list_foreach (created_namespaces
, destroy_created_namespace
, NULL
);
782 g_list_free (created_namespaces
);
784 g_hash_table_destroy (namespace_map
);
787 g_string_free (cdata
, TRUE
);
797 class XamlElementInfoNative
: public XamlElementInfo
{
801 XamlElementInfoNative (Type
*t
) : XamlElementInfo (NULL
, t
->GetName (), t
->GetKind ())
811 const char* GetName ()
813 return type
->GetName ();
816 const char* GetContentProperty (XamlParserInfo
*p
);
818 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
819 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
820 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
824 class XamlElementInstanceNative
: public XamlElementInstance
{
825 XamlElementInfoNative
*element_info
;
826 XamlParserInfo
*parser_info
;
829 XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true);
831 virtual DependencyObject
*CreateItem ();
833 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
835 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
836 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
837 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
838 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
842 class XamlElementInstanceValueType
: public XamlElementInstance
{
843 XamlElementInfoNative
*element_info
;
844 XamlParserInfo
*parser_info
;
847 XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
);
849 virtual bool IsDependencyObject ()
854 virtual Value
*GetAsValue ()
857 // we are an empty element (e.g. <sys:String></sys:String>). do type specific magic here.
858 CreateValueItemFromString ("");
864 bool CreateValueItemFromString (const char* str
);
866 // A Value type doesn't really support anything. It's just here so people can do <SolidColorBrush.Color><Color>#FF00FF</Color></SolidColorBrush.Color>
867 virtual DependencyObject
*CreateItem () { return NULL
; }
868 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
869 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
870 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
871 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
873 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
874 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateValueItemFromString (value
); }
877 class XamlElementInfoEnum
: public XamlElementInfo
{
879 XamlElementInfoEnum (const char *name
) : XamlElementInfo (NULL
, name
, Type::INT32
)
883 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
884 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
885 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) { return NULL
; }
888 class XamlElementInstanceEnum
: public XamlElementInstance
{
891 XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
);
893 virtual bool IsDependencyObject ()
898 virtual Value
*GetAsValue ()
903 bool CreateEnumFromString (const char* str
);
905 // An enum type doesn't really support anything. It's just here so people can do <Visibility>Visible</Visibility>
906 virtual DependencyObject
*CreateItem () { return NULL
; }
907 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
908 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
909 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
910 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
912 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
913 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateEnumFromString (value
); }
916 class XamlElementInstanceTemplate
: public XamlElementInstanceNative
{
918 XamlElementInstanceTemplate (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true)
919 : XamlElementInstanceNative (element_info
, parser_info
, name
, type
, create_item
)
923 virtual bool IsTemplate ()
930 class DefaultNamespace
: public XamlNamespace
{
932 DefaultNamespace () { }
934 virtual ~DefaultNamespace () { }
936 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
938 Type
* t
= Type::Find (el
, false);
939 if (t
&& !kind_requires_managed_load (t
->GetKind ()))
940 return new XamlElementInfoNative (t
);
942 if (enums_is_enum_name (el
))
943 return new XamlElementInfoEnum (g_strdup (el
));
945 XamlElementInfo
* managed_element
= create_element_info_from_imported_managed_type (p
, el
, attr
, create
);
947 return managed_element
;
953 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
958 virtual const char* GetUri () { return "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; }
959 virtual const char* GetPrefix () { return ""; }
962 class XmlNamespace
: public XamlNamespace
{
966 virtual ~XmlNamespace () { }
968 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
973 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
975 if (!strcmp ("lang", attr
)) {
976 if (item
->IsDependencyObject ()) {
977 DependencyObject
*dob
= item
->GetAsDependencyObject ();
978 if (dob
->Is(Type::FRAMEWORKELEMENT
)) {
979 ((FrameworkElement
*)dob
)->SetLanguage (value
);
988 virtual const char* GetUri () { return "http://www.w3.org/XML/1998/namespace"; }
989 virtual const char* GetPrefix () { return "xml"; }
992 class XNamespace
: public XamlNamespace
{
996 virtual ~XNamespace () { }
998 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1003 virtual char *FindTypeName (const char **attr
, char **xmlns
)
1010 for (int i
= 0; attr
[i
]; i
+= 2) {
1011 const char *ns
= strchr (attr
[i
], '|');
1015 if (strncmp (GetUri (), attr
[i
], ns
- attr
[i
]) || strcmp ("Class", ns
+ 1))
1018 ns
= strchr (attr
[i
+ 1], ';');
1020 *xmlns
= g_strdup ("");
1021 res
= g_strdup (attr
[i
+ 1]);
1023 *xmlns
= g_strdup (ns
+ 1);
1024 res
= g_strndup (attr
[i
+ 1], attr
[i
+ 1] - ns
);
1031 bool IsParentResourceDictionary (XamlElementInstance
*parent
)
1036 return Type::IsSubclassOf (parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
);
1039 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1041 if (!strcmp ("Name", attr
)) {
1043 // Causes breakage in airlines
1044 // Maybe x:Name overwrites but Name does not?
1046 // if (p->namescope->FindName (value)) {
1047 // parser_error (p, p->current_element->element_name, "x:Name", 2028, "The name already exists in the tree: %s.", value);
1052 if (IsParentResourceDictionary (p
->current_element
)) {
1053 if (item
->GetKey ()) {
1054 // XXX don't know the proper values here...
1055 parser_error (p
, item
->element_name
, NULL
, 2028,
1056 "The name already exists in the tree: %s.", value
);
1061 if (item
->GetName ()) {
1062 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
1066 item
->SetName (p
, value
);
1068 if (item
->IsDependencyObject ()) {
1069 NameScope
*scope
= p
->namescope
;
1070 if (!item
->GetAsDependencyObject ()->SetName (value
, scope
)) {
1071 if (IsParentResourceDictionary (p
->current_element
)) {
1072 // FIXME: inside of a resource dictionary this has an extremly
1073 // strange behavior. this isn't exactly right, since not only
1074 // does the exception get swallowed, but the name seems to also
1078 parser_error (p
, item
->element_name
, NULL
, 2028,
1079 "The name already exists in the tree: %s.", value
);
1089 if (!strcmp ("Key", attr
)) {
1090 if (item
->GetKey () && IsParentResourceDictionary (p
->current_element
) && !Type::IsSubclassOf (item
->info
->GetKind (), Type::STORYBOARD
)) {
1091 // XXX don't know the proper values here...
1092 parser_error (p
, item
->element_name
, NULL
, 2028,
1093 "The name already exists in the tree: %s.", value
);
1096 item
->SetKey (p
, value
);
1100 if (!strcmp ("Class", attr
)) {
1101 if (!is_legal_top_level_kind (item
->info
->GetKind ())) {
1102 // XXX don't know the proper values here...
1103 parser_error (p
, item
->element_name
, attr
, -1,
1104 "Cannot specify x:Class type '%s' on value type element (%s).", value
, item
->element_name
);
1108 if (p
->top_element
!= item
) {
1109 // HAH: what a useless error message
1110 parser_error (p
, item
->element_name
, attr
, 2012,
1111 "Unknown attribute %s on element %s.", attr
, item
->element_name
);
1115 // While hydrating, we do not need to create the toplevel class, its created already
1119 parser_error (p
, item
->element_name
, attr
, 4005,
1120 "Cannot specify x:Class in xaml files outside of a xap.");
1128 virtual const char* GetUri () { return X_NAMESPACE_URI
; }
1129 virtual const char* GetPrefix () { return "x"; }
1133 class PrimitiveNamespace
: public XamlNamespace
{
1140 PrimitiveNamespace (char *prefix
)
1142 this->prefix
= prefix
;
1145 virtual ~PrimitiveNamespace ()
1151 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1153 if (!strcmp ("String", el
)) {
1154 Type
* t
= Type::Find (Type::STRING
);
1155 // it's not as easy in this case, because primitive clr strings require that the
1156 // character data be read in verbatim, including all whitespace.
1157 XamlElementInfo
*info
= new XamlElementInfoNative (t
);
1158 info
->SetIsCDataVerbatim (true);
1160 } else if (!strcmp ("Int32", el
)) {
1161 Type
* t
= Type::Find (Type::INT32
);
1162 return new XamlElementInfoNative (t
);
1163 } else if (!strcmp ("Double", el
)) {
1164 Type
* t
= Type::Find (Type::DOUBLE
);
1165 return new XamlElementInfoNative (t
);
1166 } else if (!strcmp ("Boolean", el
)) {
1167 Type
* t
= Type::Find (Type::BOOL
);
1168 return new XamlElementInfoNative (t
);
1169 } else if (!strcmp ("TimeSpan", el
)) {
1170 Type
* t
= Type::Find (Type::TIMESPAN
);
1171 return new XamlElementInfoNative (t
);
1177 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1182 virtual const char* GetUri () { return PRIMITIVE_NAMESPACE_URI
; }
1183 virtual const char* GetPrefix () { return prefix
; }
1187 class MCIgnorableNamespace
: public XamlNamespace
{
1193 MCIgnorableNamespace (char *prefix
)
1195 this->prefix
= prefix
;
1198 virtual ~MCIgnorableNamespace ()
1204 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1209 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1211 if (!strcmp ("Ignorable", attr
)) {
1212 const char *start
= value
;
1214 const char *space
= strchr (start
, ' ');
1217 prefix
= g_strndup (start
, space
- start
);
1220 prefix
= g_strdup (start
);
1224 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1226 ns
->is_ignored
= true;
1236 virtual const char* GetUri () { return MC_IGNORABLE_NAMESPACE_URI
; }
1237 virtual const char* GetPrefix () { return prefix
; }
1242 destroy_created_namespace (gpointer data
, gpointer user_data
)
1244 XamlNamespace
* ns
= (XamlNamespace
*) data
;
1249 class XamlElementInfoManaged
: public XamlElementInfo
{
1251 XamlElementInfoManaged (const char *xmlns
, const char *name
, XamlElementInfo
*parent
, Type::Kind dependency_type
, Value
*obj
) : XamlElementInfo (xmlns
, name
, dependency_type
)
1258 const char* GetName () { return name
; }
1260 const char* GetContentProperty (XamlParserInfo
*p
);
1262 virtual bool RequiresManagedSet () { return true; }
1264 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1265 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1266 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1270 class XamlElementInstanceManaged
: public XamlElementInstance
{
1272 XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
);
1274 virtual bool IsDependencyObject ()
1276 return is_dependency_object
;
1279 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
1280 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
1281 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
1282 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
1284 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
1285 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
1287 virtual void* GetManagedPointer ();
1288 virtual Value
* GetParentPointer ();
1290 bool is_dependency_object
;
1294 class XamlElementInfoImportedManaged
: public XamlElementInfoManaged
{
1296 XamlElementInfoImportedManaged (const char *name
, XamlElementInfo
*parent
, Value
*obj
) : XamlElementInfoManaged (NULL
, name
, parent
, obj
->GetKind (), obj
)
1300 const char* GetContentProperty (XamlParserInfo
*p
);
1302 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1303 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1304 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1309 class ManagedNamespace
: public XamlNamespace
{
1314 ManagedNamespace (char *xmlns
, char *prefix
)
1316 this->xmlns
= xmlns
;
1317 this->prefix
= prefix
;
1320 virtual ~ManagedNamespace ()
1326 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1328 char* type_name
= NULL
;
1329 char* type_xmlns
= NULL
;
1330 const char* use_xmlns
= xmlns
;
1336 // We might have an x:Class attribute specified, so we need to use that for the
1337 // type_name that we pass to LookupObject
1338 if (strcmp ("Application", el
)) {
1339 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
1342 use_xmlns
= type_xmlns
;
1344 if (!p
->hydrating
) {
1345 parser_error (p
, el
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
1352 Value
*value
= new Value ();
1353 if (!p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), p
->current_element
? p
->current_element
->GetAsValue () : NULL
, use_xmlns
, el
, create
, false, value
)) {
1354 parser_error (p
, el
, NULL
, 2007, "Unable to resolve managed type %s.", el
);
1359 g_free (type_xmlns
);
1363 if (p
->hydrate_expecting
) {
1365 // If we are hydrating a top level managed object, use the Value* passed
1366 // to Hydrate as our value
1369 value
= p
->hydrate_expecting
;
1373 XamlElementInfoManaged
*info
= new XamlElementInfoManaged (xmlns
, g_strdup (el
), NULL
, value
->GetKind (), value
);
1377 g_free (type_xmlns
);
1381 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1387 Value v
= Value (value
);
1388 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), xmlns
, attr
, &v
, NULL
);
1394 virtual const char* GetUri () { return xmlns
; }
1395 virtual const char* GetPrefix () { return prefix
; }
1399 XamlLoader::LookupObject (void *p
, Value
*top_level
, Value
*parent
, const char* xmlns
, const char* type_name
, bool create
, bool is_property
, Value
*value
)
1401 if (callbacks
.lookup_object
) {
1402 if (!vm_loaded
&& !LoadVM ())
1405 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1406 bool res
= callbacks
.lookup_object (&data
, parent
, xmlns
, type_name
, create
, is_property
, value
, &error
);
1414 XamlLoader::GetContentPropertyName (void *p
, Value
*top_level
, Value
*object
)
1416 if (callbacks
.get_content_property_name
) {
1418 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1419 return callbacks
.get_content_property_name (&data
, object
, &error
);
1425 XamlLoader::SetProperty (void *p
, Value
*top_level
, const char* xmlns
, Value
*target
, void *target_data
, Value
*target_parent
, const char* prop_xmlns
, const char *name
, Value
*value
, void* value_data
, int flags
)
1427 if (callbacks
.set_property
) {
1429 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
, flags
);
1430 bool res
= callbacks
.set_property (&data
, xmlns
, target
, target_data
, target_parent
, prop_xmlns
, name
, value
, value_data
, &error
);
1432 if (error
.number
!= MoonError::NO_ERROR
) {
1433 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) target_data
)->element_name
, NULL
, error
.code
, error
.message
);
1444 XamlLoader::AddChild (void *p
, Value
*top_level
, Value
*parent_parent
, bool parent_is_property
, const char* parent_xmlns
, Value
*parent
, void *parent_data
, Value
*child
, void *child_data
)
1446 if (callbacks
.add_child
) {
1448 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1449 bool res
= callbacks
.add_child (&data
, parent_parent
, parent_is_property
, parent_xmlns
, parent
, parent_data
, child
, child_data
, &error
);
1451 if (error
.number
!= MoonError::NO_ERROR
) {
1452 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) child_data
)->element_name
, NULL
, error
.code
, error
.message
);
1461 XamlLoader::XamlLoader (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1463 Initialize (resourceBase
, filename
, str
, surface
, context
);
1466 XamlLoader::XamlLoader (const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1468 Initialize (NULL
, filename
, str
, surface
, context
);
1472 XamlLoader::Initialize (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1474 this->filename
= g_strdup (filename
);
1475 this->resource_base
= g_strdup (resourceBase
);
1476 this->str
= g_strdup (str
);
1477 this->surface
= surface
;
1480 this->context
= context
;
1481 this->vm_loaded
= false;
1482 this->error_args
= NULL
;
1483 this->expanding_template
= false;
1484 this->import_default_xmlns
= false;
1487 callbacks
= context
->internal
->callbacks
;
1488 this->vm_loaded
= true;
1490 if (!surface
&& context
->internal
->surface
) {
1491 this->surface
= context
->internal
->surface
;
1492 this->surface
->ref ();
1496 if (!surface
&& debug_flags
& RUNTIME_DEBUG_XAML
) {
1497 printf ("XamlLoader::XamlLoader ('%s', '%s', %p): Initializing XamlLoader without a surface.\n",
1498 filename
, str
, surface
);
1503 XamlLoader::~XamlLoader ()
1506 g_free (resource_base
);
1514 error_args
->unref();
1518 XamlLoader::LoadVM ()
1524 xaml_loader_new (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
)
1526 return new XamlLoader (resourceBase
, filename
, str
, surface
);
1530 xaml_loader_free (XamlLoader
* loader
)
1536 xaml_loader_set_callbacks (XamlLoader
* loader
, XamlLoaderCallbacks callbacks
)
1539 LOG_XAML ("Trying to set callbacks for a null object\n");
1543 loader
->callbacks
= callbacks
;
1544 loader
->vm_loaded
= true;
1548 namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
)
1550 XamlNamespace
*ns
= (XamlNamespace
*) value
;
1551 const char *prefix
= (const char *) user_data
;
1553 if (!strcmp (prefix
, ns
->GetPrefix ()))
1559 xaml_uri_for_prefix (void *parser
, char* prefix
)
1561 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
1563 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1567 return g_strdup (ns
->GetUri ());
1571 // Called when we encounter an error. Note that memory ownership is taken for everything
1572 // except the message, this allows you to use g_strdup_printf when creating the error message
1575 parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...)
1584 // if parsing fails too early it's not safe (i.e. sigsegv) to call some functions, e.g. XML_GetCurrentLineNumber
1585 bool report_line_col
= (error_code
!= XML_ERROR_XML_DECL
);
1586 int line_number
= report_line_col
? XML_GetCurrentLineNumber (p
->parser
) : 0;
1587 int char_position
= report_line_col
? XML_GetCurrentColumnNumber (p
->parser
) : 0;
1589 va_start (args
, format
);
1590 message
= g_strdup_vprintf (format
, args
);
1593 p
->error_args
= new ParserErrorEventArgs (message
, p
->file_name
, line_number
, char_position
, error_code
, el
, attr
);
1597 LOG_XAML ("PARSER ERROR, STOPPING PARSING: (%d) %s line: %d char: %d\n", error_code
, message
,
1598 line_number
, char_position
);
1600 XML_StopParser (p
->parser
, FALSE
);
1604 expat_parser_error (XamlParserInfo
*p
, XML_Error expat_error
)
1606 // Already had an error
1610 LOG_XAML ("expat error is: %d\n", expat_error
);
1612 switch (expat_error
) {
1613 case XML_ERROR_DUPLICATE_ATTRIBUTE
:
1614 parser_error (p
, NULL
, NULL
, 7031, "wfc: unique attribute spec");
1616 case XML_ERROR_UNBOUND_PREFIX
:
1617 parser_error (p
, NULL
, NULL
, 7055, "undeclared prefix");
1619 case XML_ERROR_NO_ELEMENTS
:
1620 parser_error (p
, NULL
, NULL
, 7000, "unexpected end of input");
1622 case XML_ERROR_SYNTAX
:
1623 parser_error (p
, NULL
, NULL
, 2103, "syntax error");
1626 parser_error (p
, NULL
, NULL
, expat_error
, "Unhandled XML error %s", XML_ErrorString (expat_error
));
1632 start_element (void *data
, const char *el
, const char **attr
)
1634 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1635 XamlElementInfo
*elem
= NULL
;
1636 XamlElementInstance
*inst
;
1637 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
1639 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1642 if (p
->ShouldBeginBuffering ()) {
1643 p
->BeginBuffering ();
1647 if (p
->InBufferingMode ()) {
1648 if (!strcmp (p
->buffer_until_element
, el
))
1653 const char *dot
= strchr (el
, '.');
1655 elem
= p
->current_namespace
->FindElement (p
, el
, attr
, p
->hydrate_expecting
== NULL
);
1662 if (p
->hydrate_expecting
){
1664 Type::Kind expecting_type = p->hydrate_expecting->GetObjectType ();
1666 if (!types->IsSubclassOf (expecting_type, elem->GetKind ())) {
1667 parser_error (p, el, NULL, -1, "Invalid top-level element found %s, expecting %s", el,
1668 types->Find (expecting_type)->GetName ());
1673 inst
= elem
->CreateWrappedElementInstance (p
, p
->hydrate_expecting
);
1674 p
->hydrate_expecting
= NULL
;
1676 inst
= elem
->CreateElementInstance (p
);
1681 inst
->parent
= p
->current_element
;
1683 if (!p
->top_element
) {
1684 p
->top_element
= inst
;
1685 if (inst
->GetAsDependencyObject ())
1686 NameScope::SetNameScope (inst
->GetAsDependencyObject (), p
->namescope
);
1689 inst
->SetAttributes (p
, attr
);
1693 if (inst
->IsDependencyObject ()) {
1694 if (p
->current_element
){
1695 if (p
->current_element
->info
) {
1696 p
->current_element
->AddChild (p
, inst
);
1703 // it's actually valid (from SL point of view) to have <Ellipse.Triggers> inside a <Rectangle>
1704 // however we can't add properties to something bad, like a <Recta.gle> element
1705 XamlElementInfo
*prop_info
= NULL
;
1707 gchar
*prop_elem
= g_strndup (el
, dot
- el
);
1708 prop_info
= p
->current_element
->FindPropertyElement (p
, el
, dot
);
1712 if (prop_info
!= NULL
) {
1713 inst
= prop_info
->CreatePropertyElementInstance (p
, g_strdup (el
));
1714 inst
->parent
= p
->current_element
;
1716 if (attr
[0] != NULL
) {
1717 // It appears there is a bug in the error string but it matches the MS runtime
1718 parser_error (p
, el
, NULL
, 2018, "The element %s does not support attributes.", attr
[0]);
1722 if (prop_info
&& !strcmp (el
, "TextBox.Text"))
1723 prop_info
->SetIsCDataVerbatim (true);
1725 if (!p
->top_element
) {
1726 if (types
->IsSubclassOf (prop_info
->GetKind (), Type::COLLECTION
)) {
1727 XamlElementInstance
*wrap
= prop_info
->CreateElementInstance (p
);
1728 NameScope::SetNameScope (wrap
->GetAsDependencyObject (), p
->namescope
);
1729 p
->top_element
= wrap
;
1730 p
->current_element
= wrap
;
1735 g_warning ("Unknown element: %s.", el
);
1736 parser_error (p
, el
, NULL
, 2007, "Unknown element: %s.", el
);
1741 if (p
->current_element
) {
1742 p
->current_element
->children
->Append (inst
);
1744 p
->current_element
= inst
;
1746 if (elem
&& element_begins_buffering (elem
->GetKind ())) {
1747 p
->QueueBeginBuffering (g_strdup (el
), BUFFER_MODE_TEMPLATE
);
1752 allow_value_from_str_in_flush (XamlParserInfo
*p
, XamlElementInstance
*parent
)
1754 if (parent
== NULL
|| parent
->element_type
!= XamlElementInstance::PROPERTY
|| parent
->parent
== NULL
|| !parent
->parent
->IsDependencyObject ())
1757 if (parent
->info
->GetKind () == Type::OBJECT
)
1764 flush_char_data (XamlParserInfo
*p
)
1766 if (p
->InBufferingMode ())
1769 if (!p
->cdata
|| !p
->current_element
)
1772 if (p
->current_element
->info
->IsCDataVerbatim()) {
1773 p
->cdata
->str
= g_strstrip (p
->cdata
->str
);
1776 if (p
->current_element
->element_type
== XamlElementInstance::ELEMENT
) {
1777 if (!p
->current_element
->TrySetContentProperty (p
, p
->cdata
->str
) && p
->cdata_content
) {
1778 if (allow_value_from_str_in_flush (p
, p
->current_element
->parent
)) {
1780 if (value_from_str (p
->current_element
->info
->GetKind (), NULL
, p
->cdata
->str
, &v
)) {
1781 p
->current_element
->SetValue (v
);
1785 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1786 "%s does not support text content.", p
->current_element
->element_name
);
1788 } else if (p
->current_element
->element_type
== XamlElementInstance::PROPERTY
) {
1789 if (p
->cdata_content
&& p
->current_element
->parent
&& !p
->current_element
->parent
->SetProperty (p
, p
->current_element
, p
->cdata
->str
)) {
1790 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1791 "%s does not support text content.", p
->current_element
->element_name
);
1797 g_string_free (p
->cdata
, TRUE
);
1798 p
->cdata_content
= false;
1804 element_begins_buffering (Type::Kind kind
)
1806 return Type::IsSubclassOf (kind
, Type::FRAMEWORKTEMPLATE
);
1810 is_default_namespace (gpointer key
, gpointer value
, gpointer user_data
)
1812 return value
== default_namespace
;
1816 start_element_handler (void *data
, const char *el
, const char **attr
)
1818 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1823 char **name
= g_strsplit (el
, "|", -1);
1824 XamlNamespace
*next_namespace
= NULL
;
1825 char *element
= NULL
;
1827 if (g_strv_length (name
) == 2) {
1828 // Find the proper namespace for our next element
1829 next_namespace
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, name
[0]);
1833 if (!next_namespace
&& p
->implicit_default_namespace
) {
1834 // Use the default namespace for the next element
1835 next_namespace
= default_namespace
;
1837 } else if (!next_namespace
) {
1838 if (!g_hash_table_find (p
->namespace_map
, is_default_namespace
, NULL
))
1839 return parser_error (p
, el
, NULL
, 2263, "AG_E_PARSER_MISSING_DEFAULT_NAMESPACE");
1842 if (next_namespace
&& next_namespace
->is_ignored
) {
1843 p
->current_namespace
= next_namespace
;
1844 if (!p
->InBufferingMode ())
1845 p
->QueueBeginBuffering (g_strdup (element
), BUFFER_MODE_IGNORE
);
1847 start_element (data
, element
, attr
); // This will force the buffering to start/build depth if needed
1851 p
->next_element
= element
;
1853 flush_char_data (p
);
1855 // Now update our namespace
1856 p
->current_namespace
= next_namespace
;
1858 if (!p
->current_namespace
&& !p
->InBufferingMode ()) {
1860 parser_error (p
, name
[1], NULL
, -1, "No handlers available for namespace: '%s' (%s)\n", name
[0], el
);
1862 parser_error (p
, name
[1], NULL
, -1, "No namespace mapping available for element: '%s'\n", el
);
1868 p
->next_element
= NULL
;
1869 start_element (data
, element
, attr
);
1875 get_element_name (XamlParserInfo
* p
, const char *el
)
1877 char **names
= g_strsplit (el
, "|", -1);
1878 char *name
= g_strdup (names
[g_strv_length (names
) - 1]);
1886 create_resource_list (XamlParserInfo
*p
)
1888 GSList
*list
= NULL
;
1889 XamlElementInstance
*walk
= p
->current_element
;
1891 Types
* types
= Deployment::GetCurrent ()->GetTypes ();
1893 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::FRAMEWORKELEMENT
)) {
1894 FrameworkElement
*fwe
= (FrameworkElement
*)walk
->GetAsDependencyObject ();
1895 if (g_slist_index (list
, fwe
) == -1)
1896 list
= g_slist_prepend (list
, fwe
);
1898 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
1899 ResourceDictionary
*rd
= (ResourceDictionary
*) walk
->GetAsDependencyObject ();
1900 if (g_slist_index (list
, rd
) == -1)
1901 list
= g_slist_prepend (list
, walk
->GetAsDependencyObject ());
1903 walk
= walk
->parent
;
1906 list
= g_slist_reverse (list
);
1910 static XamlContext
*
1911 create_xaml_context (XamlParserInfo
*p
, FrameworkTemplate
*template_
, XamlContext
*parent_context
)
1913 GSList
*resources
= create_resource_list (p
);
1914 XamlContextInternal
*ic
= new XamlContextInternal (p
->loader
->callbacks
, p
->GetTopElementPtr (), template_
, p
->namespace_map
, resources
, parent_context
? parent_context
->internal
: NULL
);
1915 return new XamlContext (ic
);
1919 end_element_handler (void *data
, const char *el
)
1921 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1923 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1929 if (!p
->current_element
) {
1930 g_warning ("p->current_element == NULL, current_element = %p (%s)\n",
1931 p
->current_element
, p
->current_element
? p
->current_element
->element_name
: "<NULL>");
1935 if (p
->InBufferingMode ()) {
1936 char* name
= get_element_name (p
, el
);
1937 if (!strcmp (p
->buffer_until_element
, name
)) {
1940 if (p
->buffer_depth
== 0) {
1941 if (p
->buffer_mode
== BUFFER_MODE_TEMPLATE
) {
1942 // OK we are done buffering, the element we are buffering for
1943 FrameworkTemplate
* template_
= (FrameworkTemplate
*) p
->current_element
->GetAsDependencyObject ();
1945 char* buffer
= p
->ClearBuffer ();
1947 XamlContext
*context
= create_xaml_context (p
, template_
, p
->loader
->GetContext());
1949 if (p
->validate_templates
) {
1950 p
->ValidateTemplate (buffer
, context
, template_
);
1956 template_
->SetXamlBuffer (context
, buffer
);
1957 p
->current_element
= p
->current_element
->parent
;
1958 } else if (p
->buffer_mode
== BUFFER_MODE_IGNORE
) {
1959 // For now we'll actually keep/clear this buffer because it makes testing easier
1960 char *buffer
= p
->ClearBuffer ();
1970 switch (p
->current_element
->element_type
) {
1971 case XamlElementInstance::ELEMENT
:
1973 p
->current_element
->SetDelayedProperties (p
);
1974 flush_char_data (p
);
1976 // according to http://blogs.msdn.com/devdave/archive/2008/10/11/control-lifecycle.aspx
1977 // default styles are apply when the end tag is read.
1979 if (p
->current_element
->IsDependencyObject () &&
1980 p
->current_element
->GetAsDependencyObject() &&
1981 p
->current_element
->GetAsDependencyObject()->Is(Type::CONTROL
)) {
1983 Control
*control
= (Control
*)p
->current_element
->GetAsDependencyObject();
1984 ManagedTypeInfo
*key
= control
->GetDefaultStyleKey ();
1987 if (Application::GetCurrent () == NULL
)
1988 g_warning ("attempting to use a null application applying default style while parsing.");
1990 Application::GetCurrent()->ApplyDefaultStyle (control
, key
);
1993 else if (!p
->current_element
->IsDependencyObject ()) {
1995 if (p
->current_element
->parent
)
1996 p
->current_element
->parent
->AddChild (p
, p
->current_element
);
1999 case XamlElementInstance::PROPERTY
: {
2000 List::Node
*walk
= p
->current_element
->children
->First ();
2002 XamlElementInstance
*child
= (XamlElementInstance
*) walk
;
2003 if (p
->current_element
->parent
) {
2004 p
->current_element
->parent
->SetProperty (p
, p
->current_element
, child
);
2008 flush_char_data (p
);
2013 p
->current_element
= p
->current_element
->parent
;
2017 char_data_handler (void *data
, const char *in
, int inlen
)
2019 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2020 register const char *inptr
= in
;
2021 const char *inend
= in
+ inlen
;
2024 if (p
->InBufferingMode ())
2030 if (p
->current_element
&& p
->current_element
->info
->IsCDataVerbatim()) {
2032 p
->cdata
= g_string_new ("");
2034 g_string_append_len (p
->cdata
, inptr
, inlen
);
2035 p
->cdata_content
= true;
2040 p
->cdata
= g_string_new ("");
2042 if (g_ascii_isspace (*inptr
)) {
2043 g_string_append_c (p
->cdata
, ' ');
2046 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2052 } else if (g_ascii_isspace (p
->cdata
->str
[p
->cdata
->len
- 1])) {
2053 // previous cdata chunk ended with lwsp, skip over leading lwsp for this chunk
2054 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2058 while (inptr
< inend
) {
2060 while (inptr
< inend
&& !g_ascii_isspace (*inptr
))
2063 if (inptr
> start
) {
2064 g_string_append_len (p
->cdata
, start
, inptr
- start
);
2065 p
->cdata_content
= true;
2068 if (inptr
< inend
) {
2069 g_string_append_c (p
->cdata
, ' ');
2072 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2079 start_namespace_handler (void *data
, const char *prefix
, const char *uri
)
2081 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2083 if (p
->InBufferingMode ())
2089 if (p
->loader
!= NULL
&& p
->loader
->callbacks
.import_xaml_xmlns
!= NULL
) {
2091 XamlCallbackData data
= XamlCallbackData (p
->loader
, p
, p
->GetTopElementPtr ());
2092 if (!p
->loader
->callbacks
.import_xaml_xmlns (&data
, uri
, &error
))
2093 return parser_error (p
, p
->current_element
? p
->current_element
->element_name
: NULL
, prefix
, 2005, "Unknown namespace %s", uri
);
2096 for (int i
= 0; default_namespace_names
[i
]; i
++) {
2097 if (!strcmp (default_namespace_names
[i
], uri
)) {
2098 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), default_namespace
);
2103 if (!strcmp (X_NAMESPACE_URI
, uri
)){
2104 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), x_namespace
);
2105 } else if (!strcmp (PRIMITIVE_NAMESPACE_URI
, uri
)) {
2106 PrimitiveNamespace
*pn
= new PrimitiveNamespace (g_strdup (prefix
));
2107 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), pn
);
2108 p
->AddCreatedNamespace (pn
);
2109 } else if (!strcmp (MC_IGNORABLE_NAMESPACE_URI
, uri
)) {
2110 MCIgnorableNamespace
*mc
= new MCIgnorableNamespace (g_strdup (prefix
));
2111 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), mc
);
2112 p
->AddCreatedNamespace (mc
);
2115 return parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), prefix
, -1,
2116 "No managed element callback installed to handle %s", uri
);
2120 parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), NULL
, 2262,
2121 "AG_E_PARSER_NAMESPACE_NOT_SUPPORTED");
2125 ManagedNamespace
*c
= new ManagedNamespace (g_strdup (uri
), g_strdup (prefix
));
2126 g_hash_table_insert (p
->namespace_map
, g_strdup (c
->xmlns
), c
);
2127 p
->AddCreatedNamespace (c
);
2132 start_doctype_handler (void *data
,
2133 const XML_Char
*doctype_name
,
2134 const XML_Char
*sysid
,
2135 const XML_Char
*pubid
,
2136 int has_internal_subset
)
2138 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2140 if (p
->InBufferingMode ())
2144 return parser_error (p
, NULL
, NULL
, 7050, "DTD was found but is prohibited");
2147 return parser_error (p
, NULL
, NULL
, 7016, "incorrect document syntax.");
2151 add_default_namespaces (XamlParserInfo
*p
, bool sl_xmlns
)
2154 p
->implicit_default_namespace
= true;
2155 g_hash_table_insert (p
->namespace_map
, g_strdup ("http://schemas.microsoft.com/winfx/2006/xaml/presentation"), default_namespace
);
2156 g_hash_table_insert (p
->namespace_map
, g_strdup (X_NAMESPACE_URI
), x_namespace
);
2158 g_hash_table_insert (p
->namespace_map
, g_strdup (XML_NAMESPACE_URI
), xml_namespace
);
2162 print_tree (XamlElementInstance
*el
, int depth
)
2165 if (debug_flags
& RUNTIME_DEBUG_XAML
) {
2166 for (int i
= 0; i
< depth
; i
++)
2169 const char *name
= NULL
;
2172 printf (" -null- \n");
2176 if (el
->element_type
== XamlElementInstance::ELEMENT
&& el
->IsDependencyObject ())
2177 name
= el
->GetAsDependencyObject ()->GetName ();
2178 printf ("%s (%s) (%p) (%s)\n", el
->element_name
, name
? name
: "-no name-", el
->parent
, el
->element_type
== XamlElementInstance::PROPERTY
? "PROPERTY" : "ELEMENT");
2180 for (List::Node
*walk
= el
->children
->First (); walk
!= NULL
; walk
= walk
->next
) {
2181 XamlElementInstance
*el
= (XamlElementInstance
*) walk
;
2182 print_tree (el
, depth
+ 1);
2189 xaml_parse_xmlns (const char* xmlns
, char** type_name
, char** ns
, char** assembly
)
2191 const char delimiters
[] = ";";
2193 char* buffer
= g_strdup (xmlns
);
2199 decl
= strtok (buffer
, delimiters
);
2200 while (decl
!= NULL
) {
2201 if (strstr (decl
, "clr-namespace:") == decl
) {
2204 *ns
= g_strdup (decl
+ 14);
2205 } else if (strstr (decl
, "assembly=") == decl
) {
2208 *assembly
= g_strdup (decl
+ 9);
2211 g_free (*type_name
);
2212 *type_name
= g_strdup (decl
);
2215 decl
= strtok (NULL
, delimiters
);
2221 XamlLoader::CreateFromFile (const char *xaml_file
, bool create_namescope
,
2222 Type::Kind
*element_type
)
2225 XamlParserInfo
*parser_info
= NULL
;
2226 XML_Parser p
= NULL
;
2227 bool first_read
= true;
2228 const char *inptr
, *inend
;
2233 LOG_XAML ("attemtping to load xaml file: %s\n", xaml_file
);
2235 stream
= new TextStream ();
2236 if (!stream
->OpenFile (xaml_file
, false)) {
2237 LOG_XAML ("can not open file\n");
2238 goto cleanup_and_return
;
2241 if (!(p
= XML_ParserCreateNS ("UTF-8", '|'))) {
2242 LOG_XAML ("can not create parser\n");
2243 goto cleanup_and_return
;
2246 parser_info
= new XamlParserInfo (p
, xaml_file
);
2248 parser_info
->namescope
->SetTemporary (!create_namescope
);
2250 parser_info
->loader
= this;
2252 // TODO: This is just in here temporarily, to make life less difficult for everyone
2253 // while we are developing.
2254 add_default_namespaces (parser_info
, false);
2256 XML_SetUserData (p
, parser_info
);
2258 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2259 XML_SetCharacterDataHandler (p
, char_data_handler
);
2260 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2261 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2264 XML_SetProcessingInstructionHandler (p, proc_handler);
2267 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) >= 0) {
2271 if (first_read
&& nread
> 0) {
2272 // Remove preceding white space
2273 inend
= buffer
+ nread
;
2275 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2281 n
= (inend
- inptr
);
2285 parser_info
->SetXmlBuffer (inptr
);
2286 if (!XML_Parse (p
, inptr
, n
, nread
== 0)) {
2287 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2288 goto cleanup_and_return
;
2295 print_tree (parser_info
->top_element
, 0);
2297 if (parser_info
->top_element
) {
2298 res
= parser_info
->top_element
->GetAsValue ();
2299 // We want a copy because the old one is going to be deleted
2300 res
= new Value (*res
);
2303 *element_type
= parser_info
->top_element
->info
->GetKind ();
2305 if (parser_info
->error_args
) {
2306 *element_type
= Type::INVALID
;
2307 goto cleanup_and_return
;
2314 error_args
= new ParserErrorEventArgs ("Error opening xaml file", xaml_file
, 0, 0, 1, "", "");
2315 else if (parser_info
->error_args
) {
2316 error_args
= parser_info
->error_args
;
2332 XamlLoader::CreateFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2334 return HydrateFromString (xaml
, NULL
, create_namescope
, element_type
, flags
);
2338 value_to_dependency_object (Value
*value
)
2340 if (!value
|| !value
->Is (Type::DEPENDENCY_OBJECT
))
2342 return value
->AsDependencyObject ();
2346 XamlLoader::CreateDependencyObjectFromFile (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2348 return value_to_dependency_object (CreateFromFile (xaml
, create_namescope
, element_type
));
2352 XamlLoader::CreateDependencyObjectFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2354 return value_to_dependency_object (CreateFromString (xaml
, create_namescope
, element_type
, IMPORT_DEFAULT_XMLNS
));
2358 * Hydrates an existing DependencyObject (@object) with the contents from the @xaml
2362 XamlLoader::HydrateFromString (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2364 XML_Parser p
= XML_ParserCreateNS ("utf-8", '|');
2365 XamlParserInfo
*parser_info
= NULL
;
2367 char *start
= (char*)xaml
;
2368 char *prepend
= NULL
;
2369 char *append
= NULL
;
2370 char * inputs
[4] = {NULL
, NULL
, NULL
, NULL
};
2375 LOG_XAML ("can not create parser\n");
2376 goto cleanup_and_return
;
2385 sprintf (filename
, "createFromXaml.%d.xaml", id
++);
2386 if ((fp
= fopen (filename
, "wt")) != NULL
) {
2387 fwrite (xaml
, strlen (xaml
), 1, fp
);
2393 parser_info
= new XamlParserInfo (p
, NULL
);
2395 parser_info
->namescope
->SetTemporary (!create_namescope
);
2397 parser_info
->loader
= this;
2398 parser_info
->validate_templates
= (flags
& VALIDATE_TEMPLATES
) == VALIDATE_TEMPLATES
;
2401 // If we are hydrating, we are not null
2403 if (object
!= NULL
) {
2404 parser_info
->hydrate_expecting
= object
;
2405 parser_info
->hydrating
= true;
2406 if (Type::IsSubclassOf (object
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
2407 DependencyObject
*dob
= object
->AsDependencyObject ();
2408 dob
->SetSurface (GetSurface());
2409 dob
->SetResourceBase (GetResourceBase());
2412 parser_info
->hydrate_expecting
= NULL
;
2413 parser_info
->hydrating
= false;
2416 // from_str gets the default namespaces implictly added
2417 add_default_namespaces (parser_info
, (flags
& IMPORT_DEFAULT_XMLNS
) == IMPORT_DEFAULT_XMLNS
);
2419 XML_SetUserData (p
, parser_info
);
2421 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2422 XML_SetCharacterDataHandler (p
, char_data_handler
);
2423 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2424 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2427 XML_SetProcessingInstructionHandler (p, proc_handler);
2431 prepend
= context
->internal
->CreateIgnorableTagOpen ();
2432 append
= context
->internal
->CreateIgnorableTagClose ();
2434 inputs
[0] = prepend
;
2436 inputs
[2] = append
;
2439 for (int i
= 0; inputs
[i
]; i
++) {
2440 char *start
= inputs
[i
];
2442 // don't freak out if the <?xml ... ?> isn't on the first line (see #328907)
2443 while (g_ascii_isspace (*start
))
2446 parser_info
->SetXmlBuffer (start
);
2447 if (!XML_Parse (p
, start
, strlen (start
), inputs
[i
+ 1] == NULL
)) {
2448 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2449 LOG_XAML ("error parsing: %s\n\n", xaml
);
2450 goto cleanup_and_return
;
2454 print_tree (parser_info
->top_element
, 0);
2456 if (parser_info
->top_element
) {
2457 if (is_legal_top_level_kind (parser_info
->top_element
->info
->GetKind ())) {
2458 res
= parser_info
->top_element
->GetAsValue ();
2459 res
= new Value (*res
);
2460 if (res
->Is (Type::DEPENDENCY_OBJECT
) && object
) {
2461 DependencyObject
*dob
= res
->AsDependencyObject ();
2463 dob
->SetIsHydratedFromXaml (parser_info
->hydrating
);
2468 *element_type
= parser_info
->top_element
->info
->GetKind ();
2470 if (!res
&& !parser_info
->error_args
)
2471 parser_info
->error_args
= new ParserErrorEventArgs ("No DependencyObject found", "", 0, 0, 1, "", "");
2473 if (parser_info
->error_args
) {
2477 *element_type
= Type::INVALID
;
2478 goto cleanup_and_return
;
2484 if (parser_info
->error_args
) {
2485 error_args
= parser_info
->error_args
;
2486 printf ("Could not parse element %s, attribute %s, error: %s\n",
2487 error_args
->xml_element
,
2488 error_args
->xml_attribute
,
2489 error_args
->GetErrorMessage());
2505 XamlLoader::CreateFromFileWithError (const char *xaml_file
, bool create_namescope
, Type::Kind
*element_type
, MoonError
*error
)
2507 Value
*res
= CreateFromFile (xaml_file
, create_namescope
, element_type
);
2508 if (error_args
&& error_args
->GetErrorCode () != -1)
2509 MoonError::FillIn (error
, error_args
);
2514 XamlLoader::CreateFromStringWithError (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2516 Value
*res
= CreateFromString (xaml
, create_namescope
, element_type
, flags
);
2517 if (error_args
&& error_args
->GetErrorCode () != -1)
2518 MoonError::FillIn (error
, error_args
);
2523 XamlLoader::HydrateFromStringWithError (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2525 Value
*res
= HydrateFromString (xaml
, object
, create_namescope
, element_type
, flags
);
2526 if (error_args
&& error_args
->GetErrorCode () != -1)
2527 MoonError::FillIn (error
, error_args
);
2532 parse_int (const char **pp
, const char *end
)
2534 const char *p
= *pp
;
2536 if (optional
&& AtEnd
)
2543 while (p
<= end
&& g_ascii_isdigit (*p
)) {
2544 res
= res
* 10 + *p
- '0';
2559 parse_ticks (const char **pp
, const char *end
)
2561 gint64 mag
= 1000000;
2563 bool digitseen
= false;
2565 const char *p
= *pp
;
2567 while (mag
> 0 && p
<= end
&& g_ascii_isdigit (*p
)) {
2568 res
= res
+ (*p
- '0') * mag
;
2584 time_span_from_str (const char *str
, TimeSpan
*res
)
2586 const char *end
= str
+ strlen (str
);
2589 bool negative
= false;
2603 days
= parse_int (&p
, end
);
2607 hours
= parse_int (&p
, end
);
2615 minutes
= parse_int (&p
, end
);
2617 seconds
= parse_int (&p
, end
);
2620 ticks
= parse_ticks (&p
, end
);
2626 gint64 t
= (days
* 86400) + (hours
* 3600) + (minutes
* 60) + seconds
;
2629 *res
= negative
? (-t
- ticks
) : (t
+ ticks
);
2635 repeat_behavior_from_str (const char *str
, RepeatBehavior
*res
)
2637 if (!g_ascii_strcasecmp ("Forever", str
)) {
2638 *res
= RepeatBehavior::Forever
;
2642 // check for "<float>x".
2644 // XXX more validation work is needed here.. but how do we
2646 const char *x
= strchr (str
, 'x');
2648 if (*(x
+ 1) != '\0') {
2654 double d
= g_ascii_strtod (str
, &endptr
);
2656 if (errno
|| endptr
== str
)
2659 *res
= RepeatBehavior (d
);
2664 /* XXX RepeatBehavior='XX:XX:XX' syntax is NOT correctly supported by
2665 Silverlight 1.0 (most likely a bug). It works fine in Silverlight 2.0
2666 though. We currently stick to the 2.0 behavior, not replicating the bug
2670 if (!time_span_from_str (str
, &t
))
2673 *res
= RepeatBehavior (t
);
2679 duration_from_str (const char *str
, Duration
*res
)
2681 if (!g_ascii_strcasecmp ("Automatic", str
)) {
2682 *res
= Duration::Automatic
;
2686 if (!g_ascii_strcasecmp ("Forever", str
)) {
2687 *res
= Duration::Forever
;
2692 if (!time_span_from_str (str
, &ts
))
2695 *res
= Duration (ts
);
2700 keytime_from_str (const char *str
, KeyTime
*res
)
2702 if (!g_ascii_strcasecmp ("Uniform", str
)) {
2703 *res
= KeyTime::Uniform
;
2707 if (!g_ascii_strcasecmp ("Paced", str
)) {
2708 *res
= KeyTime::Paced
;
2712 /* check for a percentage first */
2713 const char *last
= str
+ strlen(str
) - 1;
2716 double pct
= g_ascii_strtod (str
, &ep
);
2718 *res
= KeyTime (pct
);
2724 if (!time_span_from_str (str
, &ts
))
2727 *res
= KeyTime (ts
);
2732 key_spline_from_str (const char *str
, KeySpline
**res
)
2734 PointCollection
*pts
= PointCollection::FromStr (str
);
2739 if (pts
->GetCount () != 2) {
2744 *res
= new KeySpline (*pts
->GetValueAt (0)->AsPoint (), *pts
->GetValueAt (1)->AsPoint ());
2752 matrix_from_str (const char *str
)
2754 if (!g_ascii_strcasecmp ("Identity", str
)) {
2755 return new Matrix ();
2758 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2762 return new Matrix ();
2764 if (values
->GetCount () < 6) {
2769 matrix
= new Matrix ();
2770 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2771 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2772 matrix
->SetM21 (values
->GetValueAt (2)->AsDouble ());
2773 matrix
->SetM22 (values
->GetValueAt (3)->AsDouble ());
2774 matrix
->SetOffsetX (values
->GetValueAt (4)->AsDouble ());
2775 matrix
->SetOffsetY (values
->GetValueAt (5)->AsDouble ());
2783 grid_length_from_str (const char *str
, GridLength
*grid_length
)
2785 if (IS_NULL_OR_EMPTY (str
)) {
2786 *grid_length
= GridLength (0.0, GridUnitTypePixel
);
2790 if (str
[0] == '*') {
2791 *grid_length
= GridLength (1.0, GridUnitTypeStar
);
2795 // unit tests shows that "Auto", "auto", "aUtO"... all works
2796 if (!g_ascii_strcasecmp (str
, "Auto")) {
2797 *grid_length
= GridLength ();
2803 double d
= g_ascii_strtod (str
, &endptr
);
2805 if (errno
|| endptr
== str
)
2808 *grid_length
= GridLength (d
, *endptr
== '*' ? GridUnitTypeStar
: GridUnitTypePixel
);
2817 while (*inptr
&& !g_ascii_isalnum (*inptr
) && *inptr
!= '.' && *inptr
!= '-' && *inptr
!= '+')
2818 inptr
= g_utf8_next_char (inptr
);
2824 get_point (Point
*p
, char **in
)
2826 char *end
, *inptr
= *in
;
2829 x
= g_ascii_strtod (inptr
, &end
);
2834 while (g_ascii_isspace (*inptr
))
2840 while (g_ascii_isspace (*inptr
))
2843 y
= g_ascii_strtod (inptr
, &end
);
2856 make_relative (const Point
*cp
, Point
*mv
)
2863 more_points_available (char **in
)
2867 while (g_ascii_isspace (*inptr
) || *inptr
== ',')
2872 return (g_ascii_isdigit (*inptr
) || *inptr
== '.' || *inptr
== '-' || *inptr
== '+');
2876 geometry_from_str (const char *str
)
2878 char *inptr
= (char *) str
;
2879 Point cp
= Point (0, 0);
2880 Point cp1
, cp2
, cp3
;
2883 PathGeometry
*pg
= NULL
;
2884 FillRule fill_rule
= FillRuleEvenOdd
;
2885 bool cbz
= false; // last figure is a cubic bezier curve
2886 bool qbz
= false; // last figure is a quadratic bezier curve
2887 Point cbzp
, qbzp
; // points needed to create "smooth" beziers
2889 moon_path
*path
= moon_path_new (10);
2892 if (g_ascii_isspace (*inptr
))
2898 bool relative
= false;
2901 inptr
= g_utf8_next_char (inptr
);
2909 fill_rule
= FillRuleEvenOdd
;
2910 else if (*inptr
== '1')
2911 fill_rule
= FillRuleNonzero
;
2913 // FIXME: else it's a bad value and nothing should be rendered
2914 goto bad_pml
; // partial: only this Path won't be rendered
2916 inptr
= g_utf8_next_char (inptr
);
2921 if (!get_point (&cp1
, &inptr
))
2925 make_relative (&cp
, &cp1
);
2928 moon_move_to (path
, cp1
.x
, cp1
.y
);
2930 start
.x
= cp
.x
= cp1
.x
;
2931 start
.y
= cp
.y
= cp1
.y
;
2934 while (more_points_available (&inptr
)) {
2935 if (!get_point (&cp1
, &inptr
))
2939 make_relative (&cp
, &cp1
);
2941 moon_line_to (path
, cp1
.x
, cp1
.y
);
2953 while (more_points_available (&inptr
)) {
2954 if (!get_point (&cp1
, &inptr
))
2958 make_relative (&cp
, &cp1
);
2960 moon_line_to (path
, cp1
.x
, cp1
.y
);
2975 double x
= g_ascii_strtod (inptr
, &end
);
2983 cp
= Point (x
, cp
.y
);
2985 moon_line_to (path
, cp
.x
, cp
.y
);
2994 double y
= g_ascii_strtod (inptr
, &end
);
3002 cp
= Point (cp
.x
, y
);
3004 moon_line_to (path
, cp
.x
, cp
.y
);
3013 while (more_points_available (&inptr
)) {
3014 if (!get_point (&cp1
, &inptr
))
3018 make_relative (&cp
, &cp1
);
3022 if (!get_point (&cp2
, &inptr
))
3026 make_relative (&cp
, &cp2
);
3030 if (!get_point (&cp3
, &inptr
))
3034 make_relative (&cp
, &cp3
);
3038 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3055 while (more_points_available (&inptr
)) {
3056 if (!get_point (&cp2
, &inptr
))
3060 make_relative (&cp
, &cp2
);
3064 if (!get_point (&cp3
, &inptr
))
3068 make_relative (&cp
, &cp3
);
3071 cp1
.x
= 2 * cp
.x
- cbzp
.x
;
3072 cp1
.y
= 2 * cp
.y
- cbzp
.y
;
3076 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3093 while (more_points_available (&inptr
)) {
3094 if (!get_point (&cp1
, &inptr
))
3098 make_relative (&cp
, &cp1
);
3102 if (!get_point (&cp2
, &inptr
))
3106 make_relative (&cp
, &cp2
);
3110 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3125 while (more_points_available (&inptr
)) {
3126 if (!get_point (&cp2
, &inptr
))
3130 make_relative (&cp
, &cp2
);
3133 cp1
.x
= 2 * cp
.x
- qbzp
.x
;
3134 cp1
.y
= 2 * cp
.y
- qbzp
.y
;
3138 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3155 while (more_points_available (&inptr
)) {
3156 if (!get_point (&cp1
, &inptr
))
3161 double angle
= g_ascii_strtod (inptr
, &end
);
3168 int is_large
= strtol (inptr
, &end
, 10);
3175 int sweep
= strtol (inptr
, &end
, 10);
3182 if (!get_point (&cp2
, &inptr
))
3186 make_relative (&cp
, &cp2
);
3188 moon_arc_to (path
, cp1
.x
, cp1
.y
, angle
, is_large
, sweep
, cp2
.x
, cp2
.y
);
3200 moon_line_to (path
, start
.x
, start
.y
);
3201 moon_close_path (path
);
3202 moon_move_to (path
, start
.x
, start
.y
);
3213 pg
= new PathGeometry (path
);
3214 pg
->SetFillRule (fill_rule
);
3218 moon_path_destroy (path
);
3223 value_is_explicit_null (const char *str
)
3225 return !strcmp ("{x:Null}", str
);
3229 is_managed_kind (Type::Kind kind
)
3232 if (kind
== Type::MANAGED
||
3233 kind
== Type::OBJECT
||
3234 kind
== Type::URI
||
3235 kind
== Type::MANAGEDTYPEINFO
||
3236 kind
== Type::DEPENDENCYPROPERTY
)
3243 kind_requires_managed_load (Type::Kind kind
)
3245 if (kind
== Type::USERCONTROL
) {
3253 is_legal_top_level_kind (Type::Kind kind
)
3255 if (kind
== Type::MANAGED
|| kind
== Type::OBJECT
|| Type::IsSubclassOf (kind
, Type::DEPENDENCY_OBJECT
))
3260 // NOTE: Keep definition in sync with class/System.Windows/Mono/NativeMethods.cs
3262 value_from_str_with_typename (const char *type_name
, const char *prop_name
, const char *str
, Value
**v
)
3264 Type
*t
= Type::Find (type_name
);
3268 return value_from_str (t
->GetKind (), prop_name
, str
, v
);
3272 expand_property_path (XamlParserInfo
*p
, PropertyPath
*path
)
3277 bool expanded
= false;
3278 GString
*res
= g_string_new (path
->path
);
3280 int len
= strlen (res
->str
);
3281 for (int i
= 0; i
< len
; i
++) {
3282 if (res
->str
[i
] == ':') {
3286 for ( ; s
> 0; s
--) {
3287 if (!g_ascii_isalnum (res
->str
[s
]))
3291 for ( ; te
< len
; te
++) {
3292 if (!g_ascii_isalpha (res
->str
[te
]) || res
->str
[te
] == '_')
3296 char *prefix
= g_strndup (res
->str
+ s
+ 1, e
- s
- 1);
3297 char *type
= g_strndup (res
->str
+ e
+ 1, te
- e
- 1);
3299 res
= g_string_erase (res
, s
+ 1, te
- s
- 1);
3301 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
3305 g_string_free (res
, true);
3309 XamlElementInfo
*info
= ns
->FindElement (p
, type
, NULL
, false);
3314 g_string_free (res
, true);
3318 char *uri
= g_strdup_printf ("'%s'", Type::Find (info
->GetKind ())->GetName ());
3320 res
= g_string_insert (res
, s
+ 1, uri
);
3321 i
= s
+ 1 + strlen (uri
);
3322 len
= strlen (res
->str
);
3334 g_string_free (res
, true);
3338 char *expanded_str
= res
->str
;
3339 g_string_free (res
, false);
3341 return expanded_str
;
3345 value_from_str (Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
)
3349 value_from_str_with_parser (NULL
, type
, prop_name
, str
, v
, &v_set
);
3355 xaml_bool_from_str (const char *s
, bool *res
)
3360 if (!g_ascii_strcasecmp ("true", s
))
3362 else if (!g_ascii_strcasecmp ("false", s
))
3365 // Check if it's a string representing a decimal value
3369 l
= strtol (s
, &endptr
, 10);
3371 if (errno
|| endptr
== s
|| *endptr
|| l
> G_MAXINT32
|| l
< G_MININT32
)
3385 value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
)
3390 if (value_is_explicit_null (str
)) {
3396 char *s
= g_strdup (str
);
3398 if (type
== Type::OBJECT
|| type
== Type::STRING
) {
3399 // object and string use the literal string
3402 // everything else depends on the string being stripped
3407 case Type::OBJECT
: {
3408 // not much more can do here, unless we want to try to
3409 // probe str to see if it's actually meant to be a
3410 // specific type. just assume it's a string.
3419 if (!xaml_bool_from_str (s
, &b
))
3426 case Type::DOUBLE
: {
3429 // empty string should not reset default values with 0
3431 // FIXME: this causes a 2.0 unit test to fail (PrimitiveTest.ParseEmptyDouble)
3432 if (IS_NULL_OR_EMPTY(s
)) {
3437 bool is_nan
= false;
3438 if (!g_ascii_strcasecmp (s
, "NAN"))
3442 d
= g_ascii_strtod (s
, &endptr
);
3445 if (is_nan
|| errno
|| endptr
== s
|| *endptr
) {
3447 && (!strcmp (prop_name
, "Width") || !strcmp (prop_name
, "Height"))
3448 && (!g_ascii_strcasecmp (s
, "Auto") || is_nan
))
3462 l
= strtol (s
, &endptr
, 10);
3464 if (errno
|| endptr
== s
)
3467 *v
= new Value (l
, Type::INT64
);
3471 case Type::TIMESPAN
: {
3474 if (!time_span_from_str (s
, &ts
))
3477 *v
= new Value (ts
, Type::TIMESPAN
);
3484 if (IS_NULL_OR_EMPTY(s
))
3486 else if (g_ascii_isalpha (s
[0]) && prop_name
) {
3487 i
= enums_str_to_int (prop_name
, s
);
3489 // g_warning ("'%s' enum is not valid on '%s' property", str, prop_name);
3494 long l
= strtol (s
, &endptr
, 10);
3496 if (errno
|| endptr
== s
)
3507 gunichar unichar
= g_utf8_get_char_validated (str
, -1);
3510 if ((int) unichar
< 0)
3513 if (!(next
= g_utf8_next_char (str
)) || *next
!= '\0')
3516 *v
= new Value (unichar
, Type::CHAR
);
3520 case Type::STRING
: {
3521 *v
= new Value (str
);
3526 Color
*c
= color_from_str (s
);
3529 *v
= new Value (*c
);
3534 case Type::REPEATBEHAVIOR
: {
3535 RepeatBehavior rb
= RepeatBehavior::Forever
;
3537 if (!repeat_behavior_from_str (s
, &rb
))
3540 *v
= new Value (rb
);
3544 case Type::DURATION
: {
3545 Duration d
= Duration::Forever
;
3547 if (!duration_from_str (s
, &d
))
3554 case Type::KEYTIME
: {
3555 KeyTime kt
= KeyTime::Paced
;
3557 if (!keytime_from_str (s
, &kt
))
3560 *v
= new Value (kt
);
3564 case Type::KEYSPLINE
: {
3567 if (!key_spline_from_str (s
, &ks
))
3570 *v
= Value::CreateUnrefPtr (ks
);
3575 case Type::SOLIDCOLORBRUSH
: {
3576 // Only solid color brushes can be specified using attribute syntax
3577 Color
*c
= color_from_str (s
);
3582 SolidColorBrush
*scb
= new SolidColorBrush ();
3587 *v
= Value::CreateUnrefPtr (scb
);
3594 if (!Point::FromStr (s
, &p
))
3604 if (!Size::FromStr (s
, &size
))
3607 *v
= new Value (size
);
3614 if (!Rect::FromStr (s
, &rect
))
3617 *v
= new Value (rect
);
3624 if (!uri
.Parse (s
)) {
3628 *v
= new Value (uri
);
3632 case Type::DOUBLE_COLLECTION
: {
3633 DoubleCollection
*doubles
= DoubleCollection::FromStr (s
);
3635 *v
= Value::CreateUnrefPtr (new DoubleCollection ());
3640 *v
= Value::CreateUnrefPtr (doubles
);
3644 case Type::POINT_COLLECTION
: {
3645 PointCollection
*points
= PointCollection::FromStr (s
);
3647 *v
= Value::CreateUnrefPtr (new PointCollection ());
3652 *v
= Value::CreateUnrefPtr (points
);
3656 case Type::TRANSFORMGROUP
: {
3657 if (IS_NULL_OR_EMPTY(s
))
3660 Matrix
*mv
= matrix_from_str (s
);
3664 TransformGroup
*tg
= new TransformGroup ();
3665 MatrixTransform
*t
= new MatrixTransform ();
3666 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3668 tg
->GetChildren()->Add (t
);
3671 *v
= new Value (tg
);
3677 case Type::TRANSFORM
:
3679 if (!g_ascii_strcasecmp ("Identity", str
)) {
3685 // Intentional fall through, you can create a matrix from a TRANSFORM property, but not using Identity
3686 case Type::MATRIXTRANSFORM
:
3688 if (IS_NULL_OR_EMPTY(s
))
3691 Matrix
*mv
= matrix_from_str (s
);
3695 MatrixTransform
*t
= new MatrixTransform ();
3696 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3704 case Type::UNMANAGEDMATRIX
:
3705 case Type::MATRIX
: {
3706 // note: unlike TRANSFORM this creates an empty, identity, matrix for an empty string
3707 Matrix
*matrix
= matrix_from_str (s
);
3711 *v
= new Value (matrix
);
3716 case Type::PATHGEOMETRY
:
3717 case Type::GEOMETRY
: {
3718 Geometry
*geometry
= geometry_from_str (s
);
3723 *v
= new Value (geometry
);
3728 case Type::THICKNESS
: {
3731 if (!Thickness::FromStr (s
, &t
))
3738 case Type::CORNERRADIUS
: {
3741 if (!CornerRadius::FromStr (s
, &c
))
3748 case Type::GRIDLENGTH
: {
3749 GridLength grid_length
;
3751 if (!grid_length_from_str (s
, &grid_length
))
3754 *v
= new Value (grid_length
);
3758 case Type::IMAGESOURCE
:
3759 case Type::BITMAPIMAGE
: {
3765 BitmapImage
*bi
= new BitmapImage ();
3767 bi
->SetUriSource (&uri
);
3769 *v
= Value::CreateUnrefPtr (bi
);
3774 case Type::MULTISCALETILESOURCE
:
3775 case Type::DEEPZOOMIMAGETILESOURCE
: {
3776 // As far as I know the only thing you can create here is a URI based DeepZoomImageTileSource
3780 *v
= Value::CreateUnrefPtr (new DeepZoomImageTileSource (&uri
));
3785 case Type::FONTFAMILY
: {
3786 *v
= new Value (FontFamily (s
));
3790 case Type::FONTWEIGHT
: {
3791 int fw
= enums_str_to_int ("FontWeight", s
);
3793 *v
= new Value (FontWeight ((FontWeights
)fw
));
3798 case Type::FONTSTYLE
: {
3799 int fs
= enums_str_to_int ("FontStyle", s
);
3801 *v
= new Value (FontStyle ((FontStyles
)fs
));
3806 case Type::FONTSTRETCH
: {
3807 int fs
= enums_str_to_int ("FontStretch", s
);
3809 *v
= new Value (FontStretch ((FontStretches
)fs
));
3814 case Type::PROPERTYPATH
: {
3815 PropertyPath
path (s
);
3816 path
.expanded_path
= expand_property_path (p
, &path
);
3817 *v
= new Value (path
);
3822 // we don't care about NULL or empty values
3823 if (!IS_NULL_OR_EMPTY (s
)) {
3834 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
3836 const char* prop_name
= info
->GetContentProperty (p
);
3841 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (info
->GetKind (), prop_name
);
3845 bool is_collection
= Type::IsSubclassOf (dep
->GetPropertyType(), Type::DEPENDENCY_OBJECT_COLLECTION
);
3847 if (!is_collection
&& Type::IsSubclassOf (value
->info
->GetKind (), dep
->GetPropertyType())) {
3849 if (!item
->SetValueWithError (dep
, value
->GetAsValue (), &err
)) {
3850 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3856 // We only want to enter this if statement if we are NOT dealing with the content property element,
3857 // otherwise, attempting to use explicit property setting, would add the content property element
3858 // to the content property element collection
3859 if (is_collection
&& dep
->GetPropertyType() != value
->info
->GetKind ()) {
3860 Value
*col_v
= item
->GetValue (dep
);
3864 col
= collection_new (dep
->GetPropertyType ());
3865 item
->SetValue (dep
, Value (col
));
3868 col
= (Collection
*) col_v
->AsCollection ();
3872 if (-1 == col
->AddWithError (value
->GetAsValue (), &err
)) {
3873 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3884 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
3886 const char* prop_name
= info
->GetContentProperty (p
);
3890 Type::Kind prop_type
= p
->current_element
->info
->GetKind ();
3891 DependencyProperty
*content
= DependencyProperty::GetDependencyProperty (prop_type
, prop_name
);
3893 // TODO: There might be other types that can be specified here,
3894 // but string is all i have found so far. If you can specify other
3895 // types, i should pull the property setting out of set_attributes
3896 // and use that code
3898 if (content
&& (content
->GetPropertyType ()) == Type::STRING
&& value
) {
3899 item
->SetValue (content
, Value (g_strstrip (p
->cdata
->str
)));
3901 } else if (Type::IsSubclassOf (info
->GetKind (), Type::TEXTBLOCK
)) {
3902 TextBlock
*textblock
= (TextBlock
*) item
;
3903 InlineCollection
*inlines
= textblock
->GetInlines ();
3904 Inline
*last
= NULL
;
3906 if (inlines
&& inlines
->GetCount () > 0)
3907 last
= inlines
->GetValueAt (inlines
->GetCount () - 1)->AsInline ();
3909 if (!p
->cdata_content
) {
3910 if (p
->next_element
&& !strcmp (p
->next_element
, "Run") && last
&& last
->GetObjectType () == Type::RUN
&&
3911 !last
->GetAutogenerated ()) {
3912 // LWSP between <Run> elements is to be treated as a single-SPACE <Run> element
3913 // Note: p->cdata is already canonicalized
3915 // This is one of the following cases:
3917 // 1. LWSP before the first <Run> element
3918 // 2. LWSP after the last <Run> element
3919 // 3. LWSP between <Run> and <LineBreak> elements
3923 if (!p
->next_element
|| !strcmp (p
->next_element
, "LineBreak"))
3924 g_strchomp (p
->cdata
->str
);
3926 if (!last
|| last
->GetObjectType () != Type::RUN
|| last
->GetAutogenerated ())
3927 g_strchug (p
->cdata
->str
);
3930 Run
*run
= new Run ();
3931 run
->SetText (p
->cdata
->str
);
3934 inlines
= new InlineCollection ();
3935 textblock
->SetInlines (inlines
);
3948 XamlElementInstance::SetUnknownAttribute (XamlParserInfo
*p
, const char *name
, const char *value
)
3953 Value v
= Value (value
);
3954 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, name
, &v
, NULL
)) {
3961 XamlElementInstance::SetDelayedProperties (XamlParserInfo
*p
)
3963 GSList
*walk
= delayed_properties
;
3966 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
3968 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), prop
->xmlns
, prop
->name
, prop
->value
, NULL
, XamlCallbackData::SETTING_DELAYED_PROPERTY
)) {
3969 parser_error (p
, element_name
, prop
->name
, 2012,
3970 "Unknown property %s on element %s.",
3971 prop
->name
, element_name
);
3981 XamlElementInstance::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
3983 // We didn't find anything so try looking up in managed
3987 Value
*v
= new Value ();
3988 if (p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), GetAsValue (), p
->current_namespace
->GetUri (), el
, false, true, v
)) {
3989 char *type_name
= g_strndup (el
, dot
- el
);
3991 XamlElementInfoManaged
*res
= new XamlElementInfoManaged (g_strdup (p
->current_namespace
->GetUri ()), el
, info
, v
->GetKind (), v
);
3992 XamlElementInfo
*container
= p
->current_namespace
->FindElement (p
, type_name
, NULL
, false);
3993 info
->SetPropertyOwnerKind (container
->GetKind ());
4002 static XamlElementInfo
*
4003 create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
)
4008 char* type_name
= NULL
;
4009 char* type_xmlns
= NULL
;
4010 const char* use_xmlns
= NULL
;
4013 // We might have an x:Class attribute specified, so we need to use that for the
4014 // type_name that we pass to LookupObject
4015 if (strcmp ("Application", name
)) {
4016 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
4019 use_xmlns
= type_xmlns
;
4021 if (!p
->hydrating
) {
4022 parser_error (p
, name
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
4029 Value
*v
= new Value ();
4030 if (!p
->loader
->LookupObject (p
, use_xmlns
? p
->GetTopElementPtr () : NULL
, NULL
, use_xmlns
, name
, create
, false, v
)) {
4035 g_free (type_xmlns
);
4039 XamlElementInfoImportedManaged
*info
= new XamlElementInfoImportedManaged (g_strdup (name
), NULL
, v
);
4042 if (v
->Is (Type::DEPENDENCY_OBJECT
))
4043 p
->AddCreatedElement (v
->AsDependencyObject());
4051 XamlElementInfoNative::GetContentProperty (XamlParserInfo
*p
)
4053 return type
->GetContentPropertyName ();
4056 XamlElementInstance
*
4057 XamlElementInfoNative::CreateElementInstance (XamlParserInfo
*p
)
4059 if (type
->IsValueType ())
4060 return new XamlElementInstanceValueType (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4061 else if (type
->IsSubclassOf (Type::FRAMEWORKTEMPLATE
))
4062 return new XamlElementInstanceTemplate (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4064 return new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4067 XamlElementInstance
*
4068 XamlElementInfoNative::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4070 XamlElementInstance
*res
= new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
, false);
4071 res
->SetDependencyObject (o
->AsDependencyObject ());
4077 XamlElementInstanceNative::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4079 if (IsDependencyObject ()) {
4080 const char *prop_name
= dot
+ 1;
4081 DependencyProperty
*prop
= DependencyProperty::GetDependencyProperty (info
->GetKind (), prop_name
);
4083 XamlElementInfoNative
*info
= new XamlElementInfoNative (Type::Find (prop
->GetPropertyType ()));
4084 info
->SetPropertyOwnerKind (prop
->GetOwnerType ());
4089 return XamlElementInstance::FindPropertyElement (p
, el
, dot
);
4092 XamlElementInstance
*
4093 XamlElementInfoNative::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4095 return new XamlElementInstanceNative (this, p
, name
, XamlElementInstance::PROPERTY
, false);
4098 XamlElementInstanceNative::XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
) :
4099 XamlElementInstance (element_info
, name
, type
)
4101 this->element_info
= element_info
;
4102 this->parser_info
= parser_info
;
4104 SetDependencyObject (CreateItem ());
4110 XamlElementInstanceNative::CreateItem ()
4112 XamlElementInstance
*walk
= parser_info
->current_element
;
4113 Type
*type
= element_info
->GetType ();
4115 DependencyObject
*item
= NULL
;
4116 DependencyProperty
*dep
= NULL
;
4118 if (type
->IsSubclassOf (Type::COLLECTION
) || type
->IsSubclassOf (Type::RESOURCE_DICTIONARY
)) {
4119 // If we are creating a collection, try walking up the element tree,
4120 // to find the parent that we belong to and using that instance for
4121 // our collection, instead of creating a new one
4123 // We attempt to advance past the property setter, because we might be dealing with a
4126 if (walk
&& walk
->element_type
== XamlElementInstance::PROPERTY
) {
4127 char **prop_name
= g_strsplit (walk
->element_name
, ".", -1);
4129 walk
= walk
->parent
;
4130 dep
= DependencyProperty::GetDependencyProperty (walk
->info
->GetKind (), prop_name
[1]);
4132 g_strfreev (prop_name
);
4133 } else if (walk
&& walk
->info
->GetContentProperty (parser_info
)) {
4134 dep
= DependencyProperty::GetDependencyProperty (walk
->info
->GetKind (),
4135 (char *) walk
->info
->GetContentProperty (parser_info
));
4138 if (dep
&& Type::IsSubclassOf (dep
->GetPropertyType(), type
->GetKind ())) {
4139 Value
*v
= ((DependencyObject
* ) walk
->GetAsDependencyObject ())->GetValue (dep
);
4141 item
= v
->AsDependencyObject ();
4144 // note: if !v then the default collection is NULL (e.g. PathFigureCollection)
4149 item
= element_info
->GetType()->IsCtorVisible() ? element_info
->GetType ()->CreateInstance () : NULL
;
4152 parser_info
->AddCreatedElement (item
);
4154 // in case we must store the collection into the parent
4155 if (dep
&& dep
->GetPropertyType() == type
->GetKind ()) {
4157 Value
item_value (item
);
4158 if (!((DependencyObject
* ) walk
->GetAsDependencyObject ())->SetValueWithError (dep
, &item_value
, &err
))
4159 parser_error (parser_info
, element_name
, NULL
, err
.code
, err
.message
);
4162 parser_error (parser_info
, element_name
, NULL
, 2007, "Unknown element: %s.", element_name
);
4170 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4172 if (property
->info
->RequiresManagedSet () || value
->info
->RequiresManagedSet ())
4173 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), NULL
);
4175 return dependency_object_set_property (p
, this, property
, value
, true);
4179 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4181 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4182 Type
*owner
= Type::Find (prop_name
[0]);
4183 DependencyProperty
*dep
;
4188 dep
= DependencyProperty::GetDependencyProperty (owner
->GetKind (), prop_name
[1]);
4192 return xaml_set_property_from_str (item
, dep
, value
, NULL
/*XXX*/);
4196 XamlElementInstanceNative::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4198 dependency_object_add_child (p
, this, child
, true);
4202 XamlElementInstanceNative::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4204 dependency_object_set_attributes (p
, this, attr
);
4208 XamlElementInstanceValueType::XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
) :
4209 XamlElementInstance (element_info
, name
, type
)
4211 this->element_info
= element_info
;
4212 this->parser_info
= parser_info
;
4216 XamlElementInstanceValueType::CreateValueItemFromString (const char* str
)
4219 bool res
= value_from_str (element_info
->GetType ()->GetKind (), NULL
, str
, &value
);
4224 XamlElementInstanceValueType::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4226 value_type_set_attributes (p
, this, attr
);
4229 XamlElementInstanceEnum::XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
) :
4230 XamlElementInstance (element_info
, name
, type
)
4235 XamlElementInstanceEnum::CreateEnumFromString (const char* str
)
4237 int i
= enums_str_to_int (element_name
, str
);
4241 value
= new Value (i
);
4246 XamlElementInstanceEnum::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4248 value_type_set_attributes (p
, this, attr
);
4251 XamlElementInstance
*
4252 XamlElementInfoEnum::CreateElementInstance (XamlParserInfo
*p
)
4254 return new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4257 XamlElementInstance
*
4258 XamlElementInfoEnum::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4260 XamlElementInstance
*res
= new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4265 XamlElementInfoManaged::GetContentProperty (XamlParserInfo
*p
)
4270 // TODO: We could cache this, but for now lets keep things as simple as possible.
4271 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4274 return XamlElementInfo::GetContentProperty (p
);
4277 XamlElementInstance
*
4278 XamlElementInfoManaged::CreateElementInstance (XamlParserInfo
*p
)
4280 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, obj
);
4282 if (obj
->Is (Type::DEPENDENCY_OBJECT
))
4283 p
->AddCreatedElement (inst
->GetAsDependencyObject ());
4288 XamlElementInstance
*
4289 XamlElementInfoManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4291 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, o
);
4296 XamlElementInstance
*
4297 XamlElementInfoManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4299 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4304 XamlElementInstanceManaged::XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
) :
4305 XamlElementInstance (info
, name
, type
)
4307 // The managed code owns our Value objects
4308 cleanup_value
= false;
4312 if (obj
->Is (Type::DEPENDENCY_OBJECT
)) {
4313 this->is_dependency_object
= true;
4314 this->SetDependencyObject (obj
->AsDependencyObject ());
4317 this->is_dependency_object
= false;
4321 XamlElementInstanceManaged::GetManagedPointer ()
4323 if (value
->Is (Type::DEPENDENCY_OBJECT
))
4324 return value
->AsDependencyObject ();
4325 return value
->AsManagedObject ();
4329 XamlElementInstanceManaged::GetParentPointer ()
4331 XamlElementInstance
*walk
= parent
;
4332 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
4333 walk
= walk
->parent
;
4339 return walk
->GetAsValue ();
4343 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4345 if (GetAsDependencyObject () != NULL
&& dependency_object_set_property (p
, this, property
, value
, false))
4347 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), value
);
4351 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4353 Value v
= Value (value
);
4354 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, &v
, NULL
);
4358 XamlElementInstanceManaged::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4360 if (element_type
== XamlElementInstance::PROPERTY
) {
4361 Value
*prop
= new Value (element_name
);
4362 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), true, info
->xmlns
, prop
, this, child
->GetAsValue (), child
);
4367 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), false, info
->xmlns
, GetAsValue (), this, child
->GetAsValue (), child
);
4371 XamlElementInstanceManaged::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4373 dependency_object_set_attributes (p
, this, attr
);
4377 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
4379 Value
*v
= value
->GetAsValue ();
4380 const char* prop_name
= info
->GetContentProperty (p
);
4382 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, v
, value
);
4386 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
4388 if (Type::IsSubclassOf (info
->GetKind (), Type::CONTENTCONTROL
)) {
4389 // Content controls are not allowed to have their content set as text, they need to have a child element
4390 // if you want to set the content of a contentcontrol to text you need to use attribute syntax
4394 if (!XamlElementInstance::TrySetContentProperty (p
, value
)) {
4395 const char* prop_name
= info
->GetContentProperty (p
);
4396 if (!p
->cdata_content
)
4398 Value v
= Value (value
);
4399 bool res
= p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, &v
, NULL
);
4406 XamlElementInstance
*
4407 XamlElementInfoImportedManaged::CreateElementInstance (XamlParserInfo
*p
)
4409 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::ELEMENT
, obj
);
4415 XamlElementInfoImportedManaged::GetContentProperty (XamlParserInfo
*p
)
4420 // TODO: Test, it's possible that managed objects that aren't DOs are allowed to have content properties.
4421 if (!obj
->Is (Type::DEPENDENCY_OBJECT
))
4422 return XamlElementInfo::GetContentProperty (p
);
4425 // TODO: We could cache this, but for now lets keep things as simple as possible.
4426 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4430 return XamlElementInfo::GetContentProperty (p
);
4433 XamlElementInstance
*
4434 XamlElementInfoImportedManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4436 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, Type::Find (o
->GetKind ())->GetName (), XamlElementInstance::ELEMENT
, o
);
4441 XamlElementInstance
*
4442 XamlElementInfoImportedManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4444 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4455 get_key_from_child (XamlElementInstance
*child
)
4457 const char *key
= child
->GetKey ();
4461 key
= child
->GetName ();
4465 if (child
->IsDependencyObject ()) {
4466 DependencyObject
*c
= child
->GetAsDependencyObject();
4468 if (Type::IsSubclassOf (Type::STYLE
, child
->info
->GetKind ())) {
4469 Value
*v
= c
->GetValue (Style::TargetTypeProperty
);
4470 if (v
&& v
->GetKind () == Type::MANAGEDTYPEINFO
)
4471 key
= v
->AsManagedTypeInfo ()->full_name
;
4482 dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
)
4484 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4485 if (parent
->element_type
== XamlElementInstance::PROPERTY
) {
4487 if (parent
->info
->RequiresManagedSet ())
4490 char **prop_name
= g_strsplit (parent
->element_name
, ".", -1);
4491 Type
*owner
= types
->Find (prop_name
[0]);
4494 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (owner
->GetKind (), prop_name
[1]);
4496 g_strfreev (prop_name
);
4499 g_warning ("Unknown element: %s.", parent
->element_name
);
4500 if (fail_if_no_prop
)
4501 parser_error (p
, parent
->element_name
, NULL
, 2007, "Unknown element: %s.", parent
->element_name
);
4505 // XamlElementInfoEnum has Type::INVALID as
4506 // its kind, which is why that first check is
4508 if (child
->info
->GetKind() != Type::MANAGED
&&
4509 !types
->Find (child
->info
->GetKind())->IsCtorVisible()) {
4510 // we can't instantiate this type
4511 return parser_error (p
, child
->element_name
, NULL
, 2007,
4512 "Unknown element: %s.", child
->element_name
);
4515 // Don't add the child element, if it is the entire collection
4516 if (dep
->GetPropertyType() == child
->info
->GetKind ())
4519 Type::Kind prop_type
= dep
->GetPropertyType ();
4520 if (!types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)
4521 && !types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
))
4524 // Most common case, we will have a parent that we can snag the collection from
4525 DependencyObject
*obj
= (DependencyObject
*) parent
->parent
->GetAsDependencyObject ();
4529 Value
*col_v
= obj
->GetValue (dep
);
4531 Type
*col_type
= types
->Find (prop_type
);
4532 DependencyObject
*c_obj
= col_type
->CreateInstance ();
4533 obj
->SetValue (dep
, Value::CreateUnrefPtr (c_obj
));
4534 col_v
= obj
->GetValue (dep
);
4537 Collection
*col
= col_v
->AsCollection ();
4540 if (types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4541 Value
child_val (child
->GetAsDependencyObject ());
4542 if (-1 == col
->AddWithError (&child_val
, &err
))
4543 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4545 else if (types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
)) {
4546 ResourceDictionary
*dict
= (ResourceDictionary
*)col
;
4548 const char *key
= get_key_from_child (child
);
4551 // XXX don't know the proper values here...
4552 return parser_error (p
, child
->element_name
, NULL
, 2007,
4553 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4556 Value
*child_as_value
= child
->GetAsValue ();
4558 if (!child_as_value
) {
4559 // XXX don't know the proper values here...
4560 return parser_error (p
, child
->element_name
, NULL
, 2007,
4561 "Error adding child to ResourceDictionary");
4564 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4566 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4575 if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4576 Collection
*col
= (Collection
*) parent
->GetAsDependencyObject ();
4578 Value
child_val ((DependencyObject
*)child
->GetAsDependencyObject ());
4580 if (-1 == col
->AddWithError (&child_val
, &err
))
4581 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4584 else if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
4585 ResourceDictionary
*dict
= (ResourceDictionary
*) parent
->GetAsDependencyObject ();
4588 const char *key
= get_key_from_child (child
);
4591 // XXX don't know the proper values here...
4592 return parser_error (p
, child
->element_name
, NULL
, 2007,
4593 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4596 Value
*child_as_value
= child
->GetAsValue ();
4597 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4599 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4603 if (parent
->element_type
!= XamlElementInstance::PROPERTY
) {
4604 parent
->TrySetContentProperty (p
, child
);
4607 // Do nothing if we aren't adding to a collection, or a content property collection
4612 /// set property funcs
4615 // these are just a bunch of special cases
4617 dependency_object_missed_property (XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
, char **prop_name
)
4623 set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
)
4628 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), prop
->info
->xmlns
, prop
->element_name
, value
->GetAsValue (), value
);
4632 dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
)
4634 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4635 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4636 DependencyProperty
*prop
= NULL
;
4638 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4640 if (types
->Find (item
->info
->GetKind ())->IsValueType ()) {
4641 if (raise_errors
) parser_error (p
, item
->element_name
, NULL
, -1, "Value types (%s) do not have properties.", property
->element_name
);
4642 g_strfreev (prop_name
);
4646 if (types
->Find (property
->info
->GetPropertyOwnerKind ())->IsCustomType ()) {
4647 g_strfreev (prop_name
);
4648 return set_managed_attached_property (p
, item
, property
, value
);
4652 // FIXME is this really where this check should live
4654 parser_error (p
, item
->element_name
, NULL
, 2030,
4655 "Property element %s cannot be used inside another property element.",
4656 property
->element_name
);
4658 g_strfreev (prop_name
);
4662 prop
= DependencyProperty::GetDependencyProperty (item
->info
->GetKind (), prop_name
[1]);
4665 if (prop
->IsReadOnly ()) {
4667 parser_error (p
, item
->element_name
, NULL
, 2014,
4668 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4670 } else if (types
->IsSubclassOf (value
->info
->GetKind (), prop
->GetPropertyType())) {
4671 // an empty collection can be NULL and valid
4672 if (item
->IsPropertySet (prop
->GetName())) {
4674 parser_error (p
, item
->element_name
, NULL
, 2033,
4675 "Cannot specify the value multiple times for property: %s.",
4676 property
->element_name
);
4681 // HACK - since the Setter is added to the collection *before* its properties are set
4682 // we find ourselves with a sealed Setter - which should not be possible at the parse time
4683 SetterBase
*sb
= NULL
;
4684 if (types
->IsSubclassOf (dep
->GetObjectType (), Type::SETTERBASE
)) {
4685 sb
= (SetterBase
*) dep
;
4686 sb
->SetIsSealed (false);
4689 if (!is_managed_kind (value
->info
->GetKind ()) && !value
->info
->RequiresManagedSet()) {
4690 if (!dep
->SetValueWithError (prop
, value
->GetAsValue (), &err
)) {
4692 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4698 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, prop_name
[1], value
->GetAsValue (), NULL
)) {
4700 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4707 // re-seal the Setter (end-HACK)
4709 sb
->SetIsSealed (true);
4711 item
->MarkPropertyAsSet (prop
->GetName());
4714 } else if (types
->IsSubclassOf (prop
->GetPropertyType (), Type::COLLECTION
) || types
->IsSubclassOf (prop
->GetPropertyType (), Type::RESOURCE_DICTIONARY
)) {
4715 // The items were added in add_child
4719 parser_error (p
, item
->element_name
, NULL
, 2010, "does not support %s as content.", value
->element_name
);
4723 dependency_object_missed_property (item
, property
, value
, prop_name
);
4728 g_strfreev (prop_name
);
4733 xaml_set_property_from_str (DependencyObject
*obj
, DependencyProperty
*prop
, const char *value
, MoonError
*error
)
4738 if (!value_from_str (prop
->GetPropertyType(), prop
->GetName(), value
, &v
))
4741 // it's possible for (a valid) value to be NULL (and we must keep the default value)
4743 rv
= obj
->SetValueWithError (prop
, v
, error
);
4751 xaml_is_valid_event_name (Type::Kind kind
, const char *name
, bool allow_desktop_events
)
4753 Type
*type
= Type::Find (kind
);
4757 int event_id
= type
->LookupEvent (name
);
4761 if (!allow_desktop_events
|| (moonlight_flags
& RUNTIME_INIT_DESKTOP_EXTENSIONS
) == 0) {
4762 // if we're not allowing desktop-only events, or if the user hasn't allowed them,
4763 // return false if the name corresponds to one of them.
4764 if (!strcmp (name
, "MouseRightButtonDown") ||
4765 !strcmp (name
, "MouseRightButtonUp") ||
4766 !strcmp (name
, "MouseWheel"))
4774 value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4776 // the only attributes value on value types seem to be x:Key
4777 // and x:Name, but reuse the generic namespace attribute stuff
4780 for (int i
= 0; attr
[i
]; i
+= 2) {
4782 if (attr
[i
+ 1] == NULL
|| attr
[i
+ 1][0] == '\0')
4785 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4787 if (attr_name
[1]) {
4789 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4792 return parser_error (p
, item
->element_name
, attr
[i
], 7055, "undeclared prefix");
4794 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4796 g_strfreev (attr_name
);
4798 // Setting managed attributes can cause errors galore
4805 g_strfreev (attr_name
);
4810 dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4812 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4813 GList
*delay_att
= NULL
;
4815 for (int i
= 0; attr
[i
]; i
+= 2) {
4820 // Setting attributes like x:Class can change item->item, so we
4821 // need to make sure we have an up to date pointer
4822 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4823 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4825 if (attr_name
[1]) {
4826 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4828 if (ns
!= x_namespace
) {
4829 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4830 g_strfreev (attr_name
);
4835 g_strfreev (attr_name
);
4836 return parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
4839 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4841 g_strfreev (attr_name
);
4843 // Setting managed attributes can cause errors galore
4850 g_strfreev (attr_name
);
4852 const char *pname
= attr
[i
];
4853 char *atchname
= NULL
;
4854 for (int a
= 0; attr
[i
][a
]; a
++) {
4855 if (attr
[i
][a
] != '.')
4857 atchname
= g_strndup (attr
[i
], a
);
4858 pname
= attr
[i
] + a
+ 1;
4862 DependencyProperty
*prop
= NULL
;
4864 Type
*attached_type
= types
->Find (atchname
);
4866 prop
= DependencyProperty::GetDependencyProperty (attached_type
->GetKind (), pname
);
4868 prop
= DependencyProperty::GetDependencyProperty (item
->info
->GetKind (), pname
);
4872 if (prop
->GetId () == DependencyObject::NameProperty
) {
4874 if (item
->GetName ()) {
4875 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
4879 // XXX toshok - I don't like doing this here... but it fixes airlines.
4880 item
->SetKey (p
, attr
[i
+1]);
4882 NameScope
*scope
= p
->namescope
;
4883 if (!item
->GetAsDependencyObject ()->SetName (attr
[i
+1], scope
)) {
4884 parser_error (p
, item
->element_name
, NULL
, 2028,
4885 "The name already exists in the tree: %s.", attr
[i
+1]);
4887 g_list_free (delay_att
);
4893 if (prop
->IsReadOnly ()) {
4894 parser_error (p
, item
->element_name
, NULL
, 2014,
4895 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4897 g_list_free (delay_att
);
4901 if (item
->IsPropertySet (prop
->GetName())) {
4902 parser_error (p
, item
->element_name
, attr
[i
], 2033,
4903 "Cannot specify the value multiple times for property: %s.", prop
->GetName ());
4905 g_list_free (delay_att
);
4911 char *attr_value
= g_strdup (attr
[i
+1]);
4913 bool need_managed
= false;
4914 if (attr
[i
+1][0] == '{') {
4915 if (attr
[i
+1][1] == '}') {
4916 // {} is an escape sequence so you can have strings like {StaticResource}
4917 char *nv
= attr_value
;
4918 attr_value
= g_strdup (attr_value
+ 2);
4921 else if (attr
[i
+1][strlen(attr
[i
+1]) - 1] == '}') {
4922 need_managed
= true;
4926 if (!need_managed
) {
4927 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
4929 g_free (attr_value
);
4934 Type::Kind propKind
= prop
->GetPropertyType ();
4935 Type::Kind itemKind
= item
->info
->GetKind();
4937 if (need_managed
|| is_managed_kind (propKind
) || types
->Find (itemKind
)->IsCustomType () || (v
&& is_managed_kind (v
->GetKind ()))) {
4938 bool str_value
= false;
4940 v
= new Value (attr
[i
+ 1]); // Note that we passed the non escaped value, not attr_value
4945 // printf ("setting managed property: %s::%s to %s=%s\n", dep->GetType ()->GetName (), prop->GetName (), attr [i], attr [i + 1]);
4946 if (p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, g_strdup (attr
[i
]), v
, NULL
)) {
4948 g_free (attr_value
);
4955 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
4957 g_free (attr_value
);
4964 if (!v_set
&& !value_is_explicit_null (attr
[i
+ 1])) { // Check the non escaped value
4965 parser_error (p
, item
->element_name
, attr
[i
], 2024, "Invalid attribute value %s for property %s.", attr
[i
+1], attr
[i
]);
4967 g_free (attr_value
);
4969 g_list_free (delay_att
);
4974 // printf ("settng: %s %s value type: %s prop type: %s\n", attr [i], attr [i+1], v ? Type::Find (v->GetKind ())->GetName () : "--null--", Type::Find (prop->GetPropertyType ())->GetName ());
4975 if (!dep
->SetValueWithError (prop
, v
, &err
))
4976 parser_error (p
, item
->element_name
, attr
[i
], err
.code
, err
.message
);
4978 item
->MarkPropertyAsSet (prop
->GetName());
4981 g_free (attr_value
);
4983 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4990 GList
*walk
= g_list_first (delay_att
);
4992 int i
= GPOINTER_TO_INT (walk
->data
);
4997 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4999 if (attr_name
[1]) {
5000 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
5002 if (ns
== x_namespace
) {
5003 // Skip these, they are handled earlier
5004 g_strfreev (attr_name
);
5009 g_strfreev (attr_name
);
5010 parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
5014 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
5016 g_strfreev (attr_name
);
5018 // Setting managed attributes can cause errors galore
5022 if (!item
->SetUnknownAttribute (p
, attr
[i
], attr
[i
+ 1])) {
5023 parser_error (p
, item
->element_name
, attr
[i
], 2012,
5024 "Unknown attribute %s on element %s.",
5025 attr
[i
], item
->element_name
);
5033 g_list_free (delay_att
);
5038 lookup_named_item (XamlElementInstance
*top
, const char *name
)
5040 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
5041 XamlElementInstance
*inst
= top
;
5044 if (inst
->element_type
== XamlElementInstance::ELEMENT
) {
5045 ResourceDictionary
*rd
= NULL
;
5046 Type::Kind kind
= inst
->info
->GetKind ();
5048 if (types
->IsSubclassOf (kind
, Type::FRAMEWORKELEMENT
)) {
5049 rd
= inst
->GetAsDependencyObject ()->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary ();
5050 } else if (types
->IsSubclassOf (kind
, Type::RESOURCE_DICTIONARY
)) {
5051 rd
= (ResourceDictionary
*) inst
->GetAsDependencyObject ();
5056 Value
*res
= lookup_resource_dictionary (rd
, name
, &exists
);
5062 inst
= inst
->parent
;
5069 lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
)
5072 Value
*resource_value
= rd
->Get (name
, exists
);
5073 return *exists
? new Value (*resource_value
) : NULL
;
5077 xaml_lookup_named_item (void *parser
, void *instance
, const char* name
)
5079 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5080 XamlElementInstance
*inst
= (XamlElementInstance
*) instance
;
5084 res
= lookup_named_item (inst
, name
);
5086 XamlContext
*context
= p
->loader
->GetContext ();
5087 if (!res
&& context
)
5088 context
->internal
->LookupNamedItem (name
, &res
);
5091 Application
*app
= Application::GetCurrent ();
5093 ResourceDictionary
*rd
= app
->GetResources ();
5095 bool exists
= false;
5096 res
= lookup_resource_dictionary (rd
, name
, &exists
);
5098 if (res
&& Type::IsSubclassOf (res
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
5099 DependencyObject
*dob
= res
->AsDependencyObject ();
5100 NameScope::SetNameScope (dob
, dob
->FindNameScope ());
5109 xaml_get_template_parent (void *parser
, void *element_instance
)
5111 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5112 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5114 return p
->GetTemplateParent (item
);
5118 xaml_get_element_key (void *parser
, void *element_instance
)
5120 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5121 const char *key
= item
->GetKey ();
5123 key
= item
->GetName ();
5124 return g_strdup (key
);
5128 xaml_get_element_name (void *parser
, void *element_instance
)
5130 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5131 return g_strdup (item
->element_name
);
5135 xaml_is_property_set (void *parser
, void *element_instance
, char *name
)
5137 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5138 return item
->IsPropertySet (name
);
5142 xaml_mark_property_as_set (void *parser
, void *element_instance
, char *name
)
5144 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5145 item
->MarkPropertyAsSet (g_strdup (name
));
5149 xaml_delay_set_property (void *parser
, void *element_instance
, const char *xmlns
, const char *name
, const Value
*value
)
5151 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5152 item
->DelaySetProperty (xmlns
, name
, value
);
5158 default_namespace
= new DefaultNamespace ();
5159 x_namespace
= new XNamespace ();
5160 xml_namespace
= new XmlNamespace ();