1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2008 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 /*------------------------------------------------------------------*/
22 * \brief Functions involved in manipulating the STRING_LIST
25 * This file holds functions involved in manipulating the STRING_LIST
26 * structure. STRING_LIST is basically a linked list of strings
29 * \todo This could be implemented using an underlying GList
30 * structure. The count parameter could also be eliminated -
31 * either store it in the struct or preferably, calculate it
32 * when needed - I don't think the speed penalty of traversing
33 * the list is significant at all. GDE
44 /*------------------------------------------------------------------
45 * Gattrib specific includes
46 *------------------------------------------------------------------*/
47 #include <libgeda/libgeda.h> /* geda library fcns */
48 #include "../include/struct.h" /* typdef and struct declarations */
49 #include "../include/prototype.h" /* function prototypes */
50 #include "../include/globals.h"
52 #ifdef HAVE_LIBDMALLOC
58 /*------------------------------------------------------------------*/
59 /*! \brief Return a pointer to a new STRING_LIST
61 * Returns a pointer to a new STRING_LIST struct. This list is empty.
62 * \returns pointer to the new STRING_LIST struct.
64 STRING_LIST
*s_string_list_new() {
65 STRING_LIST
*local_string_list
;
67 local_string_list
= g_malloc(sizeof(STRING_LIST
));
68 local_string_list
->data
= NULL
;
69 local_string_list
->next
= NULL
;
70 local_string_list
->prev
= NULL
;
71 local_string_list
->pos
= -1; /* can look for this later . . . */
73 return local_string_list
;
77 /*------------------------------------------------------------------*/
78 /*! \brief Duplicate a STRING_LIST
80 * Given a STRING_LIST, duplicate it and returns a pointer
81 * to the new, duplicate list.
82 * \param old_string_list pointer to the STRING_LIST to be duplicated
83 * \returns a pointer to the duplicate STRING_LIST
85 STRING_LIST
*s_string_list_duplicate_string_list(STRING_LIST
*old_string_list
) {
86 STRING_LIST
*new_string_list
;
87 STRING_LIST
*local_string_list
;
91 new_string_list
= s_string_list_new();
93 if (old_string_list
->data
== NULL
)
94 /* This is an empty string list */
95 return new_string_list
;
97 local_string_list
= old_string_list
;
98 while (local_string_list
!= NULL
) {
99 data
= g_strdup(local_string_list
->data
);
100 s_string_list_add_item(new_string_list
, &count
, data
);
102 local_string_list
= local_string_list
->next
;
105 return new_string_list
;
109 /*------------------------------------------------------------------*/
110 /*! \brief Add an item to a STRING_LIST
112 * Inserts the item into a STRING_LIST.
113 * It first passes through the
114 * list to make sure that there are no duplications.
115 * \param list pointer to STRING_LIST to be added to.
116 * \param count FIXME Don't know what this does - input or output? both?
117 * \param item pointer to string to be added
119 void s_string_list_add_item(STRING_LIST
*list
, int *count
, char *item
) {
121 gchar
*trial_item
= NULL
;
123 STRING_LIST
*local_list
;
126 fprintf(stderr
, "In s_string_list_add_item, tried to add to a NULL list.\n");
130 /* First check to see if list is empty. Handle insertion of first item
131 into empty list separately. (Is this necessary?) */
132 if (list
->data
== NULL
) {
134 printf("In s_string_list_add_item, about to place first item in list.\n");
136 list
->data
= (gchar
*) g_strdup(item
);
138 list
->prev
= NULL
; /* this may have already been initialized. . . . */
139 list
->pos
= *count
; /* This enumerates the pos on the list. Value is reset later by sorting. */
140 (*count
)++; /* increment count to 1 */
144 /* Otherwise, loop through list looking for duplicates */
146 while (list
!= NULL
) {
147 trial_item
= (gchar
*) g_strdup(list
->data
);
148 if (strcmp(trial_item
, item
) == 0) {
149 /* Found item already in list. Just return. */
158 /* If we are here, it's 'cause we didn't find the item pre-existing in the list. */
159 /* In this case, we insert it. */
161 local_list
= (STRING_LIST
*) g_malloc(sizeof(STRING_LIST
)); /* allocate space for this list entry */
162 local_list
->data
= (gchar
*) g_strdup(item
); /* copy data into list */
163 local_list
->next
= NULL
;
164 local_list
->prev
= prev
; /* point this item to last entry in old list */
165 prev
->next
= local_list
; /* make last item in old list point to this one. */
166 local_list
->pos
= *count
; /* This enumerates the pos on the list. Value is reset later by sorting. */
167 (*count
)++; /* increment count */
168 /* list = local_list; */
174 /*------------------------------------------------------------------*/
175 /*! \brief Delete an item from a STRING_LIST
177 * Deletes an item in a STRING_LIST.
178 * \param list pointer to STRING_LIST
179 * \param count pointer to count of items in list
180 * \param item item to remove from list
182 void s_string_list_delete_item(STRING_LIST
**list
, int *count
, gchar
*item
) {
184 gchar
*trial_item
= NULL
;
185 STRING_LIST
*list_item
;
186 STRING_LIST
*next_item
= NULL
;
187 STRING_LIST
*prev_item
= NULL
;
189 /* First check to see if list is empty. If empty, spew error and return */
190 if ( (*list
)->data
== NULL
) {
191 fprintf(stderr
, "In s_string_list_delete_item, tried to remove item from empty list\n");
196 printf("In s_string_list_delete_item, about to delete item %s from list.\n", item
);
199 /* Now loop through list looking for item */
201 while (list_item
!= NULL
) {
202 trial_item
= (gchar
*) g_strdup(list_item
->data
);
204 printf("In s_string_list_delete_item, matching item against trial item = %s from list.\n", trial_item
);
206 if (strcmp(trial_item
, item
) == 0) {
207 /* found item, now delete it. */
209 printf("In s_string_list_delete_item, found match . . . . . \n");
211 prev_item
= list_item
->prev
;
212 next_item
= list_item
->next
;
214 /* Check position in list */
215 if (next_item
== NULL
&& prev_item
== NULL
) {
216 /* pathological case of one item list. */
218 } else if (next_item
== NULL
&& prev_item
!= NULL
) {
220 prev_item
->next
= NULL
;
221 } else if (next_item
!= NULL
&& prev_item
== NULL
) {
222 /* at list's beginning */
223 next_item
->prev
= NULL
;
224 (*list
) = next_item
; /* also need to fix pointer to list head */
227 /* normal case of element in middle of list */
228 prev_item
->next
= next_item
;
229 next_item
->prev
= prev_item
;
233 printf("In s_string_list_delete_item, now free list_item\n");
235 g_free(list_item
); /* free current list item */
236 (*count
)--; /* decrement count */
237 /* Do we need to re-number the list? */
240 printf("In s_string_list_delete_item, now free trial_item\n");
242 g_free(trial_item
); /* free trial item before returning */
244 printf("In s_string_list_delete_item, returning . . . .\n");
249 list_item
= list_item
->next
;
252 /* If we are here, it's 'cause we didn't find the item.
253 * Spew error and return.
255 fprintf(stderr
, "In s_string_list_delete_item, couldn't delete item %s\n", item
);
260 /*------------------------------------------------------------------*/
261 /*! \brief Detect item in list
263 * Look for item in the list.
265 * \param list pointer to the STRING_LIST struct
266 * \param item string to search for
267 * \returns 0 if absent, 1 if present
269 int s_string_list_in_list(STRING_LIST
*list
, char *item
) {
271 gchar
*trial_item
= NULL
;
273 /* First check to see if list is empty. If empty, return
274 * 0 automatically. (I probably don't need to handle this
276 if (list
->data
== NULL
) {
280 /* Otherwise, loop through list looking for duplicates */
281 while (list
!= NULL
) {
282 trial_item
= (gchar
*) g_strdup(list
->data
);
283 if (strcmp(trial_item
, item
) == 0) {
284 /* Found item already in list. return 1. */
292 /* If we are here, it's 'cause we didn't find the item
293 * pre-existing in the list. In this case, return 0 */
299 /*------------------------------------------------------------------*/
300 /*! \brief Get an item from a STRING_LIST by index
302 * Returns the index'th item in the string list.
303 * \param list pointer to STRING_LIST to get from
304 * \param index index of item to return
305 * \returns NULL if there is a problem otherwise a pointer to
308 gchar
*s_string_list_get_data_at_index(STRING_LIST
*list
, gint index
)
311 STRING_LIST
*local_item
;
313 /* First check to see if list is empty. If empty, return
314 * NULL automatically. */
315 if (list
->data
== NULL
) {
320 for (i
= 0 ; i
< index
; i
++) {
321 if (local_item
== NULL
) {
324 local_item
= local_item
->next
;
327 return local_item
->data
;
331 /*------------------------------------------------------------------*/
332 /*! \brief Sort the master component list
334 * Takes the master comp list
335 * sheet_head->master_comp_list_head
336 * and sorts it in this order:
337 * <all refdeses in alphabetical order>
338 * Right now it does nothing other than fill in the "position"
339 * and "length" variables.
341 void s_string_list_sort_master_comp_list() {
343 STRING_LIST
*local_list
, *p
;
345 /* Here's where we do the sort. The sort is done using a fcn found on the web. */
346 local_list
= sheet_head
->master_comp_list_head
;
347 for (p
=local_list
; p
; p
=p
->next
)
349 local_list
= listsort(local_list
, 0, 1);
351 /* Do this after sorting is done. This resets the order of the individual items
353 while (local_list
!= NULL
) { /* make sure item is not null */
355 if (local_list
->next
!= NULL
) {
357 local_list
= local_list
->next
;
359 break; /* leave loop *before* iterating to NULL EOL marker */
363 /* Now go to first item in local list and reassign list head to new first element */
364 while (local_list
->prev
!= NULL
) {
365 local_list
= local_list
->prev
;
368 sheet_head
->master_comp_list_head
= local_list
;
374 /* This list overrides the alphanumeric sort. Attribs not found in
375 this list are sorted as if they had a value of DEFAULT_ATTRIB_POS
376 within this list, but alphanumerically relative to each other. */
380 } certain_attribs
[] = {
386 #define NUM_CERTAINS (sizeof(certain_attribs)/sizeof(certain_attribs[0]))
387 #define DEFAULT_ATTRIB_POS 100
389 /*------------------------------------------------------------------*/
390 /*! \brief Sort the master component attribute list
392 * Take the master comp attrib list
393 * sheet_head->master_comp_attrib_list_head
394 * and sort it in this order:
395 * <all refdeses in alphabetical order>
396 * Right now it does nothing other than fill in the "position"
397 * and "length" variables.
399 void s_string_list_sort_master_comp_attrib_list() {
401 STRING_LIST
*local_list
, *p
;
403 /* Here's where we do the sort */
404 local_list
= sheet_head
->master_comp_attrib_list_head
;
407 * Note that this sort is TBD -- it is more than just an alphabetic sort 'cause we want
408 * certain attribs to go first.
410 for (p
=local_list
; p
; p
=p
->next
) {
412 p
->pos
= DEFAULT_ATTRIB_POS
;
413 for (i
=0; i
<NUM_CERTAINS
; i
++)
414 if (p
->data
!= NULL
) {
415 if (strcmp (certain_attribs
[i
].attrib
, p
->data
) == 0)
417 p
->pos
= certain_attribs
[i
].pos
;
423 local_list
= listsort(local_list
, 0, 1);
424 sheet_head
->master_comp_attrib_list_head
= local_list
;
426 /* Do this after sorting is done. This resets the order of the individual items
428 while (local_list
!= NULL
) {
431 local_list
= local_list
->next
;
437 /*------------------------------------------------------------------*/
438 /*! \brief Sort the master netlist
440 * This fcn takes the master net list
441 * sheet_head->master_net_list_head
442 * and sorts it in this order:
443 * <all nets in alphabetical order>
445 void s_string_list_sort_master_net_list() {
447 STRING_LIST
*local_list
;
450 /* Do this after sorting is done. This resets the order of the individual items
452 local_list
= sheet_head
->master_net_list_head
;
453 while (local_list
!= NULL
) {
456 local_list
= local_list
->next
;
462 /*------------------------------------------------------------------*/
463 /*! \brief Sort the master net attribute list
465 * Take the master net attribute list
466 * sheet_head->master_net_attrib_list_head
467 * and sort it in this order:
468 * value, footprint, model-name, file,
469 * <all other attributes in alphabetical order>
471 /*------------------------------------------------------------------*/
472 void s_string_list_sort_master_net_attrib_list() {
474 STRING_LIST
*local_list
;
477 /* Do this after sorting is done. This resets the order of the individual items
479 local_list
= sheet_head
->master_net_attrib_list_head
;
480 while (local_list
!= NULL
) {
483 local_list
= local_list
->next
;
490 /*------------------------------------------------------------------*/
491 /*! \brief Sort the master pin list
493 * Take the master pin list
494 * sheet_head->master_pin_list_head
495 * and sorts it in this order:
496 * <all refdeses in alphabetical order>
497 * Right now it does nothing other than fill in the "position"
498 * and "length" variables.
500 /*------------------------------------------------------------------*/
501 void s_string_list_sort_master_pin_list() {
503 STRING_LIST
*local_list
, *p
;
505 /* Here's where we do the sort. The sort is done using a fcn found on the web. */
506 local_list
= sheet_head
->master_pin_list_head
;
507 for (p
=local_list
; p
; p
=p
->next
)
509 local_list
= listsort(local_list
, 0, 1);
511 /* Do this after sorting is done. This resets the order of the individual items
513 while (local_list
!= NULL
) { /* make sure item is not null */
515 if (local_list
->next
!= NULL
) {
517 local_list
= local_list
->next
;
519 break; /* leave loop *before* iterating to NULL EOL marker */
523 /* Now go to first item in local list and reassign list head to new first element */
524 while (local_list
->prev
!= NULL
) {
525 local_list
= local_list
->prev
;
528 sheet_head
->master_pin_list_head
= local_list
;
533 /*------------------------------------------------------------------*/
534 /*! \brief Sort the master pin attribute list
536 * Takes the master pin attrib list
537 * sheet_head->master_pin_attrib_list_head
538 * and sorts it in this order:
539 * <all pin attribs in alphabetical order>
540 * Right now it does nothing other than fill in the "position"
541 * and "length" variables.
543 /*------------------------------------------------------------------*/
544 void s_string_list_sort_master_pin_attrib_list() {
546 STRING_LIST
*local_list
;
548 /* Here's where we do the sort */
551 * Note that this sort is TBD -- it is more than just an alphabetic sort 'cause we want
552 * certain attribs to go first.
556 /* Do this after sorting is done. This resets the order of the individual items
558 local_list
= sheet_head
->master_pin_attrib_list_head
;
559 while (local_list
!= NULL
) {
562 local_list
= local_list
->next
;