gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 #include <missing.h> 00022 00023 #include <stdio.h> 00024 00025 #include "gschem.h" 00026 00027 #ifdef HAVE_LIBDMALLOC 00028 #include <dmalloc.h> 00029 #endif 00030 00031 #define GSCHEM_THEME_ICON_NAME "geda-gschem" 00032 00038 void x_window_setup (GSCHEM_TOPLEVEL *w_current) 00039 { 00040 TOPLEVEL *toplevel = w_current->toplevel; 00041 00042 /* immediately setup user params */ 00043 i_vars_set(w_current); 00044 00045 /* Initialize the autosave callback */ 00046 s_page_autosave_init(toplevel); 00047 00048 /* Initialize the clipboard callback */ 00049 x_clipboard_init (w_current); 00050 00051 /* x_window_setup_world() - BEGIN */ 00052 toplevel->init_left = -45; 00053 toplevel->init_top = -45; 00054 /* init_right and _bottom are set before this function is called */ 00055 00056 toplevel->width = default_width; 00057 toplevel->height = default_height; 00058 00059 w_current->win_width = toplevel->width; 00060 w_current->win_height = toplevel->height; 00061 /* x_window_setup_world() - END */ 00062 00063 /* Add to the list of windows */ 00064 global_window_list = g_list_append (global_window_list, w_current); 00065 00066 /* X related stuff */ 00067 x_window_create_main (w_current); 00068 00069 x_menu_attach_recent_files_submenu(w_current); 00070 } 00071 00077 void x_window_setup_gc(GSCHEM_TOPLEVEL *w_current) 00078 { 00079 w_current->gc = gdk_gc_new(w_current->window); 00080 00081 if (w_current->gc == NULL) { 00082 fprintf(stderr, _("Couldn't allocate gc\n")); 00083 exit(-1); 00084 } 00085 } 00086 00092 void x_window_free_gc(GSCHEM_TOPLEVEL *w_current) 00093 { 00094 gdk_gc_unref(w_current->gc); 00095 } 00096 00102 void x_window_create_drawing(GtkWidget *drawbox, GSCHEM_TOPLEVEL *w_current) 00103 { 00104 /* drawing next */ 00105 w_current->drawing_area = gtk_drawing_area_new (); 00106 /* Set the size here. Be sure that it has an aspect ratio of 1.333 00107 * We could calculate this based on root window size, but for now 00108 * lets just set it to: 00109 * Width = root_width*3/4 Height = Width/1.3333333333 00110 * 1.3333333 is the desired aspect ratio! 00111 */ 00112 00113 gtk_drawing_area_size (GTK_DRAWING_AREA (w_current->drawing_area), 00114 w_current->win_width, 00115 w_current->win_height); 00116 00117 gtk_box_pack_start (GTK_BOX (drawbox), w_current->drawing_area, 00118 TRUE, TRUE, 0); 00119 GTK_WIDGET_SET_FLAGS (w_current->drawing_area, GTK_CAN_FOCUS ); 00120 gtk_widget_grab_focus (w_current->drawing_area); 00121 gtk_widget_show (w_current->drawing_area); 00122 00123 } 00124 00130 void x_window_setup_draw_events(GSCHEM_TOPLEVEL *w_current) 00131 { 00132 struct event_reg_t { 00133 gchar *detailed_signal; 00134 GCallback c_handler; 00135 }; 00136 00137 struct event_reg_t drawing_area_events[] = { 00138 { "expose_event", G_CALLBACK(x_event_expose) }, 00139 { "button_press_event", G_CALLBACK(x_event_button_pressed) }, 00140 { "button_release_event", G_CALLBACK(x_event_button_released) }, 00141 { "motion_notify_event", G_CALLBACK(x_event_motion) }, 00142 { "configure_event", G_CALLBACK(x_event_configure) }, 00143 { "key_press_event", G_CALLBACK(x_event_key) }, 00144 { "key_release_event", G_CALLBACK(x_event_key) }, 00145 { NULL, NULL } }; 00146 struct event_reg_t main_window_events[] = { 00147 { "enter_notify_event", G_CALLBACK(x_event_enter) }, 00148 { "scroll_event", G_CALLBACK(x_event_scroll) }, 00149 { NULL, NULL } }; 00150 struct event_reg_t *tmp; 00151 00152 /* is the configure event type missing here? hack */ 00153 gtk_widget_set_events (w_current->drawing_area, 00154 GDK_EXPOSURE_MASK | 00155 GDK_POINTER_MOTION_MASK | 00156 GDK_BUTTON_PRESS_MASK | 00157 GDK_ENTER_NOTIFY_MASK | 00158 GDK_KEY_PRESS_MASK | 00159 GDK_BUTTON_RELEASE_MASK); 00160 00161 for (tmp = drawing_area_events; tmp->detailed_signal != NULL; tmp++) { 00162 g_signal_connect (w_current->drawing_area, 00163 tmp->detailed_signal, 00164 tmp->c_handler, 00165 w_current); 00166 } 00167 00168 for (tmp = main_window_events; tmp->detailed_signal != NULL; tmp++) { 00169 g_signal_connect (w_current->main_window, 00170 tmp->detailed_signal, 00171 tmp->c_handler, 00172 w_current); 00173 } 00174 } 00175 00176 00186 static GtkWidget *x_window_stock_pixmap(const char *stock, GSCHEM_TOPLEVEL *w_current) 00187 { 00188 GtkWidget *wpixmap = NULL; 00189 GdkPixmap *pixmap; 00190 GdkBitmap *mask; 00191 GtkStockItem item; 00192 00193 GdkWindow *window=w_current->main_window->window; 00194 GdkColor *background=&w_current->main_window->style->bg[GTK_STATE_NORMAL]; 00195 00196 gchar *filename=g_strconcat(w_current->toplevel->bitmap_directory, 00197 G_DIR_SEPARATOR_S, 00198 "gschem-", stock, ".xpm", NULL); 00199 00200 gchar *stockid=g_strconcat("gtk-", stock, NULL); 00201 00202 /* First check if GTK knows this stock icon */ 00203 if(gtk_stock_lookup(stockid, &item)) { 00204 wpixmap = gtk_image_new_from_stock(stockid, 00205 GTK_ICON_SIZE_SMALL_TOOLBAR); 00206 } else { 00207 /* Fallback to the original custom icon */ 00208 pixmap = gdk_pixmap_create_from_xpm (window, &mask, 00209 background, filename); 00210 if (pixmap != NULL) { 00211 wpixmap = gtk_image_new_from_pixmap (pixmap, mask); 00212 } else { 00213 s_log_message("Could not find image at file: %s.\n", filename); 00214 wpixmap = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE , 00215 GTK_ICON_SIZE_SMALL_TOOLBAR); 00216 } 00217 } 00218 00219 g_free(filename); 00220 g_free(stockid); 00221 00222 return wpixmap; 00223 } 00224 00225 static void x_window_invoke_macro(GtkEntry *entry, void *userdata) 00226 { 00227 GSCHEM_TOPLEVEL *w_current = userdata; 00228 SCM interpreter; 00229 00230 interpreter = scm_list_2(scm_from_utf8_symbol("invoke-macro"), 00231 scm_from_utf8_string(gtk_entry_get_text(entry))); 00232 00233 scm_dynwind_begin (0); 00234 g_dynwind_window (w_current); 00235 g_scm_eval_protected(interpreter, SCM_UNDEFINED); 00236 scm_dynwind_end (); 00237 00238 gtk_widget_hide(w_current->macro_box); 00239 gtk_widget_grab_focus(w_current->drawing_area); 00240 } 00241 00247 void x_window_create_main(GSCHEM_TOPLEVEL *w_current) 00248 { 00249 TOPLEVEL *toplevel = w_current->toplevel; 00250 00251 GtkWidget *label=NULL; 00252 GtkWidget *main_box=NULL; 00253 GtkWidget *menubar=NULL; 00254 GtkWidget *drawbox=NULL; 00255 GtkWidget *bottom_box=NULL; 00256 GtkWidget *toolbar=NULL; 00257 GtkWidget *handlebox=NULL; 00258 00259 /* used to signify that the window isn't mapped yet */ 00260 w_current->window = NULL; 00261 00262 w_current->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 00263 00264 gtk_widget_set_name (w_current->main_window, "gschem"); 00265 gtk_window_set_policy (GTK_WINDOW (w_current->main_window), TRUE, TRUE, TRUE); 00266 00267 /* We want the widgets to flow around the drawing area, so we don't 00268 * set a size of the main window. The drawing area's size is fixed, 00269 * see below 00270 */ 00271 00272 /* 00273 * normally we let the window manager handle locating and sizing 00274 * the window. However, for some batch processing of schematics 00275 * (generating a pdf of all schematics for example) we want to 00276 * override this. Hence "auto_place_mode". 00277 */ 00278 if( auto_place_mode ) 00279 gtk_widget_set_uposition (w_current->main_window, 10, 10); 00280 00281 /* this should work fine */ 00282 g_signal_connect (G_OBJECT (w_current->main_window), "delete_event", 00283 G_CALLBACK (i_callback_close_wm), 00284 w_current); 00285 00286 /* Containers first */ 00287 main_box = gtk_vbox_new(FALSE, 1); 00288 gtk_container_border_width(GTK_CONTAINER(main_box), 0); 00289 gtk_container_add(GTK_CONTAINER(w_current->main_window), main_box); 00290 00291 menubar = get_main_menu (w_current); 00292 if (w_current->handleboxes) { 00293 handlebox = gtk_handle_box_new (); 00294 gtk_box_pack_start(GTK_BOX(main_box), handlebox, FALSE, FALSE, 0); 00295 gtk_container_add (GTK_CONTAINER (handlebox), menubar); 00296 } else { 00297 gtk_box_pack_start(GTK_BOX(main_box), menubar, FALSE, FALSE, 0); 00298 } 00299 00300 w_current->menubar = menubar; 00301 gtk_widget_realize (w_current->main_window); 00302 00303 if (w_current->handleboxes && w_current->toolbars) { 00304 handlebox = gtk_handle_box_new (); 00305 gtk_box_pack_start (GTK_BOX (main_box), handlebox, FALSE, FALSE, 0); 00306 } 00307 00308 if (w_current->toolbars) { 00309 toolbar = gtk_toolbar_new(); 00310 gtk_toolbar_set_orientation (GTK_TOOLBAR(toolbar), 00311 GTK_ORIENTATION_HORIZONTAL); 00312 gtk_toolbar_set_style (GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); 00313 00314 if (w_current->handleboxes) { 00315 gtk_container_add (GTK_CONTAINER (handlebox), toolbar); 00316 } else { 00317 gtk_box_pack_start(GTK_BOX(main_box), toolbar, FALSE, FALSE, 0); 00318 } 00319 00320 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00321 _("New"), 00322 _("New file"), 00323 "toolbar/new", 00324 x_window_stock_pixmap("new", w_current), 00325 (GtkSignalFunc) i_callback_toolbar_file_new, 00326 w_current); 00327 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00328 _("Open"), 00329 _("Open file..."), 00330 "toolbar/open", 00331 x_window_stock_pixmap("open", w_current), 00332 (GtkSignalFunc) i_callback_toolbar_file_open, 00333 w_current); 00334 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00335 _("Save"), 00336 _("Save file"), 00337 "toolbar/save", 00338 x_window_stock_pixmap("save", w_current), 00339 (GtkSignalFunc) i_callback_toolbar_file_save, 00340 w_current); 00341 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 00342 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00343 _("Undo"), 00344 _("Undo last operation"), 00345 "toolbar/undo", 00346 x_window_stock_pixmap("undo", w_current), 00347 (GtkSignalFunc) i_callback_toolbar_edit_undo, 00348 w_current); 00349 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00350 _("Redo"), 00351 _("Redo last undo"), 00352 "toolbar/redo", 00353 x_window_stock_pixmap("redo", w_current), 00354 (GtkSignalFunc) i_callback_toolbar_edit_redo, 00355 w_current); 00356 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 00357 /* not part of any radio button group */ 00358 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00359 _("Component"), 00360 _("Add component...\nSelect library and component from list, move the mouse into main window, click to place\nRight mouse button to cancel"), 00361 "toolbar/component", 00362 x_window_stock_pixmap("comp", w_current), 00363 (GtkSignalFunc) i_callback_toolbar_add_component, 00364 w_current); 00365 w_current->toolbar_net = 00366 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), 00367 GTK_TOOLBAR_CHILD_RADIOBUTTON, 00368 NULL, 00369 _("Nets"), 00370 _("Add nets mode\nRight mouse button to cancel"), 00371 "toolbar/nets", 00372 x_window_stock_pixmap("net", w_current), 00373 (GtkSignalFunc) i_callback_toolbar_add_net, 00374 w_current); 00375 w_current->toolbar_bus = 00376 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), 00377 GTK_TOOLBAR_CHILD_RADIOBUTTON, 00378 w_current->toolbar_net, 00379 _("Bus"), 00380 _("Add buses mode\nRight mouse button to cancel"), 00381 "toolbar/bus", 00382 x_window_stock_pixmap("bus", w_current), 00383 (GtkSignalFunc) i_callback_toolbar_add_bus, 00384 w_current); 00385 /* not part of any radio button group */ 00386 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 00387 _("Text"), 00388 _("Add Text..."), 00389 "toolbar/text", 00390 x_window_stock_pixmap("text", w_current), 00391 (GtkSignalFunc) i_callback_toolbar_add_text, 00392 w_current); 00393 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 00394 w_current->toolbar_select = 00395 gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), 00396 GTK_TOOLBAR_CHILD_RADIOBUTTON, 00397 w_current->toolbar_bus, 00398 _("Select"), 00399 _("Select mode"), 00400 "toolbar/select", 00401 x_window_stock_pixmap("select", w_current), 00402 (GtkSignalFunc) i_callback_toolbar_edit_select, 00403 w_current); 00404 00405 00406 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 00407 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_current->toolbar_select), 00408 TRUE); 00409 } 00410 00411 00412 /* Try to create popup menu (appears in right mouse button */ 00413 w_current->popup_menu = (GtkWidget *) get_main_popup(w_current); 00414 00415 drawbox = gtk_hbox_new(FALSE, 0); 00416 gtk_container_border_width(GTK_CONTAINER(drawbox), 0); 00417 gtk_container_add(GTK_CONTAINER(main_box), drawbox); 00418 00419 x_window_create_drawing(drawbox, w_current); 00420 x_window_setup_draw_events(w_current); 00421 00422 if (w_current->scrollbars_flag == TRUE) { 00423 /* setup scroll bars */ 00424 w_current->v_adjustment = GTK_ADJUSTMENT ( 00425 gtk_adjustment_new (toplevel->init_bottom, 0.0, toplevel->init_bottom, 00426 100.0, 100.0, 10.0)); 00427 00428 w_current->v_scrollbar = gtk_vscrollbar_new (w_current->v_adjustment); 00429 00430 gtk_range_set_update_policy (GTK_RANGE (w_current->v_scrollbar), 00431 GTK_UPDATE_CONTINUOUS); 00432 00433 gtk_box_pack_start (GTK_BOX (drawbox), w_current->v_scrollbar, 00434 FALSE, FALSE, 0); 00435 00436 g_signal_connect (w_current->v_adjustment, 00437 "value_changed", 00438 G_CALLBACK (x_event_vschanged), 00439 w_current); 00440 00441 w_current->h_adjustment = GTK_ADJUSTMENT ( 00442 gtk_adjustment_new (0.0, 0.0, toplevel->init_right, 100.0, 100.0, 10.0)); 00443 00444 w_current->h_scrollbar = gtk_hscrollbar_new (w_current->h_adjustment); 00445 00446 gtk_range_set_update_policy (GTK_RANGE (w_current->h_scrollbar), 00447 GTK_UPDATE_CONTINUOUS); 00448 00449 gtk_box_pack_start (GTK_BOX (main_box), w_current->h_scrollbar, 00450 FALSE, FALSE, 0); 00451 00452 g_signal_connect (w_current->h_adjustment, 00453 "value_changed", 00454 G_CALLBACK (x_event_hschanged), 00455 w_current); 00456 } 00457 00458 /* macro box */ 00459 w_current->macro_entry = gtk_entry_new(); 00460 g_signal_connect(w_current->macro_entry, "activate", 00461 G_CALLBACK(&x_window_invoke_macro), w_current); 00462 00463 w_current->macro_box = gtk_hbox_new(FALSE, 0); 00464 gtk_box_pack_start(GTK_BOX (w_current->macro_box), 00465 gtk_label_new (_("Evaluate:")), FALSE, FALSE, 2); 00466 gtk_box_pack_start(GTK_BOX(w_current->macro_box), w_current->macro_entry, 00467 TRUE, TRUE, 2); 00468 gtk_container_border_width(GTK_CONTAINER(w_current->macro_box), 1); 00469 gtk_box_pack_start (GTK_BOX (main_box), w_current->macro_box, 00470 FALSE, FALSE, 0); 00471 00472 /* bottom box */ 00473 bottom_box = gtk_hbox_new(FALSE, 0); 00474 gtk_container_border_width(GTK_CONTAINER(bottom_box), 1); 00475 gtk_box_pack_start (GTK_BOX (main_box), bottom_box, FALSE, FALSE, 0); 00476 00477 /* label = gtk_label_new ("Mouse buttons:"); 00478 gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 10); 00479 */ 00480 00481 label = gtk_label_new (" "); 00482 gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 2); 00483 00484 w_current->left_label = gtk_label_new (_("Pick")); 00485 gtk_box_pack_start (GTK_BOX (bottom_box), w_current->left_label, 00486 FALSE, FALSE, 0); 00487 00488 label = gtk_label_new ("|"); 00489 gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5); 00490 00491 if (w_current->middle_button == STROKE) { 00492 #ifdef HAVE_LIBSTROKE 00493 w_current->middle_label = gtk_label_new (_("Stroke")); 00494 #else 00495 w_current->middle_label = gtk_label_new (_("none")); 00496 #endif 00497 } else if (w_current->middle_button == ACTION) { 00498 w_current->middle_label = gtk_label_new (_("Action")); 00499 } else { 00500 w_current->middle_label = gtk_label_new (_("Repeat/none")); 00501 } 00502 00503 gtk_box_pack_start (GTK_BOX (bottom_box), w_current->middle_label, 00504 FALSE, FALSE, 0); 00505 00506 label = gtk_label_new ("|"); 00507 gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5); 00508 00509 if (default_third_button == POPUP_ENABLED) { 00510 w_current->right_label = gtk_label_new (_("Menu/Cancel")); 00511 } else { 00512 w_current->right_label = gtk_label_new (_("Pan/Cancel")); 00513 } 00514 gtk_box_pack_start (GTK_BOX (bottom_box), w_current->right_label, 00515 FALSE, FALSE, 0); 00516 00517 label = gtk_label_new (" "); 00518 gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5); 00519 00520 w_current->grid_label = gtk_label_new (" "); 00521 gtk_box_pack_start (GTK_BOX (bottom_box), w_current->grid_label, 00522 FALSE, FALSE, 10); 00523 00524 w_current->status_label = gtk_label_new (_("Select Mode")); 00525 gtk_box_pack_end (GTK_BOX (bottom_box), w_current->status_label, FALSE, 00526 FALSE, 10); 00527 00528 gtk_widget_show_all (w_current->main_window); 00529 gtk_widget_hide(w_current->macro_box); 00530 00531 w_current->window = w_current->drawing_area->window; 00532 00533 w_current->drawable = w_current->window; 00534 00535 x_window_setup_gc(w_current); 00536 } 00537 00543 void x_window_close(GSCHEM_TOPLEVEL *w_current) 00544 { 00545 TOPLEVEL *toplevel = w_current->toplevel; 00546 gboolean last_window = FALSE; 00547 00548 /* If we're closing whilst inside a move action, re-wind the 00549 * page contents back to their state before we started */ 00550 if (w_current->inside_action && 00551 (w_current->event_state == MOVE || 00552 w_current->event_state == ENDMOVE)) { 00553 o_move_cancel (w_current); 00554 } 00555 00556 /* last chance to save possible unsaved pages */ 00557 if (!x_dialog_close_window (w_current)) { 00558 /* user somehow cancelled the close */ 00559 return; 00560 } 00561 00562 x_clipboard_finish (w_current); 00563 00564 #if DEBUG 00565 o_conn_print_hash(w_current->page_current->conn_table); 00566 #endif 00567 00568 /* close all the dialog boxes */ 00569 if (w_current->sowindow) 00570 gtk_widget_destroy(w_current->sowindow); 00571 00572 if (w_current->cswindow) 00573 gtk_widget_destroy(w_current->cswindow); 00574 00575 if (w_current->tiwindow) 00576 gtk_widget_destroy(w_current->tiwindow); 00577 00578 if (w_current->tewindow) 00579 gtk_widget_destroy(w_current->tewindow); 00580 00581 if (w_current->aawindow) 00582 gtk_widget_destroy(w_current->aawindow); 00583 00584 x_multiattrib_close (w_current); 00585 00586 if (w_current->aewindow) 00587 gtk_widget_destroy(w_current->aewindow); 00588 00589 if (w_current->trwindow) 00590 gtk_widget_destroy(w_current->trwindow); 00591 00592 x_pagesel_close (w_current); 00593 00594 if (w_current->tswindow) 00595 gtk_widget_destroy(w_current->tswindow); 00596 00597 if (w_current->iwindow) 00598 gtk_widget_destroy(w_current->iwindow); 00599 00600 if (w_current->hkwindow) 00601 gtk_widget_destroy(w_current->hkwindow); 00602 00603 if (w_current->cowindow) 00604 gtk_widget_destroy(w_current->cowindow); 00605 00606 if (w_current->clwindow) 00607 gtk_widget_destroy(w_current->clwindow); 00608 00609 if (w_current->sewindow) 00610 gtk_widget_destroy(w_current->sewindow); 00611 00612 if (g_list_length (global_window_list) == 1) { 00613 /* no more window after this one, remember to quit */ 00614 last_window = TRUE; 00615 } 00616 00617 if (toplevel->major_changed_refdes) { 00618 GList* current = toplevel->major_changed_refdes; 00619 while (current) 00620 { 00621 /* printf("yeah freeing: %s\n", (char*) current->data); */ 00622 g_free(current->data); 00623 current = g_list_next(current); 00624 } 00625 g_list_free(toplevel->major_changed_refdes); 00626 } 00627 00628 /* stuff that has to be done before we free w_current */ 00629 if (last_window) { 00630 /* close the log file */ 00631 s_log_close (); 00632 /* free the buffers */ 00633 o_buffer_free (w_current); 00634 } 00635 00636 x_window_free_gc(w_current); 00637 00638 /* Clear Guile smob weak ref */ 00639 if (w_current->smob != SCM_UNDEFINED) { 00640 SCM_SET_SMOB_DATA (w_current->smob, NULL); 00641 w_current->smob = SCM_UNDEFINED; 00642 } 00643 00644 /* finally close the main window */ 00645 gtk_widget_destroy(w_current->main_window); 00646 00647 s_toplevel_delete (toplevel); 00648 global_window_list = g_list_remove (global_window_list, w_current); 00649 g_free (w_current); 00650 00651 /* just closed last window, so quit */ 00652 if (last_window) { 00653 gschem_quit(); 00654 } 00655 } 00656 00662 void x_window_close_all(GSCHEM_TOPLEVEL *w_current) 00663 { 00664 GSCHEM_TOPLEVEL *current; 00665 GList *list_copy, *iter; 00666 00667 iter = list_copy = g_list_copy (global_window_list); 00668 while (iter != NULL ) { 00669 current = (GSCHEM_TOPLEVEL *)iter->data; 00670 iter = g_list_next (iter); 00671 x_window_close (current); 00672 } 00673 g_list_free (list_copy); 00674 } 00675 00699 PAGE* 00700 x_window_open_page (GSCHEM_TOPLEVEL *w_current, const gchar *filename) 00701 { 00702 TOPLEVEL *toplevel = w_current->toplevel; 00703 PAGE *old_current, *page; 00704 gchar *fn; 00705 00706 g_return_val_if_fail (toplevel != NULL, NULL); 00707 00708 /* Generate untitled filename if none was specified */ 00709 if (filename == NULL) { 00710 gchar *cwd, *tmp; 00711 cwd = g_get_current_dir (); 00712 tmp = g_strdup_printf ("%s_%d.sch", 00713 toplevel->untitled_name, 00714 ++w_current->num_untitled); 00715 fn = g_build_filename (cwd, tmp, NULL); 00716 g_free(cwd); 00717 g_free(tmp); 00718 } else { 00719 fn = g_strdup (filename); 00720 } 00721 00722 /* Return existing page if it is already loaded */ 00723 page = s_page_search (toplevel, fn); 00724 if ( page != NULL ) { 00725 g_free(fn); 00726 return page; 00727 } 00728 00729 old_current = toplevel->page_current; 00730 page = s_page_new (toplevel, fn); 00731 s_page_goto (toplevel, page); 00732 00733 /* Load from file if necessary, otherwise just print a message */ 00734 if (filename != NULL) { 00735 GError *err = NULL; 00736 if (!quiet_mode) 00737 s_log_message (_("Loading schematic [%s]\n"), fn); 00738 00739 if (!f_open (toplevel, page, (gchar *) fn, &err)) { 00740 GtkWidget *dialog; 00741 00742 g_warning ("%s\n", err->message); 00743 dialog = gtk_message_dialog_new_with_markup 00744 (GTK_WINDOW (w_current->main_window), 00745 GTK_DIALOG_DESTROY_WITH_PARENT, 00746 GTK_MESSAGE_ERROR, 00747 GTK_BUTTONS_CLOSE, 00748 _("<b>An error occurred while loading the requested file.</b>\n\nLoading from '%s' failed: %s. The gschem log may contain more information."), 00749 fn, err->message); 00750 gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to load file")); 00751 gtk_dialog_run (GTK_DIALOG (dialog)); 00752 gtk_widget_destroy (dialog); 00753 g_error_free (err); 00754 } else { 00755 gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL)); 00756 } 00757 } else { 00758 if (!quiet_mode) 00759 s_log_message (_("New file [%s]\n"), 00760 toplevel->page_current->page_filename); 00761 00762 g_run_hook_page (w_current, "%new-page-hook", toplevel->page_current); 00763 } 00764 00765 a_zoom_extents (w_current, 00766 s_page_objects (toplevel->page_current), 00767 A_PAN_DONT_REDRAW); 00768 00769 o_undo_savestate (w_current, UNDO_ALL); 00770 00771 if ( old_current != NULL ) 00772 s_page_goto (toplevel, old_current); 00773 00774 /* This line is generally un-needed, however if some code 00775 * wants to open a page, yet not bring it to the front, it is 00776 * needed needed to add it into the page manager. Otherwise, 00777 * it will get done in x_window_set_current_page(...) 00778 */ 00779 x_pagesel_update (w_current); /* ??? */ 00780 00781 g_free (fn); 00782 00783 return page; 00784 } 00785 00799 void 00800 x_window_set_current_page (GSCHEM_TOPLEVEL *w_current, PAGE *page) 00801 { 00802 TOPLEVEL *toplevel = w_current->toplevel; 00803 00804 g_return_if_fail (toplevel != NULL); 00805 g_return_if_fail (page != NULL); 00806 00807 o_redraw_cleanstates (w_current); 00808 00809 s_page_goto (toplevel, page); 00810 00811 i_update_menus (w_current); 00812 i_set_filename (w_current, page->page_filename); 00813 00814 x_pagesel_update (w_current); 00815 x_multiattrib_update (w_current); 00816 00817 x_manual_resize (w_current); 00818 x_hscrollbar_update (w_current); 00819 x_vscrollbar_update (w_current); 00820 00821 o_invalidate_all (w_current); 00822 } 00823 00841 gint 00842 x_window_save_page (GSCHEM_TOPLEVEL *w_current, PAGE *page, const gchar *filename) 00843 { 00844 TOPLEVEL *toplevel = w_current->toplevel; 00845 PAGE *old_current; 00846 const gchar *log_msg, *state_msg; 00847 gint ret; 00848 GError *err = NULL; 00849 00850 g_return_val_if_fail (toplevel != NULL, 0); 00851 g_return_val_if_fail (page != NULL, 0); 00852 g_return_val_if_fail (filename != NULL, 0); 00853 00854 /* save current page for restore after opening */ 00855 old_current = toplevel->page_current; 00856 00857 /* change to page */ 00858 s_page_goto (toplevel, page); 00859 /* and try saving current page to filename */ 00860 ret = (gint)f_save (toplevel, toplevel->page_current, filename, &err); 00861 if (ret != 1) { 00862 log_msg = _("Could NOT save page [%s]\n"); 00863 state_msg = _("Error while trying to save"); 00864 00865 GtkWidget *dialog; 00866 00867 dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window), 00868 GTK_DIALOG_DESTROY_WITH_PARENT, 00869 GTK_MESSAGE_ERROR, 00870 GTK_BUTTONS_CLOSE, 00871 "%s", 00872 err->message); 00873 gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to save file")); 00874 gtk_dialog_run (GTK_DIALOG (dialog)); 00875 gtk_widget_destroy (dialog); 00876 g_clear_error (&err); 00877 } else { 00878 /* successful save of page to file, update page... */ 00879 /* change page name if necessary and prepare log message */ 00880 if (g_ascii_strcasecmp (page->page_filename, filename) != 0) { 00881 g_free (page->page_filename); 00882 page->page_filename = g_strdup (filename); 00883 00884 log_msg = _("Saved as [%s]\n"); 00885 } else { 00886 log_msg = _("Saved [%s]\n"); 00887 } 00888 state_msg = _("Saved"); 00889 00890 /* reset page CHANGED flag */ 00891 page->CHANGED = 0; 00892 00893 /* add to recent file list */ 00894 gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(filename, NULL, NULL)); 00895 } 00896 00897 /* log status of operation */ 00898 s_log_message (log_msg, filename); 00899 00900 /* update display and page manager */ 00901 x_window_set_current_page (w_current, old_current); 00902 00903 i_set_state_msg (w_current, SELECT, state_msg); 00904 i_update_toolbar (w_current); 00905 00906 return ret; 00907 } 00908 00920 void 00921 x_window_close_page (GSCHEM_TOPLEVEL *w_current, PAGE *page) 00922 { 00923 TOPLEVEL *toplevel = w_current->toplevel; 00924 PAGE *new_current = NULL; 00925 GList *iter; 00926 00927 g_return_if_fail (toplevel != NULL); 00928 g_return_if_fail (page != NULL); 00929 00930 g_assert (page->pid != -1); 00931 00932 /* If we're closing whilst inside a move action, re-wind the 00933 * page contents back to their state before we started */ 00934 if (w_current->inside_action && 00935 (w_current->event_state == MOVE || 00936 w_current->event_state == ENDMOVE)) { 00937 o_move_cancel (w_current); 00938 } 00939 00940 if (page == toplevel->page_current) { 00941 /* as it will delete current page, select new current page */ 00942 /* first look up in page hierarchy */ 00943 new_current = s_page_search_by_page_id (toplevel->pages, page->up); 00944 00945 if (new_current == NULL) { 00946 /* no up in hierarchy, choice is prev, next, new page */ 00947 iter = g_list_find( geda_list_get_glist( toplevel->pages ), page ); 00948 00949 if ( g_list_previous( iter ) ) { 00950 new_current = (PAGE *)g_list_previous( iter )->data; 00951 } else if ( g_list_next( iter ) ) { 00952 new_current = (PAGE *)g_list_next( iter )->data; 00953 } else { 00954 /* need to add a new untitled page */ 00955 new_current = NULL; 00956 } 00957 } 00958 /* new_current will be the new current page at the end of the function */ 00959 } 00960 00961 s_log_message (page->CHANGED ? 00962 _("Discarding page [%s]\n") : _("Closing [%s]\n"), 00963 page->page_filename); 00964 /* remove page from toplevel list of page and free */ 00965 s_page_delete (toplevel, page); 00966 00967 /* Switch to a different page if we just removed the current */ 00968 if (toplevel->page_current == NULL) { 00969 00970 /* Create a new page if there wasn't another to switch to */ 00971 if (new_current == NULL) { 00972 new_current = x_window_open_page (w_current, NULL); 00973 } 00974 00975 /* change to new_current and update display */ 00976 x_window_set_current_page (w_current, new_current); 00977 } 00978 } 00979 00980 00987 void x_window_set_default_icon( void ) 00988 { 00989 gtk_window_set_default_icon_name( GSCHEM_THEME_ICON_NAME ); 00990 }