replace unicode dash with (monospace) minus.
[ardour.git] / gtk2_ardour / editor.cc
index b85d28beb5f8c1ca966e1e7f7b61a804657a8fa3..1c9c613e4b72ffdafef6660ff62bd3cbf2a6cfb5 100644 (file)
@@ -44,6 +44,7 @@
 #include "pbd/memento_command.h"
 #include "pbd/unknown_type.h"
 #include "pbd/unwind.h"
+#include "pbd/stacktrace.h"
 
 #include <glibmm/miscutils.h>
 #include <gtkmm/image.h>
@@ -80,7 +81,6 @@
 #include "audio_time_axis.h"
 #include "automation_time_axis.h"
 #include "bundle_manager.h"
-#include "button_joiner.h"
 #include "canvas-noevent-text.h"
 #include "canvas_impl.h"
 #include "crossfade_edit.h"
@@ -208,12 +208,6 @@ static const gchar *_rb_opt_strings[] = {
 };
 #endif
 
-void
-show_me_the_size (Requisition* r, const char* what)
-{
-       cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
-}
-
 static void
 pane_size_watcher (Paned* pane)
 {
@@ -390,67 +384,67 @@ Editor::Editor ()
        set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
 
-       bbt_label.set_name ("EditorTimeButton");
+       bbt_label.set_name ("EditorRulerLabel");
        bbt_label.set_size_request (-1, (int)timebar_height);
        bbt_label.set_alignment (1.0, 0.5);
        bbt_label.set_padding (5,0);
        bbt_label.hide ();
        bbt_label.set_no_show_all();
-       minsec_label.set_name ("EditorTimeButton");
+       minsec_label.set_name ("EditorRulerLabel");
        minsec_label.set_size_request (-1, (int)timebar_height);
        minsec_label.set_alignment (1.0, 0.5);
        minsec_label.set_padding (5,0);
        minsec_label.hide ();
        minsec_label.set_no_show_all();
-       timecode_label.set_name ("EditorTimeButton");
+       timecode_label.set_name ("EditorRulerLabel");
        timecode_label.set_size_request (-1, (int)timebar_height);
        timecode_label.set_alignment (1.0, 0.5);
        timecode_label.set_padding (5,0);
        timecode_label.hide ();
        timecode_label.set_no_show_all();
-       samples_label.set_name ("EditorTimeButton");
+       samples_label.set_name ("EditorRulerLabel");
        samples_label.set_size_request (-1, (int)timebar_height);
        samples_label.set_alignment (1.0, 0.5);
        samples_label.set_padding (5,0);
        samples_label.hide ();
        samples_label.set_no_show_all();
 
-       tempo_label.set_name ("EditorTimeButton");
+       tempo_label.set_name ("EditorRulerLabel");
        tempo_label.set_size_request (-1, (int)timebar_height);
        tempo_label.set_alignment (1.0, 0.5);
        tempo_label.set_padding (5,0);
        tempo_label.hide();
        tempo_label.set_no_show_all();
 
-       meter_label.set_name ("EditorTimeButton");
+       meter_label.set_name ("EditorRulerLabel");
        meter_label.set_size_request (-1, (int)timebar_height);
        meter_label.set_alignment (1.0, 0.5);
        meter_label.set_padding (5,0);
        meter_label.hide();
        meter_label.set_no_show_all();
 
-       mark_label.set_name ("EditorTimeButton");
+       mark_label.set_name ("EditorRulerLabel");
        mark_label.set_size_request (-1, (int)timebar_height);
        mark_label.set_alignment (1.0, 0.5);
        mark_label.set_padding (5,0);
        mark_label.hide();
        mark_label.set_no_show_all();
 
-       cd_mark_label.set_name ("EditorTimeButton");
+       cd_mark_label.set_name ("EditorRulerLabel");
        cd_mark_label.set_size_request (-1, (int)timebar_height);
        cd_mark_label.set_alignment (1.0, 0.5);
        cd_mark_label.set_padding (5,0);
        cd_mark_label.hide();
        cd_mark_label.set_no_show_all();
 
-       range_mark_label.set_name ("EditorTimeButton");
+       range_mark_label.set_name ("EditorRulerLabel");
        range_mark_label.set_size_request (-1, (int)timebar_height);
        range_mark_label.set_alignment (1.0, 0.5);
        range_mark_label.set_padding (5,0);
        range_mark_label.hide();
        range_mark_label.set_no_show_all();
 
-       transport_mark_label.set_name ("EditorTimeButton");
+       transport_mark_label.set_name ("EditorRulerLabel");
        transport_mark_label.set_size_request (-1, (int)timebar_height);
        transport_mark_label.set_alignment (1.0, 0.5);
        transport_mark_label.set_padding (5,0);
@@ -659,11 +653,13 @@ Editor::Editor ()
 
        /* nudge stuff */
 
-       nudge_forward_button.add (*(manage (new Image (::get_icon("nudge_right")))));
-       nudge_backward_button.add (*(manage (new Image (::get_icon("nudge_left")))));
+       nudge_forward_button.set_name ("zoom button");
+       nudge_forward_button.add_elements (ArdourButton::FlatFace);
+       nudge_forward_button.set_image(::get_icon("nudge_right"));
 
-       nudge_forward_button.set_name ("TransportButton");
-       nudge_backward_button.set_name ("TransportButton");
+       nudge_backward_button.set_name ("zoom button");
+       nudge_backward_button.add_elements (ArdourButton::FlatFace);
+       nudge_backward_button.set_image(::get_icon("nudge_left"));
 
        fade_context_menu.set_name ("ArdourContextMenu");
 
@@ -800,6 +796,12 @@ Editor::add_toplevel_controls (Container& cont)
        cont.show_all ();
 }
 
+bool
+Editor::get_smart_mode () const
+{
+       return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() );
+}
+
 void
 Editor::catch_vanishing_regionview (RegionView *rv)
 {
@@ -1178,6 +1180,8 @@ Editor::update_title ()
                WindowTitle title(session_name);
                title += Glib::get_application_name();
                set_title (title.get_string());
+       } else {
+               /* ::session_going_away() will have taken care of it */
        }
 }
 
@@ -1366,7 +1370,7 @@ Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
        
        items.push_back (
                ImageMenuElem (
-                       _("ConstantPower"),
+                       _("Constant power"),
                        *(*images)[FadeConstantPower],
                        sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
                        ));
@@ -1404,7 +1408,7 @@ Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
 
 /** Pop up a context menu for when the user clicks on a start crossfade */
 void
-Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
+Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
 {
        using namespace Menu_Helpers;
 
@@ -1419,7 +1423,7 @@ Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Ite
 
 /** Pop up a context menu for when the user clicks on an end crossfade */
 void
-Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
+Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
 {
        using namespace Menu_Helpers;
 
@@ -1503,7 +1507,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
                                
                        items.push_back (
                                ImageMenuElem (
-                                       _("Constant Power"),
+                                       _("Constant power"),
                                        *_fade_in_images[FadeConstantPower],
                                        sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeConstantPower)
                                        ));
@@ -1565,7 +1569,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
 
                        items.push_back (
                                ImageMenuElem (
-                                       _("Constant Power"),
+                                       _("Constant power"),
                                        *_fade_out_images[FadeConstantPower],
                                        sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeConstantPower)
                                        ));
@@ -2106,10 +2110,17 @@ Editor::set_snap_to (SnapType st)
        case SnapToBeatDiv5:
        case SnapToBeatDiv4:
        case SnapToBeatDiv3:
-       case SnapToBeatDiv2:
-               compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_frames());
-               update_tempo_based_rulers ();
+       case SnapToBeatDiv2: {
+               ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
+               ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
+               
+               compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_frames(),
+                                           current_bbt_points_begin, current_bbt_points_end);
+               compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_frames(),
+                                        current_bbt_points_begin, current_bbt_points_end);
+               update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
                break;
+       }
 
        case SnapToRegionStart:
        case SnapToRegionEnd:
@@ -2129,9 +2140,16 @@ Editor::set_snap_to (SnapType st)
 void
 Editor::set_snap_mode (SnapMode mode)
 {
-       _snap_mode = mode;
        string str = snap_mode_strings[(int)mode];
 
+       if (_internal_editing) {
+               internal_snap_mode = mode;
+       } else {
+               pre_internal_snap_mode = mode;
+       }
+
+       _snap_mode = mode;
+
        if (str != snap_mode_selector.get_active_text ()) {
                snap_mode_selector.set_active_text (str);
        }
@@ -2279,6 +2297,7 @@ Editor::set_state (const XMLNode& node, int /*version*/)
                pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
        }
 
+
        if ((prop = node.property ("pre-internal-snap-mode"))) {
                pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
        }
@@ -2315,7 +2334,14 @@ Editor::set_state (const XMLNode& node, int /*version*/)
        }
 
        if ((prop = node.property ("join-object-range"))) {
-               ActionManager::set_toggle_action ("MouseMode", "set-mouse-mode-object-range", string_is_affirmative (prop->value ()));
+               RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
+               bool yn = string_is_affirmative (prop->value());
+               if (act) {
+                       RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+                       tact->set_active (!yn);
+                       tact->set_active (yn);
+               }
+               set_mouse_mode(mouse_mode, true);
        }
 
        if ((prop = node.property ("edit-point"))) {
@@ -2743,7 +2769,10 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
 
                _session->locations()->marks_either_side (start, before, after);
 
-               if (before == max_framepos) {
+               if (before == max_framepos && after == max_framepos) {
+                       /* No marks to snap to, so just don't snap */
+                       return;
+               } else if (before == max_framepos) {
                        start = after;
                } else if (after == max_framepos) {
                        start = before;
@@ -2823,14 +2852,12 @@ Editor::setup_toolbar ()
        mode_box->set_spacing(4);
 
        HBox* mouse_mode_box = manage (new HBox);
-       HBox* mouse_mode_hbox1 = manage (new HBox);
-       HBox* mouse_mode_hbox2 = manage (new HBox);
-       VBox* mouse_mode_vbox1 = manage (new VBox);
-       VBox* mouse_mode_vbox2 = manage (new VBox);
-       Alignment* mouse_mode_align1 = manage (new Alignment);
-       Alignment* mouse_mode_align2 = manage (new Alignment);
+       HBox* mouse_mode_hbox = manage (new HBox);
+       VBox* mouse_mode_vbox = manage (new VBox);
+       Alignment* mouse_mode_align = manage (new Alignment);
 
        Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
+//     mouse_mode_size_group->add_widget (smart_mode_button);
        mouse_mode_size_group->add_widget (mouse_move_button);
        mouse_mode_size_group->add_widget (mouse_select_button);
        mouse_mode_size_group->add_widget (mouse_zoom_button);
@@ -2841,32 +2868,26 @@ Editor::setup_toolbar ()
        mouse_mode_size_group->add_widget (internal_edit_button);
 
        /* make them just a bit bigger */
-       mouse_move_button.set_size_request (-1, 25);
-
-       smart_mode_joiner = manage (new ButtonJoiner ("mouse mode button", mouse_move_button, mouse_select_button, true));
-       smart_mode_joiner->set_related_action (smart_mode_action);
+       mouse_move_button.set_size_request (-1, 30);
 
-       mouse_mode_hbox2->set_spacing (2);
-       mouse_mode_box->set_spacing (2);
+       mouse_mode_hbox->set_spacing (2);
 
-       mouse_mode_hbox1->pack_start (*smart_mode_joiner, false, false);
-       mouse_mode_hbox2->pack_start (mouse_zoom_button, false, false);
-       mouse_mode_hbox2->pack_start (mouse_gain_button, false, false);
-       mouse_mode_hbox2->pack_start (mouse_timefx_button, false, false);
-       mouse_mode_hbox2->pack_start (mouse_audition_button, false, false);
-       mouse_mode_hbox2->pack_start (mouse_draw_button, false, false);
-       mouse_mode_hbox2->pack_start (internal_edit_button, false, false);
+       mouse_mode_hbox->pack_start (smart_mode_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_move_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_select_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
+       mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
 
-       mouse_mode_vbox1->pack_start (*mouse_mode_hbox1, false, false);
-       mouse_mode_vbox2->pack_start (*mouse_mode_hbox2, false, false);
+       mouse_mode_vbox->pack_start (*mouse_mode_hbox);
 
-       mouse_mode_align1->add (*mouse_mode_vbox1);
-       mouse_mode_align1->set (0.5, 1.0, 0.0, 0.0);
-       mouse_mode_align2->add (*mouse_mode_vbox2);
-       mouse_mode_align2->set (0.5, 1.0, 0.0, 0.0);
+       mouse_mode_align->add (*mouse_mode_vbox);
+       mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
 
-       mouse_mode_box->pack_start (*mouse_mode_align1, false, false);
-       mouse_mode_box->pack_start (*mouse_mode_align2, false, false);
+       mouse_mode_box->pack_start (*mouse_mode_align, false, false);
 
        edit_mode_strings.push_back (edit_mode_to_string (Slide));
        if (!Profile->get_sae()) {
@@ -2906,20 +2927,23 @@ Editor::setup_toolbar ()
        RefPtr<Action> act;
 
        zoom_in_button.set_name ("zoom button");
-       zoom_in_button.set_image (::get_icon ("zoom_in"));
-       zoom_in_button.set_tweaks (ArdourButton::ShowClick);
+       zoom_in_button.add_elements ( ArdourButton::FlatFace );
+       zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
+       zoom_in_button.set_image(::get_icon ("zoom_in"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
        zoom_in_button.set_related_action (act);
 
        zoom_out_button.set_name ("zoom button");
-       zoom_out_button.set_image (::get_icon ("zoom_out"));
-       zoom_out_button.set_tweaks (ArdourButton::ShowClick);
+       zoom_out_button.add_elements ( ArdourButton::FlatFace );
+       zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
+       zoom_out_button.set_image(::get_icon ("zoom_out"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
        zoom_out_button.set_related_action (act);
 
        zoom_out_full_button.set_name ("zoom button");
-       zoom_out_full_button.set_image (::get_icon ("zoom_full"));
-       zoom_out_full_button.set_tweaks (ArdourButton::ShowClick);
+       zoom_out_full_button.add_elements ( ArdourButton::FlatFace );
+       zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
+       zoom_out_full_button.set_image(::get_icon ("zoom_full"));
        act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
        zoom_out_full_button.set_related_action (act);
 
@@ -2934,17 +2958,21 @@ Editor::setup_toolbar ()
        _zoom_box.pack_start (zoom_focus_selector, false, false);
 
        /* Track zoom buttons */
-       tav_expand_button.set_name ("TrackHeightButton");
+       tav_expand_button.set_name ("zoom button");
+       tav_expand_button.add_elements ( ArdourButton::FlatFace );
+       tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        tav_expand_button.set_size_request (-1, 20);
-       tav_expand_button.add (*(manage (new Image (::get_icon ("tav_exp")))));
+       tav_expand_button.set_image(::get_icon ("tav_exp"));
        act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
-       act->connect_proxy (tav_expand_button);
+       tav_expand_button.set_related_action (act);
 
-       tav_shrink_button.set_name ("TrackHeightButton");
+       tav_shrink_button.set_name ("zoom button");
+       tav_shrink_button.add_elements ( ArdourButton::FlatFace );
+       tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        tav_shrink_button.set_size_request (-1, 20);
-       tav_shrink_button.add (*(manage (new Image (::get_icon ("tav_shrink")))));
+       tav_shrink_button.set_image(::get_icon ("tav_shrink"));
        act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
-       act->connect_proxy (tav_shrink_button);
+       tav_shrink_button.set_related_action (act);
 
        _zoom_box.pack_start (tav_shrink_button);
        _zoom_box.pack_start (tav_expand_button);
@@ -2960,7 +2988,7 @@ Editor::setup_toolbar ()
        _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                                    &_zoom_tearoff->tearoff_window(), 0));
 
-       snap_box.set_spacing (1);
+       snap_box.set_spacing (2);
        snap_box.set_border_width (2);
 
        snap_type_selector.set_name ("SnapTypeSelector");
@@ -2988,6 +3016,9 @@ Editor::setup_toolbar ()
        nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
        nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
 
+       nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
+       nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
+
        nudge_box->pack_start (nudge_backward_button, false, false);
        nudge_box->pack_start (nudge_forward_button, false, false);
        nudge_box->pack_start (*nudge_clock, false, false);
@@ -3047,15 +3078,15 @@ Editor::setup_toolbar ()
 void
 Editor::setup_tooltips ()
 {
-       ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Select/Move Objects"));
-       ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Select/Move Ranges"));
+       ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
+       ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
+       ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
        ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
        ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
        ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
        ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
        ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
-       ARDOUR_UI::instance()->set_tip (smart_mode_joiner, _("Smart Mode (Select/Move Objects + Ranges)"));
-       ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Edit Region Contents (e.g. notes)"));
+       ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
        ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
        ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
        ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
@@ -3109,8 +3140,8 @@ Editor::convert_drop_to_paths (
                const char* q;
 
                p = (const char *) malloc (txt.length() + 1);
-               txt.copy ((char *) p, txt.length(), 0);
-               ((char*)p)[txt.length()] = '\0';
+               txt.copy (const_cast<char *> (p), txt.length(), 0);
+               const_cast<char*>(p)[txt.length()] = '\0';
 
                while (p)
                {
@@ -3191,7 +3222,7 @@ Editor::new_tempo_section ()
 void
 Editor::map_transport_state ()
 {
-       ENSURE_GUI_THREAD (*this, &Editor::map_transport_state)
+       ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
 
        if (_session && _session->transport_stopped()) {
                have_pending_keyboard_selection = false;
@@ -3255,15 +3286,9 @@ Editor::duplicate_range (bool with_dialog)
 {
        float times = 1.0f;
 
-       if (mouse_mode == MouseRange) {
-               if (selection->time.length() == 0) {
-                       return;
-               }
-       }
-
        RegionSelection rs = get_regions_from_selection_and_entered ();
 
-       if (mouse_mode != MouseRange && rs.empty()) {
+       if ( selection->time.length() == 0 && rs.empty()) {
                return;
        }
 
@@ -3310,8 +3335,15 @@ Editor::duplicate_range (bool with_dialog)
                times = adjustment.get_value();
        }
 
-       if (mouse_mode == MouseRange) {
-               duplicate_selection (times);
+       if ((current_mouse_mode() == Editing::MouseRange)) {
+               if (selection->time.length()) {
+                       duplicate_selection (times);
+               }
+       } else if (get_smart_mode()) {
+               if (selection->time.length()) {
+                       duplicate_selection (times);
+               } else 
+                       duplicate_some_regions (rs, times);
        } else {
                duplicate_some_regions (rs, times);
        }
@@ -3555,6 +3587,31 @@ Editor::set_zoom_focus (ZoomFocus f)
        }
 }
 
+void
+Editor::cycle_zoom_focus ()
+{
+       switch (zoom_focus) {
+       case ZoomFocusLeft:
+               set_zoom_focus (ZoomFocusRight);
+               break;
+       case ZoomFocusRight:
+               set_zoom_focus (ZoomFocusCenter);
+               break;
+       case ZoomFocusCenter:
+               set_zoom_focus (ZoomFocusPlayhead);
+               break;
+       case ZoomFocusPlayhead:
+               set_zoom_focus (ZoomFocusMouse);
+               break;
+       case ZoomFocusMouse:
+               set_zoom_focus (ZoomFocusEdit);
+               break;
+       case ZoomFocusEdit:
+               set_zoom_focus (ZoomFocusLeft);
+               break;
+       }
+}
+
 void
 Editor::ensure_float (Window& win)
 {
@@ -3654,9 +3711,10 @@ Editor::set_show_measures (bool yn)
                hide_measures ();
 
                if ((_show_measures = yn) == true) {
-                       if (tempo_lines)
+                       if (tempo_lines) {
                                tempo_lines->show();
-                       draw_measures ();
+                       }
+                       (void) redraw_measures ();
                }
                instant_save ();
        }
@@ -3976,7 +4034,7 @@ Editor::new_playlists (TimeAxisView* v)
        begin_reversible_command (_("new playlists"));
        vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
        _session->playlists->get (playlists);
-       mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::edit.property_id);
+       mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
        commit_reversible_command ();
 }
 
@@ -3992,7 +4050,7 @@ Editor::copy_playlists (TimeAxisView* v)
        begin_reversible_command (_("copy playlists"));
        vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
        _session->playlists->get (playlists);
-       mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::edit.property_id);
+       mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
        commit_reversible_command ();
 }
 
@@ -4007,7 +4065,7 @@ Editor::clear_playlists (TimeAxisView* v)
        begin_reversible_command (_("clear playlists"));
        vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
        _session->playlists->get (playlists);
-       mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::edit.property_id);
+       mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
        commit_reversible_command ();
 }
 
@@ -4198,9 +4256,7 @@ Editor::set_frames_per_unit (double fpu)
                zoom_range_clock->set (frames);
        }
 
-       bool const showing_time_selection =
-               mouse_mode == MouseRange ||
-               (mouse_mode == MouseObject && _join_object_range_state != JOIN_OBJECT_RANGE_NONE);
+       bool const showing_time_selection = selection->time.length() > 0;
 
        if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
                for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
@@ -4250,6 +4306,7 @@ Editor::idle_visual_changer ()
           super-rapid-screen-update can be dropped if we are still processing
           the last one.
        */
+
        pending_visual_change.idle_handler_id = -1;
        pending_visual_change.being_handled = true;
        
@@ -4262,9 +4319,15 @@ Editor::idle_visual_changer ()
                set_frames_per_unit (pending_visual_change.frames_per_unit);
 
                compute_fixed_ruler_scale ();
-               compute_current_bbt_points(pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames());
-               compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames());
-               update_tempo_based_rulers ();
+
+               ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
+               ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
+               
+               compute_current_bbt_points (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames(),
+                                           current_bbt_points_begin, current_bbt_points_end);
+               compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames(),
+                                        current_bbt_points_begin, current_bbt_points_end);
+               update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
        }
        if (p & VisualChange::TimeOrigin) {
                set_horizontal_position (pending_visual_change.time_origin / frames_per_unit);
@@ -4391,7 +4454,7 @@ Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
        Location* tpl;
 
        if ((tpl = transport_punch_location()) == 0) {
-               Location* loc = new Location (*_session, start, end, _("Loop"),  Location::IsAutoPunch);
+               Location* loc = new Location (*_session, start, end, _("Punch"),  Location::IsAutoPunch);
                XMLNode &before = _session->locations()->get_state();
                _session->locations()->add (loc, true);
                _session->set_auto_loop_location (loc);
@@ -4492,7 +4555,7 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie
 RegionSelection
 Editor::get_regions_from_selection ()
 {
-       return get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
+       return get_equivalent_regions (selection->regions, ARDOUR::Properties::select.property_id);
 }
 
 /** Get regions using the following method:
@@ -4540,7 +4603,7 @@ Editor::get_regions_from_selection_and_edit_point ()
        /* Add any other regions that are in the same
           edit-activated route group as one of our regions.
         */
-       regions = get_equivalent_regions (regions, ARDOUR::Properties::edit.property_id);
+       regions = get_equivalent_regions (regions, ARDOUR::Properties::select.property_id);
        framepos_t const where = get_preferred_edit_position ();
 
        if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
@@ -4590,11 +4653,11 @@ Editor::get_regions_from_selection_and_entered ()
                regions.add (entered_regionview);
        }
 
-       return get_equivalent_regions (regions, ARDOUR::Properties::edit.property_id);
+       return get_equivalent_regions (regions, ARDOUR::Properties::select.property_id);
 }
 
 void
-Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
+Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
 {
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
 
@@ -4613,7 +4676,11 @@ Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<R
                        }
 
                        if ((pl = (tr->playlist())) != 0) {
-                               pl->get_region_list_equivalent_regions (region, results);
+                               if (src_comparison) {
+                                       pl->get_source_equivalent_regions (region, results);
+                               } else {
+                                       pl->get_region_list_equivalent_regions (region, results);
+                               }
                        }
 
                        for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
@@ -4733,9 +4800,11 @@ Editor::located ()
 {
        ENSURE_GUI_THREAD (*this, &Editor::located);
 
-       playhead_cursor->set_position (_session->audible_frame ());
-       if (_follow_playhead && !_pending_initial_locate) {
-               reset_x_origin_to_follow_playhead ();
+       if (_session) {
+               playhead_cursor->set_position (_session->audible_frame ());
+               if (_follow_playhead && !_pending_initial_locate) {
+                       reset_x_origin_to_follow_playhead ();
+               }
        }
 
        _pending_locate_request = false;
@@ -5297,8 +5366,8 @@ Editor::session_going_away ()
        hide_measures ();
        clear_marker_display ();
 
-       current_bbt_points_begin = current_bbt_points_end;
-
+       stop_step_editing ();
+       
        /* get rid of any existing editor mixer strip */
 
        WindowTitle title(Glib::get_application_name());