+void
+MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
+{
+ if (_selection.empty()) {
+ return;
+ }
+
+ PublicEditor& editor (trackview.editor());
+
+ switch (op) {
+ case Cut:
+ case Copy:
+ editor.get_cut_buffer().add (selection_as_cut_buffer());
+ break;
+ default:
+ break;
+ }
+
+ start_delta_command();
+
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
+ switch (op) {
+ case Copy:
+ break;
+ case Cut:
+ delta_remove_note (*i);
+ break;
+ case Clear:
+ break;
+ }
+ }
+
+ apply_delta();
+}
+
+MidiCutBuffer*
+MidiRegionView::selection_as_cut_buffer () const
+{
+ Notes notes;
+
+ cerr << "Convert selection of " << _selection.size() << " into a cut buffer\n";
+
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
+ NoteType* n = (*i)->note().get();
+ cerr << "CNE's note is " << n << endl;
+ notes.insert (boost::shared_ptr<NoteType> (new NoteType (*n)));
+ }
+
+ MidiCutBuffer* cb = new MidiCutBuffer (trackview.session());
+ cb->set (notes);
+
+ return cb;
+}
+
+void
+MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
+{
+ if (mcb.empty()) {
+ return;
+ }
+
+ start_delta_command (_("paste"));
+
+ Evoral::MusicalTime beat_delta;
+ Evoral::MusicalTime paste_pos_beats;
+ Evoral::MusicalTime duration;
+ Evoral::MusicalTime end_point;
+
+ duration = (*mcb.notes().rbegin())->end_time() - (*mcb.notes().begin())->time();
+ paste_pos_beats = frames_to_beats (pos - _region->position());
+ beat_delta = (*mcb.notes().begin())->time() - paste_pos_beats;
+ paste_pos_beats = 0;
+
+ _selection.clear ();
+
+ for (int n = 0; n < (int) times; ++n) {
+
+ for (Notes::const_iterator i = mcb.notes().begin(); i != mcb.notes().end(); ++i) {
+
+ boost::shared_ptr<NoteType> copied_note (new NoteType (*((*i).get())));
+ copied_note->set_time (paste_pos_beats + copied_note->time() - beat_delta);
+
+ /* make all newly added notes selected */
+
+ delta_add_note (copied_note, true);
+ end_point = copied_note->end_time();
+ }
+
+ paste_pos_beats += duration;
+ }
+
+ /* if we pasted past the current end of the region, extend the region */
+
+ nframes64_t end_frame = _region->position() + beats_to_frames (end_point);
+ nframes64_t region_end = _region->position() + _region->length() - 1;
+
+ if (end_frame > region_end) {
+
+ trackview.session()->begin_reversible_command (_("paste"));
+
+ _region->clear_history ();
+ _region->set_length (end_frame, this);
+ trackview.session()->add_command (new StatefulDiffCommand (_region));
+ }
+
+ apply_delta ();
+}
+
+struct EventNoteTimeEarlyFirstComparator {
+ bool operator() (CanvasNoteEvent* a, CanvasNoteEvent* b) {
+ return a->note()->time() < b->note()->time();
+ }
+};
+
+void
+MidiRegionView::time_sort_events ()
+{
+ if (!_sort_needed) {
+ return;
+ }
+
+ EventNoteTimeEarlyFirstComparator cmp;
+ _events.sort (cmp);
+
+ _sort_needed = false;
+}
+
+void
+MidiRegionView::goto_next_note ()
+{
+ // nframes64_t pos = -1;
+ bool use_next = false;
+
+ if (_events.back()->selected()) {
+ return;
+ }
+
+ time_sort_events ();
+
+ for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
+ if ((*i)->selected()) {
+ use_next = true;
+ continue;
+ } else if (use_next) {
+ unique_select (*i);
+ // pos = _region->position() + beats_to_frames ((*i)->note()->time());
+ return;
+ }
+ }
+
+ /* use the first one */
+
+ unique_select (_events.front());
+
+}
+
+void
+MidiRegionView::goto_previous_note ()
+{
+ // nframes64_t pos = -1;
+ bool use_next = false;
+
+ if (_events.front()->selected()) {
+ return;
+ }
+
+ time_sort_events ();
+
+ for (Events::reverse_iterator i = _events.rbegin(); i != _events.rend(); ++i) {
+ if ((*i)->selected()) {
+ use_next = true;
+ continue;
+ } else if (use_next) {
+ unique_select (*i);
+ // pos = _region->position() + beats_to_frames ((*i)->note()->time());
+ return;
+ }
+ }
+
+ /* use the last one */
+
+ unique_select (*(_events.rbegin()));
+}
+
+void
+MidiRegionView::selection_as_notelist (Notes& selected)
+{
+ time_sort_events ();
+
+ for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
+ if ((*i)->selected()) {
+ selected.insert ((*i)->note());
+ }
+ }
+}