gattrib
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gattrib -- gEDA component and net attribute manipulation using spreadsheet. 00003 * Copyright (C) 2003-2010 Stuart D. Brorson. 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 */ 00019 00020 /*------------------------------------------------------------------*/ 00036 #include <config.h> 00037 00038 #include <stdio.h> 00039 #ifdef HAVE_STRING_H 00040 #include <string.h> 00041 #endif 00042 #include <math.h> 00043 00044 /*------------------------------------------------------------------ 00045 * Gattrib specific includes 00046 *------------------------------------------------------------------*/ 00047 #include <libgeda/libgeda.h> /* geda library fcns */ 00048 #include "../include/struct.h" /* typdef and struct declarations */ 00049 #include "../include/prototype.h" /* function prototypes */ 00050 #include "../include/globals.h" 00051 00052 #ifdef HAVE_LIBDMALLOC 00053 #include <dmalloc.h> 00054 #endif 00055 00056 00057 00058 /*------------------------------------------------------------------*/ 00064 STRING_LIST *s_string_list_new() { 00065 STRING_LIST *local_string_list; 00066 00067 local_string_list = g_malloc(sizeof(STRING_LIST)); 00068 local_string_list->data = NULL; 00069 local_string_list->next = NULL; 00070 local_string_list->prev = NULL; 00071 local_string_list->pos = -1; /* can look for this later . . . */ 00072 00073 return local_string_list; 00074 } 00075 00076 00077 /*------------------------------------------------------------------*/ 00085 STRING_LIST *s_string_list_duplicate_string_list(STRING_LIST *old_string_list) { 00086 STRING_LIST *new_string_list; 00087 STRING_LIST *local_string_list; 00088 char *data; 00089 gint count; 00090 00091 new_string_list = s_string_list_new(); 00092 00093 if (old_string_list->data == NULL) 00094 /* This is an empty string list */ 00095 return new_string_list; 00096 00097 local_string_list = old_string_list; 00098 while (local_string_list != NULL) { 00099 data = g_strdup(local_string_list->data); 00100 s_string_list_add_item(new_string_list, &count, data); 00101 g_free(data); 00102 local_string_list = local_string_list->next; 00103 } 00104 00105 return new_string_list; 00106 } 00107 00108 00109 /*------------------------------------------------------------------*/ 00119 void s_string_list_add_item(STRING_LIST *list, int *count, char *item) { 00120 00121 gchar *trial_item = NULL; 00122 STRING_LIST *prev; 00123 STRING_LIST *local_list; 00124 00125 if (list == NULL) { 00126 fprintf(stderr, "In s_string_list_add_item, tried to add to a NULL list.\n"); 00127 return; 00128 } 00129 00130 /* First check to see if list is empty. Handle insertion of first item 00131 into empty list separately. (Is this necessary?) */ 00132 if (list->data == NULL) { 00133 #ifdef DEBUG 00134 printf("In s_string_list_add_item, about to place first item in list.\n"); 00135 #endif 00136 list->data = (gchar *) g_strdup(item); 00137 list->next = NULL; 00138 list->prev = NULL; /* this may have already been initialized. . . . */ 00139 list->pos = *count; /* This enumerates the pos on the list. Value is reset later by sorting. */ 00140 (*count)++; /* increment count to 1 */ 00141 return; 00142 } 00143 00144 /* Otherwise, loop through list looking for duplicates */ 00145 prev = list; 00146 while (list != NULL) { 00147 trial_item = (gchar *) g_strdup(list->data); 00148 if (strcmp(trial_item, item) == 0) { 00149 /* Found item already in list. Just return. */ 00150 g_free(trial_item); 00151 return; 00152 } 00153 g_free(trial_item); 00154 prev = list; 00155 list = list->next; 00156 } 00157 00158 /* If we are here, it's 'cause we didn't find the item pre-existing in the list. */ 00159 /* In this case, we insert it. */ 00160 00161 local_list = (STRING_LIST *) g_malloc(sizeof(STRING_LIST)); /* allocate space for this list entry */ 00162 local_list->data = (gchar *) g_strdup(item); /* copy data into list */ 00163 local_list->next = NULL; 00164 local_list->prev = prev; /* point this item to last entry in old list */ 00165 prev->next = local_list; /* make last item in old list point to this one. */ 00166 local_list->pos = *count; /* This enumerates the pos on the list. Value is reset later by sorting. */ 00167 (*count)++; /* increment count */ 00168 /* list = local_list; */ 00169 return; 00170 00171 } 00172 00173 00174 /*------------------------------------------------------------------*/ 00182 void s_string_list_delete_item(STRING_LIST **list, int *count, gchar *item) { 00183 00184 gchar *trial_item = NULL; 00185 STRING_LIST *list_item; 00186 STRING_LIST *next_item = NULL; 00187 STRING_LIST *prev_item = NULL; 00188 00189 /* First check to see if list is empty. If empty, spew error and return */ 00190 if ( (*list)->data == NULL) { 00191 fprintf(stderr, "In s_string_list_delete_item, tried to remove item from empty list\n"); 00192 return; 00193 } 00194 00195 #ifdef DEBUG 00196 printf("In s_string_list_delete_item, about to delete item %s from list.\n", item); 00197 #endif 00198 00199 /* Now loop through list looking for item */ 00200 list_item = (*list); 00201 while (list_item != NULL) { 00202 trial_item = (gchar *) g_strdup(list_item->data); 00203 #ifdef DEBUG 00204 printf("In s_string_list_delete_item, matching item against trial item = %s from list.\n", trial_item); 00205 #endif 00206 if (strcmp(trial_item, item) == 0) { 00207 /* found item, now delete it. */ 00208 #ifdef DEBUG 00209 printf("In s_string_list_delete_item, found match . . . . . \n"); 00210 #endif 00211 prev_item = list_item->prev; 00212 next_item = list_item->next; 00213 00214 /* Check position in list */ 00215 if (next_item == NULL && prev_item == NULL) { 00216 /* pathological case of one item list. */ 00217 (*list) = NULL; 00218 } else if (next_item == NULL && prev_item != NULL) { 00219 /* at list's end */ 00220 prev_item->next = NULL; 00221 } else if (next_item != NULL && prev_item == NULL) { 00222 /* at list's beginning */ 00223 next_item->prev = NULL; 00224 (*list) = next_item; /* also need to fix pointer to list head */ 00225 /* g_free(list); */ 00226 } else { 00227 /* normal case of element in middle of list */ 00228 prev_item->next = next_item; 00229 next_item->prev = prev_item; 00230 } 00231 00232 #ifdef DEBUG 00233 printf("In s_string_list_delete_item, now free list_item\n"); 00234 #endif 00235 g_free(list_item); /* free current list item */ 00236 (*count)--; /* decrement count */ 00237 /* Do we need to re-number the list? */ 00238 00239 #ifdef DEBUG 00240 printf("In s_string_list_delete_item, now free trial_item\n"); 00241 #endif 00242 g_free(trial_item); /* free trial item before returning */ 00243 #ifdef DEBUG 00244 printf("In s_string_list_delete_item, returning . . . .\n"); 00245 #endif 00246 return; 00247 } 00248 g_free(trial_item); 00249 list_item = list_item->next; 00250 } 00251 00252 /* If we are here, it's 'cause we didn't find the item. 00253 * Spew error and return. 00254 */ 00255 fprintf(stderr, "In s_string_list_delete_item, couldn't delete item %s\n", item); 00256 return; 00257 00258 } 00259 00260 /*------------------------------------------------------------------*/ 00269 int s_string_list_in_list(STRING_LIST *list, char *item) { 00270 00271 gchar *trial_item = NULL; 00272 00273 /* First check to see if list is empty. If empty, return 00274 * 0 automatically. (I probably don't need to handle this 00275 * separately.) */ 00276 if (list->data == NULL) { 00277 return 0; 00278 } 00279 00280 /* Otherwise, loop through list looking for duplicates */ 00281 while (list != NULL) { 00282 trial_item = (gchar *) g_strdup(list->data); 00283 if (strcmp(trial_item, item) == 0) { 00284 /* Found item already in list. return 1. */ 00285 g_free(trial_item); 00286 return 1; 00287 } 00288 g_free(trial_item); 00289 list = list->next; 00290 } 00291 00292 /* If we are here, it's 'cause we didn't find the item 00293 * pre-existing in the list. In this case, return 0 */ 00294 return 0; 00295 00296 } 00297 00298 00299 /*------------------------------------------------------------------*/ 00309 gint s_string_list_find_in_list(STRING_LIST *list, char *item) { 00310 00311 gint index = 0; 00312 gchar *trial_item = NULL; 00313 00314 /* First check to see if list is empty. If empty, return -1. */ 00315 if (list->data == NULL) { 00316 return -1; 00317 } 00318 00319 /* Otherwise, loop through list looking for the item */ 00320 while (list != NULL) { 00321 trial_item = (gchar *) g_strdup(list->data); 00322 if (strcmp(trial_item, item) == 0) { 00323 /* Found item in list; return index. */ 00324 g_free(trial_item); 00325 return index; 00326 } 00327 g_free(trial_item); 00328 list = list->next; 00329 index++; 00330 } 00331 00332 /* If we are here, it's 'cause we didn't find the item 00333 * pre-existing in the list. In this case, return -1 */ 00334 return -1; 00335 00336 } 00337 00338 00339 /*------------------------------------------------------------------*/ 00348 gchar *s_string_list_get_data_at_index(STRING_LIST *list, gint index) 00349 { 00350 gint i; 00351 STRING_LIST *local_item; 00352 00353 /* First check to see if list is empty. If empty, return 00354 * NULL automatically. */ 00355 if (list->data == NULL) { 00356 return NULL; 00357 } 00358 00359 local_item = list; 00360 for (i = 0 ; i < index ; i++) { 00361 if (local_item == NULL) { 00362 return NULL; 00363 } else { 00364 local_item = local_item->next; 00365 } 00366 } 00367 return local_item->data; 00368 } 00369 00370 00371 /*------------------------------------------------------------------*/ 00381 void s_string_list_sort_master_comp_list() { 00382 int i = 0; 00383 STRING_LIST *local_list, *p; 00384 00385 /* Here's where we do the sort. The sort is done using a fcn found on the web. */ 00386 local_list = sheet_head->master_comp_list_head; 00387 for (p=local_list; p; p=p->next) 00388 p->pos = 0; 00389 local_list = listsort(local_list, 0, 1); 00390 00391 /* Do this after sorting is done. This resets the order of the individual items 00392 * in the list. */ 00393 while (local_list != NULL) { /* make sure item is not null */ 00394 local_list->pos = i; 00395 if (local_list->next != NULL) { 00396 i++; 00397 local_list = local_list->next; 00398 } else { 00399 break; /* leave loop *before* iterating to NULL EOL marker */ 00400 } 00401 } 00402 00403 /* Now go to first item in local list and reassign list head to new first element */ 00404 while (local_list->prev != NULL) { 00405 local_list = local_list->prev; 00406 } 00407 00408 sheet_head->master_comp_list_head = local_list; 00409 00410 return; 00411 } 00412 00413 00414 /* This list overrides the alphanumeric sort. Attribs not found in 00415 this list are sorted as if they had a value of DEFAULT_ATTRIB_POS 00416 within this list, but alphanumerically relative to each other. */ 00417 static struct { 00418 const char *attrib; 00419 int pos; 00420 } certain_attribs[] = { 00421 {"device", 1}, 00422 {"footprint", 2}, 00423 {"value", 3}, 00424 {"symversion", 200} 00425 }; 00426 #define NUM_CERTAINS (sizeof(certain_attribs)/sizeof(certain_attribs[0])) 00427 #define DEFAULT_ATTRIB_POS 100 00428 00429 /*------------------------------------------------------------------*/ 00439 void s_string_list_sort_master_comp_attrib_list() { 00440 int i = 0; 00441 STRING_LIST *local_list, *p; 00442 00443 /* Here's where we do the sort */ 00444 local_list = sheet_head->master_comp_attrib_list_head; 00445 00446 /* 00447 * Note that this sort is TBD -- it is more than just an alphabetic sort 'cause we want 00448 * certain attribs to go first. 00449 */ 00450 for (p=local_list; p; p=p->next) { 00451 int i; 00452 p->pos = DEFAULT_ATTRIB_POS; 00453 for (i=0; i<NUM_CERTAINS; i++) 00454 if (p->data != NULL) { 00455 if (strcmp (certain_attribs[i].attrib, p->data) == 0) 00456 { 00457 p->pos = certain_attribs[i].pos; 00458 break; 00459 } 00460 } 00461 } 00462 00463 local_list = listsort(local_list, 0, 1); 00464 sheet_head->master_comp_attrib_list_head = local_list; 00465 00466 /* Do this after sorting is done. This resets the order of the individual items 00467 * in the list. */ 00468 while (local_list != NULL) { 00469 local_list->pos = i; 00470 i++; 00471 local_list = local_list->next; 00472 } 00473 00474 return; 00475 } 00476 00477 /*------------------------------------------------------------------*/ 00485 void s_string_list_sort_master_net_list() { 00486 int i = 0; 00487 STRING_LIST *local_list; 00488 00489 00490 /* Do this after sorting is done. This resets the order of the individual items 00491 * in the list. */ 00492 local_list = sheet_head->master_net_list_head; 00493 while (local_list != NULL) { 00494 local_list->pos = i; 00495 i++; 00496 local_list = local_list->next; 00497 } 00498 00499 return; 00500 } 00501 00502 /*------------------------------------------------------------------*/ 00511 /*------------------------------------------------------------------*/ 00512 void s_string_list_sort_master_net_attrib_list() { 00513 int i = 0; 00514 STRING_LIST *local_list; 00515 00516 00517 /* Do this after sorting is done. This resets the order of the individual items 00518 * in the list. */ 00519 local_list = sheet_head->master_net_attrib_list_head; 00520 while (local_list != NULL) { 00521 local_list->pos = i; 00522 i++; 00523 local_list = local_list->next; 00524 } 00525 00526 return; 00527 } 00528 00529 00530 /*------------------------------------------------------------------*/ 00540 /*------------------------------------------------------------------*/ 00541 void s_string_list_sort_master_pin_list() { 00542 int i = 0; 00543 STRING_LIST *local_list, *p; 00544 00545 /* Here's where we do the sort. The sort is done using a fcn found on the web. */ 00546 local_list = sheet_head->master_pin_list_head; 00547 for (p=local_list; p; p=p->next) 00548 p->pos = 0; 00549 local_list = listsort(local_list, 0, 1); 00550 00551 /* Do this after sorting is done. This resets the order of the individual items 00552 * in the list. */ 00553 while (local_list != NULL) { /* make sure item is not null */ 00554 local_list->pos = i; 00555 if (local_list->next != NULL) { 00556 i++; 00557 local_list = local_list->next; 00558 } else { 00559 break; /* leave loop *before* iterating to NULL EOL marker */ 00560 } 00561 } 00562 00563 /* Now go to first item in local list and reassign list head to new first element */ 00564 while (local_list->prev != NULL) { 00565 local_list = local_list->prev; 00566 } 00567 00568 sheet_head->master_pin_list_head = local_list; 00569 00570 return; 00571 } 00572 00573 /*------------------------------------------------------------------*/ 00583 /*------------------------------------------------------------------*/ 00584 void s_string_list_sort_master_pin_attrib_list() { 00585 int i = 0; 00586 STRING_LIST *local_list; 00587 00588 /* Here's where we do the sort */ 00589 00590 /* 00591 * Note that this sort is TBD -- it is more than just an alphabetic sort 'cause we want 00592 * certain attribs to go first. 00593 */ 00594 00595 00596 /* Do this after sorting is done. This resets the order of the individual items 00597 * in the list. */ 00598 local_list = sheet_head->master_pin_attrib_list_head; 00599 while (local_list != NULL) { 00600 local_list->pos = i; 00601 i++; 00602 local_list = local_list->next; 00603 } 00604 00605 return; 00606 } 00607