/* This locks the entire selected list. It does lock components, but does NOT * change the color (of primatives of the components) though * this cannot be called recursively */ void o_lock(GSCHEM_TOPLEVEL *w_current) { OBJECT *object = NULL; GList *s_current = NULL; /* skip over head */ s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list ); while(s_current != NULL) { object = (OBJECT *) s_current->data; if (object) { /* check to see if locked_color is already being used */ if (object->locked_color == -1) { object->selectable = FALSE; object->locked_color = object->color; object->color = LOCK_COLOR; w_current->toplevel->page_current->CHANGED=1; } else { s_log_message(_("Object already locked\n")); } } s_current = g_list_next(s_current); } if (!w_current->SHIFTKEY) o_select_unselect_all(w_current); o_undo_savestate(w_current, UNDO_ALL); i_update_menus(w_current); }
/* \brief Callback for handling system clipboard owner change. * \par Function Description * */ static void clip_handle_owner_change (GtkClipboard *cb, GdkEvent *event, gpointer user_data) { GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) user_data; i_update_menus (w_current); }
/*! \brief Tests a if a given OBJECT was hit at a given set of coordinates * * \par Function Description * Tests a if a given OBJECT was hit at a given set of coordinates. If so, * processes selection changes as appropriate for the object and passed * flag. Saves a pointer to the found object so future find operations * resume after this object. * * \param [in] w_current The GschemToplevel object. * \param [in] object The OBJECT being hit-tested. * \param [in] w_x The X coordinate to test (in world coords). * \param [in] w_y The Y coordinate to test (in world coords). * \param [in] w_slack The slack applied to the hit-test. * \param [in] change_selection Whether to select the found object or not. * \returns TRUE if the OBJECT was hit, otherwise FALSE. */ static gboolean find_single_object (GschemToplevel *w_current, OBJECT *object, int w_x, int w_y, int w_slack, int change_selection) { if (!is_object_hit (w_current, object, w_x, w_y, w_slack)) return FALSE; if (change_selection) { /* FIXME: should this be moved to o_select_object()? (Werner) */ if (object->type == OBJ_NET && w_current->net_selection_mode) o_select_connected_nets (w_current, object); else o_select_object (w_current, object, SINGLE, 0); /* 0 is count */ } w_current->toplevel->page_current->object_lastplace = object; i_update_menus (w_current); return TRUE; }
/*! \brief Changes the current page. * \par Function Description * This function displays the specified page <B>page</B> in the * window attached to <B>toplevel</B>. * * It changes the <B>toplevel</B>'s current page to <B>page</B>, * draws it and updates the user interface. * * <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>. * * \param [in] w_current The toplevel environment. * \param [in] page The page to become current page. */ void x_window_set_current_page (GschemToplevel *w_current, PAGE *page) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page != NULL); g_return_if_fail (page_view != NULL); o_redraw_cleanstates (w_current); gschem_page_view_set_page (page_view, page); i_update_menus (w_current); i_set_filename (w_current, page->page_filename); x_pagesel_update (w_current); x_multiattrib_update (w_current); gschem_page_view_update_scroll_adjustments (page_view); gschem_page_view_invalidate_all (page_view); }
/*! \brief Changes the current page. * \par Function Description * This function displays the specified page <B>page</B> in the * window attached to <B>toplevel</B>. * * It changes the <B>toplevel</B>'s current page to <B>page</B>, * draws it and updates the user interface. * * <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>. * * \param [in] w_current The toplevel environment. * \param [in] page The page to become current page. */ void x_window_set_current_page (GSCHEM_TOPLEVEL *w_current, PAGE *page) { TOPLEVEL *toplevel = w_current->toplevel; g_return_if_fail (toplevel != NULL); g_return_if_fail (page != NULL); o_redraw_cleanstates (w_current); s_page_goto (toplevel, page); i_update_menus (w_current); i_set_filename (w_current, page->page_filename); x_pagesel_update (w_current); x_multiattrib_update (w_current); x_manual_resize (w_current); x_hscrollbar_update (w_current); x_vscrollbar_update (w_current); o_invalidate_all (w_current); }
/*! \brief End placement action * * \par Function Description * This function finishes the current placement action by adding * objects to the current page at the given new world coordinates * and redrawing them on the canvas. It also saves the current * state in the undo list and updates the menus. * * If \a continue_placing is TRUE, a copy of the placement list * is saved to start a new place action. * * \param [in] w_current GschemToplevel which we're drawing for. * \param [in] w_x The current world X coordinate. * \param [in] w_y The current world Y coordinate. * \param [in] hook_name The hook to run after adding the objects. */ void o_place_end (GschemToplevel *w_current, int w_x, int w_y, int continue_placing, const char* hook_name) { int w_diff_x, w_diff_y; OBJECT *o_current; GList *temp_dest_list = NULL; GList *connected_objects = NULL; GList *iter; g_return_if_fail (w_current != NULL); g_assert (w_current->inside_action != 0); GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); /* erase old image */ /* o_place_invalidate_rubber (w_current, FALSE); */ w_current->rubber_visible = 0; /* Calc final object positions */ w_current->second_wx = w_x; w_current->second_wy = w_y; w_diff_x = w_current->second_wx - w_current->first_wx; w_diff_y = w_current->second_wy - w_current->first_wy; if (continue_placing) { /* Make a copy of the place list if we want to keep it afterwards */ temp_dest_list = o_glist_copy_all (page->toplevel, page->place_list, temp_dest_list); } else { /* Otherwise just take it */ temp_dest_list = page->place_list; page->place_list = NULL; } geda_object_list_translate (temp_dest_list, w_diff_x, w_diff_y); /* Attach each item back onto the page's object list. Update object * connectivity and add the new objects to the selection list.*/ for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) { o_current = (OBJECT*) iter->data; s_page_append (page->toplevel, page, o_current); /* Update object connectivity */ s_conn_update_object (page, o_current); connected_objects = s_conn_return_others (connected_objects, o_current); } if (hook_name != NULL) { g_run_hook_object_list (w_current, hook_name, temp_dest_list); } o_invalidate_glist (w_current, connected_objects); g_list_free (connected_objects); connected_objects = NULL; gschem_toplevel_page_content_changed (w_current, page); o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */ g_list_free (temp_dest_list); o_undo_savestate_old (w_current, UNDO_ALL); i_update_menus (w_current); if (!continue_placing) { i_set_state(w_current, SELECT); i_action_stop (w_current); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ gint x_event_button_pressed(GschemPageView *page_view, GdkEventButton *event, GschemToplevel *w_current) { PAGE *page = gschem_page_view_get_page (page_view); int w_x, w_y; int unsnapped_wx, unsnapped_wy; g_return_val_if_fail ((w_current != NULL), 0); if (page == NULL) { return TRUE; /* terminate event */ } if (!gtk_widget_has_focus (GTK_WIDGET (page_view))) { gtk_widget_grab_focus (GTK_WIDGET (page_view)); } scm_dynwind_begin ((scm_t_dynwind_flags) 0); g_dynwind_window (w_current); #if DEBUG printf("pressed button %d! \n", event->button); printf("event state: %d \n", event->state); printf("w_current state: %d \n", w_current->event_state); printf("Selection is:\n"); o_selection_print_all(&(page->selection_list)); printf("\n"); #endif gschem_page_view_SCREENtoWORLD (page_view, (int) event->x, (int) event->y, &unsnapped_wx, &unsnapped_wy); w_x = snap_grid (w_current, unsnapped_wx); w_y = snap_grid (w_current, unsnapped_wy); if (event->type == GDK_2BUTTON_PRESS && w_current->event_state == SELECT) { /* Don't re-select an object (lp-912978) */ /* o_find_object(w_current, w_x, w_y, TRUE); */ /* GDK_BUTTON_EVENT is emitted before GDK_2BUTTON_EVENT, which * leads to setting of the inside_action flag. If o_edit() * brings up a modal window (e.g., the edit attribute dialog), * it intercepts the release button event and thus doesn't * allow resetting of the inside_action flag so we do it * manually here before processing the double-click event. */ i_action_stop (w_current); o_edit(w_current, geda_list_get_glist( page->selection_list )); scm_dynwind_end (); return(0); } w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0; w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0; w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0; /* Huge switch statement to evaluate state transitions. Jump to * end_button_pressed label to escape the state evaluation rather than * returning from the function directly. */ if (event->button == 1) { if (w_current->inside_action) { /* End action */ if (page->place_list != NULL) { switch(w_current->event_state) { case (COMPMODE) : o_place_end(w_current, w_x, w_y, w_current->continue_component_place, "%add-objects-hook"); break; case (TEXTMODE) : o_place_end(w_current, w_x, w_y, FALSE, "%add-objects-hook"); break; case (PASTEMODE) : o_place_end(w_current, w_x, w_y, FALSE, "%paste-objects-hook"); break; default: break; } } else { switch(w_current->event_state) { case (ARCMODE) : o_arc_end1(w_current, w_x, w_y); break; case (BOXMODE) : o_box_end(w_current, w_x, w_y); break; case (BUSMODE) : o_bus_end(w_current, w_x, w_y); break; case (CIRCLEMODE) : o_circle_end(w_current, w_x, w_y); break; case (LINEMODE) : o_line_end(w_current, w_x, w_y); break; case (NETMODE) : o_net_end(w_current, w_x, w_y); break; case (PATHMODE) : o_path_continue (w_current, w_x, w_y); break; case (PICTUREMODE): o_picture_end(w_current, w_x, w_y); break; case (PINMODE) : o_pin_end (w_current, w_x, w_y); break; default: break; } } } else { /* Start action */ switch(w_current->event_state) { case (ARCMODE) : o_arc_start(w_current, w_x, w_y); break; case (BOXMODE) : o_box_start(w_current, w_x, w_y); break; case (BUSMODE) : o_bus_start(w_current, w_x, w_y); break; case (CIRCLEMODE) : o_circle_start(w_current, w_x, w_y); break; case (LINEMODE) : o_line_start(w_current, w_x, w_y); break; case (NETMODE) : o_net_start(w_current, w_x, w_y); break; case (PATHMODE) : o_path_start (w_current, w_x, w_y); break; case (PICTUREMODE): o_picture_start(w_current, w_x, w_y); break; case (PINMODE) : o_pin_start (w_current, w_x, w_y); break; case (ZOOMBOX) : a_zoom_box_start(w_current, unsnapped_wx, unsnapped_wy); break; case (SELECT) : o_select_start(w_current, w_x, w_y); break; case (COPYMODE) : case (MCOPYMODE) : o_copy_start(w_current, w_x, w_y); break; case (MOVEMODE) : o_move_start(w_current, w_x, w_y); break; default: break; } } switch(w_current->event_state) { case(ROTATEMODE): o_rotate_world_update(w_current, w_x, w_y, 90, geda_list_get_glist(page->selection_list)); break; case(MIRRORMODE): o_mirror_world_update(w_current, w_x, w_y, geda_list_get_glist(page->selection_list)); break; case(PAN): gschem_page_view_pan (page_view, w_x, w_y); i_set_state(w_current, SELECT); break; } } else if (event->button == 2) { /* try this out and see how it behaves */ if (w_current->inside_action) { if (!(w_current->event_state == COMPMODE|| w_current->event_state == TEXTMODE|| w_current->event_state == MOVEMODE|| w_current->event_state == COPYMODE || w_current->event_state == MCOPYMODE || w_current->event_state == PASTEMODE )) { i_callback_cancel(w_current, 0, NULL); } goto end_button_pressed; } switch(w_current->middle_button) { case(ACTION): /* don't want to search if shift */ /* key is pressed */ if (!w_current->SHIFTKEY) { o_find_object(w_current, unsnapped_wx, unsnapped_wy, TRUE); } /* make sure the list is not empty */ if (!o_select_selected(w_current)) { /* this means the above find did not * find anything */ i_action_stop (w_current); i_set_state(w_current, SELECT); goto end_button_pressed; } /* determine here if copy or move */ if (w_current->ALTKEY) { i_set_state(w_current, COPYMODE); o_copy_start(w_current, w_x, w_y); } else { o_move_start(w_current, w_x, w_y); } break; case(REPEAT): if (w_current->last_callback != NULL) { (*w_current->last_callback)(w_current, 0, NULL); } break; #ifdef HAVE_LIBSTROKE case(STROKE): DOING_STROKE=TRUE; break; #endif /* HAVE_LIBSTROKE */ case(MID_MOUSEPAN_ENABLED): gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); break; } } else if (event->button == 3) { if (!w_current->inside_action) { if (w_current->third_button == POPUP_ENABLED) { /* (third-button "popup") */ i_update_menus(w_current); /* update menus before popup */ do_popup(w_current, event); } else { /* (third-button "mousepan") */ gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); } } else { if ((w_current->third_button == MOUSEPAN_ENABLED) && (!w_current->third_button_cancel)) { gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); } else { /* this is the default cancel */ /* reset all draw and place actions */ switch (w_current->event_state) { case (ARCMODE) : o_arc_invalidate_rubber (w_current); break; case (BOXMODE) : o_box_invalidate_rubber (w_current); break; case (BUSMODE) : o_bus_invalidate_rubber (w_current); break; case (CIRCLEMODE) : o_circle_invalidate_rubber (w_current); break; case (LINEMODE) : o_line_invalidate_rubber (w_current); break; case (NETMODE) : o_net_reset (w_current); break; case (PATHMODE) : o_path_invalidate_rubber (w_current); break; case (PICTUREMODE): o_picture_invalidate_rubber (w_current); break; case (PINMODE) : o_pin_invalidate_rubber (w_current); break; default: i_callback_cancel(w_current, 0, NULL); break; } } } } end_button_pressed: scm_dynwind_end (); return(0); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * * <B>type</B> can be one of the following values: * <DL> * <DT>*</DT><DD>UNDO_ACTION * <DT>*</DT><DD>REDO_ACTION * </DL> */ void o_undo_callback (GschemToplevel *w_current, PAGE *page, int type) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); UNDO *u_current; UNDO *u_next; UNDO *save_bottom; UNDO *save_tos; UNDO *save_current; int save_logging; int find_prev_data=FALSE; char *save_filename; g_return_if_fail (w_current != NULL); g_return_if_fail (page != NULL); if (w_current->undo_control == FALSE) { s_log_message(_("Undo/Redo disabled in rc file\n")); return; } if (page->undo_current == NULL) { return; } if (type == UNDO_ACTION) { u_current = page->undo_current->prev; } else { u_current = page->undo_current->next; } u_next = page->undo_current; if (u_current == NULL) { return; } if (u_next->type == UNDO_ALL && u_current->type == UNDO_VIEWPORT_ONLY) { #if DEBUG printf("Type: %d\n", u_current->type); printf("Current is an undo all, next is viewport only!\n"); #endif find_prev_data = TRUE; if (w_current->undo_type == UNDO_DISK) { u_current->filename = o_undo_find_prev_filename(u_current); } else { u_current->object_list = o_undo_find_prev_object_head (u_current); } } /* save filename */ save_filename = g_strdup (page->page_filename); /* save structure so it's not nuked */ save_bottom = page->undo_bottom; save_tos = page->undo_tos; save_current = page->undo_current; page->undo_bottom = NULL; page->undo_tos = NULL; page->undo_current = NULL; o_select_unselect_all (w_current); if (w_current->undo_type == UNDO_DISK && u_current->filename) { /* delete objects of page */ s_page_delete_objects (toplevel, page); /* Free the objects in the place list. */ geda_object_list_delete (toplevel, page->place_list); page->place_list = NULL; gschem_toplevel_page_content_changed (w_current, page); } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) { /* delete objects of page */ s_page_delete_objects (toplevel, page); /* Free the objects in the place list. */ geda_object_list_delete (toplevel, page->place_list); page->place_list = NULL; gschem_toplevel_page_content_changed (w_current, page); } /* temporarily disable logging */ save_logging = do_logging; do_logging = FALSE; if (w_current->undo_type == UNDO_DISK && u_current->filename) { f_open(toplevel, page, u_current->filename, NULL); } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) { s_page_append_list (toplevel, page, o_glist_copy_all (toplevel, u_current->object_list, NULL)); } page->page_control = u_current->page_control; page->up = u_current->up; gschem_toplevel_page_content_changed (w_current, page); GschemPageView *view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (view != NULL); GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (view); if (u_current->scale != 0) { gschem_page_geometry_set_viewport (geometry, u_current->x, u_current->y, u_current->scale); gschem_page_view_invalidate_all (view); } else { gschem_page_view_zoom_extents (view, u_current->object_list); } /* restore logging */ do_logging = save_logging; /* set filename right */ g_free(page->page_filename); page->page_filename = save_filename; /* final redraw */ x_pagesel_update (w_current); x_multiattrib_update (w_current); i_update_menus(w_current); /* restore saved undo structures */ page->undo_bottom = save_bottom; page->undo_tos = save_tos; page->undo_current = save_current; if (type == UNDO_ACTION) { if (page->undo_current) { page->undo_current = page->undo_current->prev; if (page->undo_current == NULL) { page->undo_current = page->undo_bottom; } } } else { /* type is REDO_ACTION */ if (page->undo_current) { page->undo_current = page->undo_current->next; if (page->undo_current == NULL) { page->undo_current = page->undo_tos; } } } /* don't have to free data here since filename, object_list are */ /* just pointers to the real data (lower in the stack) */ if (find_prev_data) { u_current->filename = NULL; u_current->object_list = NULL; } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(page->undo_bottom); printf("TOS: %s\n", page->undo_tos->filename); printf("CURRENT: %s\n", page->undo_current->filename); printf("----\n"); #endif }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * * <B>type</B> can be one of the following values: * <DL> * <DT>*</DT><DD>UNDO_ACTION * <DT>*</DT><DD>REDO_ACTION * </DL> */ void o_undo_callback(GSCHEM_TOPLEVEL *w_current, int type) { TOPLEVEL *toplevel = w_current->toplevel; UNDO *u_current; UNDO *u_next; UNDO *save_bottom; UNDO *save_tos; UNDO *save_current; int save_logging; int find_prev_data=FALSE; char *save_filename; if (w_current->undo_control == FALSE) { s_log_message(_("Undo/Redo disabled in rc file\n")); return; } if (toplevel->page_current->undo_current == NULL) { return; } if (type == UNDO_ACTION) { u_current = toplevel->page_current->undo_current->prev; } else { u_current = toplevel->page_current->undo_current->next; } u_next = toplevel->page_current->undo_current; if (u_current == NULL) { return; } if (u_next->type == UNDO_ALL && u_current->type == UNDO_VIEWPORT_ONLY) { #if DEBUG printf("Type: %d\n", u_current->type); printf("Current is an undo all, next is viewport only!\n"); #endif find_prev_data = TRUE; if (w_current->undo_type == UNDO_DISK) { u_current->filename = o_undo_find_prev_filename(u_current); } else { u_current->object_list = o_undo_find_prev_object_head (u_current); } } /* save filename */ save_filename = g_strdup (toplevel->page_current->page_filename); /* save structure so it's not nuked */ save_bottom = toplevel->page_current->undo_bottom; save_tos = toplevel->page_current->undo_tos; save_current = toplevel->page_current->undo_current; toplevel->page_current->undo_bottom = NULL; toplevel->page_current->undo_tos = NULL; toplevel->page_current->undo_current = NULL; if (w_current->undo_type == UNDO_DISK && u_current->filename) { PAGE *p_new; s_page_delete (toplevel, toplevel->page_current); p_new = s_page_new(toplevel, u_current->filename); s_page_goto (toplevel, p_new); } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) { PAGE *p_new; s_page_delete (toplevel, toplevel->page_current); p_new = s_page_new (toplevel, save_filename); s_page_goto (toplevel, p_new); } /* temporarily disable logging */ save_logging = do_logging; do_logging = FALSE; if (w_current->undo_type == UNDO_DISK && u_current->filename) { f_open(toplevel, toplevel->page_current, u_current->filename, NULL); x_manual_resize(w_current); toplevel->page_current->page_control = u_current->page_control; toplevel->page_current->up = u_current->up; toplevel->page_current->CHANGED=1; } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) { s_page_delete_objects (toplevel, toplevel->page_current); s_page_append_list (toplevel, toplevel->page_current, o_glist_copy_all (toplevel, u_current->object_list, NULL)); x_manual_resize(w_current); toplevel->page_current->page_control = u_current->page_control; toplevel->page_current->up = u_current->up; toplevel->page_current->CHANGED=1; } /* do misc setups */ set_window(toplevel, toplevel->page_current, u_current->left, u_current->right, u_current->top, u_current->bottom); x_hscrollbar_update(w_current); x_vscrollbar_update(w_current); /* restore logging */ do_logging = save_logging; /* set filename right */ g_free(toplevel->page_current->page_filename); toplevel->page_current->page_filename = save_filename; /* final redraw */ x_pagesel_update (w_current); x_multiattrib_update (w_current); /* Let the caller to decide if redraw or not */ o_invalidate_all (w_current); i_update_menus(w_current); /* restore saved undo structures */ toplevel->page_current->undo_bottom = save_bottom; toplevel->page_current->undo_tos = save_tos; toplevel->page_current->undo_current = save_current; if (type == UNDO_ACTION) { if (toplevel->page_current->undo_current) { toplevel->page_current->undo_current = toplevel->page_current->undo_current->prev; if (toplevel->page_current->undo_current == NULL) { toplevel->page_current->undo_current = toplevel->page_current->undo_bottom; } } } else { /* type is REDO_ACTION */ if (toplevel->page_current->undo_current) { toplevel->page_current->undo_current = toplevel->page_current->undo_current->next; if (toplevel->page_current->undo_current == NULL) { toplevel->page_current->undo_current = toplevel->page_current->undo_tos; } } } /* don't have to free data here since filename, object_list are */ /* just pointers to the real data (lower in the stack) */ if (find_prev_data) { u_current->filename = NULL; u_current->object_list = NULL; } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(toplevel->page_current->undo_bottom); printf("TOS: %s\n", toplevel->page_current->undo_tos->filename); printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename); printf("----\n"); #endif }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_place_end (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int continue_placing, GList **ret_new_objects, const char* hook_name) { TOPLEVEL *toplevel = w_current->toplevel; int w_diff_x, w_diff_y; OBJECT *o_current; PAGE *p_current; GList *temp_dest_list = NULL; GList *connected_objects = NULL; GList *iter; /* erase old image */ /* o_place_invaidate_rubber (w_current, FALSE); */ w_current->rubber_visible = 0; /* Calc final object positions */ w_current->second_wx = w_x; w_current->second_wy = w_y; w_diff_x = w_current->second_wx - w_current->first_wx; w_diff_y = w_current->second_wy - w_current->first_wy; if (continue_placing) { /* Make a copy of the place list if we want to keep it afterwards */ temp_dest_list = o_glist_copy_all (toplevel, toplevel->page_current->place_list, temp_dest_list); } else { /* Otherwise just take it */ temp_dest_list = toplevel->page_current->place_list; toplevel->page_current->place_list = NULL; } if (ret_new_objects != NULL) { *ret_new_objects = g_list_copy (temp_dest_list); } o_glist_translate_world(toplevel, w_diff_x, w_diff_y, temp_dest_list); /* Attach each item back onto the page's object list. Update object * connectivity and add the new objects to the selection list.*/ p_current = toplevel->page_current; for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; s_page_append (toplevel, p_current, o_current); /* Update object connectivity */ s_conn_update_object (toplevel, o_current); connected_objects = s_conn_return_others (connected_objects, o_current); } if (hook_name != NULL) { g_run_hook_object_list (hook_name, temp_dest_list); } o_invalidate_glist (w_current, connected_objects); g_list_free (connected_objects); connected_objects = NULL; toplevel->page_current->CHANGED = 1; o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */ g_list_free (temp_dest_list); o_undo_savestate (w_current, UNDO_ALL); i_update_menus (w_current); }
/*! \brief Find an OBJECT at a given set of coordinates * * \par Function Description * Tests for OBJECTS hit at a given set of coordinates. If * change_selection is TRUE, it updates the page's selection. * * Find operations resume searching after the last object which was * found, so multiple find operations at the same point will cycle * through any objects on top of each other at this location. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x The X coordinate to test (in world coords). * \param [in] w_y The Y coordinate to test (in world coords). * \param [in] change_selection Whether to select the found object or not. * \returns TRUE if the object was hit at the given coordinates, * otherwise FALSE. */ gboolean o_find_object (GschemToplevel *w_current, int w_x, int w_y, gboolean change_selection) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_val_if_fail (page_view != NULL, FALSE); TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); g_return_val_if_fail (toplevel != NULL, FALSE); int w_slack; const GList *iter = NULL; w_slack = gschem_page_view_WORLDabs (page_view, w_current->select_slack_pixels); /* Decide whether to iterate over all object or start at the last found object. If there is more than one object below the (w_x/w_y) position, this will select the next object below the position point. You can change the selected object by clicking at the same place multiple times. */ if (toplevel->page_current->object_lastplace != NULL) { /* NB: g_list_find doesn't declare its input const, so we cast */ iter = g_list_find ((GList *)s_page_objects (toplevel->page_current), toplevel->page_current->object_lastplace); iter = g_list_next (iter); } /* do first search (if we found any objects after the last found object) */ while (iter != NULL) { OBJECT *o_current = iter->data; if (find_single_object (w_current, o_current, w_x, w_y, w_slack, change_selection)) { return TRUE; } iter = g_list_next (iter); } /* now search from the beginning up until the object_lastplace */ for (iter = s_page_objects (toplevel->page_current); iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; if (find_single_object (w_current, o_current, w_x, w_y, w_slack, change_selection)) { return TRUE; } /* break once we've inspected up to where we started the first loop */ if (o_current == toplevel->page_current->object_lastplace) break; } /* didn't find anything.... reset lastplace */ toplevel->page_current->object_lastplace = NULL; /* deselect everything only if shift key isn't pressed and the caller allows it */ if (change_selection && (!w_current->SHIFTKEY)) { o_select_unselect_all (w_current); } i_update_menus(w_current); return FALSE; }
/*! \brief Delete objects from the selection. * \par Function Description * This function deletes the objects selected on the current page of * toplevel \a w_current. * * \param [in] w_current The GschemToplevel object. */ void o_delete_selected (GschemToplevel *w_current) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); SELECTION *selection = toplevel->page_current->selection_list; GList *to_remove; GList *iter; OBJECT *obj; unsigned int locked_num = 0; g_return_if_fail (o_select_selected (w_current)); to_remove = g_list_copy (geda_list_get_glist (selection)); for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) { obj = (OBJECT *) iter->data; if (obj->selectable == FALSE) locked_num++; } if (locked_num > 0) { GList *non_locked = NULL; gint resp; GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, ngettext ("Delete locked object?", "Delete %u locked objects?", locked_num), locked_num); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_YES, GTK_RESPONSE_YES, GTK_STOCK_NO, GTK_RESPONSE_NO, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO); resp = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); switch (resp) { case GTK_RESPONSE_YES: /* Remove all */ break; case GTK_RESPONSE_NO: /* Remove non locked */ for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) { obj = (OBJECT *) iter->data; if (obj->selectable == TRUE) non_locked = g_list_append (non_locked, iter->data); } g_list_free (to_remove); to_remove = non_locked; break; default: /* Cancel */ g_list_free (to_remove); return; } } for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) { obj = (OBJECT *) iter->data; o_selection_remove (toplevel, selection, obj); s_page_remove (toplevel, toplevel->page_current, obj); } g_run_hook_object_list (w_current, "%remove-objects-hook", to_remove); for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) { obj = (OBJECT *) iter->data; s_delete_object (toplevel, obj); } g_list_free (to_remove); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); w_current->inside_action = 0; o_undo_savestate_old (w_current, UNDO_ALL); i_update_menus (w_current); }