Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. static xml_element *
  5. xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip)
  6. {
  7.         xps_resource *head, *node;
  8.         for (head = dict; head; head = head->parent)
  9.         {
  10.                 for (node = head; node; node = node->next)
  11.                 {
  12.                         if (!strcmp(node->name, name))
  13.                         {
  14.                                 if (urip && head->base_uri)
  15.                                         *urip = head->base_uri;
  16.                                 return node->data;
  17.                         }
  18.                 }
  19.         }
  20.         return NULL;
  21. }
  22.  
  23. static xml_element *
  24. xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, char **urip)
  25. {
  26.         char name[1024];
  27.         char *s;
  28.  
  29.         if (strstr(att, "{StaticResource ") != att)
  30.                 return NULL;
  31.  
  32.         fz_strlcpy(name, att + 16, sizeof name);
  33.         s = strrchr(name, '}');
  34.         if (s)
  35.                 *s = 0;
  36.  
  37.         return xps_find_resource(ctx, dict, name, urip);
  38. }
  39.  
  40. void
  41. xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict,
  42.                 char **attp, xml_element **tagp, char **urip)
  43. {
  44.         if (*attp)
  45.         {
  46.                 xml_element *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip);
  47.                 if (rsrc)
  48.                 {
  49.                         *attp = NULL;
  50.                         *tagp = rsrc;
  51.                 }
  52.         }
  53. }
  54.  
  55. static int
  56. xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, char *source_att)
  57. {
  58.         char part_name[1024];
  59.         char part_uri[1024];
  60.         xps_resource *dict;
  61.         xps_part *part;
  62.         xml_element *xml;
  63.         char *s;
  64.         int code;
  65.  
  66.         /* External resource dictionaries MUST NOT reference other resource dictionaries */
  67.         xps_absolute_path(part_name, base_uri, source_att, sizeof part_name);
  68.         part = xps_read_part(ctx, part_name);
  69.         if (!part)
  70.         {
  71.                 return fz_throw("cannot find remote resource part '%s'", part_name);
  72.         }
  73.  
  74.         xml = xml_parse_document(part->data, part->size);
  75.         if (!xml)
  76.         {
  77.                 xps_free_part(ctx, part);
  78.                 return fz_rethrow(-1, "cannot parse xml");
  79.         }
  80.  
  81.         if (strcmp(xml_tag(xml), "ResourceDictionary"))
  82.         {
  83.                 xml_free_element(xml);
  84.                 xps_free_part(ctx, part);
  85.                 return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml));
  86.         }
  87.  
  88.         fz_strlcpy(part_uri, part_name, sizeof part_uri);
  89.         s = strrchr(part_uri, '/');
  90.         if (s)
  91.                 s[1] = 0;
  92.  
  93.         code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml);
  94.         if (code)
  95.         {
  96.                 xml_free_element(xml);
  97.                 xps_free_part(ctx, part);
  98.                 return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri);
  99.         }
  100.  
  101.         dict->base_xml = xml; /* pass on ownership */
  102.  
  103.         xps_free_part(ctx, part);
  104.  
  105.         *dictp = dict;
  106.         return fz_okay;
  107. }
  108.  
  109. int
  110. xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root)
  111. {
  112.         xps_resource *head;
  113.         xps_resource *entry;
  114.         xml_element *node;
  115.         char *source;
  116.         char *key;
  117.         int code;
  118.  
  119.         source = xml_att(root, "Source");
  120.         if (source)
  121.         {
  122.                 code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source);
  123.                 if (code)
  124.                         return fz_rethrow(code, "cannot parse remote resource dictionary");
  125.                 return fz_okay;
  126.         }
  127.  
  128.         head = NULL;
  129.  
  130.         for (node = xml_down(root); node; node = xml_next(node))
  131.         {
  132.                 key = xml_att(node, "x:Key");
  133.                 if (key)
  134.                 {
  135.                         entry = fz_malloc(sizeof(xps_resource));
  136.                         entry->name = key;
  137.                         entry->base_uri = NULL;
  138.                         entry->base_xml = NULL;
  139.                         entry->data = node;
  140.                         entry->next = head;
  141.                         entry->parent = NULL;
  142.                         head = entry;
  143.                 }
  144.         }
  145.  
  146.         if (head)
  147.                 head->base_uri = fz_strdup(base_uri);
  148.         else
  149.                 return fz_throw("empty resource dictionary");
  150.  
  151.         *dictp = head;
  152.         return fz_okay;
  153. }
  154.  
  155. void
  156. xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict)
  157. {
  158.         xps_resource *next;
  159.         while (dict)
  160.         {
  161.                 next = dict->next;
  162.                 if (dict->base_xml)
  163.                         xml_free_element(dict->base_xml);
  164.                 if (dict->base_uri)
  165.                         fz_free(dict->base_uri);
  166.                 fz_free(dict);
  167.                 dict = next;
  168.         }
  169. }
  170.  
  171. void
  172. xps_debug_resource_dictionary(xps_resource *dict)
  173. {
  174.         while (dict)
  175.         {
  176.                 if (dict->base_uri)
  177.                         printf("URI = '%s'\n", dict->base_uri);
  178.                 printf("KEY = '%s' VAL = %p\n", dict->name, dict->data);
  179.                 if (dict->parent)
  180.                 {
  181.                         printf("PARENT = {\n");
  182.                         xps_debug_resource_dictionary(dict->parent);
  183.                         printf("}\n");
  184.                 }
  185.                 dict = dict->next;
  186.         }
  187. }
  188.