gsch2pcb: Make --m4-file and -m4-pcbdir arguments work again.
[geda-gaf/peter-b.git] / gattrib / src / s_table.c
blobed8a3ccf59470a6b0073a75cfda92fbb1e91d6ab
1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*------------------------------------------------------------------*/
21 /*! \file
22 * \brief Functions to manipulate the TABLE structure
24 * This file holds functions involved in manipulating the TABLE structure,
25 * which is subsidiary to SHEET_DATA. TABLE is a 2 dimensional array
26 * of structs; each struct corresponds to the data about an element
27 * in a single cell of the spreadsheet.
28 * \todo TABLE should also store its dimensions in its own data
29 * structure to save carrying the dimensions around separately.
32 #include <config.h>
34 #include <stdio.h>
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
38 #include <math.h>
40 /*------------------------------------------------------------------
41 * Gattrib specific includes
42 *------------------------------------------------------------------*/
43 #include <libgeda/libgeda.h> /* geda library functions */
44 #include "../include/struct.h" /* typdef and struct declarations */
45 #include "../include/prototype.h" /* function prototypes */
46 #include "../include/globals.h"
48 #ifdef HAVE_LIBDMALLOC
49 #include <dmalloc.h>
50 #endif
52 /* =================== Public Functions ====================== */
54 /*------------------------------------------------------------------*/
55 /*! \brief Create a new table
57 * This is the table creator. It returns a pointer to
58 * an initialized TABLE struct. As calling args, it needs
59 * the number of rows and cols to allocate. The table is a
60 * dynamically allocated 2D array of structs. To access data in
61 * a cell in the table, you reference (for example):
62 * ((sheet_data->comp_table)[i][j]).attrib_value
63 * (Parens used only for clarity. It works without parens.)
64 * \param rows Number of rows required in the new table
65 * \param cols Number of columns required in the new table
66 * \returns a pointer to an initialized TABLE struct.
68 TABLE **s_table_new(int rows, int cols)
70 TABLE **new_table;
71 int i, j;
73 /* Here I am trying to create a 2 dimensional array of structs */
74 new_table = (TABLE **) g_malloc(rows*sizeof(TABLE *));
75 for (i = 0; i < rows; i++) {
76 new_table[i] = (TABLE *) g_malloc(cols * sizeof(TABLE));
77 /* Note that I should put some checks in here to verify that
78 * malloc worked correctly. */
81 /* Now pre-load the table with NULLs */
82 for (i = 0; i < rows; i++) {
83 for (j = 0; j < cols; j++) {
84 (new_table[i][j]).attrib_value = NULL;
85 (new_table[i][j]).row_name = NULL;
86 (new_table[i][j]).col_name = NULL;
87 (new_table[i][j]).row = i;
88 (new_table[i][j]).col = j;
89 (new_table[i][j]).visibility = VISIBLE;
90 (new_table[i][j]).show_name_value = SHOW_VALUE;
94 return (new_table);
99 /*------------------------------------------------------------------*/
100 /*! \brief Resize a TABLE
102 * This function recreates the table with
103 * a new size. It can only increase
104 * the number of cols. You can't increase the number of rows since
105 * gattrib doesn't allow you to input new components. Decreasing the
106 * number of cols is also TBD.
107 * \param table Table to resize
108 * \param rows Number of rows in the table
109 * \param old_cols Number of columns previously in the table
110 * \param new_cols Number of columns required in the table
111 * \returns a pointer to the resized table
112 * \todo The row and column information could be stored in the
113 * TABLE struct.
115 TABLE **s_table_resize(TABLE **table,
116 int rows, int old_cols, int new_cols)
118 int i, j;
120 /* Here I am trying to resize the 2 dimensional array of structs */
121 for (i = 0; i < rows; i++) {
122 table[i] = (TABLE *) realloc(table[i], new_cols*sizeof(TABLE) );
123 if (table[i] == NULL) exit(-1); /* die if failed to realloc new memory */
126 /* Now pre-load new cols with NULLs */
127 for (i = 0; i < rows; i++) {
128 for (j = old_cols; j < new_cols; j++) {
129 (table[i][j]).attrib_value = NULL;
130 (table[i][j]).row_name = NULL;
131 (table[i][j]).col_name = NULL;
132 (table[i][j]).row = i;
133 (table[i][j]).col = j;
134 (table[i][j]).visibility = VISIBLE;
135 (table[i][j]).show_name_value = SHOW_VALUE;
139 return table;
143 /*------------------------------------------------------------------*/
144 /*! \brief Destroy a table
146 * This function destroys the old table.
147 * Use it after reading in a new
148 * page to get rid of the old table before building a new one.
149 * \param table Table to destroy
150 * \param row_count Number of rows in table
151 * \param col_count Number of columns in table
153 void s_table_destroy(TABLE **table, int row_count, int col_count)
155 int i, j;
157 if (table == NULL)
158 return;
160 for (i = 0; i < row_count; i++) {
161 for (j = 0; j < col_count; j++) {
162 g_free( (table[i][j]).attrib_value );
163 g_free( (table[i][j]).row_name );
164 g_free( (table[i][j]).col_name );
168 for (i = 0; i < row_count; i++) {
169 g_free( table[i] );
172 g_free(table);
173 table = NULL;
175 return;
180 /*------------------------------------------------------------------*/
181 /*! \brief Get a string index number
183 * This function returns the index number
184 * when given a STRING_LIST and a
185 * string to match. It finds the index
186 * number by iterating through the master list.
187 * \param local_list
188 * \param local_string
189 * \returns the index of the string
191 int s_table_get_index(STRING_LIST *local_list, char *local_string) {
192 int count = 0;
193 STRING_LIST *list_element;
195 #ifdef DEBUG
196 printf("In s_table_get_index, examining %s to see if it is in the list.\n", local_string);
197 #endif
200 list_element = local_list;
201 while (list_element != NULL) {
202 if (strcmp(list_element->data, local_string) == 0) {
203 return count;
205 count++;
206 list_element = list_element->next;
208 return(-1); /* return code when string is not in master_list */
213 /*------------------------------------------------------------------*/
214 /*! \brief Create attribute pair
216 * This function takes a table, a row list, and a row name,
217 * and returns a list holding
218 * name=value pairs for all attribs pertainent to that particular
219 * row.
220 * If the row holds no attribs, it just returns NULL.
222 * \param row_name Name of the row to search for
223 * \param table Table to be searched
224 * \param row_list list of rows
225 * \param num_attribs
226 * \returns STRING_LIST of name=value pairs
228 STRING_LIST *s_table_create_attrib_pair(gchar *row_name,
229 TABLE **table,
230 STRING_LIST *row_list,
231 int num_attribs)
233 STRING_LIST *attrib_pair_list;
234 char *attrib_name, *attrib_value, *name_value_pair;
235 int row, col;
236 int count = 0;
238 attrib_pair_list = s_string_list_new();
240 row = s_table_get_index(row_list, row_name);
241 /* Sanity check */
242 if (row == -1) {
243 /* we didn't find the item in the list */
244 fprintf (stderr,
245 "In s_table_create_attrib_pair, we didn't find the row name in the row list!\n");
246 return attrib_pair_list;
249 for (col = 0; col < num_attribs; col++) {
250 /* pull attrib from table. If non-null, add it to attrib_pair_list */
251 if ( (table[row][col]).attrib_value != NULL) {
252 attrib_name = (table[row][col]).col_name;
253 attrib_value = (table[row][col]).attrib_value;
254 name_value_pair = g_strconcat(attrib_name, "=", attrib_value, NULL);
255 s_string_list_add_item(attrib_pair_list, &count, name_value_pair);
256 g_free(name_value_pair);
260 return attrib_pair_list;
266 /*------------------------------------------------------------------*/
267 /*! \brief Add components to the component table
269 * This fcn iterates over adds all
270 * objects found on this page looking
271 * for components. When it finds a component, it finds all component
272 * attribs and sticks them in the TABLE.
273 * \param obj_list pointer to GList containing objects on this page
275 void s_table_add_toplevel_comp_items_to_comp_table (const GList *obj_list) {
276 gchar *temp_uref;
277 int row, col;
278 gchar *attrib_text;
279 gchar *attrib_name;
280 gchar *attrib_value;
281 const GList *o_iter;
282 GList *a_iter;
283 OBJECT *a_current;
284 gint old_visibility, old_show_name_value;
287 if (verbose_mode) {
288 printf("- Starting internal component TABLE creation\n");
291 #ifdef DEBUG
292 fflush(stderr);
293 fflush(stdout);
294 printf("=========== Just entered s_table_add_toplevel_comp_items_to_comp_table! ==============\n");
295 #endif
297 /* ----- Iterate through all objects found on page ----- */
298 for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
299 OBJECT *o_current = o_iter->data;
301 #ifdef DEBUG
302 printf(" ---> In s_table_add_toplevel_comp_items_to_comp_table, examining o_current->name = %s\n", o_current->name);
303 #endif
305 /* ----- Now process objects found on page ----- */
306 if (o_current->type == OBJ_COMPLEX &&
307 o_current->attribs != NULL) {
309 /* ---- Don't process part if it lacks a refdes ----- */
310 temp_uref = g_strdup(s_attrib_get_refdes(o_current));
311 if (temp_uref) {
313 #if DEBUG
314 printf(" In s_table_add_toplevel_comp_items_to_comp_table, found component on page. Refdes = %s\n", temp_uref);
315 #endif
316 verbose_print(" C");
318 /* Having found a component, we loop over all attribs in this
319 * component, and stick them
320 * into cells in the table. */
321 a_iter = o_current->attribs;
322 while (a_iter != NULL) {
323 a_current = a_iter->data;
324 if (a_current->type == OBJ_TEXT
325 && a_current->text != NULL) { /* found an attribute */
326 /* may need to check more thoroughly here. . . . */
327 attrib_text = g_strdup(a_current->text->string);
328 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
329 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
330 old_visibility = o_is_visible (pr_current, a_current)
331 ? VISIBLE : INVISIBLE;
332 old_show_name_value = a_current->show_name_value;
334 /* Don't include "refdes" or "slot" because they form the row name. */
335 /* Also don't include "net" per bug found by Steve W. 4.3.2007 -- SDB */
336 if ( (strcmp(attrib_name, "refdes") != 0) &&
337 (strcmp(attrib_name, "net") != 0) &&
338 (strcmp(attrib_name, "slot") != 0) ) {
340 /* Get row and col where to put this attrib */
341 row = s_table_get_index(sheet_head->master_comp_list_head, temp_uref);
342 col = s_table_get_index(sheet_head->master_comp_attrib_list_head, attrib_name);
343 /* Sanity check */
344 if (row == -1 || col == -1) {
345 /* we didn't find the item in the table */
346 fprintf (stderr,
347 "In s_table_add_toplevel_comp_items_to_comp_table, we didn't find either row or col in the lists!\n");
348 } else {
350 #if DEBUG
351 printf(" In s_table_add_toplevel_comp_items_to_comp_table, about to add row %d, col %d, attrib_value = %s\n",
352 row, col, attrib_value);
353 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value);
354 #endif
355 /* Is there a compelling reason for me to put this into a separate fcn? */
356 ((sheet_head->component_table)[row][col]).row = row;
357 ((sheet_head->component_table)[row][col]).col = col;
358 ((sheet_head->component_table)[row][col]).row_name = g_strdup(temp_uref);
359 ((sheet_head->component_table)[row][col]).col_name = g_strdup(attrib_name);
360 ((sheet_head->component_table)[row][col]).attrib_value = g_strdup(attrib_value);
361 ((sheet_head->component_table)[row][col]).visibility = old_visibility;
362 ((sheet_head->component_table)[row][col]).show_name_value = old_show_name_value;
365 g_free(attrib_name);
366 g_free(attrib_text);
367 g_free(attrib_value);
369 a_iter = g_list_next (a_iter);
371 } /* while (a_current != NULL) */
372 g_free(temp_uref);
373 } /* if (temp_uref) */
374 } /* if (o_current->type == OBJ_COMPLEX) */
377 verbose_done();
381 #if 0
382 /*------------------------------------------------------------------*/
383 /*! \brief Add nets to net table
385 * This function iterates over adds all
386 * items found on this page looking
387 * for nets and adds them individually to the net table. Looping over
388 * objects occurs here.
390 * \param start_obj Pointer to first object
392 * \todo Why do the calling semantics of this function disagree with
393 * s_table_add_toplevel_pin_items_to_pin_table()? That function
394 * takes a GList, this one takes a pointer to OBJECT.
396 void s_table_add_toplevel_net_items_to_net_table(OBJECT *start_obj) {
397 OBJECT *o_current;
398 char *temp_netname;
399 int row, col;
400 char *attrib_text;
401 char *attrib_name;
402 char *attrib_value;
403 ATTRIB *a_current;
405 /* ----- Iterate through all objects found on page ----- */
406 o_current = start_obj;
407 while (o_current != NULL) {
409 /* ----- Now process objects found on page ----- */
410 if (o_current->type == OBJ_NET) {
411 #if DEBUG
412 fflush(stderr);
413 fflush(stdout);
414 printf("In s_table_add_toplevel_net_items_to_net_table, Found net on page\n");
415 #endif
416 verbose_print(" N");
418 /* Having found a net, we stick it into the table. */
419 a_current = o_current->attribs;
420 while (a_current != NULL) {
421 if (a_current->object->type == OBJ_TEXT
422 && a_current->object->text != NULL) { /* found an attribute */
423 /* may need to check more thoroughly here. . . . */
424 attrib_text = g_strdup(a_current->object->text->string);
425 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
426 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
427 if (strcmp(attrib_name, "netname") != 0) {
428 /* Don't include "netname" */
430 /* Get row and col where to put this attrib */
431 row = s_table_get_index(sheet_head->master_net_list_head, temp_netname);
432 col = s_table_get_index(sheet_head->master_net_attrib_list_head, attrib_name);
433 #if DEBUG
434 fflush(stderr);
435 fflush(stdout);
436 printf("In s_table_add_toplevel_net_items_to_net_table, about to add row %d, col %d, attrib_value = %s\n",
437 row, col, attrib_value);
438 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->net_table)[row][col]).attrib_value);
439 #endif
440 /* Is there a compelling reason for me to put this into a separate fcn? */
441 ((sheet_head->net_table)[row][col]).row = row;
442 ((sheet_head->net_table)[row][col]).col = col;
443 ((sheet_head->net_table)[row][col]).row_name = g_strdup(temp_netname);
444 ((sheet_head->net_table)[row][col]).col_name = g_strdup(attrib_name);
445 ((sheet_head->net_table)[row][col]).attrib_value = g_strdup(attrib_value);
447 g_free(attrib_name);
448 g_free(attrib_text);
449 g_free(attrib_value);
451 a_current = a_current->next;
453 } /* while (a_current != NULL) */
454 g_free(temp_netname);
456 } /*--- if (o_current->type == OBJ_NET) ---*/
459 o_current = o_current->next; /* iterate to next object on page */
460 } /* while o_current != NULL */
462 verbose_done();
464 #if DEBUG
465 fflush(stderr);
466 fflush(stdout);
467 printf("In s_table_add_toplevel_net_items_to_net_table -- we are about to return\n");
468 #endif
471 #endif
474 /*------------------------------------------------------------------*/
475 /*! \brief Add pins to pin table.
477 * This function iterates over adds all items found on this page
478 * looking for pins. WHen it finds a pin, it gathers all
479 * pin attribs and sticks them into the pin table.
480 * \param obj_list List of objects on page
482 void s_table_add_toplevel_pin_items_to_pin_table (const GList *obj_list) {
483 gchar *temp_uref;
484 gchar *pinnumber;
485 gchar *row_label;
486 int row, col;
487 gchar *attrib_text;
488 gchar *attrib_name;
489 gchar *attrib_value;
490 const GList *o_iter;
491 GList *a_iter;
492 GList *o_lower_iter;
493 OBJECT *pin_attrib;
495 if (verbose_mode) {
496 printf("- Starting internal pin TABLE creation\n");
499 #ifdef DEBUG
500 printf("=========== Just entered s_table_add_toplevel_pin_items_to_pin_table! ==============\n");
501 #endif
503 /* ----- Iterate through all objects found on page ----- */
504 for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
505 OBJECT *o_current = o_iter->data;
507 #ifdef DEBUG
508 printf(" ---> In s_table_add_toplevel_pin_items_to_pin_table, examining o_current->name = %s\n", o_current->name);
509 #endif
511 /* ----- Now process objects found on page ----- */
512 if (o_current->type == OBJ_COMPLEX &&
513 o_current->attribs != NULL) {
515 /* ---- Don't process part if it lacks a refdes ----- */
516 temp_uref = s_attrib_get_refdes(o_current);
517 if (temp_uref) {
519 /* ----- Now iterate through lower level objects looking for pins. ----- */
520 for (o_lower_iter = o_current->complex->prim_objs;
521 o_lower_iter != NULL;
522 o_lower_iter = g_list_next (o_lower_iter)) {
523 OBJECT *o_lower_current = o_lower_iter->data;
525 if (o_lower_current->type == OBJ_PIN) {
526 /* ----- Found a pin. First get its pinnumber. then get attrib head and loop on attribs. ----- */
527 pinnumber = o_attrib_search_object_attribs_by_name (o_lower_current, "pinnumber", 0);
528 row_label = g_strconcat(temp_uref, ":", pinnumber, NULL);
530 #if DEBUG
531 printf(" In s_table_add_toplevel_pin_items_to_pin_table, examining pin %s\n", row_label);
532 #endif
534 a_iter = o_lower_current->attribs;
535 while (a_iter != NULL) {
536 pin_attrib = a_iter->data;
537 if (pin_attrib->type == OBJ_TEXT
538 && pin_attrib->text != NULL) { /* found an attribute */
539 attrib_text = g_strdup(pin_attrib->text->string);
540 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
541 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
543 if ( (strcmp(attrib_name, "pinnumber") != 0)
544 && (attrib_value != 0) ) {
545 /* Don't include "pinnumber" because it is already in other master list.
546 * Also must ensure that value is non-null; certain symbols are not well formed.
549 /* Get row and col where to put this attrib */
550 row = s_table_get_index(sheet_head->master_pin_list_head, row_label);
551 col = s_table_get_index(sheet_head->master_pin_attrib_list_head, attrib_name);
552 /* Sanity check */
553 if (row == -1 || col == -1) {
554 /* we didn't find the item in the table */
555 fprintf (stderr,
556 "In s_table_add_toplevel_pin_items_to_pin_table, we didn't find either row or col in the lists!\n");
557 } else {
559 #if DEBUG
560 printf(" In s_table_add_toplevel_pin_items_to_pin_table, about to add row %d, col %d, attrib_value = %s\n",
561 row, col, attrib_value);
562 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value);
563 #endif
564 /* Is there a compelling reason for me to put this into a separate fcn? */
565 ((sheet_head->pin_table)[row][col]).row = row;
566 ((sheet_head->pin_table)[row][col]).col = col;
567 ((sheet_head->pin_table)[row][col]).row_name = g_strdup(row_label);
568 ((sheet_head->pin_table)[row][col]).col_name = g_strdup(attrib_name);
569 ((sheet_head->pin_table)[row][col]).attrib_value = g_strdup(attrib_value);
572 g_free(attrib_name);
573 g_free(attrib_text);
574 g_free(attrib_value);
576 a_iter = g_list_next (a_iter);
578 } /* while (pin_attrib != NULL) */
579 g_free(pinnumber);
580 g_free(row_label);
586 g_free(temp_uref);
591 verbose_done();
595 /*------------------------------------------------------------------*/
596 /*! \brief Push spreadsheet data to TABLEs.
598 * This function traverses the spreadsheet,
599 * extracts the attribs from
600 * the cells, and places them back into TABLE. This is the
601 * first step in saving out a project.
603 void s_table_gtksheet_to_all_tables() {
605 int num_rows;
606 int num_cols;
607 STRING_LIST *master_row_list;
608 STRING_LIST *master_col_list;
609 TABLE **local_table;
610 GtkSheet *local_gtk_sheet;
612 /* First handle component sheet */
613 num_rows = sheet_head->comp_count;
614 num_cols = sheet_head->comp_attrib_count;
615 local_gtk_sheet = sheets[0];
616 master_row_list = sheet_head->master_comp_list_head;
617 master_col_list = sheet_head->master_comp_attrib_list_head;
619 local_table = sheet_head->component_table;
621 /* now fill out new table */
622 #ifdef DEBUG
623 printf("In s_table_gtksheet_to_all_tables, now about to fill out new component table.\n");
624 #endif
625 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
626 master_col_list, local_table,
627 num_rows, num_cols);
629 #if 0
630 /* Next handle net sheet */
631 num_rows = sheet_head->net_count;
632 num_cols = sheet_head->net_attrib_count;
633 local_gtk_sheet = sheets[1];
634 master_row_list = sheet_head->master_net_list_head;
635 master_col_list = sheet_head->master_net_attrib_list_head;
636 local_table = sheet_head->net_table;
638 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
639 master_col_list, local_table,
640 num_rows, num_cols);
641 #endif
643 #ifdef UNIMPLEMENTED_FEATURES
644 /* Finally, handle component pin sheet */
645 num_rows = sheet_head->pin_count;
646 num_cols = sheet_head->pin_attrib_count;
647 local_gtk_sheet = sheets[2];
648 master_row_list = sheet_head->master_pin_list_head;
649 master_col_list = sheet_head->master_pin_attrib_list_head;
650 /* local_table = s_table_new(num_rows, num_cols); */
651 local_table = sheet_head->pin_table;
653 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
654 master_col_list, local_table,
655 num_rows, num_cols);
656 #endif
658 return;
662 /* =================== Private Functions ====================== */
663 /*------------------------------------------------------------------*/
664 /*! \brief Extract attributes from gtksheet into TABLE
666 * This function does the actual heavy lifting of looping
667 * through the spreadsheet, extracting the attribs from
668 * the cells, and placing them back into TABLE. This is the
669 * first step in saving out a project.
671 * \param local_gtk_sheet GtkSheet to save
672 * \param master_row_list STRING_LIST of rows
673 * \param master_col_list STRING_LIST of columns
674 * \param local_table TABLE structure to fill
675 * \param num_rows Number of rows in table
676 * \param num_cols Number of columns in table
678 void s_table_gtksheet_to_table(GtkSheet *local_gtk_sheet, STRING_LIST *master_row_list,
679 STRING_LIST *master_col_list, TABLE **local_table,
680 int num_rows, int num_cols)
682 int row, col;
684 STRING_LIST *row_list_item;
685 gchar *row_title;
687 STRING_LIST *col_list_item;
688 gchar *col_title;
690 gchar *attrib_value;
692 #ifdef DEBUG
693 printf("********** Entering s_table_gtksheet_to_table ******************\n");
694 #endif
697 row_list_item = master_row_list;
698 for (row = 0; row < num_rows; row++) {
699 row_title = (gchar *) g_strdup(row_list_item->data);
701 col_list_item = master_col_list;
702 for (col = 0; col < num_cols; col++) {
703 col_title = (gchar *) g_strdup(col_list_item->data);
705 /* get value of attrib in cell */
706 attrib_value = (gchar *) gtk_sheet_cell_get_text(GTK_SHEET(local_gtk_sheet), row, col);
708 #if 0
709 if (strlen(attrib_value) == 0) {
710 /* g_free(attrib_value); */ /* sometimes we have spurious, zero length strings creep */
711 attrib_value = NULL; /* into the GtkSheet */
713 #endif
716 #ifdef DEBUG
717 printf("In s_table_gtksheet_to_table, found attrib_value = %s in cell row=%d, col=%d\n",
718 attrib_value, row, col);
719 #endif
721 /* first handle attrib value in cell */
722 #ifdef DEBUG
723 printf(" Updating attrib_value %s\n", attrib_value);
724 #endif
725 g_free( local_table[row][col].attrib_value );
726 if (attrib_value != NULL) {
727 local_table[row][col].attrib_value = (gchar *) g_strdup(attrib_value);
728 } else {
729 local_table[row][col].attrib_value = NULL;
732 /* next handle name of row (also held in TABLE cell) */
733 #ifdef DEBUG
734 printf(" Updating row_name %s\n", row_title);
735 #endif
736 g_free( local_table[row][col].row_name );
737 if (row_title != NULL) {
738 local_table[row][col].row_name = (gchar *) g_strdup(row_title);
739 } else {
740 local_table[row][col].row_name = NULL;
743 /* finally handle name of col */
744 #ifdef DEBUG
745 printf(" Updating col_name %s\n", col_title);
746 #endif
747 g_free( local_table[row][col].col_name );
748 if (col_title != NULL) {
749 local_table[row][col].col_name = (gchar *) g_strdup(col_title);
750 } else {
751 local_table[row][col].col_name = NULL;
754 /* get next col list item and then iterate. */
755 col_list_item = col_list_item->next;
758 row_list_item = row_list_item->next;
761 return;