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"
54 #include "managedtypeinfo.h"
57 class XamlElementInfo
;
58 class XamlElementInstance
;
61 class DefaultNamespace
;
64 class PrimitiveNamespace
;
65 class MCIgnorableNamespace
;
66 class XamlElementInfoNative
;
67 class XamlElementInstanceNative
;
68 class XamlElementInstanceValueType
;
69 class XamlElementInfoEnum
;
70 class XamlElementInstanceEnum
;
71 class XamlElementInfoManaged
;
72 class XamlElementInstanceManaged
;
73 class XamlElementInfoImportedManaged
;
74 class XamlElementInstanceTemplate
;
76 #define INTERNAL_IGNORABLE_ELEMENT "MoonlightInternalIgnorableElement"
78 #define IS_NULL_OR_EMPTY(str) (!str || (*str == 0))
80 static DefaultNamespace
*default_namespace
= NULL
;
81 static XNamespace
*x_namespace
= NULL
;
82 static XmlNamespace
*xml_namespace
= NULL
;
84 static const char* default_namespace_names
[] = {
85 "http://schemas.microsoft.com/winfx/2006/xaml/presentation",
86 "http://schemas.microsoft.com/client/2007",
87 "http://schemas.microsoft.com/xps/2005/06",
88 "http://schemas.microsoft.com/client/2007/deployment",
92 #define X_NAMESPACE_URI "http://schemas.microsoft.com/winfx/2006/xaml"
93 #define XML_NAMESPACE_URI "http://www.w3.org/XML/1998/namespace"
94 #define PRIMITIVE_NAMESPACE_URI "clr-namespace:System;assembly=mscorlib"
95 #define MC_IGNORABLE_NAMESPACE_URI "http://schemas.openxmlformats.org/markup-compatibility/2006"
98 static bool value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
);
99 static bool dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
);
100 static bool set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
);
101 static void dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
);
102 static void dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
103 static void value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
104 static bool element_begins_buffering (Type::Kind kind
);
105 static bool is_managed_kind (Type::Kind kind
);
106 static bool kind_requires_managed_load (Type::Kind kind
);
107 static bool is_legal_top_level_kind (Type::Kind kind
);
108 static Value
*lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
);
109 static void parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...);
110 static gboolean
namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
);
112 static XamlElementInfo
*create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
);
113 static void destroy_created_namespace (gpointer data
, gpointer user_data
);
116 BUFFER_MODE_TEMPLATE
,
121 class XamlNamespace
{
132 virtual ~XamlNamespace () { }
133 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
) = 0;
134 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
) = 0;
136 virtual const char* GetUri () = 0;
137 virtual const char* GetPrefix () = 0;
141 add_namespace_data (gpointer key
, gpointer value
, gpointer user_data
)
143 XamlNamespace
*ns
= (XamlNamespace
*) value
;
144 GHashTable
*table
= (GHashTable
*) user_data
;
146 if ((void *)ns
!= (void *)default_namespace
)
147 g_hash_table_insert (table
, g_strdup (ns
->GetPrefix ()), g_strdup (ns
->GetUri ()));
151 add_namespace_to_ignorable (gpointer key
, gpointer value
, gpointer user_data
)
153 char *prefix
= (char *) key
;
154 char *uri
= (char *) value
;
155 GString
*str
= (GString
*) user_data
;
157 g_string_append_printf (str
, "xmlns:%s=\"%s\" ", prefix
, uri
);
160 class XamlContextInternal
{
164 FrameworkTemplate
*template_parent
;
165 GHashTable
*imported_namespaces
;
167 XamlLoaderCallbacks callbacks
;
169 XamlContextInternal
*parent_context
;
171 DependencyObject
*source
;
173 XamlContextInternal (XamlLoaderCallbacks callbacks
, Value
*top_element
, FrameworkTemplate
*template_parent
, GHashTable
*namespaces
, GSList
*resources
, XamlContextInternal
*parent_context
)
175 this->callbacks
= callbacks
;
176 this->top_element
= new Value (*top_element
);
177 this->template_parent
= template_parent
;
178 this->surface
= template_parent
->GetSurface ();
179 this->resources
= resources
;
180 this->parent_context
= parent_context
;
182 if (this->callbacks
.create_gchandle
)
183 this->callbacks
.create_gchandle ();
184 imported_namespaces
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
185 g_hash_table_foreach (namespaces
, add_namespace_data
, imported_namespaces
);
189 ~XamlContextInternal ()
191 if (imported_namespaces
)
192 g_hash_table_destroy (imported_namespaces
);
194 g_slist_free (resources
);
198 char *CreateIgnorableTagOpen ()
200 GString
*str
= g_string_new ("<" INTERNAL_IGNORABLE_ELEMENT
" ");
201 g_hash_table_foreach (imported_namespaces
, add_namespace_to_ignorable
, str
);
203 str
= g_string_append (str
, ">");
205 char *res
= str
->str
;
206 g_string_free (str
, false);
211 char *CreateIgnorableTagClose ()
213 return g_strdup ("</" INTERNAL_IGNORABLE_ELEMENT
">");
216 bool LookupNamedItem (const char* name
, Value
**v
)
222 GSList
*walk
= resources
;
224 DependencyObject
*dob
= (DependencyObject
*)walk
->data
;
225 if (dob
->Is (Type::RESOURCE_DICTIONARY
))
226 *v
= lookup_resource_dictionary ((ResourceDictionary
*) walk
->data
, name
, &exists
);
227 else /* dob->Is (Type::FRAMEWORKELEMENT) */ {
228 ResourceDictionary
*rd
= dob
->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary();
229 *v
= lookup_resource_dictionary (rd
, name
, &exists
);
239 else if (!parent_context
)
242 return parent_context
->LookupNamedItem (name
, v
);
245 void SetTemplateBindingSource (DependencyObject
*source
)
247 this->source
= source
;
250 DependencyObject
* GetTemplateBindingSource ()
257 XamlContext::XamlContext (XamlContextInternal
*internal
)
259 this->internal
= internal
;
262 XamlContext::~XamlContext ()
268 XamlContext::SetTemplateBindingSource (DependencyObject
*source
)
270 internal
->SetTemplateBindingSource (source
);
274 XamlContext::GetTemplateBindingSource ()
276 return internal
->GetTemplateBindingSource ();
279 class XamlElementInfo
{
282 Type::Kind property_owner_kind
;
286 XamlElementInfo
*parent
;
290 XamlElementInfo (const char *xmlns
, const char *name
, Type::Kind kind
)
296 this->cdata_verbatim
= false;
298 this->property_owner_kind
= Type::INVALID
;
305 virtual Type::Kind
GetKind () { return kind
; }
307 virtual void SetPropertyOwnerKind (Type::Kind value
) { property_owner_kind
= value
; }
308 virtual Type::Kind
GetPropertyOwnerKind () { return property_owner_kind
; }
310 virtual const char *GetContentProperty (XamlParserInfo
*p
)
312 Type
*t
= Type::Find (Deployment::GetCurrent (), kind
);
314 return t
->GetContentPropertyName ();
318 void SetIsCDataVerbatim (bool flag
)
320 cdata_verbatim
= flag
;
323 bool IsCDataVerbatim ()
325 return cdata_verbatim
;
328 virtual bool RequiresManagedSet () { return false; }
330 virtual XamlElementInstance
*CreateElementInstance (XamlParserInfo
*p
) = 0;
331 virtual XamlElementInstance
*CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
) = 0;
332 virtual XamlElementInstance
*CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) = 0;
336 struct DelayedProperty
{
341 DelayedProperty (const char *xmlns
, const char *name
, const Value
*value
)
343 this->xmlns
= g_strdup (xmlns
);
344 this->name
= g_strdup (name
);
345 this->value
= new Value (*value
);
357 free_property_list (GSList
*list
)
362 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
371 class XamlElementInstance
: public List::Node
{
374 DependencyObject
*item
;
377 GSList
*delayed_properties
;
380 const char *element_name
;
381 XamlElementInfo
*info
;
383 XamlElementInstance
*parent
;
393 bool requires_managed
;
397 GHashTable
*set_properties
;
399 XamlElementInstance (XamlElementInfo
*info
, const char* element_name
, ElementType type
, bool requires_managed
= false)
401 this->element_name
= element_name
;
402 this->set_properties
= NULL
;
403 this->element_type
= type
;
410 this->cleanup_value
= true;
411 this->requires_managed
= requires_managed
;
412 this->delayed_properties
= NULL
;
414 children
= new List ();
417 virtual ~XamlElementInstance ()
419 children
->Clear (true);
430 g_hash_table_destroy (set_properties
);
432 if (element_name
&& element_type
== PROPERTY
)
433 g_free ((void*) element_name
);
435 free_property_list (delayed_properties
);
438 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) = 0;
439 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
) = 0;
440 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) = 0;
441 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
) = 0;
443 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
444 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
447 char *GetKey () { return x_key
; }
448 char *GetName () { return x_name
; }
450 void SetName (XamlParserInfo
*p
, const char *name
)
452 this->x_name
= g_strdup (name
);
455 void SetKey (XamlParserInfo
*p
, const char *key
)
457 this->x_key
= g_strdup (key
);
460 virtual bool IsDependencyObject ()
465 virtual bool SetUnknownAttribute (XamlParserInfo
*p
, const char* name
, const char* value
);
467 void SetValue (Value
*v
)
469 if (value
&& cleanup_value
)
474 virtual Value
*GetAsValue ()
477 value
= new Value (item
);
482 virtual DependencyObject
*GetAsDependencyObject ()
487 virtual void SetDependencyObject (DependencyObject
*value
)
492 virtual void* GetManagedPointer ()
497 virtual Value
* GetParentPointer ()
499 XamlElementInstance
*walk
= parent
;
500 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
506 return walk
->GetAsValue ();
509 virtual bool IsTemplate ()
514 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
516 void SetDelayedProperties (XamlParserInfo
*p
);
518 void DelaySetProperty (const char *xmlns
, const char *name
, const Value
*value
)
520 DelayedProperty
*prop
= new DelayedProperty (xmlns
, name
, value
);
522 delayed_properties
= g_slist_append (delayed_properties
, prop
);
525 bool IsPropertySet (const char *name
)
530 return g_hash_table_lookup (set_properties
, name
) != NULL
;
533 void MarkPropertyAsSet (const char *name
)
536 set_properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
538 g_hash_table_insert (set_properties
, (void *) name
, GINT_TO_POINTER (TRUE
));
543 unref_xaml_element (gpointer data
, gpointer user_data
)
545 DependencyObject
* dob
= (DependencyObject
*) data
;
546 //printf ("unref_xaml_element: %i\n", dob->id);
551 class XamlParserInfo
{
555 const char *file_name
;
557 NameScope
*namescope
;
558 XamlElementInstance
*top_element
;
559 XamlNamespace
*current_namespace
;
560 XamlElementInstance
*current_element
;
561 const char *next_element
;
562 Deployment
*deployment
;
564 GHashTable
*namespace_map
;
568 bool implicit_default_namespace
;
570 ParserErrorEventArgs
*error_args
;
576 // If set, this is used to hydrate an existing object, not to create a new toplevel one
578 Value
*hydrate_expecting
;
581 char* buffer_until_element
;
583 BufferMode buffer_mode
;
585 bool validate_templates
;
588 GList
*created_elements
;
589 GList
*created_namespaces
;
590 const char* xml_buffer
;
591 int multi_buffer_offset
;
592 int xml_buffer_start_index
;
595 XamlParserInfo (XML_Parser parser
, const char *file_name
)
597 this->deployment
= Deployment::GetCurrent ();
598 this->parser
= parser
;
599 this->file_name
= file_name
;
600 this->namescope
= new NameScope ();
603 current_namespace
= NULL
;
604 current_element
= NULL
;
605 cdata_content
= false;
607 implicit_default_namespace
= false;
610 created_elements
= NULL
;
611 created_namespaces
= NULL
;
612 hydrate_expecting
= NULL
;
615 buffer_until_element
= NULL
;
619 multi_buffer_offset
= 0;
620 validate_templates
= false;
622 namespace_map
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
625 void AddCreatedElement (DependencyObject
* element
)
627 // if we have a loader, set the surface and base resource location
629 element
->SetSurface (loader
->GetSurface());
630 element
->SetResourceBase (loader
->GetResourceBase());
633 // When instantiating a template, some elements are created which are not explicitly
634 // mentioned in the xaml. Therefore we need to keep walking up the tree until we find
635 // the last element which we set a value for Control::IsTemplateItem and propagate
637 XamlElementInstance
*instance
= current_element
;
639 if (!instance
->IsDependencyObject () || !instance
->GetAsDependencyObject ()) {
640 instance
= instance
->parent
;
643 if (!instance
->GetAsDependencyObject ()->ReadLocalValue (Control::IsTemplateItemProperty
)) {
644 instance
= instance
->parent
;
647 Control::SetIsTemplateItem (element
, Control::GetIsTemplateItem (instance
->GetAsDependencyObject ()));
651 if (instance
== NULL
)
652 Control::SetIsTemplateItem (element
, loader
->GetExpandingTemplate ());
654 if (Control::GetIsTemplateItem (element
))
655 NameScope::SetNameScope (element
, namescope
);
656 created_elements
= g_list_prepend (created_elements
, element
);
659 void AddCreatedNamespace (XamlNamespace
* ns
)
661 created_namespaces
= g_list_prepend (created_namespaces
, ns
);
664 void QueueBeginBuffering (char* buffer_until
, BufferMode mode
)
666 buffer_until_element
= buffer_until
;
670 xml_buffer_start_index
= -1;
673 void BeginBuffering ()
675 xml_buffer_start_index
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
676 buffer
= g_string_new (NULL
);
679 bool ShouldBeginBuffering ()
681 return InBufferingMode () && xml_buffer_start_index
== -1;
684 bool InBufferingMode ()
686 return buffer_until_element
!= NULL
;
689 void AppendCurrentXml ()
693 int pos
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
694 g_string_append_len (buffer
, xml_buffer
+ xml_buffer_start_index
, pos
- xml_buffer_start_index
);
702 buffer_until_element
= NULL
;
705 return g_strdup ("");
707 char* res
= buffer
->str
;
708 g_string_free (buffer
, FALSE
);
713 void SetXmlBuffer (const char* xml_buffer
)
715 if (InBufferingMode ())
718 if (this->xml_buffer
)
719 multi_buffer_offset
+= strlen (this->xml_buffer
);
721 this->xml_buffer
= xml_buffer
;
722 xml_buffer_start_index
= 0;
725 void ValidateTemplate (const char* buffer
, XamlContext
* context
, FrameworkTemplate
*binding_source
)
727 XamlLoader
*loader
= new XamlLoader (NULL
, buffer
, NULL
, context
);
730 context
->SetTemplateBindingSource (binding_source
);
732 loader
->SetImportDefaultXmlns (true);
735 Value
*result
= loader
->CreateFromStringWithError (buffer
, true, &dummy
, XamlLoader::IMPORT_DEFAULT_XMLNS
| XamlLoader::VALIDATE_TEMPLATES
, &error
);
740 if (error
.number
!= MoonError::NO_ERROR
) {
741 int line_number
= error
.line_number
+ XML_GetCurrentLineNumber (parser
);
742 error_args
= new ParserErrorEventArgs (error
.message
, file_name
, line_number
, error
.char_position
, error
.code
, NULL
, NULL
);
746 FrameworkTemplate
*GetTemplateParent (XamlElementInstance
*item
)
748 XamlElementInstance
*parent
= item
->parent
;
750 while (parent
&& !parent
->IsTemplate ())
751 parent
= parent
->parent
;
754 return (FrameworkTemplate
*) parent
->GetManagedPointer ();
759 XamlContext
*context
= loader
->GetContext ();
763 return context
->internal
->template_parent
;
766 Value
*GetTopElementPtr ()
768 XamlContext
*context
= loader
->GetContext ();
770 return context
->internal
->top_element
;
773 return top_element
->GetAsValue ();
780 created_elements
= g_list_reverse (created_elements
);
781 g_list_foreach (created_elements
, unref_xaml_element
, NULL
);
782 g_list_free (created_elements
);
784 g_list_foreach (created_namespaces
, destroy_created_namespace
, NULL
);
785 g_list_free (created_namespaces
);
787 g_hash_table_destroy (namespace_map
);
790 g_string_free (cdata
, TRUE
);
800 class XamlElementInfoNative
: public XamlElementInfo
{
804 XamlElementInfoNative (Type
*t
) : XamlElementInfo (NULL
, t
->GetName (), t
->GetKind ())
814 const char* GetName ()
816 return type
->GetName ();
819 const char* GetContentProperty (XamlParserInfo
*p
);
821 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
822 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
823 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
827 class XamlElementInstanceNative
: public XamlElementInstance
{
828 XamlElementInfoNative
*element_info
;
829 XamlParserInfo
*parser_info
;
832 XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true);
834 virtual DependencyObject
*CreateItem ();
836 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
838 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
839 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
840 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
841 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
845 class XamlElementInstanceValueType
: public XamlElementInstance
{
846 XamlElementInfoNative
*element_info
;
847 XamlParserInfo
*parser_info
;
850 XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
);
852 virtual bool IsDependencyObject ()
857 virtual Value
*GetAsValue ()
860 // we are an empty element (e.g. <sys:String></sys:String>). do type specific magic here.
861 CreateValueItemFromString ("");
867 bool CreateValueItemFromString (const char* str
);
869 // A Value type doesn't really support anything. It's just here so people can do <SolidColorBrush.Color><Color>#FF00FF</Color></SolidColorBrush.Color>
870 virtual DependencyObject
*CreateItem () { return NULL
; }
871 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
872 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
873 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
874 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
876 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
877 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateValueItemFromString (value
); }
880 class XamlElementInfoEnum
: public XamlElementInfo
{
882 XamlElementInfoEnum (const char *name
) : XamlElementInfo (NULL
, name
, Type::INT32
)
886 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
887 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
888 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) { return NULL
; }
891 class XamlElementInstanceEnum
: public XamlElementInstance
{
894 XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
);
896 virtual bool IsDependencyObject ()
901 virtual Value
*GetAsValue ()
906 bool CreateEnumFromString (const char* str
);
908 // An enum type doesn't really support anything. It's just here so people can do <Visibility>Visible</Visibility>
909 virtual DependencyObject
*CreateItem () { return NULL
; }
910 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
911 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
912 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
913 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
915 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
916 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateEnumFromString (value
); }
919 class XamlElementInstanceTemplate
: public XamlElementInstanceNative
{
921 XamlElementInstanceTemplate (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true)
922 : XamlElementInstanceNative (element_info
, parser_info
, name
, type
, create_item
)
926 virtual bool IsTemplate ()
933 class DefaultNamespace
: public XamlNamespace
{
935 DefaultNamespace () { }
937 virtual ~DefaultNamespace () { }
939 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
941 Type
* t
= Type::Find (p
->deployment
, el
, false);
942 if (t
&& !kind_requires_managed_load (t
->GetKind ()))
943 return new XamlElementInfoNative (t
);
945 if (enums_is_enum_name (el
))
946 return new XamlElementInfoEnum (g_strdup (el
));
948 XamlElementInfo
* managed_element
= create_element_info_from_imported_managed_type (p
, el
, attr
, create
);
950 return managed_element
;
956 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
961 virtual const char* GetUri () { return "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; }
962 virtual const char* GetPrefix () { return ""; }
965 class XmlNamespace
: public XamlNamespace
{
969 virtual ~XmlNamespace () { }
971 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
976 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
978 if (!strcmp ("lang", attr
)) {
979 if (item
->IsDependencyObject ()) {
980 DependencyObject
*dob
= item
->GetAsDependencyObject ();
981 if (dob
->Is(Type::FRAMEWORKELEMENT
)) {
982 ((FrameworkElement
*)dob
)->SetLanguage (value
);
991 virtual const char* GetUri () { return "http://www.w3.org/XML/1998/namespace"; }
992 virtual const char* GetPrefix () { return "xml"; }
995 class XNamespace
: public XamlNamespace
{
999 virtual ~XNamespace () { }
1001 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1006 virtual char *FindTypeName (const char **attr
, char **xmlns
)
1013 for (int i
= 0; attr
[i
]; i
+= 2) {
1014 const char *ns
= strchr (attr
[i
], '|');
1018 if (strncmp (GetUri (), attr
[i
], ns
- attr
[i
]) || strcmp ("Class", ns
+ 1))
1021 ns
= strchr (attr
[i
+ 1], ';');
1023 *xmlns
= g_strdup ("");
1024 res
= g_strdup (attr
[i
+ 1]);
1026 *xmlns
= g_strdup (ns
+ 1);
1027 res
= g_strndup (attr
[i
+ 1], attr
[i
+ 1] - ns
);
1034 bool IsParentResourceDictionary (XamlElementInstance
*parent
)
1039 return Type::IsSubclassOf (Deployment::GetCurrent (), parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
);
1042 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1044 if (!strcmp ("Name", attr
)) {
1046 // Causes breakage in airlines
1047 // Maybe x:Name overwrites but Name does not?
1049 // if (p->namescope->FindName (value)) {
1050 // parser_error (p, p->current_element->element_name, "x:Name", 2028, "The name already exists in the tree: %s.", value);
1055 if (IsParentResourceDictionary (p
->current_element
)) {
1056 if (item
->GetKey ()) {
1057 // XXX don't know the proper values here...
1058 parser_error (p
, item
->element_name
, NULL
, 2028,
1059 "The name already exists in the tree: %s.", value
);
1064 if (item
->GetName ()) {
1065 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
1069 item
->SetName (p
, value
);
1071 if (item
->IsDependencyObject ()) {
1072 NameScope
*scope
= p
->namescope
;
1073 if (!item
->GetAsDependencyObject ()->SetName (value
, scope
)) {
1074 if (IsParentResourceDictionary (p
->current_element
)) {
1075 // FIXME: inside of a resource dictionary this has an extremly
1076 // strange behavior. this isn't exactly right, since not only
1077 // does the exception get swallowed, but the name seems to also
1081 parser_error (p
, item
->element_name
, NULL
, 2028,
1082 "The name already exists in the tree: %s.", value
);
1092 if (!strcmp ("Key", attr
)) {
1093 if (item
->GetKey () && IsParentResourceDictionary (p
->current_element
) && !Type::IsSubclassOf (p
->deployment
, item
->info
->GetKind (), Type::STORYBOARD
)) {
1094 // XXX don't know the proper values here...
1095 parser_error (p
, item
->element_name
, NULL
, 2028,
1096 "The name already exists in the tree: %s.", value
);
1099 item
->SetKey (p
, value
);
1103 if (!strcmp ("Class", attr
)) {
1104 if (!is_legal_top_level_kind (item
->info
->GetKind ())) {
1105 // XXX don't know the proper values here...
1106 parser_error (p
, item
->element_name
, attr
, -1,
1107 "Cannot specify x:Class type '%s' on value type element (%s).", value
, item
->element_name
);
1111 if (p
->top_element
!= item
) {
1112 // HAH: what a useless error message
1113 parser_error (p
, item
->element_name
, attr
, 2012,
1114 "Unknown attribute %s on element %s.", attr
, item
->element_name
);
1118 // While hydrating, we do not need to create the toplevel class, its created already
1122 parser_error (p
, item
->element_name
, attr
, 4005,
1123 "Cannot specify x:Class in xaml files outside of a xap.");
1131 virtual const char* GetUri () { return X_NAMESPACE_URI
; }
1132 virtual const char* GetPrefix () { return "x"; }
1136 class PrimitiveNamespace
: public XamlNamespace
{
1143 PrimitiveNamespace (char *prefix
)
1145 this->prefix
= prefix
;
1148 virtual ~PrimitiveNamespace ()
1154 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1156 if (!strcmp ("String", el
)) {
1157 Type
* t
= Type::Find (p
->deployment
, Type::STRING
);
1158 // it's not as easy in this case, because primitive clr strings require that the
1159 // character data be read in verbatim, including all whitespace.
1160 XamlElementInfo
*info
= new XamlElementInfoNative (t
);
1161 info
->SetIsCDataVerbatim (true);
1163 } else if (!strcmp ("Int32", el
)) {
1164 Type
* t
= Type::Find (p
->deployment
, Type::INT32
);
1165 return new XamlElementInfoNative (t
);
1166 } else if (!strcmp ("Double", el
)) {
1167 Type
* t
= Type::Find (p
->deployment
, Type::DOUBLE
);
1168 return new XamlElementInfoNative (t
);
1169 } else if (!strcmp ("Boolean", el
)) {
1170 Type
* t
= Type::Find (p
->deployment
, Type::BOOL
);
1171 return new XamlElementInfoNative (t
);
1172 } else if (!strcmp ("TimeSpan", el
)) {
1173 Type
* t
= Type::Find (p
->deployment
, Type::TIMESPAN
);
1174 return new XamlElementInfoNative (t
);
1180 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1185 virtual const char* GetUri () { return PRIMITIVE_NAMESPACE_URI
; }
1186 virtual const char* GetPrefix () { return prefix
; }
1190 class MCIgnorableNamespace
: public XamlNamespace
{
1196 MCIgnorableNamespace (char *prefix
)
1198 this->prefix
= prefix
;
1201 virtual ~MCIgnorableNamespace ()
1207 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1212 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1214 if (!strcmp ("Ignorable", attr
)) {
1215 const char *start
= value
;
1217 const char *space
= strchr (start
, ' ');
1220 prefix
= g_strndup (start
, space
- start
);
1223 prefix
= g_strdup (start
);
1227 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1229 ns
->is_ignored
= true;
1239 virtual const char* GetUri () { return MC_IGNORABLE_NAMESPACE_URI
; }
1240 virtual const char* GetPrefix () { return prefix
; }
1245 destroy_created_namespace (gpointer data
, gpointer user_data
)
1247 XamlNamespace
* ns
= (XamlNamespace
*) data
;
1252 class XamlElementInfoManaged
: public XamlElementInfo
{
1254 XamlElementInfoManaged (const char *xmlns
, const char *name
, XamlElementInfo
*parent
, Type::Kind dependency_type
, Value
*obj
) : XamlElementInfo (xmlns
, name
, dependency_type
)
1261 const char* GetName () { return name
; }
1263 const char* GetContentProperty (XamlParserInfo
*p
);
1265 virtual bool RequiresManagedSet () { return true; }
1267 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1268 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1269 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1273 class XamlElementInstanceManaged
: public XamlElementInstance
{
1275 XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
);
1277 virtual bool IsDependencyObject ()
1279 return is_dependency_object
;
1282 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
1283 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
1284 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
1285 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
1287 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
1288 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
1290 virtual void* GetManagedPointer ();
1291 virtual Value
* GetParentPointer ();
1293 bool is_dependency_object
;
1297 class XamlElementInfoImportedManaged
: public XamlElementInfoManaged
{
1299 XamlElementInfoImportedManaged (const char *name
, XamlElementInfo
*parent
, Value
*obj
) : XamlElementInfoManaged (NULL
, name
, parent
, obj
->GetKind (), obj
)
1303 const char* GetContentProperty (XamlParserInfo
*p
);
1305 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1306 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1307 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1312 class ManagedNamespace
: public XamlNamespace
{
1317 ManagedNamespace (char *xmlns
, char *prefix
)
1319 this->xmlns
= xmlns
;
1320 this->prefix
= prefix
;
1323 virtual ~ManagedNamespace ()
1329 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1331 char* type_name
= NULL
;
1332 char* type_xmlns
= NULL
;
1333 const char* use_xmlns
= xmlns
;
1339 // We might have an x:Class attribute specified, so we need to use that for the
1340 // type_name that we pass to LookupObject
1341 if (strcmp ("Application", el
)) {
1342 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
1345 use_xmlns
= type_xmlns
;
1347 if (!p
->hydrating
) {
1348 parser_error (p
, el
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
1355 Value
*value
= new Value ();
1356 if (!p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), p
->current_element
? p
->current_element
->GetAsValue () : NULL
, use_xmlns
, el
, create
, false, value
)) {
1357 parser_error (p
, el
, NULL
, 2007, "Unable to resolve managed type %s.", el
);
1362 g_free (type_xmlns
);
1366 if (p
->hydrate_expecting
) {
1368 // If we are hydrating a top level managed object, use the Value* passed
1369 // to Hydrate as our value
1372 value
= p
->hydrate_expecting
;
1376 XamlElementInfoManaged
*info
= new XamlElementInfoManaged (xmlns
, g_strdup (el
), NULL
, value
->GetKind (), value
);
1380 g_free (type_xmlns
);
1384 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1390 Value v
= Value (value
);
1391 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), xmlns
, attr
, &v
, NULL
);
1397 virtual const char* GetUri () { return xmlns
; }
1398 virtual const char* GetPrefix () { return prefix
; }
1402 XamlLoader::LookupObject (void *p
, Value
*top_level
, Value
*parent
, const char* xmlns
, const char* type_name
, bool create
, bool is_property
, Value
*value
)
1404 if (callbacks
.lookup_object
) {
1405 if (!vm_loaded
&& !LoadVM ())
1408 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1409 bool res
= callbacks
.lookup_object (&data
, parent
, xmlns
, type_name
, create
, is_property
, value
, &error
);
1417 XamlLoader::GetContentPropertyName (void *p
, Value
*top_level
, Value
*object
)
1419 if (callbacks
.get_content_property_name
) {
1421 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1422 return callbacks
.get_content_property_name (&data
, object
, &error
);
1428 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
)
1430 if (callbacks
.set_property
) {
1432 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
, flags
);
1433 bool res
= callbacks
.set_property (&data
, xmlns
, target
, target_data
, target_parent
, prop_xmlns
, name
, value
, value_data
, &error
);
1435 if (error
.number
!= MoonError::NO_ERROR
) {
1436 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) target_data
)->element_name
, NULL
, error
.code
, error
.message
);
1447 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
)
1449 if (callbacks
.add_child
) {
1451 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1452 bool res
= callbacks
.add_child (&data
, parent_parent
, parent_is_property
, parent_xmlns
, parent
, parent_data
, child
, child_data
, &error
);
1454 if (error
.number
!= MoonError::NO_ERROR
) {
1455 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) child_data
)->element_name
, NULL
, error
.code
, error
.message
);
1464 XamlLoader::XamlLoader (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1466 Initialize (resourceBase
, filename
, str
, surface
, context
);
1469 XamlLoader::XamlLoader (const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1471 Initialize (NULL
, filename
, str
, surface
, context
);
1475 XamlLoader::Initialize (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1477 this->filename
= g_strdup (filename
);
1478 this->resource_base
= g_strdup (resourceBase
);
1479 this->str
= g_strdup (str
);
1480 this->surface
= surface
;
1483 this->context
= context
;
1484 this->vm_loaded
= false;
1485 this->error_args
= NULL
;
1486 this->expanding_template
= false;
1487 this->import_default_xmlns
= false;
1490 callbacks
= context
->internal
->callbacks
;
1491 this->vm_loaded
= true;
1493 if (!surface
&& context
->internal
->surface
) {
1494 this->surface
= context
->internal
->surface
;
1495 this->surface
->ref ();
1499 if (!surface
&& debug_flags
& RUNTIME_DEBUG_XAML
) {
1500 printf ("XamlLoader::XamlLoader ('%s', '%s', %p): Initializing XamlLoader without a surface.\n",
1501 filename
, str
, surface
);
1506 XamlLoader::~XamlLoader ()
1509 g_free (resource_base
);
1517 error_args
->unref();
1521 XamlLoader::LoadVM ()
1527 xaml_loader_new (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
)
1529 return new XamlLoader (resourceBase
, filename
, str
, surface
);
1533 xaml_loader_free (XamlLoader
* loader
)
1539 xaml_loader_set_callbacks (XamlLoader
* loader
, XamlLoaderCallbacks callbacks
)
1542 LOG_XAML ("Trying to set callbacks for a null object\n");
1546 loader
->callbacks
= callbacks
;
1547 loader
->vm_loaded
= true;
1551 namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
)
1553 XamlNamespace
*ns
= (XamlNamespace
*) value
;
1554 const char *prefix
= (const char *) user_data
;
1556 if (!strcmp (prefix
, ns
->GetPrefix ()))
1562 xaml_uri_for_prefix (void *parser
, char* prefix
)
1564 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
1566 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1570 return g_strdup (ns
->GetUri ());
1574 // Called when we encounter an error. Note that memory ownership is taken for everything
1575 // except the message, this allows you to use g_strdup_printf when creating the error message
1578 parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...)
1587 // if parsing fails too early it's not safe (i.e. sigsegv) to call some functions, e.g. XML_GetCurrentLineNumber
1588 bool report_line_col
= (error_code
!= XML_ERROR_XML_DECL
);
1589 int line_number
= report_line_col
? XML_GetCurrentLineNumber (p
->parser
) : 0;
1590 int char_position
= report_line_col
? XML_GetCurrentColumnNumber (p
->parser
) : 0;
1592 va_start (args
, format
);
1593 message
= g_strdup_vprintf (format
, args
);
1596 p
->error_args
= new ParserErrorEventArgs (message
, p
->file_name
, line_number
, char_position
, error_code
, el
, attr
);
1600 LOG_XAML ("PARSER ERROR, STOPPING PARSING: (%d) %s line: %d char: %d\n", error_code
, message
,
1601 line_number
, char_position
);
1603 XML_StopParser (p
->parser
, FALSE
);
1607 expat_parser_error (XamlParserInfo
*p
, XML_Error expat_error
)
1609 // Already had an error
1613 LOG_XAML ("expat error is: %d\n", expat_error
);
1615 switch (expat_error
) {
1616 case XML_ERROR_DUPLICATE_ATTRIBUTE
:
1617 parser_error (p
, NULL
, NULL
, 7031, "wfc: unique attribute spec");
1619 case XML_ERROR_UNBOUND_PREFIX
:
1620 parser_error (p
, NULL
, NULL
, 7055, "undeclared prefix");
1622 case XML_ERROR_NO_ELEMENTS
:
1623 parser_error (p
, NULL
, NULL
, 7000, "unexpected end of input");
1625 case XML_ERROR_SYNTAX
:
1626 parser_error (p
, NULL
, NULL
, 2103, "syntax error");
1629 parser_error (p
, NULL
, NULL
, expat_error
, "Unhandled XML error %s", XML_ErrorString (expat_error
));
1635 start_element (void *data
, const char *el
, const char **attr
)
1637 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1638 XamlElementInfo
*elem
= NULL
;
1639 XamlElementInstance
*inst
;
1640 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
1642 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1645 if (p
->ShouldBeginBuffering ()) {
1646 p
->BeginBuffering ();
1650 if (p
->InBufferingMode ()) {
1651 if (!strcmp (p
->buffer_until_element
, el
))
1656 const char *dot
= strchr (el
, '.');
1658 elem
= p
->current_namespace
->FindElement (p
, el
, attr
, p
->hydrate_expecting
== NULL
);
1665 if (p
->hydrate_expecting
){
1667 Type::Kind expecting_type = p->hydrate_expecting->GetObjectType ();
1669 if (!types->IsSubclassOf (expecting_type, elem->GetKind ())) {
1670 parser_error (p, el, NULL, -1, "Invalid top-level element found %s, expecting %s", el,
1671 types->Find (expecting_type)->GetName ());
1676 inst
= elem
->CreateWrappedElementInstance (p
, p
->hydrate_expecting
);
1677 p
->hydrate_expecting
= NULL
;
1679 inst
= elem
->CreateElementInstance (p
);
1684 inst
->parent
= p
->current_element
;
1686 if (!p
->top_element
) {
1687 p
->top_element
= inst
;
1688 if (inst
->GetAsDependencyObject ())
1689 NameScope::SetNameScope (inst
->GetAsDependencyObject (), p
->namescope
);
1692 if (inst
->GetAsDependencyObject ())
1693 inst
->GetAsDependencyObject ()->SetIsBeingParsed (true);
1695 inst
->SetAttributes (p
, attr
);
1699 if (inst
->IsDependencyObject ()) {
1700 if (p
->current_element
){
1701 if (p
->current_element
->info
) {
1702 p
->current_element
->AddChild (p
, inst
);
1709 // it's actually valid (from SL point of view) to have <Ellipse.Triggers> inside a <Rectangle>
1710 // however we can't add properties to something bad, like a <Recta.gle> element
1711 XamlElementInfo
*prop_info
= NULL
;
1713 gchar
*prop_elem
= g_strndup (el
, dot
- el
);
1714 prop_info
= p
->current_element
->FindPropertyElement (p
, el
, dot
);
1718 if (prop_info
!= NULL
) {
1719 inst
= prop_info
->CreatePropertyElementInstance (p
, g_strdup (el
));
1720 inst
->parent
= p
->current_element
;
1722 if (attr
[0] != NULL
) {
1723 // It appears there is a bug in the error string but it matches the MS runtime
1724 parser_error (p
, el
, NULL
, 2018, "The element %s does not support attributes.", attr
[0]);
1728 if (prop_info
&& !strcmp (el
, "TextBox.Text"))
1729 prop_info
->SetIsCDataVerbatim (true);
1731 if (!p
->top_element
) {
1732 if (types
->IsSubclassOf (prop_info
->GetKind (), Type::COLLECTION
)) {
1733 XamlElementInstance
*wrap
= prop_info
->CreateElementInstance (p
);
1734 NameScope::SetNameScope (wrap
->GetAsDependencyObject (), p
->namescope
);
1735 p
->top_element
= wrap
;
1736 p
->current_element
= wrap
;
1741 g_warning ("Unknown element: %s.", el
);
1742 parser_error (p
, el
, NULL
, 2007, "Unknown element: %s.", el
);
1747 if (p
->current_element
) {
1748 p
->current_element
->children
->Append (inst
);
1750 p
->current_element
= inst
;
1752 if (elem
&& element_begins_buffering (elem
->GetKind ())) {
1753 p
->QueueBeginBuffering (g_strdup (el
), BUFFER_MODE_TEMPLATE
);
1758 allow_value_from_str_in_flush (XamlParserInfo
*p
, XamlElementInstance
*parent
)
1760 if (parent
== NULL
|| parent
->element_type
!= XamlElementInstance::PROPERTY
|| parent
->parent
== NULL
|| !parent
->parent
->IsDependencyObject ())
1763 if (parent
->info
->GetKind () == Type::OBJECT
)
1770 flush_char_data (XamlParserInfo
*p
)
1772 if (p
->InBufferingMode ())
1775 if (!p
->cdata
|| !p
->current_element
)
1778 if (p
->current_element
->info
->IsCDataVerbatim()) {
1779 p
->cdata
->str
= g_strstrip (p
->cdata
->str
);
1782 if (p
->current_element
->element_type
== XamlElementInstance::ELEMENT
) {
1783 if (!p
->current_element
->TrySetContentProperty (p
, p
->cdata
->str
) && p
->cdata_content
) {
1784 if (allow_value_from_str_in_flush (p
, p
->current_element
->parent
)) {
1786 if (value_from_str (p
->current_element
->info
->GetKind (), NULL
, p
->cdata
->str
, &v
)) {
1787 p
->current_element
->SetValue (v
);
1791 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1792 "%s does not support text content.", p
->current_element
->element_name
);
1794 } else if (p
->current_element
->element_type
== XamlElementInstance::PROPERTY
) {
1795 if (p
->cdata_content
&& p
->current_element
->parent
&& !p
->current_element
->parent
->SetProperty (p
, p
->current_element
, p
->cdata
->str
)) {
1796 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1797 "%s does not support text content.", p
->current_element
->element_name
);
1803 g_string_free (p
->cdata
, TRUE
);
1804 p
->cdata_content
= false;
1810 element_begins_buffering (Type::Kind kind
)
1812 return Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::FRAMEWORKTEMPLATE
);
1816 is_default_namespace (gpointer key
, gpointer value
, gpointer user_data
)
1818 return value
== default_namespace
;
1822 start_element_handler (void *data
, const char *el
, const char **attr
)
1824 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1829 char **name
= g_strsplit (el
, "|", -1);
1830 XamlNamespace
*next_namespace
= NULL
;
1831 char *element
= NULL
;
1833 if (g_strv_length (name
) == 2) {
1834 // Find the proper namespace for our next element
1835 next_namespace
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, name
[0]);
1839 if (!next_namespace
&& p
->implicit_default_namespace
) {
1840 // Use the default namespace for the next element
1841 next_namespace
= default_namespace
;
1843 } else if (!next_namespace
) {
1844 if (!g_hash_table_find (p
->namespace_map
, is_default_namespace
, NULL
))
1845 return parser_error (p
, el
, NULL
, 2263, "AG_E_PARSER_MISSING_DEFAULT_NAMESPACE");
1848 if (next_namespace
&& next_namespace
->is_ignored
) {
1849 p
->current_namespace
= next_namespace
;
1850 if (!p
->InBufferingMode ())
1851 p
->QueueBeginBuffering (g_strdup (element
), BUFFER_MODE_IGNORE
);
1853 start_element (data
, element
, attr
); // This will force the buffering to start/build depth if needed
1857 p
->next_element
= element
;
1859 flush_char_data (p
);
1861 // Now update our namespace
1862 p
->current_namespace
= next_namespace
;
1864 if (!p
->current_namespace
&& !p
->InBufferingMode ()) {
1866 parser_error (p
, name
[1], NULL
, -1, "No handlers available for namespace: '%s' (%s)\n", name
[0], el
);
1868 parser_error (p
, name
[1], NULL
, -1, "No namespace mapping available for element: '%s'\n", el
);
1874 p
->next_element
= NULL
;
1875 start_element (data
, element
, attr
);
1881 get_element_name (XamlParserInfo
* p
, const char *el
)
1883 char **names
= g_strsplit (el
, "|", -1);
1884 char *name
= g_strdup (names
[g_strv_length (names
) - 1]);
1892 create_resource_list (XamlParserInfo
*p
)
1894 GSList
*list
= NULL
;
1895 XamlElementInstance
*walk
= p
->current_element
;
1897 Types
* types
= Deployment::GetCurrent ()->GetTypes ();
1899 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::FRAMEWORKELEMENT
)) {
1900 FrameworkElement
*fwe
= (FrameworkElement
*)walk
->GetAsDependencyObject ();
1901 if (g_slist_index (list
, fwe
) == -1)
1902 list
= g_slist_prepend (list
, fwe
);
1904 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
1905 ResourceDictionary
*rd
= (ResourceDictionary
*) walk
->GetAsDependencyObject ();
1906 if (g_slist_index (list
, rd
) == -1)
1907 list
= g_slist_prepend (list
, walk
->GetAsDependencyObject ());
1909 walk
= walk
->parent
;
1912 list
= g_slist_reverse (list
);
1916 static XamlContext
*
1917 create_xaml_context (XamlParserInfo
*p
, FrameworkTemplate
*template_
, XamlContext
*parent_context
)
1919 GSList
*resources
= create_resource_list (p
);
1920 XamlContextInternal
*ic
= new XamlContextInternal (p
->loader
->callbacks
, p
->GetTopElementPtr (), template_
, p
->namespace_map
, resources
, parent_context
? parent_context
->internal
: NULL
);
1921 return new XamlContext (ic
);
1925 end_element_handler (void *data
, const char *el
)
1927 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1928 DependencyObject
*obj
;
1930 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1936 if (!p
->current_element
) {
1937 g_warning ("p->current_element == NULL, current_element = %p (%s)\n",
1938 p
->current_element
, p
->current_element
? p
->current_element
->element_name
: "<NULL>");
1942 if (p
->InBufferingMode ()) {
1943 char* name
= get_element_name (p
, el
);
1944 if (!strcmp (p
->buffer_until_element
, name
)) {
1947 if (p
->buffer_depth
== 0) {
1948 if (p
->buffer_mode
== BUFFER_MODE_TEMPLATE
) {
1949 // OK we are done buffering, the element we are buffering for
1950 FrameworkTemplate
* template_
= (FrameworkTemplate
*) p
->current_element
->GetAsDependencyObject ();
1952 char* buffer
= p
->ClearBuffer ();
1954 XamlContext
*context
= create_xaml_context (p
, template_
, p
->loader
->GetContext());
1956 if (p
->validate_templates
) {
1957 p
->ValidateTemplate (buffer
, context
, template_
);
1963 template_
->SetXamlBuffer (context
, buffer
);
1964 p
->current_element
= p
->current_element
->parent
;
1965 } else if (p
->buffer_mode
== BUFFER_MODE_IGNORE
) {
1966 // For now we'll actually keep/clear this buffer because it makes testing easier
1967 char *buffer
= p
->ClearBuffer ();
1977 switch (p
->current_element
->element_type
) {
1978 case XamlElementInstance::ELEMENT
:
1980 p
->current_element
->SetDelayedProperties (p
);
1981 flush_char_data (p
);
1983 // according to http://blogs.msdn.com/devdave/archive/2008/10/11/control-lifecycle.aspx
1984 // default styles are apply when the end tag is read.
1986 if (p
->current_element
->IsDependencyObject () &&
1987 p
->current_element
->GetAsDependencyObject() &&
1988 p
->current_element
->GetAsDependencyObject()->Is(Type::CONTROL
)) {
1990 Control
*control
= (Control
*)p
->current_element
->GetAsDependencyObject();
1991 ManagedTypeInfo
*key
= control
->GetDefaultStyleKey ();
1994 if (Application::GetCurrent () == NULL
)
1995 g_warning ("attempting to use a null application applying default style while parsing.");
1997 Application::GetCurrent()->ApplyDefaultStyle (control
, key
);
2000 else if (!p
->current_element
->IsDependencyObject ()) {
2002 if (p
->current_element
->parent
)
2003 p
->current_element
->parent
->AddChild (p
, p
->current_element
);
2006 case XamlElementInstance::PROPERTY
: {
2007 List::Node
*walk
= p
->current_element
->children
->First ();
2009 XamlElementInstance
*child
= (XamlElementInstance
*) walk
;
2010 if (p
->current_element
->parent
) {
2011 p
->current_element
->parent
->SetProperty (p
, p
->current_element
, child
);
2015 flush_char_data (p
);
2020 if ((obj
= p
->current_element
->GetAsDependencyObject ()))
2021 obj
->SetIsBeingParsed (false);
2023 p
->current_element
= p
->current_element
->parent
;
2027 char_data_handler (void *data
, const char *in
, int inlen
)
2029 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2030 register const char *inptr
= in
;
2031 const char *inend
= in
+ inlen
;
2034 if (p
->InBufferingMode ())
2040 if (p
->current_element
&& p
->current_element
->info
->IsCDataVerbatim()) {
2042 p
->cdata
= g_string_new ("");
2044 g_string_append_len (p
->cdata
, inptr
, inlen
);
2045 p
->cdata_content
= true;
2050 p
->cdata
= g_string_new ("");
2052 if (g_ascii_isspace (*inptr
)) {
2053 g_string_append_c (p
->cdata
, ' ');
2056 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2062 } else if (g_ascii_isspace (p
->cdata
->str
[p
->cdata
->len
- 1])) {
2063 // previous cdata chunk ended with lwsp, skip over leading lwsp for this chunk
2064 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2068 while (inptr
< inend
) {
2070 while (inptr
< inend
&& !g_ascii_isspace (*inptr
))
2073 if (inptr
> start
) {
2074 g_string_append_len (p
->cdata
, start
, inptr
- start
);
2075 p
->cdata_content
= true;
2078 if (inptr
< inend
) {
2079 g_string_append_c (p
->cdata
, ' ');
2082 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2089 start_namespace_handler (void *data
, const char *prefix
, const char *uri
)
2091 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2093 if (p
->InBufferingMode ())
2099 if (p
->loader
!= NULL
&& p
->loader
->callbacks
.import_xaml_xmlns
!= NULL
) {
2101 XamlCallbackData data
= XamlCallbackData (p
->loader
, p
, p
->GetTopElementPtr ());
2102 if (!p
->loader
->callbacks
.import_xaml_xmlns (&data
, uri
, &error
))
2103 return parser_error (p
, p
->current_element
? p
->current_element
->element_name
: NULL
, prefix
, 2005, "Unknown namespace %s", uri
);
2106 for (int i
= 0; default_namespace_names
[i
]; i
++) {
2107 if (!strcmp (default_namespace_names
[i
], uri
)) {
2108 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), default_namespace
);
2113 if (!strcmp (X_NAMESPACE_URI
, uri
)){
2114 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), x_namespace
);
2115 } else if (!strcmp (PRIMITIVE_NAMESPACE_URI
, uri
)) {
2116 PrimitiveNamespace
*pn
= new PrimitiveNamespace (g_strdup (prefix
));
2117 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), pn
);
2118 p
->AddCreatedNamespace (pn
);
2119 } else if (!strcmp (MC_IGNORABLE_NAMESPACE_URI
, uri
)) {
2120 MCIgnorableNamespace
*mc
= new MCIgnorableNamespace (g_strdup (prefix
));
2121 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), mc
);
2122 p
->AddCreatedNamespace (mc
);
2125 return parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), prefix
, -1,
2126 "No managed element callback installed to handle %s", uri
);
2130 parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), NULL
, 2262,
2131 "AG_E_PARSER_NAMESPACE_NOT_SUPPORTED");
2135 ManagedNamespace
*c
= new ManagedNamespace (g_strdup (uri
), g_strdup (prefix
));
2136 g_hash_table_insert (p
->namespace_map
, g_strdup (c
->xmlns
), c
);
2137 p
->AddCreatedNamespace (c
);
2142 start_doctype_handler (void *data
,
2143 const XML_Char
*doctype_name
,
2144 const XML_Char
*sysid
,
2145 const XML_Char
*pubid
,
2146 int has_internal_subset
)
2148 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2150 if (p
->InBufferingMode ())
2154 return parser_error (p
, NULL
, NULL
, 7050, "DTD was found but is prohibited");
2157 return parser_error (p
, NULL
, NULL
, 7016, "incorrect document syntax.");
2161 add_default_namespaces (XamlParserInfo
*p
, bool sl_xmlns
)
2164 p
->implicit_default_namespace
= true;
2165 g_hash_table_insert (p
->namespace_map
, g_strdup ("http://schemas.microsoft.com/winfx/2006/xaml/presentation"), default_namespace
);
2166 g_hash_table_insert (p
->namespace_map
, g_strdup (X_NAMESPACE_URI
), x_namespace
);
2168 g_hash_table_insert (p
->namespace_map
, g_strdup (XML_NAMESPACE_URI
), xml_namespace
);
2172 print_tree (XamlElementInstance
*el
, int depth
)
2175 if (debug_flags
& RUNTIME_DEBUG_XAML
) {
2176 for (int i
= 0; i
< depth
; i
++)
2179 const char *name
= NULL
;
2182 printf (" -null- \n");
2186 if (el
->element_type
== XamlElementInstance::ELEMENT
&& el
->IsDependencyObject ())
2187 name
= el
->GetAsDependencyObject ()->GetName ();
2188 printf ("%s (%s) (%p) (%s)\n", el
->element_name
, name
? name
: "-no name-", el
->parent
, el
->element_type
== XamlElementInstance::PROPERTY
? "PROPERTY" : "ELEMENT");
2190 for (List::Node
*walk
= el
->children
->First (); walk
!= NULL
; walk
= walk
->next
) {
2191 XamlElementInstance
*el
= (XamlElementInstance
*) walk
;
2192 print_tree (el
, depth
+ 1);
2199 xaml_parse_xmlns (const char* xmlns
, char** type_name
, char** ns
, char** assembly
)
2201 const char delimiters
[] = ";";
2203 char* buffer
= g_strdup (xmlns
);
2209 decl
= strtok (buffer
, delimiters
);
2210 while (decl
!= NULL
) {
2211 if (strstr (decl
, "clr-namespace:") == decl
) {
2214 *ns
= g_strdup (decl
+ 14);
2215 } else if (strstr (decl
, "assembly=") == decl
) {
2218 *assembly
= g_strdup (decl
+ 9);
2221 g_free (*type_name
);
2222 *type_name
= g_strdup (decl
);
2225 decl
= strtok (NULL
, delimiters
);
2231 XamlLoader::CreateFromFile (const char *xaml_file
, bool create_namescope
,
2232 Type::Kind
*element_type
)
2235 XamlParserInfo
*parser_info
= NULL
;
2236 XML_Parser p
= NULL
;
2237 bool first_read
= true;
2238 const char *inptr
, *inend
;
2243 LOG_XAML ("attemtping to load xaml file: %s\n", xaml_file
);
2245 stream
= new TextStream ();
2246 if (!stream
->OpenFile (xaml_file
, false)) {
2247 LOG_XAML ("can not open file\n");
2248 goto cleanup_and_return
;
2251 if (!(p
= XML_ParserCreateNS ("UTF-8", '|'))) {
2252 LOG_XAML ("can not create parser\n");
2253 goto cleanup_and_return
;
2256 parser_info
= new XamlParserInfo (p
, xaml_file
);
2258 parser_info
->namescope
->SetTemporary (!create_namescope
);
2260 parser_info
->loader
= this;
2262 // TODO: This is just in here temporarily, to make life less difficult for everyone
2263 // while we are developing.
2264 add_default_namespaces (parser_info
, false);
2266 XML_SetUserData (p
, parser_info
);
2268 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2269 XML_SetCharacterDataHandler (p
, char_data_handler
);
2270 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2271 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2274 XML_SetProcessingInstructionHandler (p, proc_handler);
2277 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) >= 0) {
2281 if (first_read
&& nread
> 0) {
2282 // Remove preceding white space
2283 inend
= buffer
+ nread
;
2285 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2291 n
= (inend
- inptr
);
2295 parser_info
->SetXmlBuffer (inptr
);
2296 if (!XML_Parse (p
, inptr
, n
, nread
== 0)) {
2297 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2298 goto cleanup_and_return
;
2305 print_tree (parser_info
->top_element
, 0);
2307 if (parser_info
->top_element
) {
2308 res
= parser_info
->top_element
->GetAsValue ();
2309 // We want a copy because the old one is going to be deleted
2310 res
= new Value (*res
);
2313 *element_type
= parser_info
->top_element
->info
->GetKind ();
2315 if (parser_info
->error_args
) {
2316 *element_type
= Type::INVALID
;
2317 goto cleanup_and_return
;
2324 error_args
= new ParserErrorEventArgs ("Error opening xaml file", xaml_file
, 0, 0, 1, "", "");
2325 else if (parser_info
->error_args
) {
2326 error_args
= parser_info
->error_args
;
2342 XamlLoader::CreateFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2344 return HydrateFromString (xaml
, NULL
, create_namescope
, element_type
, flags
);
2348 value_to_dependency_object (Value
*value
)
2350 if (!value
|| !value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
2352 return value
->AsDependencyObject ();
2356 XamlLoader::CreateDependencyObjectFromFile (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2358 return value_to_dependency_object (CreateFromFile (xaml
, create_namescope
, element_type
));
2362 XamlLoader::CreateDependencyObjectFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2364 return value_to_dependency_object (CreateFromString (xaml
, create_namescope
, element_type
, IMPORT_DEFAULT_XMLNS
));
2368 * Hydrates an existing DependencyObject (@object) with the contents from the @xaml
2372 XamlLoader::HydrateFromString (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2374 XML_Parser p
= XML_ParserCreateNS ("utf-8", '|');
2375 XamlParserInfo
*parser_info
= NULL
;
2377 char *start
= (char*)xaml
;
2378 char *prepend
= NULL
;
2379 char *append
= NULL
;
2380 char * inputs
[4] = {NULL
, NULL
, NULL
, NULL
};
2385 LOG_XAML ("can not create parser\n");
2386 goto cleanup_and_return
;
2395 sprintf (filename
, "createFromXaml.%d.xaml", id
++);
2396 if ((fp
= fopen (filename
, "wt")) != NULL
) {
2397 fwrite (xaml
, strlen (xaml
), 1, fp
);
2403 parser_info
= new XamlParserInfo (p
, NULL
);
2405 parser_info
->namescope
->SetTemporary (!create_namescope
);
2407 parser_info
->loader
= this;
2408 parser_info
->validate_templates
= (flags
& VALIDATE_TEMPLATES
) == VALIDATE_TEMPLATES
;
2411 // If we are hydrating, we are not null
2413 if (object
!= NULL
) {
2414 parser_info
->hydrate_expecting
= object
;
2415 parser_info
->hydrating
= true;
2416 if (Type::IsSubclassOf (parser_info
->deployment
, object
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
2417 DependencyObject
*dob
= object
->AsDependencyObject ();
2418 dob
->SetSurface (GetSurface());
2419 dob
->SetResourceBase (GetResourceBase());
2422 parser_info
->hydrate_expecting
= NULL
;
2423 parser_info
->hydrating
= false;
2426 // from_str gets the default namespaces implictly added
2427 add_default_namespaces (parser_info
, (flags
& IMPORT_DEFAULT_XMLNS
) == IMPORT_DEFAULT_XMLNS
);
2429 XML_SetUserData (p
, parser_info
);
2431 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2432 XML_SetCharacterDataHandler (p
, char_data_handler
);
2433 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2434 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2437 XML_SetProcessingInstructionHandler (p, proc_handler);
2441 prepend
= context
->internal
->CreateIgnorableTagOpen ();
2442 append
= context
->internal
->CreateIgnorableTagClose ();
2444 inputs
[0] = prepend
;
2446 inputs
[2] = append
;
2449 for (int i
= 0; inputs
[i
]; i
++) {
2450 char *start
= inputs
[i
];
2452 // don't freak out if the <?xml ... ?> isn't on the first line (see #328907)
2453 while (g_ascii_isspace (*start
))
2456 parser_info
->SetXmlBuffer (start
);
2457 if (!XML_Parse (p
, start
, strlen (start
), inputs
[i
+ 1] == NULL
)) {
2458 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2459 LOG_XAML ("error parsing: %s\n\n", xaml
);
2460 goto cleanup_and_return
;
2464 print_tree (parser_info
->top_element
, 0);
2466 if (parser_info
->top_element
) {
2467 if (is_legal_top_level_kind (parser_info
->top_element
->info
->GetKind ())) {
2468 res
= parser_info
->top_element
->GetAsValue ();
2469 res
= new Value (*res
);
2470 if (res
->Is (parser_info
->deployment
, Type::DEPENDENCY_OBJECT
) && object
) {
2471 DependencyObject
*dob
= res
->AsDependencyObject ();
2473 dob
->SetIsHydratedFromXaml (parser_info
->hydrating
);
2478 *element_type
= parser_info
->top_element
->info
->GetKind ();
2480 if (!res
&& !parser_info
->error_args
)
2481 parser_info
->error_args
= new ParserErrorEventArgs ("No DependencyObject found", "", 0, 0, 1, "", "");
2483 if (parser_info
->error_args
) {
2487 *element_type
= Type::INVALID
;
2488 goto cleanup_and_return
;
2494 if (parser_info
->error_args
) {
2495 error_args
= parser_info
->error_args
;
2496 printf ("Could not parse element %s, attribute %s, error: %s\n",
2497 error_args
->xml_element
,
2498 error_args
->xml_attribute
,
2499 error_args
->GetErrorMessage());
2515 XamlLoader::CreateFromFileWithError (const char *xaml_file
, bool create_namescope
, Type::Kind
*element_type
, MoonError
*error
)
2517 Value
*res
= CreateFromFile (xaml_file
, create_namescope
, element_type
);
2518 if (error_args
&& error_args
->GetErrorCode () != -1)
2519 MoonError::FillIn (error
, error_args
);
2524 XamlLoader::CreateFromStringWithError (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2526 Value
*res
= CreateFromString (xaml
, create_namescope
, element_type
, flags
);
2527 if (error_args
&& error_args
->GetErrorCode () != -1)
2528 MoonError::FillIn (error
, error_args
);
2533 XamlLoader::HydrateFromStringWithError (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2535 Value
*res
= HydrateFromString (xaml
, object
, create_namescope
, element_type
, flags
);
2536 if (error_args
&& error_args
->GetErrorCode () != -1)
2537 MoonError::FillIn (error
, error_args
);
2542 parse_int (const char **pp
, const char *end
)
2544 const char *p
= *pp
;
2546 if (optional
&& AtEnd
)
2553 while (p
<= end
&& g_ascii_isdigit (*p
)) {
2554 res
= res
* 10 + *p
- '0';
2569 parse_ticks (const char **pp
, const char *end
)
2571 gint64 mag
= 1000000;
2573 bool digitseen
= false;
2575 const char *p
= *pp
;
2577 while (mag
> 0 && p
<= end
&& g_ascii_isdigit (*p
)) {
2578 res
= res
+ (*p
- '0') * mag
;
2594 time_span_from_str (const char *str
, TimeSpan
*res
)
2596 const char *end
= str
+ strlen (str
);
2599 bool negative
= false;
2613 days
= parse_int (&p
, end
);
2617 hours
= parse_int (&p
, end
);
2625 minutes
= parse_int (&p
, end
);
2627 seconds
= parse_int (&p
, end
);
2630 ticks
= parse_ticks (&p
, end
);
2636 gint64 t
= (days
* 86400) + (hours
* 3600) + (minutes
* 60) + seconds
;
2639 *res
= negative
? (-t
- ticks
) : (t
+ ticks
);
2645 repeat_behavior_from_str (const char *str
, RepeatBehavior
*res
)
2647 if (!g_ascii_strcasecmp ("Forever", str
)) {
2648 *res
= RepeatBehavior::Forever
;
2652 // check for "<float>x".
2654 // XXX more validation work is needed here.. but how do we
2656 const char *x
= strchr (str
, 'x');
2658 if (*(x
+ 1) != '\0') {
2664 double d
= g_ascii_strtod (str
, &endptr
);
2666 if (errno
|| endptr
== str
)
2669 *res
= RepeatBehavior (d
);
2674 /* XXX RepeatBehavior='XX:XX:XX' syntax is NOT correctly supported by
2675 Silverlight 1.0 (most likely a bug). It works fine in Silverlight 2.0
2676 though. We currently stick to the 2.0 behavior, not replicating the bug
2680 if (!time_span_from_str (str
, &t
))
2683 *res
= RepeatBehavior (t
);
2689 duration_from_str (const char *str
, Duration
*res
)
2691 if (!g_ascii_strcasecmp ("Automatic", str
)) {
2692 *res
= Duration::Automatic
;
2696 if (!g_ascii_strcasecmp ("Forever", str
)) {
2697 *res
= Duration::Forever
;
2702 if (!time_span_from_str (str
, &ts
))
2705 *res
= Duration (ts
);
2710 keytime_from_str (const char *str
, KeyTime
*res
)
2712 if (!g_ascii_strcasecmp ("Uniform", str
)) {
2713 *res
= KeyTime::Uniform
;
2717 if (!g_ascii_strcasecmp ("Paced", str
)) {
2718 *res
= KeyTime::Paced
;
2722 /* check for a percentage first */
2723 const char *last
= str
+ strlen(str
) - 1;
2726 double pct
= g_ascii_strtod (str
, &ep
);
2728 *res
= KeyTime (pct
);
2734 if (!time_span_from_str (str
, &ts
))
2737 *res
= KeyTime (ts
);
2742 key_spline_from_str (const char *str
, KeySpline
**res
)
2744 PointCollection
*pts
= PointCollection::FromStr (str
);
2749 if (pts
->GetCount () != 2) {
2754 *res
= new KeySpline (*pts
->GetValueAt (0)->AsPoint (), *pts
->GetValueAt (1)->AsPoint ());
2762 matrix_from_str (const char *str
)
2764 if (!g_ascii_strcasecmp ("Identity", str
)) {
2765 return new Matrix ();
2768 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2772 return new Matrix ();
2774 if (values
->GetCount () < 6) {
2779 matrix
= new Matrix ();
2780 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2781 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2782 matrix
->SetM21 (values
->GetValueAt (2)->AsDouble ());
2783 matrix
->SetM22 (values
->GetValueAt (3)->AsDouble ());
2784 matrix
->SetOffsetX (values
->GetValueAt (4)->AsDouble ());
2785 matrix
->SetOffsetY (values
->GetValueAt (5)->AsDouble ());
2793 grid_length_from_str (const char *str
, GridLength
*grid_length
)
2795 if (IS_NULL_OR_EMPTY (str
)) {
2796 *grid_length
= GridLength (0.0, GridUnitTypePixel
);
2800 if (str
[0] == '*') {
2801 *grid_length
= GridLength (1.0, GridUnitTypeStar
);
2805 // unit tests shows that "Auto", "auto", "aUtO"... all works
2806 if (!g_ascii_strcasecmp (str
, "Auto")) {
2807 *grid_length
= GridLength ();
2813 double d
= g_ascii_strtod (str
, &endptr
);
2815 if (errno
|| endptr
== str
)
2818 *grid_length
= GridLength (d
, *endptr
== '*' ? GridUnitTypeStar
: GridUnitTypePixel
);
2827 while (*inptr
&& !g_ascii_isalnum (*inptr
) && *inptr
!= '.' && *inptr
!= '-' && *inptr
!= '+')
2828 inptr
= g_utf8_next_char (inptr
);
2834 get_point (Point
*p
, char **in
)
2836 char *end
, *inptr
= *in
;
2839 x
= g_ascii_strtod (inptr
, &end
);
2844 while (g_ascii_isspace (*inptr
))
2850 while (g_ascii_isspace (*inptr
))
2853 y
= g_ascii_strtod (inptr
, &end
);
2866 make_relative (const Point
*cp
, Point
*mv
)
2873 more_points_available (char **in
)
2877 while (g_ascii_isspace (*inptr
) || *inptr
== ',')
2882 return (g_ascii_isdigit (*inptr
) || *inptr
== '.' || *inptr
== '-' || *inptr
== '+');
2886 geometry_from_str (const char *str
)
2888 char *inptr
= (char *) str
;
2889 Point cp
= Point (0, 0);
2890 Point cp1
, cp2
, cp3
;
2893 PathGeometry
*pg
= NULL
;
2894 FillRule fill_rule
= FillRuleEvenOdd
;
2895 bool cbz
= false; // last figure is a cubic bezier curve
2896 bool qbz
= false; // last figure is a quadratic bezier curve
2897 Point cbzp
, qbzp
; // points needed to create "smooth" beziers
2899 moon_path
*path
= moon_path_new (10);
2902 if (g_ascii_isspace (*inptr
))
2908 bool relative
= false;
2911 inptr
= g_utf8_next_char (inptr
);
2919 fill_rule
= FillRuleEvenOdd
;
2920 else if (*inptr
== '1')
2921 fill_rule
= FillRuleNonzero
;
2923 // FIXME: else it's a bad value and nothing should be rendered
2924 goto bad_pml
; // partial: only this Path won't be rendered
2926 inptr
= g_utf8_next_char (inptr
);
2931 if (!get_point (&cp1
, &inptr
))
2935 make_relative (&cp
, &cp1
);
2938 moon_move_to (path
, cp1
.x
, cp1
.y
);
2940 start
.x
= cp
.x
= cp1
.x
;
2941 start
.y
= cp
.y
= cp1
.y
;
2944 while (more_points_available (&inptr
)) {
2945 if (!get_point (&cp1
, &inptr
))
2949 make_relative (&cp
, &cp1
);
2951 moon_line_to (path
, cp1
.x
, cp1
.y
);
2963 while (more_points_available (&inptr
)) {
2964 if (!get_point (&cp1
, &inptr
))
2968 make_relative (&cp
, &cp1
);
2970 moon_line_to (path
, cp1
.x
, cp1
.y
);
2985 double x
= g_ascii_strtod (inptr
, &end
);
2993 cp
= Point (x
, cp
.y
);
2995 moon_line_to (path
, cp
.x
, cp
.y
);
3004 double y
= g_ascii_strtod (inptr
, &end
);
3012 cp
= Point (cp
.x
, y
);
3014 moon_line_to (path
, cp
.x
, cp
.y
);
3023 while (more_points_available (&inptr
)) {
3024 if (!get_point (&cp1
, &inptr
))
3028 make_relative (&cp
, &cp1
);
3032 if (!get_point (&cp2
, &inptr
))
3036 make_relative (&cp
, &cp2
);
3040 if (!get_point (&cp3
, &inptr
))
3044 make_relative (&cp
, &cp3
);
3048 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3065 while (more_points_available (&inptr
)) {
3066 if (!get_point (&cp2
, &inptr
))
3070 make_relative (&cp
, &cp2
);
3074 if (!get_point (&cp3
, &inptr
))
3078 make_relative (&cp
, &cp3
);
3081 cp1
.x
= 2 * cp
.x
- cbzp
.x
;
3082 cp1
.y
= 2 * cp
.y
- cbzp
.y
;
3086 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3103 while (more_points_available (&inptr
)) {
3104 if (!get_point (&cp1
, &inptr
))
3108 make_relative (&cp
, &cp1
);
3112 if (!get_point (&cp2
, &inptr
))
3116 make_relative (&cp
, &cp2
);
3120 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3135 while (more_points_available (&inptr
)) {
3136 if (!get_point (&cp2
, &inptr
))
3140 make_relative (&cp
, &cp2
);
3143 cp1
.x
= 2 * cp
.x
- qbzp
.x
;
3144 cp1
.y
= 2 * cp
.y
- qbzp
.y
;
3148 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3165 while (more_points_available (&inptr
)) {
3166 if (!get_point (&cp1
, &inptr
))
3171 double angle
= g_ascii_strtod (inptr
, &end
);
3178 int is_large
= strtol (inptr
, &end
, 10);
3185 int sweep
= strtol (inptr
, &end
, 10);
3192 if (!get_point (&cp2
, &inptr
))
3196 make_relative (&cp
, &cp2
);
3198 moon_arc_to (path
, cp1
.x
, cp1
.y
, angle
, is_large
, sweep
, cp2
.x
, cp2
.y
);
3210 moon_line_to (path
, start
.x
, start
.y
);
3211 moon_close_path (path
);
3212 moon_move_to (path
, start
.x
, start
.y
);
3223 pg
= new PathGeometry (path
);
3224 pg
->SetFillRule (fill_rule
);
3228 moon_path_destroy (path
);
3233 value_is_explicit_null (const char *str
)
3235 return !strcmp ("{x:Null}", str
);
3239 is_managed_kind (Type::Kind kind
)
3242 if (kind
== Type::MANAGED
||
3243 kind
== Type::OBJECT
||
3244 kind
== Type::URI
||
3245 kind
== Type::MANAGEDTYPEINFO
||
3246 kind
== Type::DEPENDENCYPROPERTY
)
3253 kind_requires_managed_load (Type::Kind kind
)
3255 if (kind
== Type::USERCONTROL
) {
3263 is_legal_top_level_kind (Type::Kind kind
)
3265 if (kind
== Type::MANAGED
|| kind
== Type::OBJECT
|| Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::DEPENDENCY_OBJECT
))
3270 // NOTE: Keep definition in sync with class/System.Windows/Mono/NativeMethods.cs
3272 value_from_str_with_typename (const char *type_name
, const char *prop_name
, const char *str
, Value
**v
)
3274 Type
*t
= Type::Find (Deployment::GetCurrent (), type_name
);
3278 return value_from_str (t
->GetKind (), prop_name
, str
, v
);
3282 expand_property_path (XamlParserInfo
*p
, PropertyPath
*path
)
3287 bool expanded
= false;
3288 GString
*res
= g_string_new (path
->path
);
3290 int len
= strlen (res
->str
);
3291 for (int i
= 0; i
< len
; i
++) {
3292 if (res
->str
[i
] == ':') {
3296 for ( ; s
> 0; s
--) {
3297 if (!g_ascii_isalnum (res
->str
[s
]))
3301 for ( ; te
< len
; te
++) {
3302 if (!g_ascii_isalpha (res
->str
[te
]) || res
->str
[te
] == '_')
3306 char *prefix
= g_strndup (res
->str
+ s
+ 1, e
- s
- 1);
3307 char *type
= g_strndup (res
->str
+ e
+ 1, te
- e
- 1);
3309 res
= g_string_erase (res
, s
+ 1, te
- s
- 1);
3311 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
3315 g_string_free (res
, true);
3319 XamlElementInfo
*info
= ns
->FindElement (p
, type
, NULL
, false);
3324 g_string_free (res
, true);
3328 char *uri
= g_strdup_printf ("'%s'", Type::Find (p
->deployment
, info
->GetKind ())->GetName ());
3330 res
= g_string_insert (res
, s
+ 1, uri
);
3331 i
= s
+ 1 + strlen (uri
);
3332 len
= strlen (res
->str
);
3344 g_string_free (res
, true);
3348 char *expanded_str
= res
->str
;
3349 g_string_free (res
, false);
3351 return expanded_str
;
3355 value_from_str (Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
)
3359 value_from_str_with_parser (NULL
, type
, prop_name
, str
, v
, &v_set
);
3365 xaml_bool_from_str (const char *s
, bool *res
)
3370 if (!g_ascii_strcasecmp ("true", s
))
3372 else if (!g_ascii_strcasecmp ("false", s
))
3375 // Check if it's a string representing a decimal value
3379 l
= strtol (s
, &endptr
, 10);
3381 if (errno
|| endptr
== s
|| *endptr
|| l
> G_MAXINT32
|| l
< G_MININT32
)
3395 value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
)
3400 if (value_is_explicit_null (str
)) {
3406 char *s
= g_strdup (str
);
3408 if (type
== Type::OBJECT
|| type
== Type::STRING
) {
3409 // object and string use the literal string
3412 // everything else depends on the string being stripped
3417 case Type::OBJECT
: {
3418 // not much more can do here, unless we want to try to
3419 // probe str to see if it's actually meant to be a
3420 // specific type. just assume it's a string.
3429 if (!xaml_bool_from_str (s
, &b
))
3436 case Type::DOUBLE
: {
3439 // empty string should not reset default values with 0
3441 // FIXME: this causes a 2.0 unit test to fail (PrimitiveTest.ParseEmptyDouble)
3442 if (IS_NULL_OR_EMPTY(s
)) {
3447 bool is_nan
= false;
3448 if (!g_ascii_strcasecmp (s
, "NAN"))
3452 d
= g_ascii_strtod (s
, &endptr
);
3455 if (is_nan
|| errno
|| endptr
== s
|| *endptr
) {
3457 && (!strcmp (prop_name
, "Width") || !strcmp (prop_name
, "Height"))
3458 && (!g_ascii_strcasecmp (s
, "Auto") || is_nan
))
3472 l
= strtol (s
, &endptr
, 10);
3474 if (errno
|| endptr
== s
)
3477 *v
= new Value (l
, Type::INT64
);
3481 case Type::TIMESPAN
: {
3484 if (!time_span_from_str (s
, &ts
))
3487 *v
= new Value (ts
, Type::TIMESPAN
);
3494 if (IS_NULL_OR_EMPTY(s
))
3496 else if (g_ascii_isalpha (s
[0]) && prop_name
) {
3497 i
= enums_str_to_int (prop_name
, s
);
3499 // g_warning ("'%s' enum is not valid on '%s' property", str, prop_name);
3504 long l
= strtol (s
, &endptr
, 10);
3506 if (errno
|| endptr
== s
)
3517 gunichar unichar
= g_utf8_get_char_validated (str
, -1);
3520 if ((int) unichar
< 0)
3523 if (!(next
= g_utf8_next_char (str
)) || *next
!= '\0')
3526 *v
= new Value (unichar
, Type::CHAR
);
3530 case Type::STRING
: {
3531 *v
= new Value (str
);
3536 Color
*c
= color_from_str (s
);
3539 *v
= new Value (*c
);
3544 case Type::REPEATBEHAVIOR
: {
3545 RepeatBehavior rb
= RepeatBehavior::Forever
;
3547 if (!repeat_behavior_from_str (s
, &rb
))
3550 *v
= new Value (rb
);
3554 case Type::DURATION
: {
3555 Duration d
= Duration::Forever
;
3557 if (!duration_from_str (s
, &d
))
3564 case Type::KEYTIME
: {
3565 KeyTime kt
= KeyTime::Paced
;
3567 if (!keytime_from_str (s
, &kt
))
3570 *v
= new Value (kt
);
3574 case Type::KEYSPLINE
: {
3577 if (!key_spline_from_str (s
, &ks
))
3580 *v
= Value::CreateUnrefPtr (ks
);
3585 case Type::SOLIDCOLORBRUSH
: {
3586 // Only solid color brushes can be specified using attribute syntax
3587 Color
*c
= color_from_str (s
);
3592 SolidColorBrush
*scb
= new SolidColorBrush ();
3597 *v
= Value::CreateUnrefPtr (scb
);
3604 if (!Point::FromStr (s
, &p
))
3614 if (!Size::FromStr (s
, &size
))
3617 *v
= new Value (size
);
3624 if (!Rect::FromStr (s
, &rect
))
3627 *v
= new Value (rect
);
3634 if (!uri
.Parse (s
)) {
3638 *v
= new Value (uri
);
3642 case Type::DOUBLE_COLLECTION
: {
3643 DoubleCollection
*doubles
= DoubleCollection::FromStr (s
);
3645 *v
= Value::CreateUnrefPtr (new DoubleCollection ());
3650 *v
= Value::CreateUnrefPtr (doubles
);
3654 case Type::POINT_COLLECTION
: {
3655 PointCollection
*points
= PointCollection::FromStr (s
);
3657 *v
= Value::CreateUnrefPtr (new PointCollection ());
3662 *v
= Value::CreateUnrefPtr (points
);
3666 case Type::TRANSFORMGROUP
: {
3667 if (IS_NULL_OR_EMPTY(s
))
3670 Matrix
*mv
= matrix_from_str (s
);
3674 TransformGroup
*tg
= new TransformGroup ();
3675 MatrixTransform
*t
= new MatrixTransform ();
3676 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3678 tg
->GetChildren()->Add (t
);
3681 *v
= new Value (tg
);
3687 case Type::TRANSFORM
:
3689 if (!g_ascii_strcasecmp ("Identity", str
)) {
3695 // Intentional fall through, you can create a matrix from a TRANSFORM property, but not using Identity
3696 case Type::MATRIXTRANSFORM
:
3698 if (IS_NULL_OR_EMPTY(s
))
3701 Matrix
*mv
= matrix_from_str (s
);
3705 MatrixTransform
*t
= new MatrixTransform ();
3706 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3714 case Type::UNMANAGEDMATRIX
:
3715 case Type::MATRIX
: {
3716 // note: unlike TRANSFORM this creates an empty, identity, matrix for an empty string
3717 Matrix
*matrix
= matrix_from_str (s
);
3721 *v
= new Value (matrix
);
3726 case Type::PATHGEOMETRY
:
3727 case Type::GEOMETRY
: {
3728 Geometry
*geometry
= geometry_from_str (s
);
3733 *v
= new Value (geometry
);
3738 case Type::THICKNESS
: {
3741 if (!Thickness::FromStr (s
, &t
))
3748 case Type::CORNERRADIUS
: {
3751 if (!CornerRadius::FromStr (s
, &c
))
3758 case Type::GRIDLENGTH
: {
3759 GridLength grid_length
;
3761 if (!grid_length_from_str (s
, &grid_length
))
3764 *v
= new Value (grid_length
);
3768 case Type::IMAGESOURCE
:
3769 case Type::BITMAPIMAGE
: {
3775 BitmapImage
*bi
= new BitmapImage ();
3777 bi
->SetUriSource (&uri
);
3779 *v
= Value::CreateUnrefPtr (bi
);
3784 case Type::MULTISCALETILESOURCE
:
3785 case Type::DEEPZOOMIMAGETILESOURCE
: {
3786 // As far as I know the only thing you can create here is a URI based DeepZoomImageTileSource
3790 *v
= Value::CreateUnrefPtr (new DeepZoomImageTileSource (&uri
));
3795 case Type::FONTFAMILY
: {
3796 *v
= new Value (FontFamily (s
));
3800 case Type::FONTWEIGHT
: {
3801 int fw
= enums_str_to_int ("FontWeight", s
);
3803 *v
= new Value (FontWeight ((FontWeights
)fw
));
3808 case Type::FONTSTYLE
: {
3809 int fs
= enums_str_to_int ("FontStyle", s
);
3811 *v
= new Value (FontStyle ((FontStyles
)fs
));
3816 case Type::FONTSTRETCH
: {
3817 int fs
= enums_str_to_int ("FontStretch", s
);
3819 *v
= new Value (FontStretch ((FontStretches
)fs
));
3824 case Type::PROPERTYPATH
: {
3825 PropertyPath
path (s
);
3826 path
.expanded_path
= expand_property_path (p
, &path
);
3827 *v
= new Value (path
);
3832 // we don't care about NULL or empty values
3833 if (!IS_NULL_OR_EMPTY (s
)) {
3844 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
3846 const char* prop_name
= info
->GetContentProperty (p
);
3851 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
3855 bool is_collection
= Type::IsSubclassOf (p
->deployment
, dep
->GetPropertyType(), Type::DEPENDENCY_OBJECT_COLLECTION
);
3857 if (!is_collection
&& Type::IsSubclassOf (p
->deployment
, value
->info
->GetKind (), dep
->GetPropertyType())) {
3859 if (!item
->SetValueWithError (dep
, value
->GetAsValue (), &err
)) {
3860 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3866 // We only want to enter this if statement if we are NOT dealing with the content property element,
3867 // otherwise, attempting to use explicit property setting, would add the content property element
3868 // to the content property element collection
3869 if (is_collection
&& dep
->GetPropertyType() != value
->info
->GetKind ()) {
3870 Value
*col_v
= item
->GetValue (dep
);
3874 col
= collection_new (dep
->GetPropertyType ());
3875 item
->SetValue (dep
, Value (col
));
3878 col
= (Collection
*) col_v
->AsCollection ();
3882 if (-1 == col
->AddWithError (value
->GetAsValue (), &err
)) {
3883 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3894 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
3896 const char* prop_name
= info
->GetContentProperty (p
);
3900 Type::Kind prop_type
= p
->current_element
->info
->GetKind ();
3901 DependencyProperty
*content
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, prop_type
), prop_name
);
3903 // TODO: There might be other types that can be specified here,
3904 // but string is all i have found so far. If you can specify other
3905 // types, i should pull the property setting out of set_attributes
3906 // and use that code
3908 if (content
&& (content
->GetPropertyType ()) == Type::STRING
&& value
) {
3909 item
->SetValue (content
, Value (g_strstrip (p
->cdata
->str
)));
3911 } else if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::TEXTBLOCK
)) {
3912 TextBlock
*textblock
= (TextBlock
*) item
;
3913 InlineCollection
*inlines
= textblock
->GetInlines ();
3914 Inline
*last
= NULL
;
3916 if (inlines
&& inlines
->GetCount () > 0)
3917 last
= inlines
->GetValueAt (inlines
->GetCount () - 1)->AsInline ();
3919 if (!p
->cdata_content
) {
3920 if (p
->next_element
&& !strcmp (p
->next_element
, "Run") && last
&& last
->GetObjectType () == Type::RUN
&&
3921 !last
->GetAutogenerated ()) {
3922 // LWSP between <Run> elements is to be treated as a single-SPACE <Run> element
3923 // Note: p->cdata is already canonicalized
3925 // This is one of the following cases:
3927 // 1. LWSP before the first <Run> element
3928 // 2. LWSP after the last <Run> element
3929 // 3. LWSP between <Run> and <LineBreak> elements
3933 if (!p
->next_element
|| !strcmp (p
->next_element
, "LineBreak"))
3934 g_strchomp (p
->cdata
->str
);
3936 if (!last
|| last
->GetObjectType () != Type::RUN
|| last
->GetAutogenerated ())
3937 g_strchug (p
->cdata
->str
);
3940 Run
*run
= new Run ();
3941 run
->SetText (p
->cdata
->str
);
3944 inlines
= new InlineCollection ();
3945 textblock
->SetInlines (inlines
);
3958 XamlElementInstance::SetUnknownAttribute (XamlParserInfo
*p
, const char *name
, const char *value
)
3963 Value v
= Value (value
);
3964 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, name
, &v
, NULL
)) {
3971 XamlElementInstance::SetDelayedProperties (XamlParserInfo
*p
)
3973 GSList
*walk
= delayed_properties
;
3976 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
3978 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), prop
->xmlns
, prop
->name
, prop
->value
, NULL
, XamlCallbackData::SETTING_DELAYED_PROPERTY
)) {
3979 parser_error (p
, element_name
, prop
->name
, 2012,
3980 "Unknown property %s on element %s.",
3981 prop
->name
, element_name
);
3991 XamlElementInstance::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
3993 // We didn't find anything so try looking up in managed
3997 Value
*v
= new Value ();
3998 if (p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), GetAsValue (), p
->current_namespace
->GetUri (), el
, false, true, v
)) {
3999 char *type_name
= g_strndup (el
, dot
- el
);
4001 XamlElementInfoManaged
*res
= new XamlElementInfoManaged (g_strdup (p
->current_namespace
->GetUri ()), el
, info
, v
->GetKind (), v
);
4002 XamlElementInfo
*container
= p
->current_namespace
->FindElement (p
, type_name
, NULL
, false);
4003 info
->SetPropertyOwnerKind (container
->GetKind ());
4012 static XamlElementInfo
*
4013 create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
)
4018 char* type_name
= NULL
;
4019 char* type_xmlns
= NULL
;
4020 const char* use_xmlns
= NULL
;
4023 // We might have an x:Class attribute specified, so we need to use that for the
4024 // type_name that we pass to LookupObject
4025 if (strcmp ("Application", name
)) {
4026 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
4029 use_xmlns
= type_xmlns
;
4031 if (!p
->hydrating
) {
4032 parser_error (p
, name
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
4039 Value
*v
= new Value ();
4040 if (!p
->loader
->LookupObject (p
, use_xmlns
? p
->GetTopElementPtr () : NULL
, NULL
, use_xmlns
, name
, create
, false, v
)) {
4045 g_free (type_xmlns
);
4049 XamlElementInfoImportedManaged
*info
= new XamlElementInfoImportedManaged (g_strdup (name
), NULL
, v
);
4052 if (v
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4053 p
->AddCreatedElement (v
->AsDependencyObject());
4061 XamlElementInfoNative::GetContentProperty (XamlParserInfo
*p
)
4063 return type
->GetContentPropertyName ();
4066 XamlElementInstance
*
4067 XamlElementInfoNative::CreateElementInstance (XamlParserInfo
*p
)
4069 if (type
->IsValueType ())
4070 return new XamlElementInstanceValueType (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4071 else if (type
->IsSubclassOf (Type::FRAMEWORKTEMPLATE
))
4072 return new XamlElementInstanceTemplate (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4074 return new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4077 XamlElementInstance
*
4078 XamlElementInfoNative::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4080 XamlElementInstance
*res
= new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
, false);
4081 res
->SetDependencyObject (o
->AsDependencyObject ());
4087 XamlElementInstanceNative::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4089 if (IsDependencyObject ()) {
4090 const char *prop_name
= dot
+ 1;
4091 DependencyProperty
*prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
4093 XamlElementInfoNative
*info
= new XamlElementInfoNative (Type::Find (p
->deployment
, prop
->GetPropertyType ()));
4094 info
->SetPropertyOwnerKind (prop
->GetOwnerType ());
4099 return XamlElementInstance::FindPropertyElement (p
, el
, dot
);
4102 XamlElementInstance
*
4103 XamlElementInfoNative::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4105 return new XamlElementInstanceNative (this, p
, name
, XamlElementInstance::PROPERTY
, false);
4108 XamlElementInstanceNative::XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
) :
4109 XamlElementInstance (element_info
, name
, type
)
4111 this->element_info
= element_info
;
4112 this->parser_info
= parser_info
;
4114 SetDependencyObject (CreateItem ());
4120 XamlElementInstanceNative::CreateItem ()
4122 XamlElementInstance
*walk
= parser_info
->current_element
;
4123 Type
*type
= element_info
->GetType ();
4125 DependencyObject
*item
= NULL
;
4126 DependencyProperty
*dep
= NULL
;
4128 if (type
->IsSubclassOf (Type::COLLECTION
) || type
->IsSubclassOf (Type::RESOURCE_DICTIONARY
)) {
4129 // If we are creating a collection, try walking up the element tree,
4130 // to find the parent that we belong to and using that instance for
4131 // our collection, instead of creating a new one
4133 // We attempt to advance past the property setter, because we might be dealing with a
4136 if (walk
&& walk
->element_type
== XamlElementInstance::PROPERTY
) {
4137 char **prop_name
= g_strsplit (walk
->element_name
, ".", -1);
4139 walk
= walk
->parent
;
4140 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()), prop_name
[1]);
4142 g_strfreev (prop_name
);
4143 } else if (walk
&& walk
->info
->GetContentProperty (parser_info
)) {
4144 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()),
4145 (char *) walk
->info
->GetContentProperty (parser_info
));
4148 if (dep
&& Type::IsSubclassOf (parser_info
->deployment
, dep
->GetPropertyType(), type
->GetKind ())) {
4149 Value
*v
= ((DependencyObject
* ) walk
->GetAsDependencyObject ())->GetValue (dep
);
4151 item
= v
->AsDependencyObject ();
4154 // note: if !v then the default collection is NULL (e.g. PathFigureCollection)
4159 item
= element_info
->GetType()->IsCtorVisible() ? element_info
->GetType ()->CreateInstance () : NULL
;
4162 parser_info
->AddCreatedElement (item
);
4164 // in case we must store the collection into the parent
4165 if (dep
&& dep
->GetPropertyType() == type
->GetKind ()) {
4167 Value
item_value (item
);
4168 if (!((DependencyObject
* ) walk
->GetAsDependencyObject ())->SetValueWithError (dep
, &item_value
, &err
))
4169 parser_error (parser_info
, element_name
, NULL
, err
.code
, err
.message
);
4172 parser_error (parser_info
, element_name
, NULL
, 2007, "Unknown element: %s.", element_name
);
4180 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4182 if (property
->info
->RequiresManagedSet () || value
->info
->RequiresManagedSet ())
4183 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), NULL
);
4185 return dependency_object_set_property (p
, this, property
, value
, true);
4189 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4191 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4192 Type
*owner
= Type::Find (p
->deployment
, prop_name
[0]);
4193 DependencyProperty
*dep
;
4198 dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4202 return xaml_set_property_from_str (item
, dep
, value
, NULL
/*XXX*/);
4206 XamlElementInstanceNative::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4208 dependency_object_add_child (p
, this, child
, true);
4212 XamlElementInstanceNative::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4214 dependency_object_set_attributes (p
, this, attr
);
4218 XamlElementInstanceValueType::XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
) :
4219 XamlElementInstance (element_info
, name
, type
)
4221 this->element_info
= element_info
;
4222 this->parser_info
= parser_info
;
4226 XamlElementInstanceValueType::CreateValueItemFromString (const char* str
)
4229 bool res
= value_from_str (element_info
->GetType ()->GetKind (), NULL
, str
, &value
);
4234 XamlElementInstanceValueType::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4236 value_type_set_attributes (p
, this, attr
);
4239 XamlElementInstanceEnum::XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
) :
4240 XamlElementInstance (element_info
, name
, type
)
4245 XamlElementInstanceEnum::CreateEnumFromString (const char* str
)
4247 int i
= enums_str_to_int (element_name
, str
);
4251 value
= new Value (i
);
4256 XamlElementInstanceEnum::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4258 value_type_set_attributes (p
, this, attr
);
4261 XamlElementInstance
*
4262 XamlElementInfoEnum::CreateElementInstance (XamlParserInfo
*p
)
4264 return new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4267 XamlElementInstance
*
4268 XamlElementInfoEnum::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4270 XamlElementInstance
*res
= new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4275 XamlElementInfoManaged::GetContentProperty (XamlParserInfo
*p
)
4280 // TODO: We could cache this, but for now lets keep things as simple as possible.
4281 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4284 return XamlElementInfo::GetContentProperty (p
);
4287 XamlElementInstance
*
4288 XamlElementInfoManaged::CreateElementInstance (XamlParserInfo
*p
)
4290 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, obj
);
4292 if (obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4293 p
->AddCreatedElement (inst
->GetAsDependencyObject ());
4298 XamlElementInstance
*
4299 XamlElementInfoManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4301 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, o
);
4306 XamlElementInstance
*
4307 XamlElementInfoManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4309 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4314 XamlElementInstanceManaged::XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
) :
4315 XamlElementInstance (info
, name
, type
)
4317 // The managed code owns our Value objects
4318 cleanup_value
= false;
4322 if (obj
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
)) {
4323 this->is_dependency_object
= true;
4324 this->SetDependencyObject (obj
->AsDependencyObject ());
4327 this->is_dependency_object
= false;
4331 XamlElementInstanceManaged::GetManagedPointer ()
4333 if (value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
4334 return value
->AsDependencyObject ();
4335 return value
->AsManagedObject ();
4339 XamlElementInstanceManaged::GetParentPointer ()
4341 XamlElementInstance
*walk
= parent
;
4342 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
4343 walk
= walk
->parent
;
4349 return walk
->GetAsValue ();
4353 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4355 if (GetAsDependencyObject () != NULL
&& dependency_object_set_property (p
, this, property
, value
, false))
4357 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), value
);
4361 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4363 Value v
= Value (value
);
4364 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, &v
, NULL
);
4368 XamlElementInstanceManaged::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4370 if (element_type
== XamlElementInstance::PROPERTY
) {
4371 Value
*prop
= new Value (element_name
);
4372 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), true, info
->xmlns
, prop
, this, child
->GetAsValue (), child
);
4377 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), false, info
->xmlns
, GetAsValue (), this, child
->GetAsValue (), child
);
4381 XamlElementInstanceManaged::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4383 dependency_object_set_attributes (p
, this, attr
);
4387 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
4389 Value
*v
= value
->GetAsValue ();
4390 const char* prop_name
= info
->GetContentProperty (p
);
4392 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, v
, value
);
4396 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
4398 if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::CONTENTCONTROL
)) {
4399 // Content controls are not allowed to have their content set as text, they need to have a child element
4400 // if you want to set the content of a contentcontrol to text you need to use attribute syntax
4404 if (!XamlElementInstance::TrySetContentProperty (p
, value
)) {
4405 const char* prop_name
= info
->GetContentProperty (p
);
4406 if (!p
->cdata_content
)
4408 Value v
= Value (value
);
4409 bool res
= p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, &v
, NULL
);
4416 XamlElementInstance
*
4417 XamlElementInfoImportedManaged::CreateElementInstance (XamlParserInfo
*p
)
4419 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::ELEMENT
, obj
);
4425 XamlElementInfoImportedManaged::GetContentProperty (XamlParserInfo
*p
)
4430 // TODO: Test, it's possible that managed objects that aren't DOs are allowed to have content properties.
4431 if (!obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4432 return XamlElementInfo::GetContentProperty (p
);
4435 // TODO: We could cache this, but for now lets keep things as simple as possible.
4436 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4440 return XamlElementInfo::GetContentProperty (p
);
4443 XamlElementInstance
*
4444 XamlElementInfoImportedManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4446 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, Type::Find (p
->deployment
, o
->GetKind ())->GetName (), XamlElementInstance::ELEMENT
, o
);
4451 XamlElementInstance
*
4452 XamlElementInfoImportedManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4454 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4465 get_key_from_child (XamlElementInstance
*child
)
4467 const char *key
= child
->GetKey ();
4471 key
= child
->GetName ();
4475 if (child
->IsDependencyObject ()) {
4476 DependencyObject
*c
= child
->GetAsDependencyObject();
4478 if (Type::IsSubclassOf (c
->GetDeployment (), Type::STYLE
, child
->info
->GetKind ())) {
4479 Value
*v
= c
->GetValue (Style::TargetTypeProperty
);
4480 if (v
&& v
->GetKind () == Type::MANAGEDTYPEINFO
)
4481 key
= v
->AsManagedTypeInfo ()->full_name
;
4492 dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
)
4494 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4495 if (parent
->element_type
== XamlElementInstance::PROPERTY
) {
4497 if (parent
->info
->RequiresManagedSet ())
4500 char **prop_name
= g_strsplit (parent
->element_name
, ".", -1);
4501 Type
*owner
= types
->Find (prop_name
[0]);
4504 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4506 g_strfreev (prop_name
);
4509 g_warning ("Unknown element: %s.", parent
->element_name
);
4510 if (fail_if_no_prop
)
4511 parser_error (p
, parent
->element_name
, NULL
, 2007, "Unknown element: %s.", parent
->element_name
);
4515 // XamlElementInfoEnum has Type::INVALID as
4516 // its kind, which is why that first check is
4518 if (child
->info
->GetKind() != Type::MANAGED
&&
4519 !types
->Find (child
->info
->GetKind())->IsCtorVisible()) {
4520 // we can't instantiate this type
4521 return parser_error (p
, child
->element_name
, NULL
, 2007,
4522 "Unknown element: %s.", child
->element_name
);
4525 // Don't add the child element, if it is the entire collection
4526 if (dep
->GetPropertyType() == child
->info
->GetKind ())
4529 Type::Kind prop_type
= dep
->GetPropertyType ();
4530 if (!types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)
4531 && !types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
))
4534 // Most common case, we will have a parent that we can snag the collection from
4535 DependencyObject
*obj
= (DependencyObject
*) parent
->parent
->GetAsDependencyObject ();
4539 Value
*col_v
= obj
->GetValue (dep
);
4541 Type
*col_type
= types
->Find (prop_type
);
4542 DependencyObject
*c_obj
= col_type
->CreateInstance ();
4543 obj
->SetValue (dep
, Value::CreateUnrefPtr (c_obj
));
4544 col_v
= obj
->GetValue (dep
);
4547 Collection
*col
= col_v
->AsCollection ();
4550 if (types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4551 Value
child_val (child
->GetAsDependencyObject ());
4552 if (-1 == col
->AddWithError (&child_val
, &err
))
4553 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4555 else if (types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
)) {
4556 ResourceDictionary
*dict
= (ResourceDictionary
*)col
;
4558 const char *key
= get_key_from_child (child
);
4561 // XXX don't know the proper values here...
4562 return parser_error (p
, child
->element_name
, NULL
, 2007,
4563 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4566 Value
*child_as_value
= child
->GetAsValue ();
4568 if (!child_as_value
) {
4569 // XXX don't know the proper values here...
4570 return parser_error (p
, child
->element_name
, NULL
, 2007,
4571 "Error adding child to ResourceDictionary");
4574 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4576 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4585 if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4586 Collection
*col
= (Collection
*) parent
->GetAsDependencyObject ();
4588 Value
child_val ((DependencyObject
*)child
->GetAsDependencyObject ());
4590 if (-1 == col
->AddWithError (&child_val
, &err
))
4591 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4594 else if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
4595 ResourceDictionary
*dict
= (ResourceDictionary
*) parent
->GetAsDependencyObject ();
4598 const char *key
= get_key_from_child (child
);
4601 // XXX don't know the proper values here...
4602 return parser_error (p
, child
->element_name
, NULL
, 2007,
4603 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4606 Value
*child_as_value
= child
->GetAsValue ();
4607 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4609 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4613 if (parent
->element_type
!= XamlElementInstance::PROPERTY
) {
4614 parent
->TrySetContentProperty (p
, child
);
4617 // Do nothing if we aren't adding to a collection, or a content property collection
4622 /// set property funcs
4625 // these are just a bunch of special cases
4627 dependency_object_missed_property (XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
, char **prop_name
)
4633 set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
)
4638 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), prop
->info
->xmlns
, prop
->element_name
, value
->GetAsValue (), value
);
4642 dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
)
4644 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4645 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4646 DependencyProperty
*prop
= NULL
;
4648 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4650 if (types
->Find (item
->info
->GetKind ())->IsValueType ()) {
4651 if (raise_errors
) parser_error (p
, item
->element_name
, NULL
, -1, "Value types (%s) do not have properties.", property
->element_name
);
4652 g_strfreev (prop_name
);
4656 if (types
->Find (property
->info
->GetPropertyOwnerKind ())->IsCustomType ()) {
4657 g_strfreev (prop_name
);
4658 return set_managed_attached_property (p
, item
, property
, value
);
4662 // FIXME is this really where this check should live
4664 parser_error (p
, item
->element_name
, NULL
, 2030,
4665 "Property element %s cannot be used inside another property element.",
4666 property
->element_name
);
4668 g_strfreev (prop_name
);
4672 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), prop_name
[1]);
4675 if (prop
->IsReadOnly ()) {
4677 parser_error (p
, item
->element_name
, NULL
, 2014,
4678 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4680 } else if (types
->IsSubclassOf (value
->info
->GetKind (), prop
->GetPropertyType())) {
4681 // an empty collection can be NULL and valid
4682 if (item
->IsPropertySet (prop
->GetName())) {
4684 parser_error (p
, item
->element_name
, NULL
, 2033,
4685 "Cannot specify the value multiple times for property: %s.",
4686 property
->element_name
);
4691 // HACK - since the Setter is added to the collection *before* its properties are set
4692 // we find ourselves with a sealed Setter - which should not be possible at the parse time
4693 SetterBase
*sb
= NULL
;
4694 if (types
->IsSubclassOf (dep
->GetObjectType (), Type::SETTERBASE
)) {
4695 sb
= (SetterBase
*) dep
;
4696 sb
->SetIsSealed (false);
4699 if (!is_managed_kind (value
->info
->GetKind ()) && !value
->info
->RequiresManagedSet()) {
4700 if (!dep
->SetValueWithError (prop
, value
->GetAsValue (), &err
)) {
4702 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4708 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, prop_name
[1], value
->GetAsValue (), NULL
)) {
4710 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4717 // re-seal the Setter (end-HACK)
4719 sb
->SetIsSealed (true);
4721 item
->MarkPropertyAsSet (prop
->GetName());
4724 } else if (types
->IsSubclassOf (prop
->GetPropertyType (), Type::COLLECTION
) || types
->IsSubclassOf (prop
->GetPropertyType (), Type::RESOURCE_DICTIONARY
)) {
4725 // The items were added in add_child
4729 parser_error (p
, item
->element_name
, NULL
, 2010, "does not support %s as content.", value
->element_name
);
4733 dependency_object_missed_property (item
, property
, value
, prop_name
);
4738 g_strfreev (prop_name
);
4743 xaml_set_property_from_str (DependencyObject
*obj
, DependencyProperty
*prop
, const char *value
, MoonError
*error
)
4748 if (!value_from_str (prop
->GetPropertyType(), prop
->GetName(), value
, &v
))
4751 // it's possible for (a valid) value to be NULL (and we must keep the default value)
4753 rv
= obj
->SetValueWithError (prop
, v
, error
);
4761 xaml_is_valid_event_name (Deployment
*deployment
, Type::Kind kind
, const char *name
, bool allow_desktop_events
)
4763 Type
*type
= Type::Find (deployment
, kind
);
4767 int event_id
= type
->LookupEvent (name
);
4771 if (!allow_desktop_events
|| (moonlight_flags
& RUNTIME_INIT_DESKTOP_EXTENSIONS
) == 0) {
4772 // if we're not allowing desktop-only events, or if the user hasn't allowed them,
4773 // return false if the name corresponds to one of them.
4774 if (!strcmp (name
, "MouseRightButtonDown") ||
4775 !strcmp (name
, "MouseRightButtonUp") ||
4776 !strcmp (name
, "MouseWheel"))
4784 value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4786 // the only attributes value on value types seem to be x:Key
4787 // and x:Name, but reuse the generic namespace attribute stuff
4790 for (int i
= 0; attr
[i
]; i
+= 2) {
4792 if (attr
[i
+ 1] == NULL
|| attr
[i
+ 1][0] == '\0')
4795 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4797 if (attr_name
[1]) {
4799 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4802 return parser_error (p
, item
->element_name
, attr
[i
], 7055, "undeclared prefix");
4804 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4806 g_strfreev (attr_name
);
4808 // Setting managed attributes can cause errors galore
4815 g_strfreev (attr_name
);
4820 dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4822 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4823 GList
*delay_att
= NULL
;
4825 for (int i
= 0; attr
[i
]; i
+= 2) {
4830 // Setting attributes like x:Class can change item->item, so we
4831 // need to make sure we have an up to date pointer
4832 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4833 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4835 if (attr_name
[1]) {
4836 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4838 if (ns
!= x_namespace
) {
4839 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4840 g_strfreev (attr_name
);
4845 g_strfreev (attr_name
);
4846 return parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
4849 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4851 g_strfreev (attr_name
);
4853 // Setting managed attributes can cause errors galore
4860 g_strfreev (attr_name
);
4862 const char *pname
= attr
[i
];
4863 char *atchname
= NULL
;
4864 for (int a
= 0; attr
[i
][a
]; a
++) {
4865 if (attr
[i
][a
] != '.')
4867 atchname
= g_strndup (attr
[i
], a
);
4868 pname
= attr
[i
] + a
+ 1;
4872 DependencyProperty
*prop
= NULL
;
4874 Type
*attached_type
= types
->Find (atchname
);
4876 prop
= DependencyProperty::GetDependencyProperty (attached_type
, pname
);
4878 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), pname
);
4882 if (prop
->GetId () == DependencyObject::NameProperty
) {
4884 if (item
->GetName ()) {
4885 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
4889 // XXX toshok - I don't like doing this here... but it fixes airlines.
4890 item
->SetKey (p
, attr
[i
+1]);
4892 NameScope
*scope
= p
->namescope
;
4893 if (!item
->GetAsDependencyObject ()->SetName (attr
[i
+1], scope
)) {
4894 parser_error (p
, item
->element_name
, NULL
, 2028,
4895 "The name already exists in the tree: %s.", attr
[i
+1]);
4897 g_list_free (delay_att
);
4903 if (prop
->IsReadOnly ()) {
4904 parser_error (p
, item
->element_name
, NULL
, 2014,
4905 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4907 g_list_free (delay_att
);
4911 if (item
->IsPropertySet (prop
->GetName())) {
4912 parser_error (p
, item
->element_name
, attr
[i
], 2033,
4913 "Cannot specify the value multiple times for property: %s.", prop
->GetName ());
4915 g_list_free (delay_att
);
4921 char *attr_value
= g_strdup (attr
[i
+1]);
4923 bool need_managed
= false;
4924 if (attr
[i
+1][0] == '{') {
4925 if (attr
[i
+1][1] == '}') {
4926 // {} is an escape sequence so you can have strings like {StaticResource}
4927 char *nv
= attr_value
;
4928 attr_value
= g_strdup (attr_value
+ 2);
4931 else if (attr
[i
+1][strlen(attr
[i
+1]) - 1] == '}') {
4932 need_managed
= true;
4936 if (!need_managed
) {
4937 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
4939 g_free (attr_value
);
4944 Type::Kind propKind
= prop
->GetPropertyType ();
4946 if (need_managed
|| is_managed_kind (propKind
) || types
->Find (prop
->GetOwnerType ())->IsCustomType () || (v
&& is_managed_kind (v
->GetKind ()))) {
4947 bool str_value
= false;
4949 v
= new Value (attr
[i
+ 1]); // Note that we passed the non escaped value, not attr_value
4954 // printf ("setting managed property: %s::%s to %s=%s\n", dep->GetType ()->GetName (), prop->GetName (), attr [i], attr [i + 1]);
4955 if (p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, g_strdup (attr
[i
]), v
, NULL
)) {
4957 g_free (attr_value
);
4964 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
4966 g_free (attr_value
);
4973 if (!v_set
&& !value_is_explicit_null (attr
[i
+ 1])) { // Check the non escaped value
4974 parser_error (p
, item
->element_name
, attr
[i
], 2024, "Invalid attribute value %s for property %s.", attr
[i
+1], attr
[i
]);
4976 g_free (attr_value
);
4978 g_list_free (delay_att
);
4983 // 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 ());
4984 if (!dep
->SetValueWithError (prop
, v
, &err
))
4985 parser_error (p
, item
->element_name
, attr
[i
], err
.code
, err
.message
);
4987 item
->MarkPropertyAsSet (prop
->GetName());
4990 g_free (attr_value
);
4992 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4999 GList
*walk
= g_list_first (delay_att
);
5001 int i
= GPOINTER_TO_INT (walk
->data
);
5006 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
5008 if (attr_name
[1]) {
5009 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
5011 if (ns
== x_namespace
) {
5012 // Skip these, they are handled earlier
5013 g_strfreev (attr_name
);
5018 g_strfreev (attr_name
);
5019 parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
5023 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
5025 g_strfreev (attr_name
);
5027 // Setting managed attributes can cause errors galore
5031 if (!item
->SetUnknownAttribute (p
, attr
[i
], attr
[i
+ 1])) {
5032 parser_error (p
, item
->element_name
, attr
[i
], 2012,
5033 "Unknown attribute %s on element %s.",
5034 attr
[i
], item
->element_name
);
5042 g_list_free (delay_att
);
5047 lookup_named_item (XamlElementInstance
*top
, const char *name
)
5049 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
5050 XamlElementInstance
*inst
= top
;
5053 if (inst
->element_type
== XamlElementInstance::ELEMENT
) {
5054 ResourceDictionary
*rd
= NULL
;
5055 Type::Kind kind
= inst
->info
->GetKind ();
5057 if (types
->IsSubclassOf (kind
, Type::FRAMEWORKELEMENT
)) {
5058 rd
= inst
->GetAsDependencyObject ()->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary ();
5059 } else if (types
->IsSubclassOf (kind
, Type::RESOURCE_DICTIONARY
)) {
5060 rd
= (ResourceDictionary
*) inst
->GetAsDependencyObject ();
5065 Value
*res
= lookup_resource_dictionary (rd
, name
, &exists
);
5071 inst
= inst
->parent
;
5078 lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
)
5081 Value
*resource_value
= rd
->Get (name
, exists
);
5082 return *exists
? new Value (*resource_value
) : NULL
;
5086 xaml_lookup_named_item (void *parser
, void *instance
, const char* name
)
5088 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5089 XamlElementInstance
*inst
= (XamlElementInstance
*) instance
;
5093 res
= lookup_named_item (inst
, name
);
5095 XamlContext
*context
= p
->loader
->GetContext ();
5096 if (!res
&& context
)
5097 context
->internal
->LookupNamedItem (name
, &res
);
5100 Application
*app
= Application::GetCurrent ();
5102 ResourceDictionary
*rd
= app
->GetResources ();
5104 bool exists
= false;
5105 res
= lookup_resource_dictionary (rd
, name
, &exists
);
5107 if (res
&& Type::IsSubclassOf (p
->deployment
, res
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
5108 DependencyObject
*dob
= res
->AsDependencyObject ();
5109 NameScope::SetNameScope (dob
, dob
->FindNameScope ());
5118 xaml_get_template_parent (void *parser
, void *element_instance
)
5120 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5121 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5123 return p
->GetTemplateParent (item
);
5127 xaml_get_element_key (void *parser
, void *element_instance
)
5129 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5130 const char *key
= item
->GetKey ();
5132 key
= item
->GetName ();
5133 return g_strdup (key
);
5137 xaml_get_element_name (void *parser
, void *element_instance
)
5139 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5140 return g_strdup (item
->element_name
);
5144 xaml_is_property_set (void *parser
, void *element_instance
, char *name
)
5146 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5147 return item
->IsPropertySet (name
);
5151 xaml_mark_property_as_set (void *parser
, void *element_instance
, char *name
)
5153 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5154 item
->MarkPropertyAsSet (g_strdup (name
));
5158 xaml_delay_set_property (void *parser
, void *element_instance
, const char *xmlns
, const char *name
, const Value
*value
)
5160 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5161 item
->DelaySetProperty (xmlns
, name
, value
);
5167 default_namespace
= new DefaultNamespace ();
5168 x_namespace
= new XNamespace ();
5169 xml_namespace
= new XmlNamespace ();