1 /* Lepton EDA attribute editor
2  * Copyright (C) 2003-2010 Stuart D. Brorson.
3  * Copyright (C) 2016 Peter Brett <peter@peter-b.co.uk>
4  * Copyright (C) 2003-2016 gEDA Contributors
5  * Copyright (C) 2017-2021 Lepton EDA Contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*------------------------------------------------------------------*/
23 /*! \file
24  * \brief Functions for the toplevel window
25  *
26  * This file holds functions used to handle the toplevel window and
27  * various widgets held by that window.  Widges used to handle
28  * (GtkSheet *sheet) itself are held in a different file.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 
36 /*------------------------------------------------------------------
37  * Includes required to run graphical widgets.
38  *------------------------------------------------------------------*/
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <gtk/gtk.h>
42 
43 #ifdef HAVE_STRING_H
44 #include <string.h>
45 #endif
46 
47 /*------------------------------------------------------------------
48  * Gattrib specific includes
49  *------------------------------------------------------------------*/
50 #include <liblepton/liblepton.h>
51 #include <liblepton/libleptonguile.h>
52 #include "../include/struct.h"     /* typdef and struct declarations */
53 #include "../include/prototype.h"  /* function prototypes */
54 #include "../include/globals.h"
55 #include "../include/gettext.h"
56 
57 /*------------------------------------------------------------------
58  * Gattrib specific defines
59  *------------------------------------------------------------------*/
60 #define GATTRIB_THEME_ICON_NAME "lepton-attrib"
61 
62 static void
63 x_window_init ();
64 
65 static void
66 x_window_create_menu(GtkWindow *window, GtkWidget **menubar);
67 
68 static void
69 x_window_set_default_icon( void );
70 
71 static void
72 x_window_set_title (GList* plist);
73 
74 static LeptonToplevel *window_toplevel = NULL;
75 
76 void
x_window_set_toplevel(LeptonToplevel * toplevel)77 x_window_set_toplevel (LeptonToplevel *toplevel)
78 {
79   window_toplevel = toplevel;
80 }
81 
82 LeptonToplevel*
x_window_get_toplevel()83 x_window_get_toplevel ()
84 {
85   return window_toplevel;
86 }
87 
88 static GtkWidget*
separator_new()89 separator_new ()
90 {
91 #ifdef ENABLE_GTK3
92   return gtk_separator_new (GTK_ORIENTATION_VERTICAL);
93 #else
94   return gtk_vseparator_new ();
95 #endif
96 }
97 
98 /*! \brief Initialises the toplevel gtksheet
99  *
100  * This function initializes the toplevel gtksheet stuff.
101  *
102  *  It basically just initializes the following widgets:
103  *  GTK_WINDOW *window
104  *  GTK_CONTAINER *main_vbox
105  *  GTK_MENU
106  */
107 static void
x_window_init()108 x_window_init ()
109 {
110   GtkWidget *menu_bar;
111   GtkWidget *main_vbox;
112 
113   /* Set default icon */
114   x_window_set_default_icon();
115 
116   /*  window is a global declared in globals.h.  */
117   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
118 
119   g_signal_connect(window, "delete_event",
120                    G_CALLBACK (attrib_really_quit), 0);
121 
122   /* -----  Now create main_vbox.  This is a container which organizes child  ----- */
123   /* -----  widgets into a vertical column.  ----- */
124   #ifdef ENABLE_GTK3
125   main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL,1);
126   #else
127   main_vbox = gtk_vbox_new(FALSE,1);
128   #endif
129   gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
130   gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(main_vbox) );
131 
132   /* -----  Now create menu bar  ----- */
133   x_window_create_menu(GTK_WINDOW(window), &menu_bar);
134   gtk_box_pack_start(GTK_BOX (main_vbox), menu_bar, FALSE, TRUE, 0);
135 
136   /* -----  Now init notebook widget  ----- */
137   notebook = gtk_notebook_new();
138   gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_BOTTOM);
139   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
140   gtk_box_pack_start(GTK_BOX(main_vbox), notebook, TRUE, TRUE, 0);
141 
142 
143   /* Status bar:
144   */
145   GtkWidget* sbar = gtk_statusbar_new();
146   gtk_box_pack_start (GTK_BOX (main_vbox), sbar, FALSE, TRUE, 0);
147   GtkWidget* marea = gtk_statusbar_get_message_area (GTK_STATUSBAR (sbar));
148 
149   GtkWidget* label_1 = gtk_label_new (NULL);
150   gtk_label_set_markup (GTK_LABEL (label_1), _("   Color Legend:  "));
151 
152   GtkWidget* label_inv      = gtk_label_new (_(" Invisible ") );
153   GtkWidget* label_val      = gtk_label_new (_(" Show value "));
154   GtkWidget* label_name     = gtk_label_new (_(" Show name "));
155   GtkWidget* label_name_val = gtk_label_new (_(" Show name and value "));
156 
157   gtk_box_pack_start (GTK_BOX (marea), label_1, FALSE, TRUE, 0);
158   gtk_box_pack_start (GTK_BOX (marea), separator_new() , FALSE, TRUE, 0);
159 
160   gtk_box_pack_start (GTK_BOX (marea), label_inv, FALSE, TRUE, 0);
161   gtk_box_pack_start (GTK_BOX (marea), separator_new() , FALSE, TRUE, 0);
162 
163   gtk_box_pack_start (GTK_BOX (marea), label_val, FALSE, TRUE, 0);
164   gtk_box_pack_start (GTK_BOX (marea), separator_new() , FALSE, TRUE, 0);
165 
166   gtk_box_pack_start (GTK_BOX (marea), label_name, FALSE, TRUE, 0);
167   gtk_box_pack_start (GTK_BOX (marea), separator_new() , FALSE, TRUE, 0);
168 
169   gtk_box_pack_start (GTK_BOX (marea), label_name_val, FALSE, TRUE, 0);
170 
171 #ifdef ENABLE_GTK3
172   GdkRGBA color;
173   gdk_rgba_parse (&color, "grey");
174   gtk_widget_override_color (label_inv, GTK_STATE_FLAG_NORMAL, &color);
175 
176   gdk_rgba_parse (&color, "black");
177   gtk_widget_override_color (label_val, GTK_STATE_FLAG_NORMAL, &color);
178 
179   gdk_rgba_parse (&color, "red");
180   gtk_widget_override_color (label_name, GTK_STATE_FLAG_NORMAL, &color);
181 
182   gdk_rgba_parse (&color, "blue");
183   gtk_widget_override_color (label_name_val, GTK_STATE_FLAG_NORMAL, &color);
184 #else
185   GdkColor color;
186   gdk_color_parse ("grey", &color);
187   gtk_widget_modify_fg (label_inv, GTK_STATE_NORMAL, &color);
188 
189   gdk_color_parse ("black", &color);
190   gtk_widget_modify_fg (label_val, GTK_STATE_NORMAL, &color);
191 
192   gdk_color_parse ("red", &color);
193   gtk_widget_modify_fg (label_name, GTK_STATE_NORMAL, &color);
194 
195   gdk_color_parse ("blue", &color);
196   gtk_widget_modify_fg (label_name_val, GTK_STATE_NORMAL, &color);
197 #endif
198 
199 
200   /* -----  Now malloc -- but don't fill out -- space for sheets  ----- */
201   /* This basically sets up the overhead for the sheets, as I understand
202    * it.  The memory for the actual sheet cells is allocated later,
203    * when gtk_sheet_new is invoked, I think.  */
204   sheets = g_new0 (GtkSheet*, NUM_SHEETS);
205 
206 
207   /* Restore main window's geometry:
208   */
209   EdaConfig* cfg = eda_config_get_cache_context();
210 
211   gint x = eda_config_get_int (cfg, "attrib.window-geometry", "x", NULL);
212   gint y = eda_config_get_int (cfg, "attrib.window-geometry", "y", NULL);
213 
214   gtk_window_move (GTK_WINDOW (window), x, y);
215 
216   gint width  = eda_config_get_int (cfg, "attrib.window-geometry", "width",  NULL);
217   gint height = eda_config_get_int (cfg, "attrib.window-geometry", "height", NULL);
218 
219   if (width > 0 && height > 0)
220   {
221     gtk_window_resize (GTK_WINDOW (window), width, height);
222   }
223 
224 } /* x_window_init() */
225 
226 
227 /*!
228  * \brief File->Export CSV menu item
229  *
230  * Implement the File->Export CSV menu item
231  */
232 static void
menu_file_export_csv()233 menu_file_export_csv()
234 {
235   gint cur_page;
236 
237   /* first verify that we are on the correct page (components) */
238   cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
239 
240   /* Check that we are on components page. */
241   if (cur_page == 0) {
242     x_dialog_export_file();
243   } else {
244     x_dialog_unimplemented_feature();  /* We only support export
245                                           of components now */
246   }
247 }
248 
249 /*!
250  * \brief Edit->New attrib menu item
251  *
252  * Implement the New attrib menu item
253  */
254 static void
menu_edit_newattrib()255 menu_edit_newattrib()
256 {
257   gint cur_page;
258 
259   /* first verify that we are on the correct page (components) */
260   cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
261 
262   /* Check that we are on components page. */
263   if (cur_page == 0) {
264     x_dialog_newattrib();  /* This creates dialog box  */
265   }
266 }
267 
268 /*!
269  * \brief Edit->Delete Attribute menu item
270  *
271  * Implements the Delete Attribute menu item
272  */
273 static void
menu_edit_delattrib()274 menu_edit_delattrib()
275 {
276   x_dialog_delattrib();
277 }
278 
279 
280 /*!
281  * The main menu description
282  */
283 static const gchar menu[] =
284   "<menubar>"
285     "<menu action='file'>"
286       "<!-- <menuitem action='file-open' / > -->"
287       "<menuitem action='file-save' />"
288       "<menuitem action='file-export-csv' />"
289       "<separator/>"
290       "<!-- < menuitem action='file-print' / > -->"
291       "<!-- < separator / > -->"
292       "<menuitem action='file-quit' />"
293     "</menu>"
294 
295     "<menu action='edit'>"
296       "<menuitem action='edit-add-attrib' />"
297       "<menuitem action='edit-delete-attrib' />"
298       "<!-- < menuitem action='edit-find-attrib' / > -->"
299       "<!-- < menuitem action='edit-search-replace-attrib-value' / > -->"
300       "<!-- < menuitem action='edit-search-for-refdes' / > -->"
301     "</menu>"
302 
303     "<menu action='visibility'>"
304       "<menuitem action='visibility-invisible' />"
305       "<menuitem action='visibility-name-only' />"
306       "<menuitem action='visibility-value-only' />"
307       "<menuitem action='visibility-name-value' />"
308     "</menu>"
309 
310     "<menu action='help'>"
311       "<menuitem action='help-about' />"
312     "</menu>"
313   "</menubar>";
314 
315 
316 /*!
317  * The Gtk action table
318  */
319 static const GtkActionEntry actions[] = {
320   /* name, stock-id, label, accelerator, tooltip, callback function */
321   /* File menu */
322   { "file", NULL, "_File"},
323   { "file-save", GTK_STOCK_SAVE, "Save", "<Control>S", "", s_toplevel_save_sheet},
324   { "file-export-csv", NULL, "Export CSV", "", "", menu_file_export_csv},
325   /* { "file-print", GTK_STOCK_PRINT, "Print", "<Control>P", "", x_dialog_unimplemented_feature}, */
326   { "file-quit", GTK_STOCK_QUIT, "Quit", "<Control>Q", "", G_CALLBACK(attrib_really_quit)},
327 
328   /* Edit menu */
329   { "edit", NULL, "_Edit"},
330   { "edit-add-attrib", NULL, "Add new attrib column", "", "", menu_edit_newattrib},
331   { "edit-delete-attrib", NULL, "Delete attrib column", "", "", menu_edit_delattrib},
332   /* { "edit-find-attrib", GTK_STOCK_FIND, "Find attrib value", "<Control>F", "", x_dialog_unimplemented_feature}, */
333   /* { "edit-search-replace-attrib-value", NULL, "Search and replace attrib value", "", "", x_dialog_unimplemented_feature}, */
334   /* { "edit-search-for-refdes", NULL, "Search for refdes", "", "", x_dialog_unimplemented_feature}, */
335 
336   /* Visibility menu */
337   { "visibility", NULL, "_Visibility"},
338   { "visibility-invisible", NULL, "Set selected invisible", "", "", s_visibility_set_invisible},
339   { "visibility-name-only", NULL, "Set selected name visible only", "", "", s_visibility_set_name_only},
340   { "visibility-value-only", NULL, "Set selected value visible only", "", "", s_visibility_set_value_only},
341   { "visibility-name-value", NULL, "Set selected name and value visible", "", "", s_visibility_set_name_and_value},
342 
343   /* Help menu */
344   { "help", NULL, "_Help"},
345   { "help-about", GTK_STOCK_ABOUT, "About", "", "", x_dialog_about_dialog},
346 };
347 
348 
349 /*! \brief Create and attach the menu bar
350  *
351  * Create the menu bar and attach it to the main window.
352  *
353  *  First, the GtkActionGroup object is created and filled with
354  *  entries of type GtkActionEntry (each entry specifies a single
355  *  action, such as opening a file). Then the GtkUIManager object
356  *  is created and used to load the menu description.
357  *  Finally, the GtkAccelGroup is added to the
358  *  main window to enable keyboard accelerators and a pointer
359  *  to the menu bar is retrieved from the GtkUIManager object.
360  * \param window Window to add the menubar to
361  * \param [out] menubar Created menubar
362  */
363 static void
x_window_create_menu(GtkWindow * window,GtkWidget ** menubar)364 x_window_create_menu(GtkWindow *window, GtkWidget **menubar)
365 {
366   GtkUIManager *ui;
367   GtkActionGroup *action_group;
368   GError *error = NULL;
369 
370   /* Create and fill the action group object */
371   action_group = gtk_action_group_new("");
372   gtk_action_group_add_actions(action_group, actions, G_N_ELEMENTS(actions), NULL);
373 
374   /* Create the UI manager object */
375   ui = gtk_ui_manager_new();
376 
377   gtk_ui_manager_insert_action_group(ui, action_group, 0);
378   gtk_ui_manager_add_ui_from_string (ui, menu, -1, &error);
379 
380   if(error != NULL) {
381     /* An error occured, terminate */
382     fprintf(stderr, _("Error loading menu: %1$s\n"), error->message);
383     exit(1);
384   }
385 
386   gtk_window_add_accel_group (window, gtk_ui_manager_get_accel_group(ui));
387 
388   *menubar = gtk_ui_manager_get_widget(ui, "/ui/menubar/");
389 }
390 
391 
392 /*! \brief Add all items to the top level window
393  *
394  * This function updates the top level window
395  *         after a new page is read in.
396  *
397  *  It does the following:
398  *
399  *  -# Create a new gtksheet having the current dimensions.
400  *  -# Call x_gktsheet_add_row_labels(comp_count, master_*_list_head)
401  *  -# Call x_gktsheet_add_col_labels(comp_attrib_count, master_*_attrib_list_head)
402  *  -# Call x_gktsheet_add_row_labels(net_count, master_*_list_head)
403  *  -# Call x_gktsheet_add_col_labels(net_attrib_count, master_*_attrib_list_head)
404  *  -# loop on i, j -- call x_gtksheet_add_entry(i, j, attrib_value)
405  *  -# Call gtk_widget_show(window) to show new window.
406  */
407 void
x_window_add_items()408 x_window_add_items()
409 {
410   gint i, j;
411   gint num_rows, num_cols;
412   gchar *text;
413   const gchar *error_string;
414   gint visibility, show_name_value;
415 
416   /* Do these sanity check to prevent later segfaults */
417   if (sheet_head->comp_count == 0) {
418     error_string = _("No components found in entire design!\n"
419                      "Do you have refdeses on your components?");
420     x_dialog_fatal_error(error_string, 1);
421   }
422 
423   if (sheet_head->comp_attrib_count == 0) {
424     error_string = _("No configurable component attributes found in entire design!\n"
425                      "Please attach at least some attributes before running lepton-attrib.");
426     x_dialog_fatal_error(error_string, 2);
427   }
428 
429   if (sheet_head->pin_count == 0) {
430     error_string = _("No pins found on any components!\nPlease check your design.");
431     x_dialog_fatal_error(error_string, 3);
432   }
433 
434 
435   /*  initialize the gtksheet. */
436   x_gtksheet_init();  /* this creates a new gtksheet having dimensions specified
437                        * in sheet_head->comp_count, etc. . .  */
438 
439   if (sheet_head->comp_count > 0 ) {
440     x_gtksheet_add_row_labels(GTK_SHEET(sheets[0]),
441                               sheet_head->comp_count, sheet_head->master_comp_list_head);
442     x_gtksheet_add_col_labels(GTK_SHEET(sheets[0]),
443                               sheet_head->comp_attrib_count, sheet_head->master_comp_attrib_list_head);
444   }
445 
446 #ifdef UNIMPLEMENTED_FEATURES
447   /* This is not ready.  I need to implement net attributes */
448   if (sheet_head->net_count > 0 ) {
449     x_gtksheet_add_row_labels(GTK_SHEET(sheets[1]),
450                               sheet_head->net_count, sheet_head->master_net_list_head);
451     x_gtksheet_add_col_labels(GTK_SHEET(sheets[1]),
452                               sheet_head->net_attrib_count, sheet_head->master_net_attrib_list_head);
453   } else {
454     x_gtksheet_add_row_labels(GTK_SHEET(sheets[1]), 1, NULL);
455     x_gtksheet_add_col_labels(GTK_SHEET(sheets[1]), 1, NULL);
456   }
457 #endif
458 
459 #ifdef UNIMPLEMENTED_FEATURES
460   if (sheet_head->pin_count > 0 ) {
461     x_gtksheet_add_row_labels(GTK_SHEET(sheets[2]),
462                               sheet_head->pin_count, sheet_head->master_pin_list_head);
463     x_gtksheet_add_col_labels(GTK_SHEET(sheets[2]),
464                               sheet_head->pin_attrib_count, sheet_head->master_pin_attrib_list_head);
465   }
466 #endif
467 
468   /* ------ Comp sheet: put values in the individual cells ------- */
469   num_rows = sheet_head->comp_count;
470   num_cols = sheet_head->comp_attrib_count;
471   for (i = 0; i < num_rows; i++) {
472     for (j = 0; j < num_cols; j++) {
473       if ( (sheet_head->component_table)[i][j].attrib_value ) { /* NULL = no entry */
474         text = (gchar *) g_strdup( (sheet_head->component_table)[i][j].attrib_value );
475         visibility = (sheet_head->component_table)[i][j].visibility;
476         show_name_value = (sheet_head->component_table)[i][j].show_name_value;
477         x_gtksheet_add_cell_item( GTK_SHEET(sheets[0]), i, j, (gchar *) text,
478                                   visibility, show_name_value );
479         g_free(text);
480       }
481     }
482   }
483 
484 #ifdef UNIMPLEMENTED_FEATURES
485   /* ------ Net sheet: put values in the individual cells ------- */
486   num_rows = sheet_head->net_count;
487   num_cols = sheet_head->net_attrib_count;
488   for (i = 0; i < num_rows; i++) {
489     for (j = 0; j < num_cols; j++) {
490       if ( (sheet_head->net_table)[i][j].attrib_value ) { /* NULL = no entry */
491         text = (gchar *) g_strdup( (sheet_head->net_table)[i][j].attrib_value );
492         visibility = (sheet_head->net_table)[i][j].visibility;
493         show_name_value = (sheet_head->component_table)[i][j].show_name_value;
494         x_gtksheet_add_cell_item( GTK_SHEET(sheets[1]), i, j, (gchar *) text,
495                                   visibility, show_name_value );
496         g_free(text);
497       }
498     }
499   }
500 #endif
501 
502 #ifdef UNIMPLEMENTED_FEATURES
503   /* ------ Pin sheet: put pin attribs in the individual cells ------- */
504   num_rows = sheet_head->pin_count;
505   num_cols = sheet_head->pin_attrib_count;
506   for (i = 0; i < num_rows; i++) {
507     for (j = 0; j < num_cols; j++) {
508       if ( (sheet_head->pin_table)[i][j].attrib_value ) { /* NULL = no entry */
509         text = (gchar *) g_strdup( (sheet_head->pin_table)[i][j].attrib_value );
510         /* pins have no visibility attributes, must therefore provide default. */
511         x_gtksheet_add_cell_item( GTK_SHEET(sheets[2]), i, j, (gchar *) text,
512                                   VISIBLE, SHOW_VALUE );
513         g_free(text);
514       }
515     }
516   }
517 #endif
518 
519   gtk_widget_show_all( GTK_WIDGET(window) );
520 }
521 
522 
523 /*! \brief Set application icon
524  *
525  * Setup default icon for GTK windows
526  *
527  *  Sets the default window icon by name, to be found in the current icon
528  *  theme. The name used is #defined above as GATTRIB_THEME_ICON_NAME.
529  */
530 static void
x_window_set_default_icon(void)531 x_window_set_default_icon( void )
532 {
533   gtk_window_set_default_icon_name( GATTRIB_THEME_ICON_NAME );
534 }
535 
536 
537 /*! \brief Set the main window's title.
538  *
539  *  \param plist  The list of LeptonPage objects (opened pages).
540  */
541 static void
x_window_set_title(GList * plist)542 x_window_set_title (GList* plist)
543 {
544   g_return_if_fail (plist != NULL);
545   g_return_if_fail (window != NULL);
546 
547   const gchar* prog_name = "lepton-attrib";
548   gchar* title = NULL;
549 
550   if (g_list_length (plist) == 1)
551   {
552     const gchar* fpath = lepton_page_get_filename ((LeptonPage *) plist->data);
553     gchar* fname = g_path_get_basename (fpath);
554 
555     title = g_strdup_printf ("%s - %s", fname, prog_name);
556 
557     g_free (fname);
558   }
559   else
560   if (g_list_length (plist) > 1)
561   {
562     title = g_strdup_printf ("%s - %s", _("Multiple files"), prog_name);
563   }
564   else
565   {
566     title = g_strdup_printf ("%s", prog_name);
567   }
568 
569   gtk_window_set_title (GTK_WINDOW (window), title);
570   g_free (title);
571 }
572 
573 
574 /*! \brief Indicate if document has \a changed in the title.
575  */
576 void
x_window_set_title_changed(int changed)577 x_window_set_title_changed (int changed)
578 {
579   const gchar* title = gtk_window_get_title (GTK_WINDOW (window));
580   const gchar* prefix = "* ";
581 
582   if (changed)
583   {
584     if (!g_str_has_prefix (title, prefix))
585     {
586       gchar* title_new = g_strdup_printf ("%s%s", prefix, title);
587       gtk_window_set_title (GTK_WINDOW (window), title_new);
588       g_free (title_new);
589     }
590   }
591   else
592   {
593     if (g_str_has_prefix (title, prefix))
594     {
595       gchar* title_new = g_strdup (title + strlen (prefix));
596       gtk_window_set_title (GTK_WINDOW (window), title_new);
597       g_free (title_new);
598     }
599   }
600 }
601 
602 
603 /*! \brief Open lepton-attrib window.
604  *
605  * The function populates the spreadsheet data structure and
606  * updates GUI.
607  */
608 void
lepton_attrib_window()609 lepton_attrib_window ()
610 {
611   GList *iter;
612   LeptonPage *p_local;
613 
614   LeptonToplevel *toplevel = edascm_c_current_toplevel ();
615   x_window_set_toplevel (toplevel);
616 
617   /* Initialize GTK window. */
618   x_window_init ();
619 
620   /* Initialize SHEET_DATA data structure (sheet_head was declared
621      in globals.h) */
622   sheet_head = s_sheet_data_new();
623 
624   for (iter = lepton_list_get_glist (toplevel->pages);
625        iter != NULL;
626        iter = g_list_next (iter)) {
627 
628     p_local = (LeptonPage*) iter->data;
629     lepton_toplevel_set_page_current (toplevel, p_local);
630 
631     /* Now add all items found to the master lists */
632     s_sheet_data_add_master_comp_list_items (lepton_page_objects (p_local));
633     s_sheet_data_add_master_comp_attrib_list_items (lepton_page_objects (p_local));
634 #if 0
635     /* Note that this must be changed.  We need to input the entire project
636      * before doing anything with the nets because we need to first
637      * determine where they are all connected!   */
638     s_sheet_data_add_master_net_list_items (p_local->object_list);
639     s_sheet_data_add_master_net_attrib_list_items (p_local->object_list);
640 #endif
641 
642     s_sheet_data_add_master_pin_list_items (lepton_page_objects (p_local));
643     s_sheet_data_add_master_pin_attrib_list_items (lepton_page_objects (p_local));
644   }     /* end of loop over files     */
645 
646   /* ---------- Sort the master lists  ---------- */
647   s_string_list_sort_master_comp_list();
648   s_string_list_sort_master_comp_attrib_list();
649 
650 #if 0
651   /* Note that this must be changed.  We need to input the entire project
652    * before doing anything with the nets because we need to first
653    * determine where they are all connected!   */
654   s_string_list_sort_master_net_list();
655   s_string_list_sort_master_net_attrib_list();
656 #endif
657 
658   s_string_list_sort_master_pin_list();
659   s_string_list_sort_master_pin_attrib_list();
660 
661   /* ---------- Create and load the tables  ---------- */
662   sheet_head->component_table = s_table_new(sheet_head->comp_count, sheet_head->comp_attrib_count);
663   sheet_head->net_table = s_table_new(sheet_head->net_count, sheet_head->net_attrib_count);
664   sheet_head->pin_table = s_table_new(sheet_head->pin_count, sheet_head->pin_attrib_count);
665 
666   /* must iterate over all pages in design */
667   for ( iter = lepton_list_get_glist( toplevel->pages );
668         iter != NULL;
669         iter = g_list_next( iter ) ) {
670     p_local = (LeptonPage *)iter->data;
671 
672     /* only traverse pages which are toplevel */
673     if (p_local->page_control == 0) {
674       /* adds all components from page to comp_table */
675       s_table_add_toplevel_comp_items_to_comp_table (lepton_page_objects (p_local));
676 #if 0
677       /* Note that this must be changed.  We need to input the entire project
678        * before doing anything with the nets because we need to first
679        * determine where they are all connected!   */
680 
681       /* adds all nets from page to net_table */
682       s_table_add_toplevel_net_items_to_net_table(p_local->object_head);
683 #endif
684 
685       /* adds all pins from page to pin_table */
686       s_table_add_toplevel_pin_items_to_pin_table (lepton_page_objects (p_local));
687     }
688   } /* for loop over pages */
689 
690   /* -------------- update windows --------------- */
691   x_window_add_items();    /* This updates the top level stuff,
692                             * and then calls another fcn to update
693                             * the GtkSheet itself.  */
694 
695   /* ---------- Now verify correctness of entire design.  ---------- */
696   s_toplevel_verify_design(toplevel);  /* toplevel is a global */
697 
698   x_window_set_title (lepton_list_get_glist (toplevel->pages));
699 }
700