1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003 -- 2007 Stuart D. Brorson.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*------------------------------------------------------------------
21 * This file holds fcns involved in manipulating an entire SHEET_DATA
22 * structure. The SHEET_DATA structure is the intermediate structure
23 * between TOPLEVEL (gEDA's native format) and the graphical gtksheet
24 * widget (from gtkextra), which is the spreadsheet widget displaying
26 *------------------------------------------------------------------*/
36 /*------------------------------------------------------------------
37 * Gattrib specific includes
38 *------------------------------------------------------------------*/
39 #include <libgeda/libgeda.h> /* geda library fcns */
40 #include "../include/struct.h" /* typdef and struct declarations */
41 #include "../include/prototype.h" /* function prototypes */
42 #include "../include/globals.h"
44 #ifdef HAVE_LIBDMALLOC
49 /*------------------------------------------------------------------*/
50 /*! \brief This fcn is the sheet_data creator.
51 * It returns a pointer to
52 * an initialized SHEET_DATA struct.
54 *------------------------------------------------------------------*/
55 SHEET_DATA
*s_sheet_data_new()
57 SHEET_DATA
*new_sheet
;
59 new_sheet
= (SHEET_DATA
*) g_malloc(sizeof(SHEET_DATA
));
61 /* We will malloc and fill out the comp table later. */
62 new_sheet
->component_table
= NULL
;
64 /* We will malloc and fill out the net table later. */
65 new_sheet
->net_table
= NULL
;
67 /* We will malloc and fill out the pin table later. */
68 new_sheet
->pin_table
= NULL
;
70 /* Now we create the first cell in each master list. */
71 new_sheet
->master_comp_list_head
= (STRING_LIST
*) s_string_list_new();
72 new_sheet
->master_comp_attrib_list_head
= (STRING_LIST
*) s_string_list_new();
73 new_sheet
->comp_count
= 0;
74 new_sheet
->comp_attrib_count
= 0;
76 new_sheet
->master_net_list_head
= (STRING_LIST
*) s_string_list_new();
77 new_sheet
->master_net_attrib_list_head
= (STRING_LIST
*) s_string_list_new();
78 new_sheet
->net_count
= 0;
79 new_sheet
->net_attrib_count
= 0;
81 new_sheet
->master_pin_list_head
= (STRING_LIST
*) s_string_list_new();
82 new_sheet
->master_pin_attrib_list_head
= (STRING_LIST
*) s_string_list_new();
83 new_sheet
->pin_count
= 0;
84 new_sheet
->pin_attrib_count
= 0;
86 new_sheet
->CHANGED
= FALSE
;
92 static void add_component_one(OBJECT
*o_current
, void *userdata
)
94 SHEET_DATA
*sheet
= userdata
;
97 printf("In s_sheet_data_add_master_comp_list_items, examining o_current->name = %s\n", o_current
->name
);
100 /*----- only process if this is a component with attributes ----*/
101 if (o_current
->type
== OBJ_COMPLEX
&&
102 o_current
->attribs
!= NULL
) {
106 printf(" In s_sheet_data_add_master_comp_list_items; found component on page\n");
107 printf(". . . . complex_basename = %s.\n", o_current
->complex_basename
);
111 temp_uref
= s_attrib_get_refdes(o_current
);
113 /* Now that we have refdes, store refdes and attach attrib list to component */
116 printf(" In s_sheet_add_master_comp_list, about to add to master list refdes = %s\n", temp_uref
);
118 s_string_list_add_item(sheet
->master_comp_list_head
,
119 &sheet
->comp_count
, temp_uref
);
122 } /* if (o_current->type == OBJ_COMPLEX . . . . .) */
125 /*------------------------------------------------------------------*/
126 /*! \brief This fcn adds to the master list of
127 * components refdeses by running
128 * through the components and recording the comp refdeses
129 * it discovers. Then it sorts them into alphabetical order.
130 * Data struct being searched is:
131 * OBJECT->attribs(->next. . .)->object->text->string
133 *------------------------------------------------------------------*/
134 void s_sheet_data_add_master_comp_list_items(SHEET_DATA
*sheet
, PAGE
*page
) {
136 printf("=========== Just entered s_sheet_data_add_master_comp_list_items! ==============\n");
140 printf("- Starting master comp list creation.\n");
143 /* ----- Iterate through all objects found on page looking for components ----- */
144 s_visit_page(page
, &add_component_one
, sheet
, VISIT_UNORDERED
, 1);
148 /*------------------------------------------------------------------*/
149 /*! \brief This fcn adds to the master list of comp attribs by running
150 * through each component on the page and recording all attribs
151 * it discovers. Then it sorts them into an order used for the
152 * horiz listing of the attribs on the spreadsheet.
153 * Data struct being searched is:
154 * sheet_head->component_list_head->attrib->name;
156 *------------------------------------------------------------------*/
157 void s_sheet_data_add_master_comp_attrib_list_items(OBJECT
*start_obj
) {
158 char const *attrib_text
;
167 printf("=========== Just entered s_sheet_data_add_master_comp_attrib_list_items! ==============\n");
171 printf("- Starting master comp attrib list creation.\n");
174 /* ----- Iterate through all objects found on page looking for components (OBJ_COMPLEX) ----- */
175 o_current
= start_obj
;
176 while (o_current
!= NULL
) {
179 printf("In s_sheet_data_add_master_comp_attrib_list_items, examining o_current->name = %s\n", o_current
->name
);
182 /*----- only process if this is a component with attributes ----*/
183 if (o_current
->type
== OBJ_COMPLEX
&&
184 o_current
->attribs
!= NULL
) {
188 /*------ Iterate through all attribs found on component -----*/
189 a_iter
= o_current
->attribs
; /* This has a side effect. Why? */
190 while (a_iter
!= NULL
) {
191 a_current
= a_iter
->data
;
192 if (a_current
->type
== OBJ_TEXT
193 && a_current
->text
!= NULL
) { /* found an attribute */
194 attrib_text
= o_text_get_string(a_current
);
195 attrib_name
= u_basic_breakup_string(attrib_text
, '=', 0);
197 /* Don't include "refdes" or "slot" because they form the row name */
198 /* Also don't include "net" per bug found by Steve W. -- 4.3.2007, SDB */
199 if ( (strcmp(attrib_name
, "refdes") != 0) &&
200 (strcmp(attrib_name
, "net") != 0) &&
201 (strcmp(attrib_name
, "slot") != 0) ) {
203 printf(" . . . from this component, about to add to master comp attrib list attrib = %s\n", attrib_name
);
205 s_string_list_add_item(sheet_head
->master_comp_attrib_list_head
,
206 &(sheet_head
->comp_attrib_count
), attrib_name
);
207 } /* if (strcmp(attrib_name, "refdes") != 0) */
210 a_iter
= g_list_next (a_iter
);
213 } /* if (o_current->type == OBJ_COMPLEX) */
215 o_current
= o_current
->next
;
216 } /* while (o_current != NULL) */
218 /* ----- Now sort component list into alphabetical order ----- */
225 /*------------------------------------------------------------------*/
226 /*! \brief This fcn builds the master list of net names by running
227 * through the individual cells and recording the net refdeses
229 * It's currently empty, waiting for implementation of net
232 *------------------------------------------------------------------*/
233 void s_sheet_data_add_master_net_list_items(OBJECT
*start_obj
) {
238 /*------------------------------------------------------------------*/
239 /*! \brief This fcn builds the master list of net attribs.
240 * It's currently empty, waiting for implementation of net
243 *------------------------------------------------------------------*/
244 void s_sheet_data_add_master_net_attrib_list_items(OBJECT
*start_obj
) {
249 /*------------------------------------------------------------------*/
250 /*! \brief This fcn builds the master
251 * list of pin names. It writes the
252 * label refdes:pinnumber into the global master pin list.
254 * 1. Loop on o_current looking for OBJ_COMPLEX
255 * 2. When we find a complex, save the refdes.
256 * 3. Dive down to o_lower_current = o_current->complex->prim_objs
257 * 4. Loop on o_lower_current looking for OBJ_PIN
258 * 5. When we find a pin, find the pinnumber by calling
259 * o_attrib_search_name_single(o_lower_current, "pinnumber", NULL)
260 * 6. Create the pin list label as "refdes=XXX", and stick it into
261 * the master pin list.
262 * Since this fcn operates on the global sheet_data->master_pin_list,
263 * it doesn't return a value.
265 *------------------------------------------------------------------*/
266 void s_sheet_data_add_master_pin_list_items(OBJECT
*start_obj
) {
268 char *temp_pinnumber
;
271 OBJECT
*o_lower_current
;
276 printf("=========== Just entered s_sheet_data_add_master_pin_list_items! ==============\n");
280 printf("- Starting master pin list creation.\n");
283 /* ----- Iterate through all objects found on page looking for components ----- */
284 o_current
= start_obj
;
285 while (o_current
!= NULL
) {
288 printf("In s_sheet_data_add_master_pin_list_items, examining o_current->name = %s\n", o_current
->name
);
291 if (o_current
->type
== OBJ_COMPLEX
) {
292 temp_uref
= s_attrib_get_refdes(o_current
);
293 if (temp_uref
!= NULL
) { /* make sure object complex has a refdes */
295 /* ----- Now iterate through lower level objects looking for pins. ----- */
296 o_lower_current
= o_current
->complex->prim_objs
;
297 while (o_lower_current
!= NULL
) {
299 printf("In s_sheet_data_add_master_pin_list_items, examining object name %s\n", o_lower_current
->name
);
301 if (o_lower_current
->type
== OBJ_PIN
) {
302 temp_pinnumber
= o_attrib_search_name_single(o_lower_current
, "pinnumber", NULL
);
304 if( temp_pinnumber
!= NULL
) {
305 row_label
= g_strconcat(temp_uref
, ":", temp_pinnumber
, NULL
);
307 printf("In s_sheet_data_add_master_pin_list_items, about to add to master pin list row_label = %s\n", row_label
);
309 s_string_list_add_item(sheet_head
->master_pin_list_head
, &(sheet_head
->pin_count
), row_label
);
311 } else { /* didn't find pinnumber. Report error to log. */
312 fprintf(stderr
, "In s_sheet_data_add_master_pin_list_items, found component pin with no pinnumber.\n");
314 fprintf(stderr
, ". . . . refdes = %s.\n", temp_uref
);
317 g_free(temp_pinnumber
);
320 o_lower_current
= o_lower_current
->next
;
321 } /* while (o_lower_current != NULL) */
323 } else { /* didn't find refdes. Report error to log. */
325 fprintf(stderr
, "In s_sheet_data_add_master_pin_list_items, found component with no refdes.\n");
326 fprintf(stderr
, ". . . . complex_basename = %s.\n", o_current
->complex_basename
);
331 } /* if (o_current->type == OBJ_COMPLEX) */
332 o_current
= o_current
->next
;
334 } /* while o_current != NULL */
340 /*------------------------------------------------------------------*/
341 /*! \brief This fcn builds the master
342 * list of pin attributes. It writes
343 * each attrib name into the master pin attrib list.
345 * 1. Loop on o_current looking for OBJ_COMPLEX
346 * 2. When we find a complex, save the refdes.
347 * 3. Dive down to o_lower_current = o_current->complex->prim_objs
348 * 4. Loop on o_lower_current looking for OBJ_PIN
349 * 5. When we find a pin, get pin_attribs = o_lower_current->attribs
350 * 6. Loop on attribs looking for non-NULL text.
351 * 7. When we find a non-NULL text attrib, extract the attrib name
352 * and stick it in the master pin attrib list.
354 *------------------------------------------------------------------*/
355 void s_sheet_data_add_master_pin_attrib_list_items(OBJECT
*start_obj
) {
357 char const *attrib_text
;
361 OBJECT
*o_lower_current
;
368 printf("=========== Just entered s_sheet_data_add_master_pin_attrib_list_items! ==============\n");
372 printf("- Starting master pin attrib list creation.\n");
375 /* ----- Iterate through all objects found on page looking for components ----- */
376 o_current
= start_obj
;
377 while (o_current
!= NULL
) {
380 printf("In s_sheet_data_add_master_pin_attrib_list_items, examining o_current->name = %s\n", o_current
->name
);
383 if (o_current
->type
== OBJ_COMPLEX
) {
384 temp_uref
= s_attrib_get_refdes(o_current
);
385 if (temp_uref
!= NULL
) { /* make sure object complex has a refdes */
387 /* ----- Now iterate through lower level objects looking for pins. ----- */
388 o_lower_current
= o_current
->complex->prim_objs
;
389 while (o_lower_current
!= NULL
) {
391 printf("In s_sheet_data_add_master_pin_attrib_list_items, examining component refdes = %s\n", temp_uref
);
393 if (o_lower_current
->type
== OBJ_PIN
) {
394 /* ----- Found a pin. Now get attrib head and loop on attribs. ----- */
395 a_iter
= o_lower_current
->attribs
;
396 while (a_iter
!= NULL
) {
397 pin_attrib
= a_iter
->data
;
398 if (pin_attrib
->type
== OBJ_TEXT
399 && pin_attrib
->text
!= NULL
) { /* found an attribute */
400 attrib_text
= o_text_get_string(pin_attrib
);
401 attrib_name
= u_basic_breakup_string(attrib_text
, '=', 0);
402 attrib_value
= s_misc_remaining_string(attrib_text
, '=', 1);
403 if ( (strcmp(attrib_name
, "pinnumber") != 0)
404 && (attrib_value
!= NULL
) ) {
405 /* Don't include "pinnumber" because it is already in other master list.
406 * Also guard against pathological symbols which have non-attrib text inside pins. */
409 printf("In s_sheet_data_add_master_pin_attrib_list_items, found pin attrib = %s\n", attrib_name
);
410 printf(". . . . . adding it to master_pin_attrib_list\n");
413 s_string_list_add_item(sheet_head
->master_pin_attrib_list_head
,
414 &(sheet_head
->pin_attrib_count
), attrib_name
);
415 } /* if (strcmp(attrib_name, "pinnumber") != 0) */
416 g_free(attrib_value
);
419 a_iter
= g_list_next (a_iter
);
420 } /* while (pin_attrib != NULL) */
422 o_lower_current
= o_lower_current
->next
;
423 } /* while (o_lower_current != NULL) */
426 } /* if (temp_uref != NULL ) */
428 } /* if (o_current->type == OBJ_COMPLEX) */
429 o_current
= o_current
->next
;
431 } /* while (o_current != NULL) */
439 /*------------------------------------------------------------------*/
440 /*! \brief This fcn extracts the attribs from the gtksheet
441 * cells, and places them back into SHEET_DATA. This is the
442 * first step in saving out a project. Right now I just invoke
443 * s_table_gtksheet_to_table. Do I need to do anything else here?
445 *------------------------------------------------------------------*/
446 void s_sheet_data_gtksheet_to_sheetdata() {
447 s_table_gtksheet_to_all_tables();
448 /* do I need to do anything else here? */