Fix 1968248: "Opening of any other XML-file crashes synfigstudio". Attempting to...
[synfig.git] / synfig-core / trunk / src / synfig / loadcanvas.cpp
index 8cf5cba..cf01a8c 100644 (file)
@@ -121,46 +121,25 @@ static void _canvas_file_name_changed(Canvas *x)
 }
 
 Canvas::Handle
-synfig::open_canvas(const String &filename)
+synfig::open_canvas(const String &filename,String &errors)
 {
-       CanvasParser parser;
-
-       parser.set_allow_errors(true);
-
-       Canvas::Handle canvas=parser.parse_from_file(filename);
-
-       if(parser.error_count())
-               return Canvas::Handle();
-
-       return canvas;
-}
-
-Canvas::Handle
-synfig::open_canvas_as(const String &filename,const String &as)
-{
-       CanvasParser parser;
-
-       parser.set_allow_errors(true);
-
-       Canvas::Handle canvas=parser.parse_from_file_as(filename,as);
-
-       if(parser.error_count())
-               return Canvas::Handle();
-
-       return canvas;
+       return open_canvas_as(filename, filename, errors);
 }
 
 Canvas::Handle
-synfig::string_to_canvas(const String &data)
+synfig::open_canvas_as(const String &filename,const String &as,String &errors)
 {
        CanvasParser parser;
 
        parser.set_allow_errors(true);
 
-       Canvas::Handle canvas=parser.parse_from_string(data);
+       Canvas::Handle canvas=parser.parse_from_file_as(filename,as,errors);
 
        if(parser.error_count())
+       {
+               errors = parser.get_errors_text();
                return Canvas::Handle();
+       }
 
        return canvas;
 }
@@ -195,6 +174,7 @@ CanvasParser::error(xmlpp::Node *element, const String &text)
 {
        string str=strprintf("%s:<%s>:%d: error: ",filename.c_str(),element->get_name().c_str(),element->get_line())+text;
        total_errors_++;
+       errors_text += "  * " + str + "\n";
        if(!allow_errors_)
                throw runtime_error(str);
        cerr<<str<<endl;
@@ -995,7 +975,7 @@ CanvasParser::parse_animated(xmlpp::Element *element,Canvas::Handle canvas)
                        if(child->get_attribute("temporal-tension"))
                        {
                                synfig::String str(child->get_attribute("temporal-tension")->get_value());
-                               waypoint->set_time_tension(atof(str.c_str()));
+                               waypoint->set_temporal_tension(atof(str.c_str()));
                        }
                        if(child->get_attribute("continuity"))
                        {
@@ -1292,6 +1272,18 @@ CanvasParser::parse_linkable_value_node(xmlpp::Element *element,Canvas::Handle c
                                 value_node->link_name(i) == "fixed_length"))
                                continue;
 
+                       // 'scale' was added while canvas version 0.5 was in use
+                       if ((version == "0.3" || version == "0.4" || version == "0.5") &&
+                               element->get_name() == "blinecalcwidth" &&
+                               value_node->link_name(i) == "scale")
+                               continue;
+
+                       // 'loop' was added while canvas version 0.5 was in use, as was the 'gradientcolor' node type
+                       if (version == "0.5" &&
+                               element->get_name() == "gradientcolor" &&
+                               value_node->link_name(i) == "loop")
+                               continue;
+
                        error(element, strprintf(_("<%s> is missing link %d (%s)"),
                                                                         element->get_name().c_str(),
                                                                         i,
@@ -1707,6 +1699,11 @@ CanvasParser::parse_layer(xmlpp::Element *element,Canvas::Handle canvas)
 
                        String param_name=child->get_attribute("name")->get_value();
 
+                       // SVN r2013 and r2014 renamed all 'pos' and 'offset' parameters to 'origin'
+                       // 'pos' and 'offset' will appear in old .sif files; handle them correctly
+                       if (param_name == "pos" || param_name == "offset")
+                               param_name = "origin";
+
                        if(child->get_attribute("use"))
                        {
                                // If the "use" attribute is used, then the
@@ -1730,6 +1727,12 @@ CanvasParser::parse_layer(xmlpp::Element *element,Canvas::Handle canvas)
                                        handle<ValueNode> value_node=canvas->surefind_value_node(str);
 
                                        // Assign the value_node to the dynamic parameter list
+                                       if (param_name == "segment_list" && (layer->get_name() == "region" || layer->get_name() == "outline"))
+                                       {
+                                               synfig::warning("%s: Updated valuenode connection to use the \"bline\" parameter instead of \"segment_list\".",
+                                                                               layer->get_name().c_str());
+                                               param_name = "bline";
+                                       }
                                        layer->connect_dynamic_param(param_name,value_node);
                        }
                                catch(Exception::IDNotFound)
@@ -1770,7 +1773,9 @@ CanvasParser::parse_layer(xmlpp::Element *element,Canvas::Handle canvas)
                                // the layer liked it
                                if(!layer->set_param(param_name,data))
                                {
-                                       warning((*iter),_("Layer rejected value for <param>"));
+                                       warning((*iter),strprintf(_("Layer '%s' rejected value for parameter '%s'"),
+                                                                                         element->get_attribute("type")->get_value().c_str(),
+                                                                                         param_name.c_str()));
                                        continue;
                                }
                        }
@@ -1859,10 +1864,20 @@ CanvasParser::parse_canvas(xmlpp::Element *element,Canvas::Handle parent,bool in
                canvas->set_version(parent->get_version());
 
        if(element->get_attribute("width"))
-               canvas->rend_desc().set_w(atoi(element->get_attribute("width")->get_value().c_str()));
+       {
+               int width = atoi(element->get_attribute("width")->get_value().c_str());
+               if (width < 1)
+                       fatal_error(element, _("Canvas with width or height less than one is not allowed"));
+               canvas->rend_desc().set_w(width);
+       }
 
        if(element->get_attribute("height"))
-               canvas->rend_desc().set_h(atoi(element->get_attribute("height")->get_value().c_str()));
+       {
+               int height = atoi(element->get_attribute("height")->get_value().c_str());
+               if (height < 1)
+                       fatal_error(element, _("Canvas with width or height less than one is not allowed"));
+               canvas->rend_desc().set_h(height);
+       }
 
        if(element->get_attribute("xres"))
                canvas->rend_desc().set_x_res(atof(element->get_attribute("xres")->get_value().c_str()));
@@ -2065,20 +2080,14 @@ CanvasParser::parse_canvas(xmlpp::Element *element,Canvas::Handle parent,bool in
 }
 
 Canvas::Handle
-CanvasParser::parse_from_file(const String &file)
+CanvasParser::parse_from_file_as(const String &file_,const String &as_,String &errors)
 {
-       return parse_from_file_as(file,file);
-}
+       ChangeLocale change_locale(LC_NUMERIC, "C");
+       String file(unix_to_local_path(file_));
+       String as(unix_to_local_path(as_));
 
-Canvas::Handle
-CanvasParser::parse_from_file_as(const String &file_,const String &as_)
-{
        try
        {
-        ChangeLocale change_locale(LC_NUMERIC, "C");
-               String file(unix_to_local_path(file_));
-               String as(unix_to_local_path(as_));
-
                if(get_open_canvas_map().count(etl::absolute_path(as)))
                        return get_open_canvas_map()[etl::absolute_path(as)];
 
@@ -2088,12 +2097,11 @@ CanvasParser::parse_from_file_as(const String &file_,const String &as_)
                if(parser)
                {
                        Canvas::Handle canvas(parse_canvas(parser.get_document()->get_root_node(),0,false,as));
+                       if (!canvas) return canvas;
                        get_open_canvas_map()[etl::absolute_path(as)]=canvas;
                        canvas->signal_deleted().connect(sigc::bind(sigc::ptr_fun(_remove_from_open_canvas_map),canvas.get()));
                        canvas->signal_file_name_changed().connect(sigc::bind(sigc::ptr_fun(_canvas_file_name_changed),canvas.get()));
 
-
-
                        const ValueNodeList& value_node_list(canvas->value_node_list());
 
                        again:
@@ -2116,67 +2124,24 @@ CanvasParser::parse_from_file_as(const String &file_,const String &as_)
        catch(Exception::FileNotFound) { synfig::error("FileNotFound Thrown"); }
        catch(Exception::IDNotFound) { synfig::error("IDNotFound Thrown"); }
        catch(Exception::IDAlreadyExists) { synfig::error("IDAlreadyExists Thrown"); }
-       catch(const std::exception& ex)
+       catch(xmlpp::internal_error x)
        {
-               synfig::error("Standard Exception: "+String(ex.what()));
-               return Canvas::Handle();
-       }
-       catch(const String& str)
-       {
-               cerr<<str<<endl;
-               //      synfig::error(str);
-               return Canvas::Handle();
-       }
-       return Canvas::Handle();
-}
-
-Canvas::Handle
-CanvasParser::parse_from_string(const String &data)
-{
-       try
-       {
-        ChangeLocale change_locale(LC_NUMERIC, "C");
-               filename=_("<INTERNAL>");
-               total_warnings_=0;
-               xmlpp::DomParser parser;
-               parser.parse_memory(data);
-               xmlpp::Element *root=parser.get_document()->get_root_node();
-               if(parser)
-               {
-                       Canvas::Handle canvas(parse_canvas(root));
-                       canvas->signal_deleted().connect(sigc::bind(sigc::ptr_fun(_remove_from_open_canvas_map),canvas.get()));
-                       canvas->signal_file_name_changed().connect(sigc::bind(sigc::ptr_fun(_canvas_file_name_changed),canvas.get()));
-
-                       const ValueNodeList& value_node_list(canvas->value_node_list());
-                       again:
-                       ValueNodeList::const_iterator iter;
-                       for(iter=value_node_list.begin();iter!=value_node_list.end();++iter)
-                       {
-                               ValueNode::Handle value_node(*iter);
-                               if(value_node->is_exported() && value_node->get_id().find("Unnamed")==0)
-                               {
-                                       canvas->remove_value_node(value_node);
-                                       goto again;
-                               }
-                       }
-
-                       return canvas;
-               }
+               printf("caught internal error\n");
+               if (!strcmp(x.what(), "Couldn't create parsing context"))
+                       throw runtime_error(String("  * ") + _("Can't open file") + " \"" + file + "\"");
+               throw;
        }
-       catch(Exception::BadLinkName) { synfig::error("BadLinkName Thrown"); }
-       catch(Exception::BadType) { synfig::error("BadType Thrown"); }
-       catch(Exception::FileNotFound) { synfig::error("FileNotFound Thrown"); }
-       catch(Exception::IDNotFound) { synfig::error("IDNotFound Thrown"); }
-       catch(Exception::IDAlreadyExists) { synfig::error("IDAlreadyExists Thrown"); }
        catch(const std::exception& ex)
        {
                synfig::error("Standard Exception: "+String(ex.what()));
+               errors = ex.what();
                return Canvas::Handle();
        }
        catch(const String& str)
        {
                cerr<<str<<endl;
                //      synfig::error(str);
+               errors = str;
                return Canvas::Handle();
        }
        return Canvas::Handle();