Added copyright lines for files I've edited this year.
[synfig.git] / synfig-studio / trunk / src / gtkmm / app.cpp
index 277cc80..871ac9a 100644 (file)
@@ -2,19 +2,21 @@
 /*!    \file app.cpp
 **     \brief writeme
 **
 /*!    \file app.cpp
 **     \brief writeme
 **
-**     $Id: app.cpp,v 1.11 2005/03/24 21:47:28 darco Exp $
+**     $Id$
 **
 **     \legal
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
 **
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
 **     \endlegal
 */
 /* ========================================================================= */
 **     \endlegal
 */
 /* ========================================================================= */
 
 #include <fstream>
 #include <iostream>
 
 #include <fstream>
 #include <iostream>
+#include <locale>
+#include <cstring>
 
 
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
 #include <gtkmm/fileselection.h>
 #include <gtkmm/dialog.h>
 #include <gtkmm/fileselection.h>
 #include <gtkmm/dialog.h>
+#include <gtkmm/messagedialog.h>
 #include <gtkmm/label.h>
 #include <gtkmm/stock.h>
 #include <gtkmm/stockitem.h>
 #include <gtkmm/label.h>
 #include <gtkmm/stock.h>
 #include <gtkmm/stockitem.h>
 #include <gtk/gtk.h>
 
 #include <synfig/loadcanvas.h>
 #include <gtk/gtk.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"
@@ -76,6 +86,7 @@
 
 #include "devicetracker.h"
 #include "dialog_tooloptions.h"
 
 #include "devicetracker.h"
 #include "dialog_tooloptions.h"
+#include "widget_enum.h"
 
 #include "autorecover.h"
 
 
 #include "autorecover.h"
 
 #endif
 
 #ifdef WIN32
 #endif
 
 #ifdef WIN32
+#define _WIN32_WINNT 0x0500
 #include <windows.h>
 #endif
 #include <gtkmm/accelmap.h>
 #include <windows.h>
 #endif
 #include <gtkmm/accelmap.h>
+#include <gtkmm/filechooser.h>
+#include <gtkmm/filechooserdialog.h>
+
+#include "general.h"
 
 #endif
 
 
 #endif
 
@@ -124,6 +140,16 @@ using namespace studio;
 
 /* === M A C R O S ========================================================= */
 
 
 /* === M A C R O S ========================================================= */
 
+#ifndef SYNFIG_USER_APP_DIR
+#ifdef __APPLE__
+#define SYNFIG_USER_APP_DIR    "Library/Synfig"
+#elif defined(_WIN32)
+#define SYNFIG_USER_APP_DIR    "Synfig"
+#else
+#define SYNFIG_USER_APP_DIR    ".synfig"
+#endif
+#endif
+
 #ifndef DPM2DPI
 #define DPM2DPI(x)     (float(x)/39.3700787402f)
 #define DPI2DPM(x)     (float(x)*39.3700787402f)
 #ifndef DPM2DPI
 #define DPM2DPI(x)     (float(x)/39.3700787402f)
 #define DPI2DPM(x)     (float(x)*39.3700787402f)
@@ -199,6 +225,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;
@@ -233,6 +261,8 @@ 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;
+bool studio::App::single_threaded=false;
+bool studio::App::restrict_radius_ducks=false;
 
 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_; }
@@ -241,6 +271,25 @@ void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
 static synfig::String app_base_path_;
 
 namespace studio {
 static synfig::String app_base_path_;
 
 namespace studio {
+
+bool
+really_delete_widget(Gtk::Widget *widget)
+{
+       // synfig::info("really delete %p", (void*)widget);
+       delete widget;
+       return false;
+}
+
+// nasty workaround - when we've finished with a popup menu, we want to delete it
+// attaching to the signal_hide() signal gets us here before the action on the menu has run,
+// so schedule the real delete to happen in 50ms, giving the action a chance to run
+void
+delete_widget(Gtk::Widget *widget)
+{
+       // synfig::info("delete %p", (void*)widget);
+       Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
+}
+
 }; // END of namespace studio
 studio::StateManager* state_manager;
 
 }; // END of namespace studio
 studio::StateManager* state_manager;
 
@@ -260,11 +309,11 @@ public:
                );
                Gtk::Label label(message);
                label.show();
                );
                Gtk::Label label(message);
                label.show();
-               
+
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
                dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
                dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
-               
+
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
@@ -278,12 +327,12 @@ public:
                );
                Gtk::Label label(message);
                label.show();
                );
                Gtk::Label label(message);
                label.show();
-               
+
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
                dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
                dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
                dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
                dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
-               
+
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
@@ -297,11 +346,11 @@ public:
                );
                Gtk::Label label(message);
                label.show();
                );
                Gtk::Label label(message);
                label.show();
-               
+
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
                dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
                dialog.get_vbox()->pack_start(label);
                dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
                dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
-               
+
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
                dialog.set_default_response(dflt);
                dialog.show();
                return (Response)dialog.run();
@@ -317,17 +366,8 @@ public:
 
        virtual bool
        error(const std::string &err)
 
        virtual bool
        error(const std::string &err)
-       {               
-               Gtk::Dialog dialog(
-                       "Error",                // Title
-                       true,           // Modal
-                       true            // use_separator
-               );
-               Gtk::Label label(err);
-               label.show();
-               
-               dialog.get_vbox()->pack_start(label);
-               dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
+       {
+               Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
                dialog.show();
                dialog.run();
                return true;
                dialog.show();
                dialog.run();
                return true;
@@ -342,7 +382,7 @@ public:
        }
 
        virtual bool
        }
 
        virtual bool
-       amount_complete(int current, int total)
+       amount_complete(int /*current*/, int /*total*/)
        {
                while(studio::App::events_pending())studio::App::iteration(false);
                return true;
        {
                while(studio::App::events_pending())studio::App::iteration(false);
                return true;
@@ -351,149 +391,6 @@ public:
 
 /* === P R O C E D U R E S ================================================= */
 
 
 /* === P R O C E D U R E S ================================================= */
 
-typedef unsigned char U8;
-typedef unsigned short U16;
-typedef unsigned long U32;
-
-typedef union {
-       struct {
-               U32 serial;
-               U32 checksum;
-       } element;
-       U8      raw[8];
-} V_KeyUnwound;
-
-static inline U32 hash_U32(U32 i)
-{
-       i=i*1664525+1013904223;
-       i=i*1664525+1013904223;
-       i=i*1664525+1013904223;
-       return i;
-}
-
-#ifdef BIG_ENDIAN
-static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
-#define endian_fix(x) (endian_fix_table[x])
-#else
-#define endian_fix(x) (x)
-#endif
-
-int v_unwind_key(V_KeyUnwound* unwound, const char* key)
-{
-       int i;
-       unwound->element.serial=0;
-       unwound->element.checksum=0;
-       
-       for(i=0;i<16;i++)
-       {
-               U8 data;
-               
-               switch(key[i])
-               {
-                       case '0': data=0; break;
-                       case '1': data=1; break;
-                       case '2': data=2; break;
-                       case '3': data=3; break;
-                       case '4': data=4; break;
-                       case '5': data=5; break;
-                       case '6': data=6; break;
-                       case '7': data=7; break;
-                       case '8': data=8; break;
-                       case '9': data=9; break;
-                       case 'a': case 'A':  data=10; break;
-                       case 'b': case 'B':  data=11; break;
-                       case 'c': case 'C':  data=12; break;
-                       case 'd': case 'D':  data=13; break;
-                       case 'e': case 'E':  data=14; break;
-                       case 'f': case 'F':  data=15; break;
-                       default: return 0; break;
-               }
-               int bit=i*2;
-               unwound->element.checksum|=(((U32)data&3)<<bit);
-               unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
-       }
-       return 1;
-}
-
-int v_key_check(const char* key, U32* serial, U32 appid)
-{
-       V_KeyUnwound unwound_key;
-       U32 appid_mask_a=hash_U32(appid);
-       U32 appid_mask_b=hash_U32(appid_mask_a);
-       
-       if(!v_unwind_key(&unwound_key, key))
-       {
-               // Invalid characters in key
-               return 0;
-       }
-       
-
-       // Undo obfuscation pass
-       {
-               U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
-               int i;
-               for(i=0;i<7;i++)
-               {
-                       next=hash_U32(next);
-                       unwound_key.raw[endian_fix(i)]^=(next>>24);
-               }
-       }
-       
-       unwound_key.element.serial^=appid_mask_a;
-       unwound_key.element.checksum^=appid_mask_b;
-
-       *serial=unwound_key.element.serial;
-       
-       return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
-}
-
-
-int check_license(String basedir)
-{
-#ifdef LICENSE_KEY_REQUIRED
-       String key;
-       String license_file;
-
-#ifndef _WIN32
-       license_file="/usr/local/etc/.synfiglicense";
-#else
-       license_file=basedir+"\\etc\\.synfiglicense";
-#endif         
-       
-       try {
-               key=Glib::file_get_contents(license_file);
-       } catch (Glib::FileError) { }
-       U32 serial(0);
-       if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
-       {
-               while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
-               {
-                       key.clear();
-                       
-                       if(!App::dialog_entry(
-                               _("Synfig Studio Authentication"),
-                               _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
-                               key
-                       ))
-                               throw String("No License");
-               }
-               
-               FILE* file=fopen(license_file.c_str(),"w");
-               if(file)
-               {
-                       fprintf(file,"%s",key.c_str());
-                       fclose(file);
-               }
-               else
-                       synfig::error("Unable to save license key!");
-       }
-       synfig::info("License Authenticated -- Serial #%05d",serial);
-       return serial;
-#else
-       return 1;
-#endif 
-}
-
 /*
 void
 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
 /*
 void
 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
@@ -521,30 +418,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
@@ -582,21 +473,31 @@ 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;
                }
+               if(key=="single_threaded")
+               {
+                       value=strprintf("%i",(int)App::single_threaded);
+                       return true;
+               }
                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;
+               }
+
                return synfigapp::Settings::get_value(key,value);
        }
                return synfigapp::Settings::get_value(key,value);
        }
-       
+
        virtual bool set_value(const synfig::String& key,const synfig::String& value)
        {
                if(key=="gamma")
                {
                        float r,g,b,blk;
        virtual bool set_value(const synfig::String& key,const synfig::String& value)
        {
                if(key=="gamma")
                {
                        float r,g,b,blk;
-                       
+
                        strscanf(value,"%f %f %f %f",
                                &r,
                                &g,
                        strscanf(value,"%f %f %f %f",
                                &r,
                                &g,
@@ -605,7 +506,7 @@ public:
                        );
 
                        App::gamma.set_all(r,g,b,blk);
                        );
 
                        App::gamma.set_all(r,g,b,blk);
-                       
+
                        return true;
                }
                if(key=="time_format")
                        return true;
                }
                if(key=="time_format")
@@ -637,10 +538,22 @@ public:
                        App::distance_system=Distance::ident_system(value);;
                        return true;
                }
                        App::distance_system=Distance::ident_system(value);;
                        return true;
                }
-               
+               if(key=="single_threaded")
+               {
+                       int i(atoi(value.c_str()));
+                       App::single_threaded=i;
+                       return true;
+               }
+               if(key=="restrict_radius_ducks")
+               {
+                       int i(atoi(value.c_str()));
+                       App::restrict_radius_ducks=i;
+                       return true;
+               }
+
                return synfigapp::Settings::set_value(key,value);
        }
                return synfigapp::Settings::set_value(key,value);
        }
-       
+
        virtual KeyList get_key_list()const
        {
                KeyList ret(synfigapp::Settings::get_key_list());
        virtual KeyList get_key_list()const
        {
                KeyList ret(synfigapp::Settings::get_key_list());
@@ -649,12 +562,14 @@ 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");
+               ret.push_back("single_threaded");
                ret.push_back("auto_recover_backup_interval");
                ret.push_back("auto_recover_backup_interval");
+               ret.push_back("restrict_radius_ducks");
                return ret;
        }
 };
 
                return ret;
        }
 };
 
-static Preferences _preferences;
+static ::Preferences _preferences;
 
 void
 init_ui_manager()
 
 void
 init_ui_manager()
@@ -664,19 +579,20 @@ init_ui_manager()
        Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
 
        Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
        Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
 
        Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
-       
-       menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
-       menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
-       menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
-       menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
-       menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
-       menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
-       menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
-       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-state", "State") );
-       menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
+
+       menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
+       menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
+       menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
+       menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
+       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-state", _("State")) );
+       menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
 
        // Add the synfigapp actions...
        synfigapp::Action::Book::iterator iter;
 
        // Add the synfigapp actions...
        synfigapp::Action::Book::iterator iter;
@@ -688,13 +604,14 @@ init_ui_manager()
                        iter->second.local_name,iter->second.local_name
                ));
        }
                        iter->second.local_name,iter->second.local_name
                ));
        }
-       
+
 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
 #define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
 #define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); }
 
        DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
        DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
 #define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
 #define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); }
 
        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);
@@ -709,7 +626,9 @@ init_ui_manager()
        DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
        DEFINE_ACTION("sound", _("Sound File"));
        DEFINE_ACTION("options", _("Options"));
        DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
        DEFINE_ACTION("sound", _("Sound File"));
        DEFINE_ACTION("options", _("Options"));
-       DEFINE_ACTION("close", _("Close"));
+       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"));
@@ -721,12 +640,12 @@ init_ui_manager()
        DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
        DEFINE_ACTION("properties", _("Properties"));
 
        DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
        DEFINE_ACTION("properties", _("Properties"));
 
-       DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
-       DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
-       DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
-       DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
-       DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
-       DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
+       DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
+       DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
+       DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
+       DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
+       DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
+       DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
        DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
        DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
        DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
        DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
        DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
        DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
@@ -738,13 +657,17 @@ 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("play", _("Play"));
-       DEFINE_ACTION("pause", _("Pause"));
+       // DEFINE_ACTION("pause", _("Pause"));
        DEFINE_ACTION("stop", _("Stop"));
        DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
        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("stop", _("Stop"));
        DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
        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"));
@@ -774,11 +697,11 @@ init_ui_manager()
 // Set up synfigapp actions
        /*{
                synfigapp::Action::Book::iterator iter;
 // Set up synfigapp actions
        /*{
                synfigapp::Action::Book::iterator iter;
-       
+
                for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
                {
                        Gtk::StockID stock_id;
                for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
                {
                        Gtk::StockID stock_id;
-                       
+
                        if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
                        {
                                //Gtk::Image* image(manage(new Gtk::Image()));
                        if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
                        {
                                //Gtk::Image* image(manage(new Gtk::Image()));
@@ -792,7 +715,7 @@ init_ui_manager()
                                //else if(iter->second.task=="duplicate")       stock_id=Gtk::Stock::COPY;
                                else if(iter->second.task=="remove")    stock_id=Gtk::Stock::DELETE;
                                else                                                                    stock_id=Gtk::StockID("synfig-"+iter->second.task);
                                //else if(iter->second.task=="duplicate")       stock_id=Gtk::Stock::COPY;
                                else if(iter->second.task=="remove")    stock_id=Gtk::Stock::DELETE;
                                else                                                                    stock_id=Gtk::StockID("synfig-"+iter->second.task);
-       
+
                                actions_action_group->add(Gtk::Action::create(
                                        "action-"+iter->second.name,
                                        stock_id,
                                actions_action_group->add(Gtk::Action::create(
                                        "action-"+iter->second.name,
                                        stock_id,
@@ -812,6 +735,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' />"
@@ -829,6 +754,8 @@ init_ui_manager()
 "              <separator name='bleh04'/>"
 "              <menuitem action='options' />"
 "              <menuitem action='close' />"
 "              <separator name='bleh04'/>"
 "              <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'/>"
@@ -865,9 +792,20 @@ 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'/>"
 "              <separator name='bleh08'/>"
 "              <menuitem action='play'/>"
-"              <menuitem action='pause'/>"
+//"            <menuitem action='pause'/>"
 "              <menuitem action='stop'/>"
 "              <menuitem action='dialog-flipbook'/>"
 "              <separator name='bleh09'/>"
 "              <menuitem action='stop'/>"
 "              <menuitem action='dialog-flipbook'/>"
 "              <separator name='bleh09'/>"
@@ -896,8 +834,6 @@ init_ui_manager()
 "      </menu>"
 "      <menu action='menu-canvas'>"
 "              <menuitem action='canvas-new'/>"
 "      </menu>"
 "      <menu action='menu-canvas'>"
 "              <menuitem action='canvas-new'/>"
-       "       <menuitem action='amount-inc'/>"
-       "       <menuitem action='amount-dec'/>"
 "      </menu>"
 "      <menu name='menu-state' action='menu-state'>"
 "      </menu>"
 "      </menu>"
 "      <menu name='menu-state' action='menu-state'>"
 "      </menu>"
@@ -910,6 +846,8 @@ init_ui_manager()
 //"            <menuitem action='paste'/>"
 //"            <separator name='bleh06'/>"
 "              <menu action='menu-layer-new'></menu>"
 //"            <menuitem action='paste'/>"
 //"            <separator name='bleh06'/>"
 "              <menu action='menu-layer-new'></menu>"
+"              <menuitem action='amount-inc'/>"
+"              <menuitem action='amount-dec'/>"
 "      </menu>"
 "      <menu action='menu-keyframe'>"
 "              <menuitem action='keyframe-properties'/>"
 "      </menu>"
 "      <menu action='menu-keyframe'>"
 "              <menuitem action='keyframe-properties'/>"
@@ -954,8 +892,18 @@ init_ui_manager()
        }
 
        // Add default keyboard accelerators
        }
 
        // Add default keyboard accelerators
-#define ACCEL(path,accel)      { Gtk::AccelKey accel_key(accel,path); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
-#define ACCEL2(accel)  { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
+#define ACCEL(path,accel)                                              \
+       {                                                                                       \
+               Gtk::AccelKey accel_key(accel,path);    \
+               Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod());       \
+       }
+
+#define ACCEL2(accel)                                                  \
+       {                                                                                       \
+               Gtk::AccelKey accel_key(accel);                 \
+               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>//select-all-ducks","<Control>a");
        ACCEL("<Actions>//unselect-all-layers","<Control>d");
        ACCEL("<Actions>//render","F9");
@@ -974,7 +922,6 @@ init_ui_manager()
        ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
        ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
 
        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"));
 
        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"));
 
@@ -999,6 +946,9 @@ init_ui_manager()
        ACCEL("<Actions>//time-zoom-in","+");
        ACCEL("<Actions>//time-zoom-out","_");
 */
        ACCEL("<Actions>//time-zoom-in","+");
        ACCEL("<Actions>//time-zoom-out","_");
 */
+       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::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
        ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
 
@@ -1012,19 +962,33 @@ init_ui_manager()
        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(',',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"));
+       ACCEL2(Gtk::AccelKey('o',Gdk::MOD1_MASK,"<Actions>//toggle-onion-skin"));
+       ACCEL("<Actions>//play",              "<Control>p");
        ACCEL("<Actions>//seek-begin","Home");
        ACCEL("<Actions>//seek-end","End");
        ACCEL("<Actions>//seek-begin","Home");
        ACCEL("<Actions>//seek-end","End");
-       ACCEL("<Actions>//state-normal","<Mod1>a");
-       ACCEL("<Actions>//state-rotate","<Mod1>s");
-       ACCEL("<Actions>//state-scale","<Mod1>d");
-       ACCEL("<Actions>//state-bline","<Mod1>b");
-       ACCEL("<Actions>//state-fill","<Mod1>f");
-       ACCEL("<Actions>//state-eyedrop","<Mod1>e");
-       ACCEL("<Actions>//state-gradient","<Mod1>g");
-       ACCEL("<Actions>//state-zoom","<Mod1>z");
+
+       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");
        ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
-       
+
 #undef ACCEL
 }
 
 #undef ACCEL
 }
 
@@ -1036,22 +1000,22 @@ init_ui_manager()
 
 App::App(int *argc, char ***argv):
        Gtk::Main(argc,argv),
 
 App::App(int *argc, char ***argv):
        Gtk::Main(argc,argv),
-       IconControler(etl::dirname((*argv)[0]))
+       IconController(etl::dirname((*argv)[0]))
 {
        app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
 {
        app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
-       
-       int serial_;
-       serial_=check_license(app_base_path_);
-       
-       
+
+
        ui_interface_=new GlobalUIInterface();
 
        gdk_rgb_init();
 
        ui_interface_=new GlobalUIInterface();
 
        gdk_rgb_init();
 
-       Glib::thread_init();
+       // don't call thread_init() if threads are already initialized
+       // on some machines bonobo_init() initialized threads before we get here
+       if (!g_thread_supported())
+               Glib::thread_init();
 
        distance_system=Distance::SYSTEM_UNITS;
 
        distance_system=Distance::SYSTEM_UNITS;
-               
+
        if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
        {
                if(errno!=EEXIST)
        if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
        {
                if(errno!=EEXIST)
@@ -1061,223 +1025,225 @@ App::App(int *argc, char ***argv):
        {
                synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
        }
        {
                synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
        }
-       
-       
+
+
        ipc=new IPC();
        ipc=new IPC();
-       
-       try
+
+       if(!SYNFIG_CHECK_VERSION())
        {
        {
-               if(!SYNFIG_CHECK_VERSION())
-               {
                cerr<<"FATAL: Synfig Version Mismatch"<<endl;
                cerr<<"FATAL: Synfig Version Mismatch"<<endl;
-               dialog_error_blocking("SYNFIG Studio",
-                       "This copy of SYNFIG Studio was compiled against a\n"
+               dialog_error_blocking("Synfig Studio",
+                       "This copy of Synfig Studio was compiled against a\n"
                        "different version of libsynfig than what is currently\n"
                        "installed. Synfig Studio will now abort. Try downloading\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 Development Website at\n"
-                       "http://dev.synfig.com/ "
+                       "the latest version from the Synfig website at\n"
+                       "http://synfig.org/Download"
                );
                throw 40;
                );
                throw 40;
-               }
-       }
-       catch(synfig::SoftwareExpired)
-       {
-               cerr<<"FATAL: Software Expired"<<endl;
-               dialog_error_blocking("SYNFIG Studio",
-                       "This copy of SYNFIG Studio has expired.\n"
-                       "Please erase this copy, or download and\n"
-                       "install the latest copy from the SYNFIG\n"
-                       "Development Website at http://dev.synfig.com/ ."
-               );
-               throw 39;
        }
        }
-       Glib::set_application_name(_("SYNFIG Studio"));
-       
-       About about_window;
-       about_window.set_can_self_destruct(false);
-       about_window.show();
+       Glib::set_application_name(_("Synfig Studio"));
+
+       Splash splash_screen;
+       splash_screen.set_can_self_destruct(false);
+       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)); }
        catch(...)
        {
        // Initialize the Synfig library
        try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
        catch(...)
        {
-               get_ui_interface()->error("Failed to initialize synfig!");
+               get_ui_interface()->error(_("Failed to initialize synfig!"));
                throw;
        }
 
        // add the preferences to the settings
        synfigapp::Main::settings().add_domain(&_preferences,"pref");
                throw;
        }
 
        // add the preferences to the settings
        synfigapp::Main::settings().add_domain(&_preferences,"pref");
-       
+
        try
        {
        try
        {
-               studio_init_cb.task("Init UI Manager...");
+               studio_init_cb.task(_("Init UI Manager..."));
                App::ui_manager_=studio::UIManager::create();
                init_ui_manager();
                App::ui_manager_=studio::UIManager::create();
                init_ui_manager();
-               
-               studio_init_cb.task("Init Dock Manager...");
+
+               studio_init_cb.task(_("Init Dock Manager..."));
                dock_manager=new studio::DockManager();
 
                dock_manager=new studio::DockManager();
 
-               studio_init_cb.task("Init State Manager...");
+               studio_init_cb.task(_("Init State Manager..."));
                state_manager=new StateManager();
 
                state_manager=new StateManager();
 
-               studio_init_cb.task("Init Toolbox...");
+               studio_init_cb.task(_("Init Toolbox..."));
                toolbox=new studio::Toolbox();
 
                toolbox=new studio::Toolbox();
 
-               studio_init_cb.task("Init Tool Options...");
+               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);
 
                dialog_tool_options=new studio::Dialog_ToolOptions();
                dock_manager->register_dockable(*dialog_tool_options);
 
-               studio_init_cb.task("Init History...");
+               studio_init_cb.task(_("Init History..."));
                dock_history=new studio::Dock_History();
                dock_manager->register_dockable(*dock_history);
 
                dock_history=new studio::Dock_History();
                dock_manager->register_dockable(*dock_history);
 
-               studio_init_cb.task("Init Canvases...");
+               studio_init_cb.task(_("Init Canvases..."));
                dock_canvases=new studio::Dock_Canvases();
                dock_manager->register_dockable(*dock_canvases);
 
                dock_canvases=new studio::Dock_Canvases();
                dock_manager->register_dockable(*dock_canvases);
 
-               studio_init_cb.task("Init Keyframes...");
+               studio_init_cb.task(_("Init Keyframes..."));
                dock_keyframes=new studio::Dock_Keyframes();
                dock_manager->register_dockable(*dock_keyframes);
 
                dock_keyframes=new studio::Dock_Keyframes();
                dock_manager->register_dockable(*dock_keyframes);
 
-               studio_init_cb.task("Init Layers...");
+               studio_init_cb.task(_("Init Layers..."));
                dock_layers=new studio::Dock_Layers();
                dock_manager->register_dockable(*dock_layers);
 
                dock_layers=new studio::Dock_Layers();
                dock_manager->register_dockable(*dock_layers);
 
-               studio_init_cb.task("Init Params...");
+               studio_init_cb.task(_("Init Params..."));
                dock_params=new studio::Dock_Params();
                dock_manager->register_dockable(*dock_params);
 
                dock_params=new studio::Dock_Params();
                dock_manager->register_dockable(*dock_params);
 
-               studio_init_cb.task("Init MetaData...");
+               studio_init_cb.task(_("Init MetaData..."));
                dock_meta_data=new studio::Dock_MetaData();
                dock_manager->register_dockable(*dock_meta_data);
 
                dock_meta_data=new studio::Dock_MetaData();
                dock_manager->register_dockable(*dock_meta_data);
 
-               studio_init_cb.task("Init Children...");
+               studio_init_cb.task(_("Init Children..."));
                dock_children=new studio::Dock_Children();
                dock_manager->register_dockable(*dock_children);
                dock_children=new studio::Dock_Children();
                dock_manager->register_dockable(*dock_children);
-               
-               studio_init_cb.task("Init Info...");
+
+               studio_init_cb.task(_("Init Info..."));
                dock_info = new studio::Dock_Info();
                dock_manager->register_dockable(*dock_info);
                dock_info = new studio::Dock_Info();
                dock_manager->register_dockable(*dock_info);
-               
-               studio_init_cb.task("Init Navigator...");
+
+               studio_init_cb.task(_("Init Navigator..."));
                dock_navigator = new studio::Dock_Navigator();
                dock_manager->register_dockable(*dock_navigator);
 
                dock_navigator = new studio::Dock_Navigator();
                dock_manager->register_dockable(*dock_navigator);
 
-               studio_init_cb.task("Init Timetrack...");
+               studio_init_cb.task(_("Init Timetrack..."));
                dock_timetrack = new studio::Dock_Timetrack();
                dock_manager->register_dockable(*dock_timetrack);
 
                dock_timetrack = new studio::Dock_Timetrack();
                dock_manager->register_dockable(*dock_timetrack);
 
-               studio_init_cb.task("Init Curve Editor...");
+               studio_init_cb.task(_("Init Curve Editor..."));
                dock_curves = new studio::Dock_Curves();
                dock_manager->register_dockable(*dock_curves);
 
                dock_curves = new studio::Dock_Curves();
                dock_manager->register_dockable(*dock_curves);
 
-               studio_init_cb.task("Init Layer Groups...");
+               studio_init_cb.task(_("Init Layer Groups..."));
                dock_layer_groups = new studio::Dock_LayerGroups();
                dock_manager->register_dockable(*dock_layer_groups);
                dock_layer_groups = new studio::Dock_LayerGroups();
                dock_manager->register_dockable(*dock_layer_groups);
-               
-               
-               studio_init_cb.task("Init Color Dialog...");
+
+
+               studio_init_cb.task(_("Init Color Dialog..."));
                dialog_color=new studio::Dialog_Color();
 
                dialog_color=new studio::Dialog_Color();
 
-               studio_init_cb.task("Init Gradient Dialog...");
+               studio_init_cb.task(_("Init Gradient Dialog..."));
                dialog_gradient=new studio::Dialog_Gradient();
 
                dialog_gradient=new studio::Dialog_Gradient();
 
-               studio_init_cb.task("Init DeviceTracker...");
+               studio_init_cb.task(_("Init DeviceTracker..."));
                device_tracker=new studio::DeviceTracker();
 
                device_tracker=new studio::DeviceTracker();
 
-               studio_init_cb.task("Init Tools...");
+               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();
 
 
+               /* row 2 */
                state_manager->add_state(&state_bline);
                state_manager->add_state(&state_bline);
-               state_manager->add_state(&state_polygon);
                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_gradient);
+               if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
 
 
-               state_manager->add_state(&state_draw);
-               state_manager->add_state(&state_sketch);
-
-               state_manager->add_state(&state_eyedrop);
+               /* row 3 */
+               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);
                state_manager->add_state(&state_fill);
                state_manager->add_state(&state_fill);
-               
-               state_manager->add_state(&state_width);
-               state_manager->add_state(&state_gradient);
-               
+               state_manager->add_state(&state_eyedrop);
                state_manager->add_state(&state_zoom);
 
                state_manager->add_state(&state_zoom);
 
-               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();
+               // Disabled by default - it doesn't work properly?
+               if(getenv("SYNFIG_ENABLE_WIDTH"    )) state_manager->add_state(&state_width);
 
 
+               studio_init_cb.task(_("Init ModPalette..."));
+               module_list_.push_back(new ModPalette()); module_list_.back()->start();
 
 
-               studio_init_cb.task("Init Setup Dialog...");
+               studio_init_cb.task(_("Init Setup Dialog..."));
                dialog_setup=new studio::Dialog_Setup();
                dialog_setup=new studio::Dialog_Setup();
-               
-               studio_init_cb.task("Init Input Dialog...");
+
+               studio_init_cb.task(_("Init Input Dialog..."));
                dialog_input=new Gtk::InputDialog();
                dialog_input=new Gtk::InputDialog();
+               dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
+               dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
 
 
-               studio_init_cb.task("Init auto recovery...");
+               studio_init_cb.task(_("Init auto recovery..."));
                auto_recover=new AutoRecover();
 
                studio_init_cb.amount_complete(9250,10000);
                auto_recover=new AutoRecover();
 
                studio_init_cb.amount_complete(9250,10000);
-               studio_init_cb.task("Loading Settings...");
+               studio_init_cb.task(_("Loading Settings..."));
                load_settings();
                load_settings();
-               studio_init_cb.task("Checking auto-recover...");
-       
+               studio_init_cb.task(_("Checking auto-recover..."));
+
                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,
                // and load them if found.
                for(;*argc>=1;(*argc)--)
                        if((*argv)[*argc] && (*argv)[*argc][0]!='-')
                        {
                // Look for any files given on the command line,
                // and load them if found.
                for(;*argc>=1;(*argc)--)
                        if((*argv)[*argc] && (*argv)[*argc][0]!='-')
                        {
-                               studio_init_cb.task("Loading files...");
-                               about_window.hide();
+                               studio_init_cb.task(_("Loading files..."));
+                               splash_screen.hide();
                                open((*argv)[*argc]);
                                open((*argv)[*argc]);
-                               about_window.show();
+                               opened_any = true;
+                               splash_screen.show();
                        }
                        }
-               
-               studio_init_cb.task("Done.");
+
+               // 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);
                studio_init_cb.amount_complete(10000,10000);
-       
+
                toolbox->present();
        }
                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."));
@@ -1293,27 +1259,30 @@ App::~App()
        save_settings();
 
        synfigapp::Main::settings().remove_domain("pref");
        save_settings();
 
        synfigapp::Main::settings().remove_domain("pref");
-       
+
        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 ipc;
        delete state_manager;
 
        delete ipc;
-       
+
        delete auto_recover;
 
        delete auto_recover;
 
+       delete about;
+       
        toolbox->hide();
 
        toolbox->hide();
 
-//     studio::App::iteration(false); 
-       
+//     studio::App::iteration(false);
+
        delete toolbox;
        delete toolbox;
-       
-//     studio::App::iteration(false); 
 
 
-//     studio::App::iteration(false); 
+//     studio::App::iteration(false);
+
+//     studio::App::iteration(false);
 
        delete dialog_setup;
 
 
        delete dialog_setup;
 
@@ -1333,11 +1302,7 @@ App::~App()
 String
 App::get_user_app_directory()
 {
 String
 App::get_user_app_directory()
 {
-#ifdef __APPLE__
-       return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
-#else
-       return Glib::build_filename(Glib::get_home_dir(),"Synfig");
-#endif
+       return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
 }
 
 synfig::String
 }
 
 synfig::String
@@ -1352,18 +1317,18 @@ App::add_recent_file(const std::string &file_name)
        std::string filename(file_name);
 
        assert(!filename.empty());
        std::string filename(file_name);
 
        assert(!filename.empty());
-       
+
        if(filename.empty())
                return;
        if(filename.empty())
                return;
-       
+
        // Toss out any "hidden" files
        if(basename(filename)[0]=='.')
                return;
        // Toss out any "hidden" files
        if(basename(filename)[0]=='.')
                return;
-               
-       // If we aren't an absolute path, turn outselves into one
+
+       // If we aren't an absolute path, turn ourselves into one
        if(!is_absolute_path(filename))
                filename=absolute_path(filename);
        if(!is_absolute_path(filename))
                filename=absolute_path(filename);
-       
+
        list<string>::iterator iter;
        // Check to see if the file is already on the list.
        // If it is, then remove it from the list
        list<string>::iterator iter;
        // Check to see if the file is already on the list.
        // If it is, then remove it from the list
@@ -1374,16 +1339,16 @@ App::add_recent_file(const std::string &file_name)
                        break;
                }
 
                        break;
                }
 
-       
+
        // Push the filename to the front of the list
        recent_files.push_front(filename);
        // Push the filename to the front of the list
        recent_files.push_front(filename);
-               
+
        // Clean out the files at the end of the list.
        while(recent_files.size()>(unsigned)get_max_recent_files())
                recent_files.pop_back();
        // Clean out the files at the end of the list.
        while(recent_files.size()>(unsigned)get_max_recent_files())
                recent_files.pop_back();
-       
+
        signal_recent_files_changed_();
        signal_recent_files_changed_();
-       
+
        return;
 }
 
        return;
 }
 
@@ -1405,8 +1370,11 @@ App::set_time_format(synfig::Time::Format x)
 void
 App::save_settings()
 {
 void
 App::save_settings()
 {
+       char * old_locale;
        try
        {
        try
        {
+       old_locale=strdup(setlocale(LC_NUMERIC, NULL));
+       setlocale(LC_NUMERIC, "C");
                {
                        std::string filename=get_config_file("accelrc");
                        Gtk::AccelMap::save(filename);
                {
                        std::string filename=get_config_file("accelrc");
                        Gtk::AccelMap::save(filename);
@@ -1415,21 +1383,22 @@ App::save_settings()
                        std::string filename=get_config_file("recentfiles");
 
                        std::ofstream file(filename.c_str());
                        std::string filename=get_config_file("recentfiles");
 
                        std::ofstream file(filename.c_str());
-               
+
                        if(!file)
                        {
                                synfig::warning("Unable to save %s",filename.c_str());
                                break;
                        }
                        if(!file)
                        {
                                synfig::warning("Unable to save %s",filename.c_str());
                                break;
                        }
-               
+
                        list<string>::reverse_iterator iter;
                        list<string>::reverse_iterator iter;
-       
+
                        for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
                                file<<*iter<<endl;
                }while(0);
 
                std::string filename=get_config_file("settings");
                synfigapp::Main::settings().save_to_file(filename);
                        for(iter=recent_files.rbegin();iter!=recent_files.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);
        }
        catch(...)
        {
        }
        catch(...)
        {
@@ -1440,8 +1409,11 @@ App::save_settings()
 void
 App::load_settings()
 {
 void
 App::load_settings()
 {
+       char  * old_locale;
        try
        {
        try
        {
+       old_locale=strdup(setlocale(LC_NUMERIC, NULL));
+       setlocale(LC_NUMERIC, "C");
                {
                        std::string filename=get_config_file("accelrc");
                        Gtk::AccelMap::load(filename);
                {
                        std::string filename=get_config_file("accelrc");
                        Gtk::AccelMap::load(filename);
@@ -1450,7 +1422,7 @@ App::load_settings()
                        std::string filename=get_config_file("recentfiles");
 
                        std::ifstream file(filename.c_str());
                        std::string filename=get_config_file("recentfiles");
 
                        std::ifstream file(filename.c_str());
-       
+
                        while(file)
                        {
                                std::string recent_file;
                        while(file)
                        {
                                std::string recent_file;
@@ -1466,22 +1438,10 @@ App::load_settings()
                        //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);
-                               synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
-                               synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
-                               synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
-                               synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
-                               synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
-                               synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
-                               synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
-                               synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
-                               synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
-                               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("window.toolbox.pos","4 4");
+                               reset_initial_window_configuration();
                        }
                }
                        }
                }
-               
+       setlocale(LC_NUMERIC,old_locale);
        }
        catch(...)
        {
        }
        catch(...)
        {
@@ -1489,6 +1449,26 @@ App::load_settings()
        }
 }
 
        }
 }
 
+void
+App::reset_initial_window_configuration()
+{
+       synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
+       synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
+       synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
+       synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
+       synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
+       synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
+       synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
+       synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
+       synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
+       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("pref.single_threaded","0");
+       synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
+       synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
+}
+
 bool
 App::shutdown_request(GdkEventAny*)
 {
 bool
 App::shutdown_request(GdkEventAny*)
 {
@@ -1501,12 +1481,12 @@ void
 App::quit()
 {
        if(shutdown_in_progress)return;
 App::quit()
 {
        if(shutdown_in_progress)return;
-               
-       
-       get_ui_interface()->task("Quit Request");
+
+
+       get_ui_interface()->task(_("Quit Request"));
        if(Busy::count)
        {
        if(Busy::count)
        {
-               dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
+               dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
                return;
        }
 
                return;
        }
 
@@ -1559,22 +1539,22 @@ App::quit()
                                        return;
                        }
                }
                                        return;
                        }
                }
-*/             
-               
+*/
+
                // This next line causes things to crash for some reason
                // This next line causes things to crash for some reason
-               //(*iter)->close(); 
+               //(*iter)->close();
        }
        }
-       
+
        shutdown_in_progress=true;
 
        instance_list.clear();
 
        while(studio::App::events_pending())studio::App::iteration(false);
        shutdown_in_progress=true;
 
        instance_list.clear();
 
        while(studio::App::events_pending())studio::App::iteration(false);
-               
+
        Gtk::Main::quit();
        auto_recover->normal_shutdown();
 
        Gtk::Main::quit();
        auto_recover->normal_shutdown();
 
-       get_ui_interface()->task("Quit Request sent");
+       get_ui_interface()->task(_("Quit Request sent"));
 }
 
 void
 }
 
 void
@@ -1584,8 +1564,8 @@ App::show_setup()
        dialog_setup->show();
 }
 
        dialog_setup->show();
 }
 
-gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
-gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
+gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
+gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
 
 //#ifdef WIN32
 //#define USE_WIN32_FILE_DIALOGS 1
 
 //#ifdef WIN32
 //#define USE_WIN32_FILE_DIALOGS 1
@@ -1598,17 +1578,19 @@ static OPENFILENAME ofn={};
 #ifdef WIN32
 #include <gdk/gdkwin32.h>
 #endif
 #ifdef WIN32
 #include <gdk/gdkwin32.h>
 #endif
-       
+
 bool
 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") ;
 
        GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
        HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
        HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
 #ifdef USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
        GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
        HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
        HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
-       
+
        ofn.lStructSize=sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.hInstance = hInstance;
        ofn.lStructSize=sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.hInstance = hInstance;
@@ -1628,38 +1610,67 @@ App::dialog_open_file(const std::string &title, std::string &filename)
 //     ofn.lCustData = 0l;
        ofn.lpfnHook=NULL;
 //     ofn.lpTemplateName=NULL;
 //     ofn.lCustData = 0l;
        ofn.lpfnHook=NULL;
 //     ofn.lpTemplateName=NULL;
-       
+
        CHAR szFilename[MAX_PATH];
        CHAR szTitle[500];
        strcpy(szFilename,filename.c_str());
        strcpy(szTitle,title.c_str());
        CHAR szFilename[MAX_PATH];
        CHAR szTitle[500];
        strcpy(szFilename,filename.c_str());
        strcpy(szTitle,title.c_str());
-       
+
        ofn.lpstrFile=szFilename;
        ofn.lpstrFileTitle=szTitle;
        ofn.lpstrFile=szFilename;
        ofn.lpstrFileTitle=szTitle;
-       
+
        if(GetOpenFileName(&ofn))
        {
                filename=szFilename;
                return true;
        }
        return false;
        if(GetOpenFileName(&ofn))
        {
                filename=szFilename;
                return true;
        }
        return false;
-       
+
 #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);
+
+    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);
+
+    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 false;
+
+    /*
+
        GtkWidget *ok;
        GtkWidget *cancel;
        int val=0;
        GtkWidget *ok;
        GtkWidget *cancel;
        int val=0;
-       
+
        GtkWidget *fileselection;
        fileselection = gtk_file_selection_new(title.c_str());
 
        GtkWidget *fileselection;
        fileselection = gtk_file_selection_new(title.c_str());
 
-       
+
        if(basename(filename)==filename)
        {
        if(basename(filename)==filename)
        {
-               gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());         
+               gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
        }
        else
                gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
        }
        else
                gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
@@ -1669,19 +1680,19 @@ App::dialog_open_file(const std::string &title, std::string &filename)
        ok=GTK_FILE_SELECTION(fileselection)->ok_button;
        cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
 
        ok=GTK_FILE_SELECTION(fileselection)->ok_button;
        cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
 
-       gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);              
-       gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);              
+       gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
+       gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
 
        gtk_widget_show(fileselection);
 
        while(!val)
 
        gtk_widget_show(fileselection);
 
        while(!val)
-               iteration();            
-       
-       
+               iteration();
+
+
        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
        {
@@ -1690,19 +1701,22 @@ App::dialog_open_file(const std::string &title, std::string &filename)
        }
        gtk_widget_destroy(fileselection);
        return true;
        }
        gtk_widget_destroy(fileselection);
        return true;
+    */
 #endif
 }
 
 bool
 #endif
 }
 
 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)
 {
 {
-#ifdef USE_WIN32_FILE_DIALOGS
+       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") ;
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
-       
+
        GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
        HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
        HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
        GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
        HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
        HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
-       
+
        ofn.lStructSize=sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.hInstance = hInstance;
        ofn.lStructSize=sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.hInstance = hInstance;
@@ -1722,88 +1736,93 @@ App::dialog_save_file(const std::string &title, std::string &filename)
 //     ofn.lCustData = 0l;
        ofn.lpfnHook=NULL;
 //     ofn.lpTemplateName=NULL;
 //     ofn.lCustData = 0l;
        ofn.lpfnHook=NULL;
 //     ofn.lpTemplateName=NULL;
-       
+
        CHAR szFilename[MAX_PATH];
        CHAR szTitle[500];
        strcpy(szFilename,filename.c_str());
        strcpy(szTitle,title.c_str());
        CHAR szFilename[MAX_PATH];
        CHAR szTitle[500];
        strcpy(szFilename,filename.c_str());
        strcpy(szTitle,title.c_str());
-       
+
        ofn.lpstrFile=szFilename;
        ofn.lpstrFileTitle=szTitle;
        ofn.lpstrFile=szFilename;
        ofn.lpstrFileTitle=szTitle;
-       
+
        if(GetSaveFileName(&ofn))
        {
                filename=szFilename;
        if(GetSaveFileName(&ofn))
        {
                filename=szFilename;
+               _preferences.set_value(preference,dirname(filename));
                return true;
        }
        return false;
 #else
                return true;
        }
        return false;
 #else
-       return dialog_open_file(title, filename);
-#endif
-}
+       synfig::String prev_path;
 
 
-bool
-App::dialog_saveas_file(const std::string &title, std::string &filename)
-{
-#if USE_WIN32_FILE_DIALOGS
-       static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
-       
-       GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
-       HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
-       HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
-       
-       ofn.lStructSize=sizeof(OPENFILENAME);
-       ofn.hwndOwner = hWnd;
-       ofn.hInstance = hInstance;
-       ofn.lpstrFilter = szFilter;
-//     ofn.lpstrCustomFilter=NULL;
-//     ofn.nMaxCustFilter=0;
-//     ofn.nFilterIndex=0;
-//     ofn.lpstrFile=NULL;
-       ofn.nMaxFile=MAX_PATH;
-//     ofn.lpstrFileTitle=NULL;
-//     ofn.lpstrInitialDir=NULL;
-//     ofn.lpstrTitle=NULL;
-       ofn.Flags=OFN_OVERWRITEPROMPT;
-//     ofn.nFileOffset=0;
-//     ofn.nFileExtension=0;
-       ofn.lpstrDefExt=TEXT("sif");
-//     ofn.lCustData = 0l;
-       ofn.lpfnHook=NULL;
-//     ofn.lpTemplateName=NULL;
-       
-       CHAR szFilename[MAX_PATH];
-       CHAR szTitle[500];
-       strcpy(szFilename,filename.c_str());
-       strcpy(szTitle,title.c_str());
-       
-       ofn.lpstrFile=szFilename;
-       ofn.lpstrFileTitle=szTitle;
-       
-       if(GetSaveFileName(&ofn))
+       if(!_preferences.get_value(preference, prev_path))
+               prev_path=".";
+
+       prev_path = absolute_path(prev_path);
+
+    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);
+
+       Widget_Enum *file_type_enum = 0;
+       if (preference == ANIMATION_DIR_PREFERENCE)
        {
        {
-               filename=szFilename;
-               return true;
+               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_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
+                                                                          .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);
        }
        }
-       return false;
-#else
-       return dialog_open_file(title, filename);
+
+    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;
+
+               // select the file if it exists
+               dialog->set_filename(full_path);
+
+               // if the file doesn't exist, put its name into the filename box
+               struct stat s;
+               if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
+                       dialog->set_current_name(basename(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;
+        return true;
+    }
+
+    delete dialog;
+    return false;
 #endif
 }
 
 void
 App::dialog_error_blocking(const std::string &title, const std::string &message)
 {
 #endif
 }
 
 void
 App::dialog_error_blocking(const std::string &title, const std::string &message)
 {
-       Gtk::Dialog dialog(
-               title,          // Title
-               true,           // Modal
-               true            // use_separator
-       );
-       Gtk::Label label(message);
-       label.show();
-       
-       dialog.get_vbox()->pack_start(label);
-       dialog.add_button(Gtk::StockID("gtk-ok"),1);
+       Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
+       dialog.set_title(title);
        dialog.show();
        dialog.run();
 }
        dialog.show();
        dialog.run();
 }
@@ -1811,16 +1830,8 @@ App::dialog_error_blocking(const std::string &title, const std::string &message)
 void
 App::dialog_warning_blocking(const std::string &title, const std::string &message)
 {
 void
 App::dialog_warning_blocking(const std::string &title, const std::string &message)
 {
-       Gtk::Dialog dialog(
-               title,          // Title
-               true,           // Modal
-               true            // use_separator
-       );
-       Gtk::Label label(message);
-       label.show();
-
-       dialog.get_vbox()->pack_start(label);
-       dialog.add_button(Gtk::StockID("gtk-ok"),1);
+       Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
+       dialog.set_title(title);
        dialog.show();
        dialog.run();
 }
        dialog.show();
        dialog.run();
 }
@@ -1835,7 +1846,7 @@ App::dialog_yes_no(const std::string &title, const std::string &message)
        );
        Gtk::Label label(message);
        label.show();
        );
        Gtk::Label label(message);
        label.show();
-       
+
        dialog.get_vbox()->pack_start(label);
        dialog.add_button(Gtk::StockID("gtk-yes"),1);
        dialog.add_button(Gtk::StockID("gtk-no"),0);
        dialog.get_vbox()->pack_start(label);
        dialog.add_button(Gtk::StockID("gtk-yes"),1);
        dialog.add_button(Gtk::StockID("gtk-no"),0);
@@ -1865,17 +1876,8 @@ App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
 void
 App::dialog_not_implemented()
 {
 void
 App::dialog_not_implemented()
 {
-       Gtk::Dialog dialog(
-               "Feature not available",                // Title
-               true,           // Modal
-               true            // use_separator
-       );
-       Gtk::Label label("Sorry, this feature has not yet been implemented.");
-       label.show();
-       
-       dialog.get_vbox()->pack_start(label);
-       dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
-       dialog.show();
+       Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
+       dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
        dialog.run();
 }
 
        dialog.run();
 }
 
@@ -1920,33 +1922,46 @@ App::open(std::string filename)
        return open_as(filename,filename);
 }
 
        return open_as(filename,filename);
 }
 
+// this is called from autorecover.cpp:
+//   App::open_as(get_shadow_file_name(filename),filename)
+// other than that, 'filename' and 'as' are the same
 bool
 App::open_as(std::string filename,std::string as)
 {
 bool
 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)));
+    as=long_name;
+#endif
+
        try
        {
                OneMoment one_moment;
        try
        {
                OneMoment one_moment;
-       
+
                etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
                if(canvas && get_instance(canvas))
                {
                        get_instance(canvas)->find_canvas_view(canvas)->present();
                etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
                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());
+               }
+               else
+               {
+                       if(!canvas)
+                               throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
+
+                       add_recent_file(as);
+
+                       handle<Instance> instance(Instance::create(canvas));
+
+                       if(!instance)
+                               throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
+
+                       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();
                }
                }
-               if(!canvas)
-                       throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
-
-               add_recent_file(as);
-               
-               handle<Instance> instance(Instance::create(canvas));
-
-               if(!instance)
-                       throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
-               
-               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)
        {
        }
        catch(String x)
        {
@@ -1959,8 +1974,6 @@ App::open_as(std::string filename,std::string as)
                return false;
        }
 
                return false;
        }
 
-       _preferences.set_value("curr_path",dirname(as));
-       
        return true;
 }
 
        return true;
 }
 
@@ -1969,13 +1982,13 @@ 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("Untitled%d",Instance::get_count()));
+       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("untitled%d.sif",Instance::get_count()));
-       
        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_tl(Vector(-4,2.25));
        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));
@@ -1985,8 +1998,11 @@ App::new_instance()
        canvas->rend_desc().set_antialias(1);
        canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
        canvas->set_file_name(file_name);
        canvas->rend_desc().set_antialias(1);
        canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
        canvas->set_file_name(file_name);
-       
-       Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
+
+       handle<Instance> instance = Instance::create(canvas);
+
+       if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
+               instance->find_canvas_view(canvas)->canvas_properties.present();
 }
 
 void
 }
 
 void
@@ -1994,7 +2010,7 @@ App::dialog_open()
 {
        string filename="*.sif";
 
 {
        string 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
@@ -2058,7 +2074,7 @@ App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
 }
 
 etl::loose_handle<Instance>
 }
 
 etl::loose_handle<Instance>
-App::get_instance(Canvas::Handle canvas)
+App::get_instance(etl::handle<synfig::Canvas> canvas)
 {
        if(!canvas) return 0;
        canvas=canvas->get_root();
 {
        if(!canvas) return 0;
        canvas=canvas->get_root();
@@ -2075,7 +2091,8 @@ App::get_instance(Canvas::Handle canvas)
 void
 App::dialog_about()
 {
 void
 App::dialog_about()
 {
-       (new class About())->show();
+       if(about)
+               about->show();
 }
 
 void
 }
 
 void