diff --git a/src/db/db/dbClipboardData.cc b/src/db/db/dbClipboardData.cc index 2d1f86fb4..453f6ae31 100644 --- a/src/db/db/dbClipboardData.cc +++ b/src/db/db/dbClipboardData.cc @@ -156,6 +156,11 @@ ClipboardData::add (const db::Layout &layout, const db::Cell &cell, unsigned int std::vector ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::Cell *cell, std::vector *new_tops, ClipboardDataInsertReceiver *insert_receiver) const { + // identify the cells our target is eventually called from, including itself + std::set callers; + cell->collect_caller_cells (callers); + callers.insert (cell->cell_index ()); + std::vector new_layers; PropertyMapper prop_id_map (&layout, &m_layout); @@ -279,14 +284,21 @@ ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::C for (db::Cell::const_iterator inst = c->begin (); ! inst.at_end (); ++inst) { - tl::const_map im (cell_map.find (inst->cell_index ())->second); - db::Instance new_inst = t.insert (*inst, im, prop_id_map); - if (trans) { - new_inst = t.transform (new_inst, *trans); - } + db::cell_index_type inst_cell = cell_map.find (inst->cell_index ())->second; + if (callers.find (inst_cell) == callers.end ()) { + + tl::const_map im (inst_cell); + db::Instance new_inst = t.insert (*inst, im, prop_id_map); + if (trans) { + new_inst = t.transform (new_inst, *trans); + } - if (insert_receiver) { - insert_receiver->instance_inserted (cp->second, new_inst); + if (insert_receiver) { + insert_receiver->instance_inserted (cp->second, new_inst); + } + + } else { + tl::warn << tl::sprintf (tl::to_string (tr ("Refusing to paste an instance for cell %s, as this would create a recursive hierarchy")), layout.cell_name (inst_cell)); } } diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index bbd50ee10..2756f4b18 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -2667,8 +2667,22 @@ MainService::paste () { if (view ()->is_editable ()) { + // skip, if there is nothing to insert + bool any = false; + for (db::Clipboard::iterator c = db::Clipboard::instance ().begin (); c != db::Clipboard::instance ().end () && ! any; ++c) { + const db::ClipboardValue *value = dynamic_cast *> (*c); + any = (value != 0); + } + if (! any) { + return; + } + int cv_index = view ()->active_cellview_index (); + const lay::CellView &cv = view ()->cellview (cv_index); + if (! cv.is_valid ()) { + throw tl::Exception (tl::to_string (tr ("No cell selected to paste something into"))); + } NewObjectsSelection insert_notification (cv_index, cv.cell_index (), view ()); @@ -2678,14 +2692,8 @@ MainService::paste () for (db::Clipboard::iterator c = db::Clipboard::instance ().begin (); c != db::Clipboard::instance ().end (); ++c) { const db::ClipboardValue *value = dynamic_cast *> (*c); if (value) { - - if (! cv.is_valid ()) { - throw tl::Exception (tl::to_string (tr ("No cell selected to paste something into"))); - } - std::vector nl = value->get ().insert (cv->layout (), cv.context_trans ().inverted (), &cv->layout ().cell (cv.cell_index ()), 0 /*new_tops*/, &insert_notification); new_layers.insert (new_layers.end (), nl.begin (), nl.end ()); - } }