Remove spaces and tabs at end of lines.
[synfig.git] / synfig-studio / trunk / src / gtkmm / app.cpp
index cc19fbe..ee4459b 100644 (file)
@@ -6,7 +6,9 @@
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007 Chris Moore
+**     Copyright (c) 2007, 2008 Chris Moore
+**     Copyright (c) 2008 Gerald Young
+**  Copyright (c) 2008 Carlos López
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
 #      include <config.h>
 #endif
 
 #      include <config.h>
 #endif
 
+#ifdef WIN32
+#define WINVER 0x0500
+#include <windows.h>
+#endif
+
 #include <fstream>
 #include <iostream>
 #include <locale>
 #include <fstream>
 #include <iostream>
 #include <locale>
+#include <cstring>
 
 #ifdef HAVE_SYS_ERRNO_H
 #include <sys/errno.h>
 
 #ifdef HAVE_SYS_ERRNO_H
 #include <sys/errno.h>
 #include <gtkmm/inputdialog.h>
 #include <gtkmm/accelmap.h>
 #include <gtkmm/uimanager.h>
 #include <gtkmm/inputdialog.h>
 #include <gtkmm/accelmap.h>
 #include <gtkmm/uimanager.h>
+#include <gtkmm/textview.h>
 
 #include <gtk/gtk.h>
 
 
 #include <gtk/gtk.h>
 
+#include <gdkmm/general.h>
+
 #include <synfig/loadcanvas.h>
 #include <synfig/loadcanvas.h>
+#include <synfig/savecanvas.h>
 
 #include "app.h"
 #include "about.h"
 
 #include "app.h"
 #include "about.h"
+#include "splash.h"
 #include "instance.h"
 #include "canvasview.h"
 #include "dialog_setup.h"
 #include "instance.h"
 #include "canvasview.h"
 #include "dialog_setup.h"
 #include "state_rectangle.h"
 #include "state_smoothmove.h"
 #include "state_scale.h"
 #include "state_rectangle.h"
 #include "state_smoothmove.h"
 #include "state_scale.h"
+#include "state_star.h"
+#include "state_text.h"
 #include "state_width.h"
 #include "state_rotate.h"
 #include "state_zoom.h"
 
 #include "devicetracker.h"
 #include "dialog_tooloptions.h"
 #include "state_width.h"
 #include "state_rotate.h"
 #include "state_zoom.h"
 
 #include "devicetracker.h"
 #include "dialog_tooloptions.h"
+#include "widget_enum.h"
 
 #include "autorecover.h"
 
 
 #include "autorecover.h"
 
 #include <fmod.h>
 #endif
 
 #include <fmod.h>
 #endif
 
-#ifdef WIN32
-#define _WIN32_WINNT 0x0500
-#include <windows.h>
-#endif
 #include <gtkmm/accelmap.h>
 #include <gtkmm/filechooser.h>
 #include <gtkmm/filechooserdialog.h>
 #include <gtkmm/accelmap.h>
 #include <gtkmm/filechooser.h>
 #include <gtkmm/filechooserdialog.h>
@@ -199,6 +211,8 @@ App::signal_instance_deleted() { return signal_instance_deleted_; }
 static std::list<std::string> recent_files;
 const std::list<std::string>& App::get_recent_files() { return recent_files; }
 
 static std::list<std::string> recent_files;
 const std::list<std::string>& App::get_recent_files() { return recent_files; }
 
+static std::list<std::string> recent_files_window_size;
+
 int    App::Busy::count;
 bool App::shutdown_in_progress;
 
 int    App::Busy::count;
 bool App::shutdown_in_progress;
 
@@ -221,6 +235,8 @@ const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_i
 etl::handle<Instance> App::selected_instance;
 etl::handle<CanvasView> App::selected_canvas_view;
 
 etl::handle<Instance> App::selected_instance;
 etl::handle<CanvasView> App::selected_canvas_view;
 
+studio::About *studio::App::about=NULL;
+
 studio::Toolbox *studio::App::toolbox=NULL;
 
 studio::AutoRecover *studio::App::auto_recover=NULL;
 studio::Toolbox *studio::App::toolbox=NULL;
 
 studio::AutoRecover *studio::App::auto_recover=NULL;
@@ -255,7 +271,20 @@ studio::Dock_Curves* dock_curves;
 std::list< etl::handle< studio::Module > > module_list_;
 
 bool studio::App::use_colorspace_gamma=true;
 std::list< etl::handle< studio::Module > > module_list_;
 
 bool studio::App::use_colorspace_gamma=true;
+#ifdef SINGLE_THREADED
 bool studio::App::single_threaded=false;
 bool studio::App::single_threaded=false;
+#endif
+bool studio::App::restrict_radius_ducks=false;
+bool studio::App::resize_imported_images=false;
+String studio::App::custom_filename_prefix(DEFAULT_FILENAME_PREFIX);
+int studio::App::preferred_x_size=480;
+int studio::App::preferred_y_size=270;
+String studio::App::predefined_size(DEFAULT_PREDEFINED_SIZE);
+#ifdef USE_OPEN_FOR_URLS
+String studio::App::browser_command("open"); // MacOS only
+#else
+String studio::App::browser_command("xdg-open"); // Linux XDG standard
+#endif
 
 static int max_recent_files_=25;
 int studio::App::get_max_recent_files() { return max_recent_files_; }
 
 static int max_recent_files_=25;
 int studio::App::get_max_recent_files() { return max_recent_files_; }
@@ -268,7 +297,7 @@ namespace studio {
 bool
 really_delete_widget(Gtk::Widget *widget)
 {
 bool
 really_delete_widget(Gtk::Widget *widget)
 {
-       synfig::info("really delete %p", (void*)widget);
+       // synfig::info("really delete %p", (void*)widget);
        delete widget;
        return false;
 }
        delete widget;
        return false;
 }
@@ -279,7 +308,7 @@ really_delete_widget(Gtk::Widget *widget)
 void
 delete_widget(Gtk::Widget *widget)
 {
 void
 delete_widget(Gtk::Widget *widget)
 {
-       synfig::info("delete %p", (void*)widget);
+       // synfig::info("delete %p", (void*)widget);
        Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
 }
 
        Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
 }
 
@@ -411,30 +440,24 @@ studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib
 {
        ui_manager->insert_action_group(group,0);
        return;
 {
        ui_manager->insert_action_group(group,0);
        return;
-       DEBUGPOINT();
        std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
        std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
 
        std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
        std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
 
-       DEBUGPOINT();
        for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
        {
        for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
        {
-               DEBUGPOINT();
                if(*iter && (*iter)->get_name()!="menus")
                {
                        synfig::info("Removing action group "+(*iter)->get_name());
                        ui_manager->remove_action_group(*iter);
                }
        }
                if(*iter && (*iter)->get_name()!="menus")
                {
                        synfig::info("Removing action group "+(*iter)->get_name());
                        ui_manager->remove_action_group(*iter);
                }
        }
-       DEBUGPOINT();
        ui_manager->insert_action_group(group,0);
 
        ui_manager->insert_action_group(group,0);
 
-       DEBUGPOINT();
        for(;!prev_groups.empty();prev_groups.pop_front())
        {
                if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
                        ui_manager->insert_action_group(prev_groups.front(),1);
        }
        for(;!prev_groups.empty();prev_groups.pop_front())
        {
                if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
                        ui_manager->insert_action_group(prev_groups.front(),1);
        }
-       DEBUGPOINT();
 }
 */
 class Preferences : public synfigapp::Settings
 }
 */
 class Preferences : public synfigapp::Settings
@@ -472,16 +495,53 @@ public:
                        value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
                        return true;
                }
                        value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
                        return true;
                }
+#ifdef SINGLE_THREADED
                if(key=="single_threaded")
                {
                        value=strprintf("%i",(int)App::single_threaded);
                        return true;
                }
                if(key=="single_threaded")
                {
                        value=strprintf("%i",(int)App::single_threaded);
                        return true;
                }
+#endif
                if(key=="auto_recover_backup_interval")
                {
                        value=strprintf("%i",App::auto_recover->get_timeout());
                        return true;
                }
                if(key=="auto_recover_backup_interval")
                {
                        value=strprintf("%i",App::auto_recover->get_timeout());
                        return true;
                }
+               if(key=="restrict_radius_ducks")
+               {
+                       value=strprintf("%i",(int)App::restrict_radius_ducks);
+                       return true;
+               }
+               if(key=="resize_imported_images")
+               {
+                       value=strprintf("%i",(int)App::resize_imported_images);
+                       return true;
+               }
+               if(key=="browser_command")
+               {
+                       value=App::browser_command;
+                       return true;
+               }
+               if(key=="custom_filename_prefix")
+               {
+                       value=App::custom_filename_prefix;
+                       return true;
+               }
+               if(key=="preferred_x_size")
+               {
+                       value=strprintf("%i",App::preferred_x_size);
+                       return true;
+               }
+               if(key=="preferred_y_size")
+               {
+                       value=strprintf("%i",App::preferred_y_size);
+                       return true;
+               }
+               if(key=="predefined_size")
+               {
+                       value=strprintf("%s",App::predefined_size.c_str());
+                       return true;
+               }
 
                return synfigapp::Settings::get_value(key,value);
        }
 
                return synfigapp::Settings::get_value(key,value);
        }
@@ -532,13 +592,53 @@ public:
                        App::distance_system=Distance::ident_system(value);;
                        return true;
                }
                        App::distance_system=Distance::ident_system(value);;
                        return true;
                }
+#ifdef SINGLE_THREADED
                if(key=="single_threaded")
                {
                        int i(atoi(value.c_str()));
                        App::single_threaded=i;
                        return true;
                }
                if(key=="single_threaded")
                {
                        int i(atoi(value.c_str()));
                        App::single_threaded=i;
                        return true;
                }
-
+#endif
+               if(key=="restrict_radius_ducks")
+               {
+                       int i(atoi(value.c_str()));
+                       App::restrict_radius_ducks=i;
+                       return true;
+               }
+               if(key=="resize_imported_images")
+               {
+                       int i(atoi(value.c_str()));
+                       App::resize_imported_images=i;
+                       return true;
+               }
+               if(key=="browser_command")
+               {
+                       App::browser_command=value;
+                       return true;
+               }
+               if(key=="custom_filename_prefix")
+               {
+                       App::custom_filename_prefix=value;
+                       return true;
+               }
+               if(key=="preferred_x_size")
+               {
+                       int i(atoi(value.c_str()));
+                       App::preferred_x_size=i;
+                       return true;
+               }
+               if(key=="preferred_y_size")
+               {
+                       int i(atoi(value.c_str()));
+                       App::preferred_y_size=i;
+                       return true;
+               }
+               if(key=="predefined_size")
+               {
+                       App::predefined_size=value;
+                       return true;
+               }
                return synfigapp::Settings::set_value(key,value);
        }
 
                return synfigapp::Settings::set_value(key,value);
        }
 
@@ -550,8 +650,17 @@ public:
                ret.push_back("distance_system");
                ret.push_back("file_history.size");
                ret.push_back("use_colorspace_gamma");
                ret.push_back("distance_system");
                ret.push_back("file_history.size");
                ret.push_back("use_colorspace_gamma");
+#ifdef SINGLE_THREADED
                ret.push_back("single_threaded");
                ret.push_back("single_threaded");
+#endif
                ret.push_back("auto_recover_backup_interval");
                ret.push_back("auto_recover_backup_interval");
+               ret.push_back("restrict_radius_ducks");
+               ret.push_back("resize_imported_images");
+               ret.push_back("browser_command");
+               ret.push_back("custom_filename_prefix");
+               ret.push_back("preferred_x_size");
+               ret.push_back("preferred_y_size");
+               ret.push_back("predefined_size");
                return ret;
        }
 };
                return ret;
        }
 };
@@ -574,6 +683,7 @@ init_ui_manager()
        menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
        menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
        menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
        menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
        menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
        menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
+       menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) );
        menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
        menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
        menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
        menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
        menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
        menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
@@ -597,6 +707,7 @@ init_ui_manager()
 
        DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
        DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
 
        DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
        DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
+       DEFINE_ACTION("new", Gtk::Stock::NEW);
        DEFINE_ACTION("open", Gtk::Stock::OPEN);
        DEFINE_ACTION("save", Gtk::Stock::SAVE);
        DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
        DEFINE_ACTION("open", Gtk::Stock::OPEN);
        DEFINE_ACTION("save", Gtk::Stock::SAVE);
        DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
@@ -613,6 +724,7 @@ init_ui_manager()
        DEFINE_ACTION("options", _("Options"));
        DEFINE_ACTION("close", _("Close View"));
        DEFINE_ACTION("close-document", _("Close Document"));
        DEFINE_ACTION("options", _("Options"));
        DEFINE_ACTION("close", _("Close View"));
        DEFINE_ACTION("close-document", _("Close Document"));
+       DEFINE_ACTION("quit", Gtk::Stock::QUIT);
 
 
        DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
 
 
        DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
@@ -621,6 +733,8 @@ init_ui_manager()
        DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
        DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
        DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
        DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
        DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
        DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
+       DEFINE_ACTION("unselect-all-ducks", _("Unselect All Ducks"));
+       DEFINE_ACTION("select-all-layers", _("Select All Layers"));
        DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
        DEFINE_ACTION("properties", _("Properties"));
 
        DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
        DEFINE_ACTION("properties", _("Properties"));
 
@@ -641,6 +755,8 @@ init_ui_manager()
        DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
        DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
        DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
        DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
        DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
        DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
+       for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
+               DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter));
        DEFINE_ACTION("play", _("Play"));
        // DEFINE_ACTION("pause", _("Pause"));
        DEFINE_ACTION("stop", _("Stop"));
        DEFINE_ACTION("play", _("Play"));
        // DEFINE_ACTION("pause", _("Pause"));
        DEFINE_ACTION("stop", _("Stop"));
@@ -648,6 +764,8 @@ init_ui_manager()
        DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
        DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
        DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
        DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
        DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
        DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
+       DEFINE_ACTION("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
+       DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size"));
        DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
        DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
        DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
        DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
        DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
        DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
@@ -715,6 +833,8 @@ init_ui_manager()
 "      </popup>"
 "      <popup name='menu-main' action='menu-main'>"
 "      <menu action='menu-file'>"
 "      </popup>"
 "      <popup name='menu-main' action='menu-main'>"
 "      <menu action='menu-file'>"
+"              <menuitem action='new' />"
+"              <menuitem action='open' />"
 "              <menuitem action='save' />"
 "              <menuitem action='save-as' />"
 "              <menuitem action='revert' />"
 "              <menuitem action='save' />"
 "              <menuitem action='save-as' />"
 "              <menuitem action='revert' />"
@@ -733,6 +853,7 @@ init_ui_manager()
 "              <menuitem action='options' />"
 "              <menuitem action='close' />"
 "              <menuitem action='close-document' />"
 "              <menuitem action='options' />"
 "              <menuitem action='close' />"
 "              <menuitem action='close-document' />"
+"              <menuitem action='quit' />"
 "      </menu>"
 "      <menu action='menu-edit'>"
 "              <menuitem action='undo'/>"
 "      </menu>"
 "      <menu action='menu-edit'>"
 "              <menuitem action='undo'/>"
@@ -742,8 +863,10 @@ init_ui_manager()
 "              <menuitem action='copy'/>"
 "              <menuitem action='paste'/>"
 "              <separator name='bleh06'/>"
 "              <menuitem action='copy'/>"
 "              <menuitem action='paste'/>"
 "              <separator name='bleh06'/>"
-"              <menuitem action='select-all-ducks'/>"
+"              <menuitem action='select-all-layers'/>"
 "              <menuitem action='unselect-all-layers'/>"
 "              <menuitem action='unselect-all-layers'/>"
+"              <menuitem action='select-all-ducks'/>"
+"              <menuitem action='unselect-all-ducks'/>"
 "              <separator name='bleh07'/>"
 "              <menuitem action='properties'/>"
 "      </menu>"
 "              <separator name='bleh07'/>"
 "              <menuitem action='properties'/>"
 "      </menu>"
@@ -769,6 +892,17 @@ init_ui_manager()
 "                      <menuitem action='quality-09' />"
 "                      <menuitem action='quality-10' />"
 "              </menu>"
 "                      <menuitem action='quality-09' />"
 "                      <menuitem action='quality-10' />"
 "              </menu>"
+"              <menu action='menu-lowres-pixel'>"
+"              <menuitem action='decrease-low-res-pixel-size'/>"
+"              <menuitem action='increase-low-res-pixel-size'/>"
+"              <separator name='pixel-size-separator'/>"
+;
+
+       for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
+               ui_info += strprintf("                  <menuitem action='lowres-pixel-%d' />", *iter);
+
+       ui_info +=
+"              </menu>"
 "              <separator name='bleh08'/>"
 "              <menuitem action='play'/>"
 //"            <menuitem action='pause'/>"
 "              <separator name='bleh08'/>"
 "              <menuitem action='play'/>"
 //"            <menuitem action='pause'/>"
@@ -858,7 +992,7 @@ init_ui_manager()
        }
 
        // Add default keyboard accelerators
        }
 
        // Add default keyboard accelerators
-#define ACCEL(path,accel)                                              \
+#define ACCEL(accel,path)                                              \
        {                                                                                       \
                Gtk::AccelKey accel_key(accel,path);    \
                Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod());       \
        {                                                                                       \
                Gtk::AccelKey accel_key(accel,path);    \
                Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod());       \
@@ -870,87 +1004,80 @@ init_ui_manager()
                Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod());       \
        }
 
                Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod());       \
        }
 
-       ACCEL("<Actions>//select-all-ducks","<Control>a");
-       ACCEL("<Actions>//unselect-all-layers","<Control>d");
-       ACCEL("<Actions>//render","F9");
-       ACCEL("<Actions>//preview","F11");
-       ACCEL("<Actions>//properties","F8");
-       ACCEL("<Actions>//options","F12");
-       ACCEL("<Actions>//import","<control>i");
-       ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
-       ACCEL("<Actions>//toggle-grid-show","<Control>g");
-       ACCEL("<Actions>//toggle-grid-snap","<Control>l");
-       ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
-       ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
-       ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
-       ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
-       ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
-       ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
-       ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
-
-       ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
-       ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
-
-       ACCEL("<Actions>//quality-01","<Control>1");
-       ACCEL("<Actions>//quality-02","<Control>2");
-       ACCEL("<Actions>//quality-03","<Control>3");
-       ACCEL("<Actions>//quality-04","<Control>4");
-       ACCEL("<Actions>//quality-05","<Control>5");
-       ACCEL("<Actions>//quality-06","<Control>6");
-       ACCEL("<Actions>//quality-07","<Control>7");
-       ACCEL("<Actions>//quality-08","<Control>8");
-       ACCEL("<Actions>//quality-09","<Control>9");
-       ACCEL("<Actions>//quality-10","<Control>0");
-       ACCEL("<Actions>//undo","<Control>z");
-       ACCEL("<Actions>//redo","<Control>r");
-       ACCEL("<Actions>//action-layer_remove","Delete");
-
-/*     ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
-       ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
-       ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
-       ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
-       ACCEL("<Actions>//time-zoom-in","+");
-       ACCEL("<Actions>//time-zoom-out","_");
-*/
-       ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
-       ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
-
-       ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
-       ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
-       ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
-       ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
-       ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
-       ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
-       ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
-       ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
-       ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
-       ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
-       ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
-       ACCEL("<Actions>//play",              "<Control>p");
-       ACCEL("<Actions>//seek-begin","Home");
-       ACCEL("<Actions>//seek-end","End");
-
-       ACCEL("<Actions>//state-normal",      "<Mod1>a");
-       ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
-       ACCEL("<Actions>//state-scale",       "<Mod1>d");
-       ACCEL("<Actions>//state-rotate",      "<Mod1>s");
-
-       ACCEL("<Actions>//state-bline",       "<Mod1>b");
-       ACCEL("<Actions>//state-circle",      "<Mod1>c");
-       ACCEL("<Actions>//state-rectangle",   "<Mod1>r");
-       ACCEL("<Actions>//state-gradient",    "<Mod1>g");
-
-       ACCEL("<Actions>//state-eyedrop",     "<Mod1>e");
-       ACCEL("<Actions>//state-fill",        "<Mod1>f");
-       ACCEL("<Actions>//state-zoom",        "<Mod1>z");
-       ACCEL("<Actions>//state-polygon",     "<Mod1>p");
-
-       ACCEL("<Actions>//state-draw",        "<Mod1>w");
-       ACCEL("<Actions>//state-sketch",      "<Mod1>k");
-       ACCEL("<Actions>//state-width",       "<Mod1>t");
-       ACCEL("<Actions>//state-mirror",      "<Mod1>m");
-
-       ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
+       // the toolbox
+       ACCEL("<Mod1>a",                                                                                                        "<Actions>//state-normal"                                       );
+       ACCEL("<Mod1>v",                                                                                                        "<Actions>//state-smooth_move"                          );
+       ACCEL("<Mod1>s",                                                                                                        "<Actions>//state-scale"                                        );
+       ACCEL("<Mod1>t",                                                                                                        "<Actions>//state-rotate"                                       );
+       ACCEL("<Mod1>m",                                                                                                        "<Actions>//state-mirror"                                       );
+       ACCEL("<Mod1>c",                                                                                                        "<Actions>//state-circle"                                       );
+       ACCEL("<Mod1>r",                                                                                                        "<Actions>//state-rectangle"                            );
+       ACCEL("<Mod1>q",                                                                                                        "<Actions>//state-star"                                         );
+       ACCEL("<Mod1>g",                                                                                                        "<Actions>//state-gradient"                                     );
+       ACCEL("<Mod1>p",                                                                                                        "<Actions>//state-polygon"                                      );
+       ACCEL("<Mod1>b",                                                                                                        "<Actions>//state-bline"                                        );
+       ACCEL("<Mod1>x",                                                                                                        "<Actions>//state-text"                                         );
+       ACCEL("<Mod1>f",                                                                                                        "<Actions>//state-fill"                                         );
+       ACCEL("<Mod1>e",                                                                                                        "<Actions>//state-eyedrop"                                      );
+       ACCEL("<Mod1>z",                                                                                                        "<Actions>//state-zoom"                                         );
+       ACCEL("<Mod1>d",                                                                                                        "<Actions>//state-draw"                                         );
+       ACCEL("<Mod1>k",                                                                                                        "<Actions>//state-sketch"                                       );
+       ACCEL("<Mod1>w",                                                                                                        "<Actions>//state-width"                                        );
+
+       // everything else
+       ACCEL("<Control>a",                                                                                                     "<Actions>//select-all-ducks"                           );
+       ACCEL("<Control>d",                                                                                                     "<Actions>//unselect-all-ducks"                         );
+       ACCEL("<Control><Shift>a",                                                                                      "<Actions>//select-all-layers"                          );
+       ACCEL("<Control><Shift>d",                                                                                      "<Actions>//unselect-all-layers"                        );
+       ACCEL("F9",                                                                                                                     "<Actions>//render"                                                     );
+       ACCEL("F11",                                                                                                            "<Actions>//preview"                                            );
+       ACCEL("F8",                                                                                                                     "<Actions>//properties"                                         );
+       ACCEL("F12",                                                                                                            "<Actions>//options"                                            );
+       ACCEL("<control>i",                                                                                                     "<Actions>//import"                                                     );
+       ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),      "<Actions>//stop"                                                       ));
+       ACCEL("<Control>g",                                                                                                     "<Actions>//toggle-grid-show"                           );
+       ACCEL("<Control>l",                                                                                                     "<Actions>//toggle-grid-snap"                           );
+       ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,                                                     "<Actions>//toggle-low-res"                                     ));
+       ACCEL("<Mod1>1",                                                                                                        "<Actions>//mask-position-ducks"                        );
+       ACCEL("<Mod1>2",                                                                                                        "<Actions>//mask-vertex-ducks"                          );
+       ACCEL("<Mod1>3",                                                                                                        "<Actions>//mask-tangent-ducks"                         );
+       ACCEL("<Mod1>4",                                                                                                        "<Actions>//mask-radius-ducks"                          );
+       ACCEL("<Mod1>5",                                                                                                        "<Actions>//mask-width-ducks"                           );
+       ACCEL("<Mod1>6",                                                                                                        "<Actions>//mask-angle-ducks"                           );
+       ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,                                       "<Actions>//action-LayerRaise"                          ));
+       ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,                                     "<Actions>//action-LayerLower"                          ));
+       ACCEL("<Control>1",                                                                                                     "<Actions>//quality-01"                                         );
+       ACCEL("<Control>2",                                                                                                     "<Actions>//quality-02"                                         );
+       ACCEL("<Control>3",                                                                                                     "<Actions>//quality-03"                                         );
+       ACCEL("<Control>4",                                                                                                     "<Actions>//quality-04"                                         );
+       ACCEL("<Control>5",                                                                                                     "<Actions>//quality-05"                                         );
+       ACCEL("<Control>6",                                                                                                     "<Actions>//quality-06"                                         );
+       ACCEL("<Control>7",                                                                                                     "<Actions>//quality-07"                                         );
+       ACCEL("<Control>8",                                                                                                     "<Actions>//quality-08"                                         );
+       ACCEL("<Control>9",                                                                                                     "<Actions>//quality-09"                                         );
+       ACCEL("<Control>0",                                                                                                     "<Actions>//quality-10"                                         );
+       ACCEL("<Control>z",                                                                                                     "<Actions>//undo"                                                       );
+       ACCEL("<Control>r",                                                                                                     "<Actions>//redo"                                                       );
+       ACCEL2(Gtk::AccelKey(GDK_Delete,Gdk::CONTROL_MASK,                                      "<Actions>//action-LayerRemove"                         ));
+       ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK,                                                     "<Actions>//decrease-low-res-pixel-size"        ));
+       ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK,                                                     "<Actions>//increase-low-res-pixel-size"        ));
+       ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,                      "<Actions>//amount-dec"                                         ));
+       ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,                      "<Actions>//amount-inc"                                         ));
+       ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,                                                     "<Actions>//jump-next-keyframe"                         ));
+       ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,                                                     "<Actions>//jump-prev-keyframe"                         ));
+       ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,                                                     "<Actions>//canvas-zoom-in"                                     ));
+       ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,                                                     "<Actions>//canvas-zoom-out"                            ));
+       ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,                                                     "<Actions>//time-zoom-in"                                       ));
+       ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,                                                     "<Actions>//time-zoom-out"                                      ));
+       ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,                                                     "<Actions>//seek-next-frame"                            ));
+       ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,                                                     "<Actions>//seek-prev-frame"                            ));
+       ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,                                                     "<Actions>//seek-next-second"                           ));
+       ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,                                                     "<Actions>//seek-prev-second"                           ));
+       ACCEL("<Mod1>o",                                                                                                        "<Actions>//toggle-onion-skin"                          );
+       ACCEL("<Control><Shift>z",                                                                                      "<Actions>//canvas-zoom-fit"                            );
+       ACCEL("<Control>p",                                                                                                     "<Actions>//play"                                                       );
+       ACCEL("Home",                                                                                                           "<Actions>//seek-begin"                                         );
+       ACCEL("End",                                                                                                            "<Actions>//seek-end"                                           );
 
 #undef ACCEL
 }
 
 #undef ACCEL
 }
@@ -1000,22 +1127,26 @@ App::App(int *argc, char ***argv):
                        "different version of libsynfig than what is currently\n"
                        "installed. Synfig Studio will now abort. Try downloading\n"
                        "the latest version from the Synfig website at\n"
                        "different version of libsynfig than what is currently\n"
                        "installed. Synfig Studio will now abort. Try downloading\n"
                        "the latest version from the Synfig website at\n"
-                       "http://www.synfig.com/ "
+                       "http://synfig.org/Download"
                );
                throw 40;
        }
        Glib::set_application_name(_("Synfig Studio"));
 
                );
                throw 40;
        }
        Glib::set_application_name(_("Synfig Studio"));
 
-       About about_window;
-       about_window.set_can_self_destruct(false);
-       about_window.show();
+       Splash splash_screen;
+       splash_screen.show();
 
        shutdown_in_progress=false;
 
        shutdown_in_progress=false;
-       SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
-       SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
+       SuperCallback synfig_init_cb(splash_screen.get_callback(),0,9000,10000);
+       SuperCallback studio_init_cb(splash_screen.get_callback(),9000,10000,10000);
 
        // Initialize the Synfig library
        try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
 
        // Initialize the Synfig library
        try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
+       catch(std::runtime_error x)
+       {
+               get_ui_interface()->error(strprintf("%s\n\n%s", _("Failed to initialize synfig!"), x.what()));
+               throw;
+       }
        catch(...)
        {
                get_ui_interface()->error(_("Failed to initialize synfig!"));
        catch(...)
        {
                get_ui_interface()->error(_("Failed to initialize synfig!"));
@@ -1040,6 +1171,9 @@ App::App(int *argc, char ***argv):
                studio_init_cb.task(_("Init Toolbox..."));
                toolbox=new studio::Toolbox();
 
                studio_init_cb.task(_("Init Toolbox..."));
                toolbox=new studio::Toolbox();
 
+               studio_init_cb.task(_("Init About Dialog..."));
+               about=new studio::About();
+
                studio_init_cb.task(_("Init Tool Options..."));
                dialog_tool_options=new studio::Dialog_ToolOptions();
                dock_manager->register_dockable(*dialog_tool_options);
                studio_init_cb.task(_("Init Tool Options..."));
                dialog_tool_options=new studio::Dialog_ToolOptions();
                dock_manager->register_dockable(*dialog_tool_options);
@@ -1103,41 +1237,35 @@ App::App(int *argc, char ***argv):
                device_tracker=new studio::DeviceTracker();
 
                studio_init_cb.task(_("Init Tools..."));
                device_tracker=new studio::DeviceTracker();
 
                studio_init_cb.task(_("Init Tools..."));
+
+               /* row 1 */
                state_manager->add_state(&state_normal);
                state_manager->add_state(&state_smooth_move);
                state_manager->add_state(&state_scale);
                state_manager->add_state(&state_rotate);
                state_manager->add_state(&state_normal);
                state_manager->add_state(&state_smooth_move);
                state_manager->add_state(&state_scale);
                state_manager->add_state(&state_rotate);
+               studio_init_cb.task(_("Init ModMirror...")); module_list_.push_back(new ModMirror()); module_list_.back()->start();
 
 
-               state_manager->add_state(&state_bline);
-
-
+               /* row 2 */
                state_manager->add_state(&state_circle);
                state_manager->add_state(&state_rectangle);
                state_manager->add_state(&state_circle);
                state_manager->add_state(&state_rectangle);
-
+               state_manager->add_state(&state_star);
                state_manager->add_state(&state_gradient);
                state_manager->add_state(&state_gradient);
-               state_manager->add_state(&state_eyedrop);
-               state_manager->add_state(&state_fill);
+               if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
 
 
+               /* row 3 */
+               state_manager->add_state(&state_bline);
+               state_manager->add_state(&state_text);
+               state_manager->add_state(&state_fill);
+               state_manager->add_state(&state_eyedrop);
                state_manager->add_state(&state_zoom);
 
                state_manager->add_state(&state_zoom);
 
-               // Enabled - it's useful to be able to work with polygons without tangent ducks getting in the way.
-               // I know we can switch tangent ducks off, but why not allow this kind of layer as well?
-               if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon);
-
-               // Enabled for now.  Let's see whether they're good enough yet.
-               if(!getenv("SYNFIG_DISABLE_DRAW"   )) state_manager->add_state(&state_draw);
+               if(!getenv("SYNFIG_DISABLE_DRAW"   )) state_manager->add_state(&state_draw); // Enabled for now.  Let's see whether they're good enough yet.
                if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
                if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
-
-               // Disabled by default - it doesn't work properly?
-               if(getenv("SYNFIG_ENABLE_WIDTH"    )) state_manager->add_state(&state_width);
+               if(!getenv("SYNFIG_DISABLE_WIDTH"  )) state_manager->add_state(&state_width); // Enabled since 0.61.09
 
                studio_init_cb.task(_("Init ModPalette..."));
                module_list_.push_back(new ModPalette()); module_list_.back()->start();
 
 
                studio_init_cb.task(_("Init ModPalette..."));
                module_list_.push_back(new ModPalette()); module_list_.back()->start();
 
-               studio_init_cb.task(_("Init ModMirror..."));
-               module_list_.push_back(new ModMirror()); module_list_.back()->start();
-
-
                studio_init_cb.task(_("Init Setup Dialog..."));
                dialog_setup=new studio::Dialog_Setup();
 
                studio_init_cb.task(_("Init Setup Dialog..."));
                dialog_setup=new studio::Dialog_Setup();
 
@@ -1156,32 +1284,34 @@ App::App(int *argc, char ***argv):
 
                studio_init_cb.amount_complete(9900,10000);
 
 
                studio_init_cb.amount_complete(9900,10000);
 
+               bool opened_any = false;
                if(auto_recover->recovery_needed())
                {
                if(auto_recover->recovery_needed())
                {
-                       about_window.hide();
-                       if(
-                               get_ui_interface()->yes_no(
-                                       _("Auto Recovery"),
-                                       _("Synfig Studio seems to have crashed\n"
-                                       "before you could save all your files.\n"
-                                       "Would you like to re-open those files\n"
-                                       "and recover your unsaved changes?")
-                               )==synfigapp::UIInterface::RESPONSE_YES
-                       )
+                       splash_screen.hide();
+                       if (get_ui_interface()->yes_no(_("Auto Recovery"),
+                                                                                  _("Synfig Studio seems to have crashed\n"
+                                                                                        "before you could save all your files.\n"
+                                                                                        "Would you like to re-open those files\n"
+                                                                                        "and recover your unsaved changes?")) ==
+                               synfigapp::UIInterface::RESPONSE_YES)
                        {
                        {
-                               if(!auto_recover->recover())
-                               {
-                                       get_ui_interface()->error(_("Unable to fully recover from previous crash"));
-                               }
+                               int number_recovered;
+                               if(!auto_recover->recover(number_recovered))
+                                       if (number_recovered)
+                                               get_ui_interface()->error(_("Unable to fully recover from previous crash"));
+                                       else
+                                               get_ui_interface()->error(_("Unable to recover from previous crash"));
                                else
                                else
-                               get_ui_interface()->error(
-                                       _("Synfig Studio has attempted to recover\n"
-                                       "from a previous crash. The files that it has\n"
-                                       "recovered are NOT YET SAVED. It would be a good\n"
-                                       "idea to review them and save them now.")
-                               );
+                                       get_ui_interface()->error(
+                                               _("Synfig Studio has attempted to recover\n"
+                                                 "from a previous crash. The files that it has\n"
+                                                 "recovered are NOT YET SAVED. It would be a good\n"
+                                                 "idea to review them and save them now."));
+
+                               if (number_recovered)
+                                       opened_any = true;
                        }
                        }
-                       about_window.show();
+                       splash_screen.show();
                }
 
                // Look for any files given on the command line,
                }
 
                // Look for any files given on the command line,
@@ -1190,16 +1320,25 @@ App::App(int *argc, char ***argv):
                        if((*argv)[*argc] && (*argv)[*argc][0]!='-')
                        {
                                studio_init_cb.task(_("Loading files..."));
                        if((*argv)[*argc] && (*argv)[*argc][0]!='-')
                        {
                                studio_init_cb.task(_("Loading files..."));
-                               about_window.hide();
+                               splash_screen.hide();
                                open((*argv)[*argc]);
                                open((*argv)[*argc]);
-                               about_window.show();
+                               opened_any = true;
+                               splash_screen.show();
                        }
 
                        }
 
+               // if no file was specified to be opened, create a new document to help new users get started more easily
+               if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION"))
+                       new_instance();
+
                studio_init_cb.task(_("Done."));
                studio_init_cb.amount_complete(10000,10000);
 
                toolbox->present();
        }
                studio_init_cb.task(_("Done."));
                studio_init_cb.amount_complete(10000,10000);
 
                toolbox->present();
        }
+       catch(String x)
+       {
+               get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
+       }
        catch(...)
        {
                get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
        catch(...)
        {
                get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
@@ -1219,7 +1358,8 @@ App::~App()
        selected_instance=0;
 
        // Unload all of the modules
        selected_instance=0;
 
        // Unload all of the modules
-       for(;!module_list_.empty();module_list_.pop_back());
+       for(;!module_list_.empty();module_list_.pop_back())
+               ;
 
        delete state_manager;
 
 
        delete state_manager;
 
@@ -1227,6 +1367,8 @@ App::~App()
 
        delete auto_recover;
 
 
        delete auto_recover;
 
+       delete about;
+
        toolbox->hide();
 
 //     studio::App::iteration(false);
        toolbox->hide();
 
 //     studio::App::iteration(false);
@@ -1255,7 +1397,12 @@ App::~App()
 String
 App::get_user_app_directory()
 {
 String
 App::get_user_app_directory()
 {
+//! \todo do we need locale_from_utf8() on non-Windows boxes too?  (bug #1837445)
+#ifdef WIN32
+       return Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR));
+#else
        return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
        return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
+#endif
 }
 
 synfig::String
 }
 
 synfig::String
@@ -1264,8 +1411,116 @@ App::get_config_file(const synfig::String& file)
        return Glib::build_filename(get_user_app_directory(),file);
 }
 
        return Glib::build_filename(get_user_app_directory(),file);
 }
 
+#define SCALE_FACTOR   (1280)
+//! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
+void
+App::set_recent_file_window_size(etl::handle<Instance> instance)
+{
+       int screen_w(Gdk::screen_width());
+       int screen_h(Gdk::screen_height());
+
+       const std::string &canvas_window_size = *recent_files_window_size.begin();
+
+       if(canvas_window_size.empty())
+               return;
+
+       synfig::String::size_type current=0;
+       bool seen_root(false), shown_non_root(false);
+
+       while(current != synfig::String::npos)
+       {
+               // find end of first field (canvas) or return
+               synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
+               if(separator == synfig::String::npos) break;
+
+               // find the canvas
+               synfig::Canvas::Handle canvas;
+               try {
+                       String warnings;
+                       canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current), warnings);
+               }
+               catch(Exception::IDNotFound) {
+                       // can't find the canvas; skip to the next canvas or return
+                       separator = canvas_window_size.find_first_of('\t', current);
+                       if(separator == synfig::String::npos) return;
+                       current = separator+1;
+                       continue;
+               }
+
+               if (canvas->is_root())
+                       seen_root = true;
+               else
+                       shown_non_root = true;
+
+               // check that we have the tab character the ends this canvas' data or return
+               current = separator+1;
+               separator = canvas_window_size.find_first_of('\t', current);
+               if(separator == synfig::String::npos) return;
+
+               int x,y,w,h;
+               if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
+               {
+                       current = separator+1;
+                       continue;
+               }
+
+               if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
+               if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
+               x=x*screen_w/SCALE_FACTOR;
+               y=y*screen_h/SCALE_FACTOR;
+               if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
+                       x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
+               if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
+                       y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
+
+               if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
+               if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
+
+               CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
+               canvasview->move(x,y);
+               canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR);
+               canvasview->present();
+
+               current = separator+1;
+       }
+
+       if (shown_non_root && !seen_root)
+               instance->find_canvas_view(instance->get_canvas())->hide();
+}
+
+void
+App::add_recent_file(const etl::handle<Instance> instance)
+{
+       int screen_w(Gdk::screen_width());
+       int screen_h(Gdk::screen_height());
+
+       std::string canvas_window_size;
+
+       const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
+       Instance::CanvasViewList::const_iterator iter;
+
+       for(iter=cview_list.begin();iter!=cview_list.end();iter++)
+       {
+               if( !((*iter)->is_visible()) )
+                       continue;
+
+               etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
+               int x_pos, y_pos, x_size, y_size;
+               (*iter)->get_position(x_pos,y_pos);
+               (*iter)->get_size(x_size,y_size);
+
+               canvas_window_size += strprintf("%s %d %d %d %d\t",
+                                                                               canvas->get_relative_id(canvas->get_root()).c_str(),
+                                                                               x_pos*SCALE_FACTOR/screen_w,  y_pos*SCALE_FACTOR/screen_h,
+                                                                               x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
+       }
+
+       add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
+}
+#undef SCALE_FACTOR
+
 void
 void
-App::add_recent_file(const std::string &file_name)
+App::add_recent_file(const std::string &file_name, const std::string &window_size)
 {
        std::string filename(file_name);
 
 {
        std::string filename(file_name);
 
@@ -1282,23 +1537,35 @@ App::add_recent_file(const std::string &file_name)
        if(!is_absolute_path(filename))
                filename=absolute_path(filename);
 
        if(!is_absolute_path(filename))
                filename=absolute_path(filename);
 
+       std::string old_window_size;
+
        list<string>::iterator iter;
        list<string>::iterator iter;
+       list<string>::iterator iter_wsize;
        // Check to see if the file is already on the list.
        // If it is, then remove it from the list
        // Check to see if the file is already on the list.
        // If it is, then remove it from the list
-       for(iter=recent_files.begin();iter!=recent_files.end();iter++)
+       for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
                if(*iter==filename)
                {
                        recent_files.erase(iter);
                if(*iter==filename)
                {
                        recent_files.erase(iter);
+                       old_window_size = *iter_wsize;
+                       recent_files_window_size.erase(iter_wsize);
                        break;
                }
 
 
        // Push the filename to the front of the list
        recent_files.push_front(filename);
                        break;
                }
 
 
        // Push the filename to the front of the list
        recent_files.push_front(filename);
+       if(window_size.empty())
+               recent_files_window_size.push_front(old_window_size);
+       else
+               recent_files_window_size.push_front(window_size);
 
        // Clean out the files at the end of the list.
        while(recent_files.size()>(unsigned)get_max_recent_files())
 
        // Clean out the files at the end of the list.
        while(recent_files.size()>(unsigned)get_max_recent_files())
+       {
                recent_files.pop_back();
                recent_files.pop_back();
+               recent_files_window_size.pop_back();
+       }
 
        signal_recent_files_changed_();
 
 
        signal_recent_files_changed_();
 
@@ -1348,7 +1615,23 @@ App::save_settings()
                        for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
                                file<<*iter<<endl;
                }while(0);
                        for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
                                file<<*iter<<endl;
                }while(0);
+               do{
+                       std::string filename=get_config_file("recentfiles")+std::string("_window_size");
+
+                       std::ofstream file(filename.c_str());
+
+                       if(!file)
+                       {
+                               synfig::warning("Unable to save %s",filename.c_str());
+                               break;
+                       }
+
+                       list<string>::reverse_iterator iter;
+
+                       for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
+                               file<<*iter<<endl;
 
 
+               }while(0);
                std::string filename=get_config_file("settings");
                synfigapp::Main::settings().save_to_file(filename);
        setlocale(LC_NUMERIC,old_locale);
                std::string filename=get_config_file("settings");
                synfigapp::Main::settings().save_to_file(filename);
        setlocale(LC_NUMERIC,old_locale);
@@ -1372,22 +1655,50 @@ App::load_settings()
                        Gtk::AccelMap::load(filename);
                }
                {
                        Gtk::AccelMap::load(filename);
                }
                {
+                       bool window_size_broken = false;
+
                        std::string filename=get_config_file("recentfiles");
                        std::string filename=get_config_file("recentfiles");
+                       std::string filename_window_size=filename+std::string("_window_size");
 
                        std::ifstream file(filename.c_str());
 
                        std::ifstream file(filename.c_str());
+                       std::ifstream file_window_size(filename_window_size.c_str());
+
+                       if(!file_window_size)
+                               window_size_broken = true;
 
                        while(file)
                        {
                                std::string recent_file;
 
                        while(file)
                        {
                                std::string recent_file;
+                               std::string recent_file_window_size;
                                getline(file,recent_file);
                                getline(file,recent_file);
+                               if(!window_size_broken)
+                                       getline(file_window_size,recent_file_window_size);
                                if(!recent_file.empty())
                                if(!recent_file.empty())
-                                       add_recent_file(recent_file);
+                               {
+                                       if(!window_size_broken && !file_window_size)
+                                               window_size_broken = true;
+                                       if (std::ifstream(recent_file.c_str()))
+                                       {
+                                               if(!window_size_broken)
+                                                       add_recent_file(recent_file,recent_file_window_size);
+                                               else
+                                                       add_recent_file(recent_file);
+                                       }
+                               }
+                       }
+                       if(!window_size_broken && file_window_size)
+                               window_size_broken = true;
+
+                       if(window_size_broken)
+                       {
+                               recent_files_window_size.clear();
+                               recent_files_window_size.resize(recent_files.size());
                        }
                }
                std::string filename=get_config_file("settings");
                if(!synfigapp::Main::settings().load_from_file(filename))
                {
                        }
                }
                std::string filename=get_config_file("settings");
                if(!synfigapp::Main::settings().load_from_file(filename))
                {
-                       //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
+                       //std::string filename=Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),".synfigrc"));
                        //if(!synfigapp::Main::settings().load_from_file(filename))
                        {
                                gamma.set_gamma(1.0/2.2);
                        //if(!synfigapp::Main::settings().load_from_file(filename))
                        {
                                gamma.set_gamma(1.0/2.2);
@@ -1417,7 +1728,15 @@ App::reset_initial_window_configuration()
        synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
        synfigapp::Main::settings().set_value("pref.distance_system","pt");
        synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
        synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
        synfigapp::Main::settings().set_value("pref.distance_system","pt");
        synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
+#ifdef SINGLE_THREADED
        synfigapp::Main::settings().set_value("pref.single_threaded","0");
        synfigapp::Main::settings().set_value("pref.single_threaded","0");
+#endif
+       synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
+       synfigapp::Main::settings().set_value("pref.resize_imported_images","0");
+       synfigapp::Main::settings().set_value("pref.custom_filename_prefix",DEFAULT_FILENAME_PREFIX);
+       synfigapp::Main::settings().set_value("pref.preferred_x_size","480");
+       synfigapp::Main::settings().set_value("pref.preferred_y_size","270");
+       synfigapp::Main::settings().set_value("pref.predefined_size",DEFAULT_PREDEFINED_SIZE);
        synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
 }
 
        synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
 }
 
@@ -1532,8 +1851,10 @@ static OPENFILENAME ofn={};
 #endif
 
 bool
 #endif
 
 bool
-App::dialog_open_file(const std::string &title, std::string &filename)
+App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
 {
 {
+       // info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
+
 #ifdef USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
 #ifdef USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
@@ -1578,26 +1899,36 @@ App::dialog_open_file(const std::string &title, std::string &filename)
 
 #else
        synfig::String prev_path;
 
 #else
        synfig::String prev_path;
-       if(!_preferences.get_value("curr_path",prev_path))
-               prev_path=".";
+
+       if(!_preferences.get_value(preference, prev_path))
+               prev_path = ".";
+
        prev_path = absolute_path(prev_path);
 
        prev_path = absolute_path(prev_path);
 
-    Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
+    Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
+
     dialog->set_current_folder(prev_path);
     dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
     dialog->add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_ACCEPT);
     dialog->set_current_folder(prev_path);
     dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
     dialog->add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_ACCEPT);
-    if(!filename.empty())
-               if (is_absolute_path(filename))
-                       dialog->set_filename(filename);
-               else
-                       dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
-    if(dialog->run()==GTK_RESPONSE_ACCEPT) {
-        filename=dialog->get_filename();
+
+    if (filename.empty())
+               dialog->set_filename(prev_path);
+       else if (is_absolute_path(filename))
+               dialog->set_filename(filename);
+       else
+               dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
+
+    if(dialog->run() == GTK_RESPONSE_ACCEPT) {
+        filename = dialog->get_filename();
+               // info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
+               _preferences.set_value(preference, dirname(filename));
         delete dialog;
         return true;
     }
         delete dialog;
         return true;
     }
+
     delete dialog;
     return false;
     delete dialog;
     return false;
+
     /*
 
        GtkWidget *ok;
     /*
 
        GtkWidget *ok;
@@ -1632,7 +1963,7 @@ App::dialog_open_file(const std::string &title, std::string &filename)
        if(val==1)
        {
                filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
        if(val==1)
        {
                filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
-               _preferences.set_value("curr_path",dirname(filename));
+               _preferences.set_value(preference,dirname(filename));
        }
        else
        {
        }
        else
        {
@@ -1646,8 +1977,10 @@ App::dialog_open_file(const std::string &title, std::string &filename)
 }
 
 bool
 }
 
 bool
-App::dialog_save_file(const std::string &title, std::string &filename)
+App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
 {
 {
+       // info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
+
 #if USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
 #if USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
@@ -1686,27 +2019,53 @@ App::dialog_save_file(const std::string &title, std::string &filename)
        if(GetSaveFileName(&ofn))
        {
                filename=szFilename;
        if(GetSaveFileName(&ofn))
        {
                filename=szFilename;
-               _preferences.set_value("curr_path",dirname(filename));
+               _preferences.set_value(preference,dirname(filename));
                return true;
        }
        return false;
 #else
        synfig::String prev_path;
                return true;
        }
        return false;
 #else
        synfig::String prev_path;
-       if(!_preferences.get_value("curr_path",prev_path))
+
+       if(!_preferences.get_value(preference, prev_path))
                prev_path=".";
                prev_path=".";
+
        prev_path = absolute_path(prev_path);
 
        prev_path = absolute_path(prev_path);
 
-    Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
+    Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
+
     dialog->set_current_folder(prev_path);
     dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
     dialog->add_button(Gtk::Stock::SAVE,   Gtk::RESPONSE_ACCEPT);
     dialog->set_current_folder(prev_path);
     dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
     dialog->add_button(Gtk::Stock::SAVE,   Gtk::RESPONSE_ACCEPT);
-    if(!filename.empty())
+
+       Widget_Enum *file_type_enum = 0;
+       if (preference == ANIMATION_DIR_PREFERENCE)
+       {
+               file_type_enum = manage(new Widget_Enum());
+               file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
+                                                                          .add_enum_value(synfig::RELEASE_VERSION_0_61_09, "0.61.09", strprintf("0.61.09 (%s)", _("current")))
+                                                                          .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", "0.61.08")
+                                                                          .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
+                                                                          .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
+               file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
+
+               Gtk::HBox *hbox = manage(new Gtk::HBox);
+               hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
+               hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
+               hbox->show_all();
+
+               dialog->set_extra_widget(*hbox);
+       }
+
+    if (filename.empty())
+               dialog->set_filename(prev_path);
+    else
        {
                std::string full_path;
                if (is_absolute_path(filename))
                        full_path = filename;
                else
                        full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
        {
                std::string full_path;
                if (is_absolute_path(filename))
                        full_path = filename;
                else
                        full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
+
                // select the file if it exists
                dialog->set_filename(full_path);
 
                // select the file if it exists
                dialog->set_filename(full_path);
 
@@ -1715,15 +2074,19 @@ App::dialog_save_file(const std::string &title, std::string &filename)
                if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
                        dialog->set_current_name(basename(filename));
        }
                if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
                        dialog->set_current_name(basename(filename));
        }
-    if(dialog->run()==GTK_RESPONSE_ACCEPT) {
-        filename=dialog->get_filename();
+
+    if(dialog->run() == GTK_RESPONSE_ACCEPT) {
+               if (preference == ANIMATION_DIR_PREFERENCE)
+                       set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
+        filename = dialog->get_filename();
+               // info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
+               _preferences.set_value(preference, dirname(filename));
         delete dialog;
         delete dialog;
-               _preferences.set_value("curr_path",dirname(filename));
         return true;
     }
         return true;
     }
+
     delete dialog;
     return false;
     delete dialog;
     return false;
-//     return dialog_open_file(title, filename);
 #endif
 }
 
 #endif
 }
 
@@ -1790,14 +2153,114 @@ App::dialog_not_implemented()
        dialog.run();
 }
 
        dialog.run();
 }
 
+static bool
+try_open_url(const std::string &url)
+{
+#ifdef WIN32
+       return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
+#else // !WIN32
+       std::vector<std::string> command_line;
+       std::vector<std::string> browsers;
+       browsers.reserve(23);
+
+       // Browser wrapper scripts
+#ifdef USE_OPEN_FOR_URLS
+       browsers.push_back("open");              // Apple MacOS X wrapper, on Linux it opens a virtual console
+#endif
+       browsers.push_back("xdg-open");          // XDG wrapper
+       browsers.push_back("sensible-browser");  // Debian wrapper
+       browsers.push_back("gnome-open");        // GNOME wrapper
+       browsers.push_back("kfmclient");         // KDE wrapper
+       browsers.push_back("exo-open");          // XFCE wrapper
+
+       // Alternatives system
+       browsers.push_back("gnome-www-browser"); // Debian GNOME alternative
+       browsers.push_back("x-www-browser");     // Debian GUI alternative
+
+       // Individual browsers
+       browsers.push_back("firefox");
+       browsers.push_back("epiphany-browser");
+       browsers.push_back("epiphany");
+       browsers.push_back("konqueror");
+       browsers.push_back("iceweasel");
+       browsers.push_back("mozilla");
+       browsers.push_back("netscape");
+       browsers.push_back("icecat");
+       browsers.push_back("galeon");
+       browsers.push_back("midori");
+       browsers.push_back("safari");
+       browsers.push_back("opera");
+       browsers.push_back("amaya");
+       browsers.push_back("netsurf");
+       browsers.push_back("dillo");
+
+       // Try the user-specified browser first
+       command_line.push_back(App::browser_command);
+       if( command_line[0] == "kfmclient" ) command_line.push_back("openURL");
+       command_line.push_back(url);
+
+       try { Glib::spawn_async(".", command_line, Glib::SPAWN_SEARCH_PATH); return true; }
+       catch( Glib::SpawnError& exception ){
+
+               while ( !browsers.empty() )
+               {
+                       // Skip the browser if we already tried it
+                       if( browsers[0] == App::browser_command )
+                               continue;
+
+                       // Construct the command line
+                       command_line.clear();
+                       command_line.push_back(browsers[0]);
+                       if( command_line[0] == "kfmclient" ) command_line.push_back("openURL");
+                       command_line.push_back(url);
+
+                       // Remove the browser from the list
+                       browsers.erase(browsers.begin());
+
+                       // Try to spawn the browser
+                       try { Glib::spawn_async(".", command_line, Glib::SPAWN_SEARCH_PATH); }
+                       // Failed, move on to the next one
+                       catch(Glib::SpawnError& exception){ continue; }
+                       return true; // No exception means we succeeded!
+               }
+       }
+
+       return false;
+#endif // !WIN32
+}
+
+void
+App::dialog_help()
+{
+       if (!try_open_url("http://synfig.org/Documentation"))
+       {
+               Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
+               dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
+               dialog.set_title(_("Help"));
+               dialog.run();
+       }
+}
+
+void
+App::open_url(const std::string &url)
+{
+       if(!try_open_url(url))
+       {
+               Gtk::MessageDialog dialog(_("No browser was found. Please load this website manually:"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
+               dialog.set_secondary_text(url);
+               dialog.set_title(_("No browser found"));
+               dialog.run();
+       }
+}
+
 bool
 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
 {
        Gtk::Dialog dialog(
                title,          // Title
                true,           // Modal
 bool
 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
 {
        Gtk::Dialog dialog(
                title,          // Title
                true,           // Modal
-               true            // use_separator
-       );
+               true);          // use_separator
+
        Gtk::Label label(message);
        label.show();
        dialog.get_vbox()->pack_start(label);
        Gtk::Label label(message);
        label.show();
        dialog.get_vbox()->pack_start(label);
@@ -1806,11 +2269,13 @@ App::dialog_entry(const std::string &title, const std::string &message,std::stri
        entry.set_text(text);
        entry.show();
        entry.set_activates_default(true);
        entry.set_text(text);
        entry.show();
        entry.set_activates_default(true);
+
        dialog.get_vbox()->pack_start(entry);
 
        dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
        dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
        dialog.set_default_response(Gtk::RESPONSE_OK);
        dialog.get_vbox()->pack_start(entry);
 
        dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
        dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
        dialog.set_default_response(Gtk::RESPONSE_OK);
+
        entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
        dialog.show();
 
        entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
        dialog.show();
 
@@ -1822,8 +2287,39 @@ App::dialog_entry(const std::string &title, const std::string &message,std::stri
        return true;
 }
 
        return true;
 }
 
+bool
+App::dialog_paragraph(const std::string &title, const std::string &message,std::string &text)
+{
+       Gtk::Dialog dialog(
+               title,          // Title
+               true,           // Modal
+               true);          // use_separator
+
+       Gtk::Label label(message);
+       label.show();
+       dialog.get_vbox()->pack_start(label);
+
+       Glib::RefPtr<Gtk::TextBuffer> text_buffer(Gtk::TextBuffer::create());
+       text_buffer->set_text(text);
+       Gtk::TextView text_view(text_buffer);
+       text_view.show();
+
+       dialog.get_vbox()->pack_start(text_view);
+
+       dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
+       dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
+       dialog.set_default_response(Gtk::RESPONSE_OK);
+
+       //text_entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
+       dialog.show();
+
+       if(dialog.run()!=Gtk::RESPONSE_OK)
+               return false;
 
 
+       text=text_buffer->get_text();
 
 
+       return true;
+}
 
 bool
 App::open(std::string filename)
 
 bool
 App::open(std::string filename)
@@ -1840,47 +2336,64 @@ App::open_as(std::string filename,std::string as)
 #ifdef WIN32
     char long_name[1024];
     if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
 #ifdef WIN32
     char long_name[1024];
     if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
-    as=long_name;
+       // when called from autorecover.cpp, filename doesn't exist, and so long_name is empty
+       // don't use it if that's the case
+       if (long_name[0] != '\0')
+               as=long_name;
 #endif
 
        try
        {
                OneMoment one_moment;
 #endif
 
        try
        {
                OneMoment one_moment;
+               String errors, warnings;
 
 
-               etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
+               etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as,errors,warnings));
                if(canvas && get_instance(canvas))
                {
                        get_instance(canvas)->find_canvas_view(canvas)->present();
                if(canvas && get_instance(canvas))
                {
                        get_instance(canvas)->find_canvas_view(canvas)->present();
-                       throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
+                       info("%s is already open", filename.c_str());
+                       // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
                }
                }
-               if(!canvas)
-                       throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
+               else
+               {
+                       if(!canvas)
+                               throw (String)strprintf(_("Unable to load \"%s\":\n\n"),filename.c_str()) + errors;
 
 
-               add_recent_file(as);
+                       if (warnings != "")
+                               dialog_warning_blocking(_("Warnings"), strprintf("%s:\n\n%s", _("Warnings"), warnings.c_str()));
 
 
-               handle<Instance> instance(Instance::create(canvas));
+                       if (as.find(custom_filename_prefix.c_str()) != 0)
+                               add_recent_file(as);
 
 
-               if(!instance)
-                       throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
+                       handle<Instance> instance(Instance::create(canvas));
 
 
-               one_moment.hide();
+                       if(!instance)
+                               throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
 
 
-               if(instance->is_updated() && App::dialog_yes_no(_("CVS Update"), _("There appears to be a newer version of this file available on the CVS repository.\nWould you like to update now? (It would probably be a good idea)")))
-                       instance->dialog_cvs_update();
+                       set_recent_file_window_size(instance);
+
+                       one_moment.hide();
+
+                       if(instance->is_updated() && App::dialog_yes_no(_("CVS Update"), _("There appears to be a newer version of this file available on the CVS repository.\nWould you like to update now? (It would probably be a good idea)")))
+                               instance->dialog_cvs_update();
+               }
        }
        catch(String x)
        {
                dialog_error_blocking(_("Error"), x);
                return false;
        }
        }
        catch(String x)
        {
                dialog_error_blocking(_("Error"), x);
                return false;
        }
+       catch(runtime_error x)
+       {
+               dialog_error_blocking(_("Error"), x.what());
+               return false;
+       }
        catch(...)
        {
                dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
                return false;
        }
 
        catch(...)
        {
                dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
                return false;
        }
 
-       _preferences.set_value("curr_path",dirname(as));
-
        return true;
 }
 
        return true;
 }
 
@@ -1889,35 +2402,39 @@ void
 App::new_instance()
 {
        handle<synfig::Canvas> canvas=synfig::Canvas::create();
 App::new_instance()
 {
        handle<synfig::Canvas> canvas=synfig::Canvas::create();
-       canvas->set_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
 
 
-       String file_name(strprintf("%s%d.sifz", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
+       String file_name(strprintf("%s%d", App::custom_filename_prefix.c_str(), Instance::get_count()+1));
+       canvas->set_name(file_name);
+       file_name += ".sifz";
 
        canvas->rend_desc().set_frame_rate(24.0);
        canvas->rend_desc().set_time_start(0.0);
 
        canvas->rend_desc().set_frame_rate(24.0);
        canvas->rend_desc().set_time_start(0.0);
-       canvas->rend_desc().set_time_end(00.0);
+       canvas->rend_desc().set_time_end(5.0);
        canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
        canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
        canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
        canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
-       canvas->rend_desc().set_tl(Vector(-4,2.25));
-       canvas->rend_desc().set_br(Vector(4,-2.25));
-       canvas->rend_desc().set_w(480);
-       canvas->rend_desc().set_h(270);
+       // The top left and botton right positions are expressed in units
+       // Original convention is that 1 unit = 60 pixels
+       canvas->rend_desc().set_tl(Vector(-(preferred_x_size/60.0)/2.0,(preferred_y_size/60.0)/2.0));
+       canvas->rend_desc().set_br(Vector((preferred_x_size/60.0)/2.0,-(preferred_y_size/60.0)/2.0));
+       canvas->rend_desc().set_w(preferred_x_size);
+       canvas->rend_desc().set_h(preferred_y_size);
        canvas->rend_desc().set_antialias(1);
        canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
        canvas->set_file_name(file_name);
 
        handle<Instance> instance = Instance::create(canvas);
 
        canvas->rend_desc().set_antialias(1);
        canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
        canvas->set_file_name(file_name);
 
        handle<Instance> instance = Instance::create(canvas);
 
-       if (!getenv("SYNFIG_DISABLE_NEW_CANVAS_EDIT_PROPERTIES"))
+       if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
                instance->find_canvas_view(canvas)->canvas_properties.present();
 }
 
 void
                instance->find_canvas_view(canvas)->canvas_properties.present();
 }
 
 void
-App::dialog_open()
+App::dialog_open(string filename)
 {
 {
-       string filename="*.sif";
+       if (filename.empty())
+               filename="*.sif";
 
 
-       while(dialog_open_file("Open", filename))
+       while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
        {
                // If the filename still has wildcards, then we should
                // continue looking for the file we want
        {
                // If the filename still has wildcards, then we should
                // continue looking for the file we want
@@ -1998,7 +2515,8 @@ App::get_instance(etl::handle<synfig::Canvas> canvas)
 void
 App::dialog_about()
 {
 void
 App::dialog_about()
 {
-       (new class About())->show();
+       if(about)
+               about->show();
 }
 
 void
 }
 
 void