Code

* Remove unused variables
[inkscape.git] / src / selection-chemistry.cpp
index d4bc26c5d08a68879f9d9ae2a555ecced6bb3384..1225a66f369dcbef3c0d23e87a79407ff4e2bcfd 100644 (file)
@@ -39,6 +39,9 @@
 #include "sp-flowregion.h"
 #include "text-editing.h"
 #include "text-context.h"
+#include "connector-context.h"
+#include "sp-path.h"
+#include "sp-conn-end.h"
 #include "dropper-context.h"
 #include <glibmm/i18n.h>
 #include "libnr/nr-matrix-rotate-ops.h"
@@ -65,6 +68,8 @@
 #include "layer-fns.h"
 #include "context-fns.h"
 #include <map>
+#include "helper/units.h"
+#include "sp-item.h"
 using NR::X;
 using NR::Y;
 
@@ -208,11 +213,11 @@ void sp_selection_delete()
 
     if (tools_isactive (desktop, TOOLS_TEXT))
         if (sp_text_delete_selection(desktop->event_context)) {
-            sp_document_done(SP_DT_DOCUMENT(desktop));
+            sp_document_done(sp_desktop_document(desktop));
             return;
         }
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -233,7 +238,7 @@ void sp_selection_delete()
      */
     tools_switch ( desktop, tools_active ( desktop ) );
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 /* fixme: sequencing */
@@ -243,7 +248,7 @@ void sp_selection_duplicate()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -271,7 +276,7 @@ void sp_selection_duplicate()
         Inkscape::GC::release(copy);
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 
     selection->setReprList(newsel);
 
@@ -284,8 +289,8 @@ void sp_edit_clear_all()
     if (!dt)
         return;
 
-    SPDocument *doc = SP_DT_DOCUMENT(dt);
-    SP_DT_SELECTION(dt)->clear();
+    SPDocument *doc = sp_desktop_document(dt);
+    sp_desktop_selection(dt)->clear();
 
     g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
     GSList *items = sp_item_group_item_list(SP_GROUP(dt->currentLayer()));
@@ -326,7 +331,7 @@ void sp_edit_select_all_full (bool force_all_layers, bool invert)
     if (!dt)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(dt);
+    Inkscape::Selection *selection = sp_desktop_selection(dt);
 
     g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
 
@@ -412,9 +417,9 @@ void sp_selection_group()
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT (desktop);
+    SPDocument *document = sp_desktop_document (desktop);
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // Check if something is selected.
     if (selection->isEmpty()) {
@@ -496,7 +501,7 @@ void sp_selection_group()
     // Move to the position of the topmost, reduced by the number of items deleted from topmost_parent
     group->setPosition(topmost + 1);
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 
     selection->set(group);
     Inkscape::GC::release(group);
@@ -508,7 +513,7 @@ void sp_selection_ungroup()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select a <b>group</b> to ungroup."));
@@ -557,7 +562,7 @@ void sp_selection_ungroup()
 
     g_slist_free(items);
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 static SPGroup *
@@ -617,7 +622,7 @@ sp_selection_raise()
     if (!desktop)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     GSList const *items = (GSList *) selection->itemList();
     if (!items) {
@@ -658,7 +663,7 @@ sp_selection_raise()
         rev = g_slist_remove(rev, child);
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 void sp_selection_raise_to_top()
@@ -667,8 +672,8 @@ void sp_selection_raise_to_top()
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise to top."));
@@ -703,7 +708,7 @@ sp_selection_lower()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     GSList const *items = (GSList *) selection->itemList();
     if (!items) {
@@ -749,7 +754,7 @@ sp_selection_lower()
         rev = g_slist_remove(rev, child);
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 
 }
 
@@ -759,8 +764,8 @@ void sp_selection_lower_to_bottom()
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom."));
@@ -803,14 +808,14 @@ void sp_selection_lower_to_bottom()
 void
 sp_undo(SPDesktop *desktop, SPDocument *)
 {
-        if (!sp_document_undo(SP_DT_DOCUMENT(desktop)))
+        if (!sp_document_undo(sp_desktop_document(desktop)))
             desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo."));
 }
 
 void
 sp_redo(SPDesktop *desktop, SPDocument *)
 {
-        if (!sp_document_redo(SP_DT_DOCUMENT(desktop)))
+        if (!sp_document_redo(sp_desktop_document(desktop)))
             desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo."));
 }
 
@@ -972,7 +977,7 @@ void sp_selection_copy()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (tools_isactive (desktop, TOOLS_DROPPER)) {
         sp_dropper_context_copy(desktop->event_context);
@@ -1066,13 +1071,13 @@ void sp_selection_paste(bool in_place)
         return;
     }
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
 
     if (Inkscape::have_viable_layer(desktop, desktop->messageStack()) == false) {
         return;
     }
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (tools_isactive (desktop, TOOLS_TEXT)) {
         if (sp_text_paste_inline(desktop->event_context))
@@ -1097,7 +1102,7 @@ void sp_selection_paste(bool in_place)
 
         /* Snap the offset of the new item(s) to the grid */
         /* FIXME: this gridsnap fiddling is a hack. */
-        Inkscape::GridSnapper &s = desktop->namedview->grid_snapper;
+        Inkscape::GridSnapper &s = desktop->namedview->snap_manager.grid;
         gdouble const curr_gridsnap = s.getDistance();
         s.setDistance(NR_HUGE);
         m = s.freeSnap(Inkscape::Snapper::SNAP_POINT, m, NULL).getPoint();
@@ -1113,7 +1118,7 @@ void sp_selection_paste_style()
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
     if (desktop == NULL) return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is in the clipboard
     if (clipboard == NULL) {
@@ -1127,11 +1132,11 @@ void sp_selection_paste_style()
         return;
     }
 
-    paste_defs (&defs_clipboard, SP_DT_DOCUMENT(desktop));
+    paste_defs (&defs_clipboard, sp_desktop_document(desktop));
 
     sp_desktop_set_style (desktop, style_clipboard);
 
-    sp_document_done(SP_DT_DOCUMENT (desktop));
+    sp_document_done(sp_desktop_document (desktop));
 }
 
 void sp_selection_paste_size (bool apply_x, bool apply_y)
@@ -1139,7 +1144,7 @@ void sp_selection_paste_size (bool apply_x, bool apply_y)
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
     if (desktop == NULL) return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is in the clipboard
     if (size_clipboard.extent(NR::X) < 1e-6 || size_clipboard.extent(NR::Y) < 1e-6) {
@@ -1166,7 +1171,7 @@ void sp_selection_paste_size (bool apply_x, bool apply_y)
                                      apply_x? scale_x : (desktop->isToolboxButtonActive ("lock")? scale_y : 1.0),
                                      apply_y? scale_y : (desktop->isToolboxButtonActive ("lock")? scale_x : 1.0)));
 
-    sp_document_done(SP_DT_DOCUMENT (desktop));
+    sp_document_done(sp_desktop_document (desktop));
 }
 
 void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
@@ -1174,7 +1179,7 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
     if (desktop == NULL) return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is in the clipboard
     if (size_clipboard.extent(NR::X) < 1e-6 || size_clipboard.extent(NR::Y) < 1e-6) {
@@ -1206,14 +1211,14 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
 
     }
 
-    sp_document_done(SP_DT_DOCUMENT (desktop));
+    sp_document_done(sp_desktop_document (desktop));
 }
 
 void sp_selection_to_next_layer ()
 {
     SPDesktop *dt = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(dt);
+    Inkscape::Selection *selection = sp_desktop_selection(dt);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -1223,18 +1228,30 @@ void sp_selection_to_next_layer ()
 
     const GSList *items = g_slist_copy ((GSList *) selection->itemList());
 
+    bool no_more = false; // Set to true, if no more layers above
     SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer());
     if (next) {
         GSList *temp_clip = NULL;
         sp_selection_copy_impl (items, &temp_clip, NULL, NULL); // we're in the same doc, so no need to copy defs
         sp_selection_delete_impl (items);
-        GSList *copied = sp_selection_paste_impl (SP_DT_DOCUMENT (dt), next, &temp_clip, NULL);
+        next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
+        GSList *copied;
+        if(next) {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        } else {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), dt->currentLayer(), &temp_clip, NULL);
+            no_more = true;
+        }
         selection->setReprList((GSList const *) copied);
         g_slist_free (copied);
         if (temp_clip) g_slist_free (temp_clip);
-        dt->setCurrentLayer(next);
-        sp_document_done(SP_DT_DOCUMENT (dt));
+        if (next) dt->setCurrentLayer(next);
+        sp_document_done(sp_desktop_document (dt));
     } else {
+        no_more = true;
+    }
+
+    if (no_more) {
         dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers above."));
     }
 
@@ -1245,7 +1262,7 @@ void sp_selection_to_prev_layer ()
 {
     SPDesktop *dt = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(dt);
+    Inkscape::Selection *selection = sp_desktop_selection(dt);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -1255,18 +1272,30 @@ void sp_selection_to_prev_layer ()
 
     const GSList *items = g_slist_copy ((GSList *) selection->itemList());
 
+    bool no_more = false; // Set to true, if no more layers below
     SPObject *next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer());
     if (next) {
         GSList *temp_clip = NULL;
         sp_selection_copy_impl (items, &temp_clip, NULL, NULL); // we're in the same doc, so no need to copy defs
         sp_selection_delete_impl (items);
-        GSList *copied = sp_selection_paste_impl (SP_DT_DOCUMENT (dt), next, &temp_clip, NULL);
+        next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
+        GSList *copied;
+        if(next) {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        } else {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), dt->currentLayer(), &temp_clip, NULL);
+            no_more = true;
+        }
         selection->setReprList((GSList const *) copied);
         g_slist_free (copied);
         if (temp_clip) g_slist_free (temp_clip);
-        dt->setCurrentLayer(next);
-        sp_document_done(SP_DT_DOCUMENT (dt));
+        if (next) dt->setCurrentLayer(next);
+        sp_document_done(sp_desktop_document (dt));
     } else {
+        no_more = true;
+    }
+
+    if (no_more) {
         dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers below."));
     }
 
@@ -1301,7 +1330,21 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, NR::Matrix const
         bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item (SP_TEXTPATH(sp_object_first_child(SP_OBJECT(item)))) ));
         bool transform_flowtext_with_frame = (SP_IS_FLOWTEXT(item) && selection->includes( SP_FLOWTEXT(item)->get_frame (NULL))); // only the first frame so far
         bool transform_offset_with_source = (SP_IS_OFFSET(item) && SP_OFFSET (item)->sourceHref) && selection->includes( sp_offset_get_source (SP_OFFSET(item)) );
-
+       
+        // If we're moving a connector, we want to detach it
+        // from shapes that aren't part of the selection, but
+        // leave it attached if they are
+        if (cc_item_is_connector(item)) {
+            SPItem *attItem[2];
+            SP_PATH(item)->connEndPair.getAttachedItems(attItem);
+            
+            for (int n = 0; n < 2; ++n) {
+                if (!selection->includes(attItem[n])) {
+                    sp_conn_end_detach(item, n);
+                }
+            }
+        }
+        
         // "clones are unmoved when original is moved" preference
         int compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
         bool prefs_unmoved = (compensation == SP_CLONE_COMPENSATION_UNMOVED);
@@ -1386,7 +1429,7 @@ void sp_selection_remove_transform()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     GSList const *l = (GSList *) selection->reprList();
     while (l != NULL) {
@@ -1394,7 +1437,7 @@ void sp_selection_remove_transform()
         l = l->next;
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 void
@@ -1490,7 +1533,7 @@ void sp_selection_rotate_90_cw()
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty())
         return;
@@ -1502,7 +1545,7 @@ void sp_selection_rotate_90_cw()
         sp_item_rotate_rel(item, rot_neg_90);
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 
@@ -1517,7 +1560,7 @@ void sp_selection_rotate_90_ccw()
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty())
         return;
@@ -1529,7 +1572,7 @@ void sp_selection_rotate_90_ccw()
         sp_item_rotate_rel(item, rot_neg_90);
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 void
@@ -1542,7 +1585,7 @@ sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees)
 
     sp_selection_rotate_relative(selection, center, angle_degrees);
 
-    sp_document_maybe_done(SP_DT_DOCUMENT(selection->desktop()),
+    sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( ( angle_degrees > 0 )
                              ? "selector:rotate:ccw"
                              : "selector:rotate:cw" ));
@@ -1569,7 +1612,7 @@ sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle)
 
     sp_selection_rotate_relative(selection, center, zangle);
 
-    sp_document_maybe_done(SP_DT_DOCUMENT(selection->desktop()),
+    sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( (angle > 0)
                              ? "selector:rotate:ccw"
                              : "selector:rotate:cw" ));
@@ -1593,7 +1636,7 @@ sp_selection_scale(Inkscape::Selection *selection, gdouble grow)
     double const times = 1.0 + grow / max_len;
     sp_selection_scale_relative(selection, center, NR::scale(times, times));
 
-    sp_document_maybe_done(SP_DT_DOCUMENT(selection->desktop()),
+    sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( (grow > 0)
                              ? "selector:scale:larger"
                              : "selector:scale:smaller" ));
@@ -1614,14 +1657,14 @@ sp_selection_scale_times(Inkscape::Selection *selection, gdouble times)
 
     NR::Point const center(selection->bounds().midpoint());
     sp_selection_scale_relative(selection, center, NR::scale(times, times));
-    sp_document_done(SP_DT_DOCUMENT(selection->desktop()));
+    sp_document_done(sp_desktop_document(selection->desktop()));
 }
 
 void
 sp_selection_move(gdouble dx, gdouble dy)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
     if (selection->isEmpty()) {
         return;
     }
@@ -1629,11 +1672,11 @@ sp_selection_move(gdouble dx, gdouble dy)
     sp_selection_move_relative(selection, dx, dy);
 
     if (dx == 0) {
-        sp_document_maybe_done(SP_DT_DOCUMENT(desktop), "selector:move:vertical");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical");
     } else if (dy == 0) {
-        sp_document_maybe_done(SP_DT_DOCUMENT(desktop), "selector:move:horizontal");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal");
     } else {
-        sp_document_done(SP_DT_DOCUMENT(desktop));
+        sp_document_done(sp_desktop_document(desktop));
     }
 }
 
@@ -1642,7 +1685,7 @@ sp_selection_move_screen(gdouble dx, gdouble dy)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
     if (selection->isEmpty()) {
         return;
     }
@@ -1654,11 +1697,11 @@ sp_selection_move_screen(gdouble dx, gdouble dy)
     sp_selection_move_relative(selection, zdx, zdy);
 
     if (dx == 0) {
-        sp_document_maybe_done(SP_DT_DOCUMENT(desktop), "selector:move:vertical");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical");
     } else if (dy == 0) {
-        sp_document_maybe_done(SP_DT_DOCUMENT(desktop), "selector:move:horizontal");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal");
     } else {
-        sp_document_done(SP_DT_DOCUMENT(desktop));
+        sp_document_done(sp_desktop_document(desktop));
     }
 }
 
@@ -1719,7 +1762,7 @@ sp_selection_item_next(void)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
     g_return_if_fail(desktop != NULL);
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs_get_int_attribute ("options.kbselection", "inlayer", PREFS_SELECTION_LAYER);
     bool onlyvisible = prefs_get_int_attribute ("options.kbselection", "onlyvisible", 1);
@@ -1749,7 +1792,7 @@ sp_selection_item_prev(void)
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
     g_return_if_fail(document != NULL);
     g_return_if_fail(desktop != NULL);
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs_get_int_attribute ("options.kbselection", "inlayer", PREFS_SELECTION_LAYER);
     bool onlyvisible = prefs_get_int_attribute ("options.kbselection", "onlyvisible", 1);
@@ -1881,7 +1924,7 @@ sp_selection_clone()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -1918,7 +1961,7 @@ sp_selection_clone()
         Inkscape::GC::release(clone);
     }
     
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 
     selection->setReprList(newsel);
  
@@ -1932,7 +1975,7 @@ sp_selection_unlink()
     if (!desktop)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select a <b>clone</b> to unlink."));
@@ -1969,7 +2012,7 @@ sp_selection_unlink()
         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection."));
     }
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop));
 }
 
 void
@@ -1979,7 +2022,7 @@ sp_select_clone_original()
     if (desktop == NULL)
         return;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     SPItem *item = selection->singleItem();
 
@@ -2033,9 +2076,9 @@ sp_selection_tile(bool apply)
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -2104,7 +2147,7 @@ sp_selection_tile(bool apply)
         // restore parent and position
         SP_OBJECT_REPR (parent)->appendChild(rect);
         rect->setPosition(pos > 0 ? pos : 0);
-        SPItem *rectangle = (SPItem *) SP_DT_DOCUMENT (desktop)->getObjectByRepr(rect);
+        SPItem *rectangle = (SPItem *) sp_desktop_document (desktop)->getObjectByRepr(rect);
 
         Inkscape::GC::release(rect);
 
@@ -2124,9 +2167,9 @@ sp_selection_untile()
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -2185,7 +2228,7 @@ sp_selection_untile()
     if (!did) {
         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No pattern fills</b> in the selection."));
     } else {
-        sp_document_done(SP_DT_DOCUMENT(desktop));
+        sp_document_done(sp_desktop_document(desktop));
         selection->setList(new_select);
     }
 }
@@ -2197,9 +2240,9 @@ sp_selection_create_bitmap_copy ()
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
@@ -2359,17 +2402,17 @@ sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer)
     if (desktop == NULL)
         return;
 
-    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    SPDocument *document = sp_desktop_document(desktop);
     
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     bool is_empty = selection->isEmpty();
     if ( apply_to_layer && is_empty) {
-        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create mask from."));
+        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from."));
         return;
     } else if (!apply_to_layer && ( is_empty || NULL == selection->itemList()->next )) {
-        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select mask object and <b>object(s)</b> to apply mask to."));
+        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select mask object and <b>object(s)</b> to apply clippath or mask to."));
         return;
     }
     
@@ -2467,12 +2510,12 @@ void sp_selection_unset_mask(bool apply_clip_path) {
     if (desktop == NULL)
         return;
     
-    SPDocument *document = SP_DT_DOCUMENT(desktop);    
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    SPDocument *document = sp_desktop_document(desktop);    
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is selected
     if (selection->isEmpty()) {
-        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove mask from."));
+        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove clippath or mask from."));
         return;
     }
     
@@ -2516,14 +2559,24 @@ void sp_selection_unset_mask(bool apply_clip_path) {
             obj->deleteObject(false);
         }
 
+        // remember parent and position of the item to which the clippath/mask was applied
+        Inkscape::XML::Node *parent = SP_OBJECT_REPR((*it).second)->parent();
+        gint pos = SP_OBJECT_REPR((*it).second)->position();
+
         for (GSList *i = items_to_move; NULL != i; i = i->next) {
-            SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr((Inkscape::XML::Node *)i->data));
-            selection->add((Inkscape::XML::Node *)i->data);
+            Inkscape::XML::Node *repr = (Inkscape::XML::Node *)i->data;
 
-            // transform mask, so it is moved the same spot there mask was applied
-            NR::Matrix transform (item->transform);
+            // insert into parent, restore pos
+            parent->appendChild(repr);
+            repr->setPosition((pos + 1) > 0 ? (pos + 1) : 0);
+
+            SPItem *mask_item = (SPItem *) sp_desktop_document (desktop)->getObjectByRepr(repr);
+            selection->add(repr);
+
+            // transform mask, so it is moved the same spot where mask was applied
+            NR::Matrix transform (mask_item->transform);
             transform *= (*it).second->transform;
-            sp_item_write_transform(item, SP_OBJECT_REPR(item), transform);
+            sp_item_write_transform(mask_item, SP_OBJECT_REPR(mask_item), transform);
         }
 
         g_slist_free (items_to_move);
@@ -2532,6 +2585,49 @@ void sp_selection_unset_mask(bool apply_clip_path) {
     sp_document_done (document);
 }
 
+void fit_canvas_to_selection(SPDesktop *desktop) {
+    g_return_if_fail(desktop != NULL);
+    SPDocument *doc = sp_desktop_document(desktop);
+
+    g_return_if_fail(doc != NULL);
+    g_return_if_fail(desktop->selection != NULL);
+    g_return_if_fail(!desktop->selection->isEmpty());
+    NRRect bbox = {0,0,0,0};
+
+    desktop->selection->bounds(&bbox);
+    if (!empty(bbox)) {
+        doc->fitToRect(bbox);
+    }
+};
+
+void fit_canvas_to_drawing(SPDocument *doc) {
+    g_return_if_fail(doc != NULL);
+    NRRect bbox = {0,0,0,0};
+
+    sp_document_ensure_up_to_date (doc);
+    sp_item_invoke_bbox(SP_ITEM(doc->root), &bbox, sp_item_i2r_affine(SP_ITEM(doc->root)), TRUE);
+
+    if (!empty(bbox)) {
+        doc->fitToRect(bbox);
+    }
+};
+
+void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
+    g_return_if_fail(desktop != NULL);
+    SPDocument *doc = sp_desktop_document(desktop);
+
+    g_return_if_fail(doc != NULL);
+    g_return_if_fail(desktop->selection != NULL);
+
+    if (desktop->selection->isEmpty()) {
+        fit_canvas_to_drawing(doc);
+    } else {
+        fit_canvas_to_selection(desktop);
+    }
+
+    sp_document_done(doc);
+};
+
 /*
   Local Variables:
   mode:c++