Take advantage of s_visit_page.
[geda-gaf/berndj.git] / gattrib / src / s_sheet_data.c
blob1c173e36b25f10ba7bb19de97664781f26260057
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
25 * the attribs.
26 *------------------------------------------------------------------*/
28 #include <config.h>
30 #include <stdio.h>
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif
34 #include <math.h>
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
45 #include <dmalloc.h>
46 #endif
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;
88 return (new_sheet);
92 static void add_component_one(OBJECT *o_current, void *userdata)
94 SHEET_DATA *sheet = userdata;
96 #ifdef DEBUG
97 printf("In s_sheet_data_add_master_comp_list_items, examining o_current->name = %s\n", o_current->name);
98 #endif
100 /*----- only process if this is a component with attributes ----*/
101 if (o_current->type == OBJ_COMPLEX &&
102 o_current->attribs != NULL) {
103 char *temp_uref;
105 #if DEBUG
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);
108 #endif
109 verbose_print(" C");
111 temp_uref = s_attrib_get_refdes(o_current);
113 /* Now that we have refdes, store refdes and attach attrib list to component */
114 if (temp_uref) {
115 #if DEBUG
116 printf(" In s_sheet_add_master_comp_list, about to add to master list refdes = %s\n", temp_uref);
117 #endif
118 s_string_list_add_item(sheet->master_comp_list_head,
119 &sheet->comp_count, temp_uref);
120 g_free(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) {
135 #ifdef DEBUG
136 printf("=========== Just entered s_sheet_data_add_master_comp_list_items! ==============\n");
137 #endif
139 if (verbose_mode) {
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;
159 char *attrib_name;
160 OBJECT *o_current;
161 GList *a_iter;
162 OBJECT *a_current;
164 #ifdef DEBUG
165 fflush(stderr);
166 fflush(stdout);
167 printf("=========== Just entered s_sheet_data_add_master_comp_attrib_list_items! ==============\n");
168 #endif
170 if (verbose_mode) {
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) {
178 #ifdef DEBUG
179 printf("In s_sheet_data_add_master_comp_attrib_list_items, examining o_current->name = %s\n", o_current->name);
180 #endif
182 /*----- only process if this is a component with attributes ----*/
183 if (o_current->type == OBJ_COMPLEX &&
184 o_current->attribs != NULL) {
186 verbose_print(" C");
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) ) {
202 #if DEBUG
203 printf(" . . . from this component, about to add to master comp attrib list attrib = %s\n", attrib_name);
204 #endif
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) */
208 g_free(attrib_name);
210 a_iter = g_list_next (a_iter);
211 } /* while */
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 ----- */
220 return;
225 /*------------------------------------------------------------------*/
226 /*! \brief This fcn builds the master list of net names by running
227 * through the individual cells and recording the net refdeses
228 * it discovers.
229 * It's currently empty, waiting for implementation of net
230 * attributes.
232 *------------------------------------------------------------------*/
233 void s_sheet_data_add_master_net_list_items(OBJECT *start_obj) {
234 return;
238 /*------------------------------------------------------------------*/
239 /*! \brief This fcn builds the master list of net attribs.
240 * It's currently empty, waiting for implementation of net
241 * attributes.
243 *------------------------------------------------------------------*/
244 void s_sheet_data_add_master_net_attrib_list_items(OBJECT *start_obj) {
245 return;
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.
253 * Algorithm:
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) {
267 char *temp_uref;
268 char *temp_pinnumber;
269 char *row_label;
270 OBJECT *o_current;
271 OBJECT *o_lower_current;
273 #ifdef DEBUG
274 fflush(stderr);
275 fflush(stdout);
276 printf("=========== Just entered s_sheet_data_add_master_pin_list_items! ==============\n");
277 #endif
279 if (verbose_mode) {
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) {
287 #ifdef DEBUG
288 printf("In s_sheet_data_add_master_pin_list_items, examining o_current->name = %s\n", o_current->name);
289 #endif
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) {
298 #if DEBUG
299 printf("In s_sheet_data_add_master_pin_list_items, examining object name %s\n", o_lower_current->name);
300 #endif
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);
306 #if DEBUG
307 printf("In s_sheet_data_add_master_pin_list_items, about to add to master pin list row_label = %s\n", row_label);
308 #endif
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");
313 #ifdef DEBUG
314 fprintf(stderr, ". . . . refdes = %s.\n", temp_uref);
315 #endif
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. */
324 #ifdef DEBUG
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);
327 #endif
329 g_free(temp_uref);
331 } /* if (o_current->type == OBJ_COMPLEX) */
332 o_current = o_current->next;
334 } /* while o_current != NULL */
336 return;
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.
344 * Algorithm:
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) {
356 char *temp_uref;
357 char const *attrib_text;
358 char *attrib_name;
359 char *attrib_value;
360 OBJECT *o_current;
361 OBJECT *o_lower_current;
362 GList *a_iter;
363 OBJECT *pin_attrib;
365 #ifdef DEBUG
366 fflush(stderr);
367 fflush(stdout);
368 printf("=========== Just entered s_sheet_data_add_master_pin_attrib_list_items! ==============\n");
369 #endif
371 if (verbose_mode) {
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) {
379 #ifdef DEBUG
380 printf("In s_sheet_data_add_master_pin_attrib_list_items, examining o_current->name = %s\n", o_current->name);
381 #endif
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) {
390 #if DEBUG
391 printf("In s_sheet_data_add_master_pin_attrib_list_items, examining component refdes = %s\n", temp_uref);
392 #endif
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. */
408 #if DEBUG
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");
411 #endif
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);
417 g_free(attrib_name);
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) */
425 g_free(temp_uref);
426 } /* if (temp_uref != NULL ) */
428 } /* if (o_current->type == OBJ_COMPLEX) */
429 o_current = o_current->next;
431 } /* while (o_current != NULL) */
432 return;
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? */
450 return;