missing NULL terminator in set_config_x
[geda-gaf.git] / gattrib / src / s_table.c
blobb6a39ad64f7578b351f6cb85c33c707ff5b4170a
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"
47 #include "../include/gettext.h"
49 /* =================== Public Functions ====================== */
51 /*------------------------------------------------------------------*/
52 /*! \brief Create a new table
54 * This is the table creator. It returns a pointer to
55 * an initialized TABLE struct. As calling args, it needs
56 * the number of rows and cols to allocate. The table is a
57 * dynamically allocated 2D array of structs. To access data in
58 * a cell in the table, you reference (for example):
59 * ((sheet_data->comp_table)[i][j]).attrib_value
60 * (Parens used only for clarity. It works without parens.)
61 * \param rows Number of rows required in the new table
62 * \param cols Number of columns required in the new table
63 * \returns a pointer to an initialized TABLE struct.
65 TABLE **s_table_new(int rows, int cols)
67 TABLE **new_table;
68 int i, j;
70 /* Here I am trying to create a 2 dimensional array of structs */
71 new_table = (TABLE **) g_malloc(rows*sizeof(TABLE *));
72 for (i = 0; i < rows; i++) {
73 new_table[i] = (TABLE *) g_malloc(cols * sizeof(TABLE));
74 /* Note that I should put some checks in here to verify that
75 * malloc worked correctly. */
78 /* Now pre-load the table with NULLs */
79 for (i = 0; i < rows; i++) {
80 for (j = 0; j < cols; j++) {
81 (new_table[i][j]).attrib_value = NULL;
82 (new_table[i][j]).row_name = NULL;
83 (new_table[i][j]).col_name = NULL;
84 (new_table[i][j]).row = i;
85 (new_table[i][j]).col = j;
86 (new_table[i][j]).visibility = VISIBLE;
87 (new_table[i][j]).show_name_value = SHOW_VALUE;
91 return (new_table);
96 /*------------------------------------------------------------------*/
97 /*! \brief Resize a TABLE
99 * This function recreates the table with
100 * a new size. It can only increase
101 * the number of cols. You can't increase the number of rows since
102 * gattrib doesn't allow you to input new components. Decreasing the
103 * number of cols is also TBD.
104 * \param table Table to resize
105 * \param rows Number of rows in the table
106 * \param old_cols Number of columns previously in the table
107 * \param new_cols Number of columns required in the table
108 * \returns a pointer to the resized table
109 * \todo The row and column information could be stored in the
110 * TABLE struct.
112 TABLE **s_table_resize(TABLE **table,
113 int rows, int old_cols, int new_cols)
115 int i, j;
117 /* Here I am trying to resize the 2 dimensional array of structs */
118 for (i = 0; i < rows; i++) {
119 table[i] = (TABLE *) realloc(table[i], new_cols*sizeof(TABLE) );
120 if (table[i] == NULL) exit(-1); /* die if failed to realloc new memory */
123 /* Now pre-load new cols with NULLs */
124 for (i = 0; i < rows; i++) {
125 for (j = old_cols; j < new_cols; j++) {
126 (table[i][j]).attrib_value = NULL;
127 (table[i][j]).row_name = NULL;
128 (table[i][j]).col_name = NULL;
129 (table[i][j]).row = i;
130 (table[i][j]).col = j;
131 (table[i][j]).visibility = VISIBLE;
132 (table[i][j]).show_name_value = SHOW_VALUE;
136 return table;
140 /*------------------------------------------------------------------*/
141 /*! \brief Destroy a table
143 * This function destroys the old table.
144 * Use it after reading in a new
145 * page to get rid of the old table before building a new one.
146 * \param table Table to destroy
147 * \param row_count Number of rows in table
148 * \param col_count Number of columns in table
150 void s_table_destroy(TABLE **table, int row_count, int col_count)
152 int i, j;
154 if (table == NULL)
155 return;
157 for (i = 0; i < row_count; i++) {
158 for (j = 0; j < col_count; j++) {
159 g_free( (table[i][j]).attrib_value );
160 g_free( (table[i][j]).row_name );
161 g_free( (table[i][j]).col_name );
165 for (i = 0; i < row_count; i++) {
166 g_free( table[i] );
169 g_free(table);
170 table = NULL;
172 return;
177 /*------------------------------------------------------------------*/
178 /*! \brief Get a string index number
180 * This function returns the index number
181 * when given a STRING_LIST and a
182 * string to match. It finds the index
183 * number by iterating through the master list.
184 * \param local_list
185 * \param local_string
186 * \returns the index of the string
188 int s_table_get_index(STRING_LIST *local_list, char *local_string) {
189 int count = 0;
190 STRING_LIST *list_element;
192 #ifdef DEBUG
193 printf("In s_table_get_index, examining %s to see if it is in the list.\n", local_string);
194 #endif
197 list_element = local_list;
198 while (list_element != NULL) {
199 if (strcmp(list_element->data, local_string) == 0) {
200 return count;
202 count++;
203 list_element = list_element->next;
205 return(-1); /* return code when string is not in master_list */
210 /*------------------------------------------------------------------*/
211 /*! \brief Create attribute pair
213 * This function takes a table, a row list, and a row name,
214 * and returns a list holding
215 * name=value pairs for all attribs pertainent to that particular
216 * row.
217 * If the row holds no attribs, it just returns NULL.
219 * \param row_name Name of the row to search for
220 * \param table Table to be searched
221 * \param row_list list of rows
222 * \param num_attribs
223 * \returns STRING_LIST of name=value pairs
225 STRING_LIST *s_table_create_attrib_pair(gchar *row_name,
226 TABLE **table,
227 STRING_LIST *row_list,
228 int num_attribs)
230 STRING_LIST *attrib_pair_list;
231 char *attrib_name, *attrib_value, *name_value_pair;
232 int row, col;
233 int count = 0;
235 attrib_pair_list = s_string_list_new();
237 row = s_table_get_index(row_list, row_name);
238 /* Sanity check */
239 if (row == -1) {
240 /* we didn't find the item in the list */
241 fprintf (stderr,
242 _("In s_table_create_attrib_pair, we didn't find the row name in the row list!\n"));
243 return attrib_pair_list;
246 for (col = 0; col < num_attribs; col++) {
247 /* pull attrib from table. If non-null, add it to attrib_pair_list */
248 if ( (table[row][col]).attrib_value != NULL) {
249 attrib_name = (table[row][col]).col_name;
250 attrib_value = (table[row][col]).attrib_value;
251 name_value_pair = g_strconcat(attrib_name, "=", attrib_value, NULL);
252 s_string_list_add_item(attrib_pair_list, &count, name_value_pair);
253 g_free(name_value_pair);
257 return attrib_pair_list;
263 /*------------------------------------------------------------------*/
264 /*! \brief Add components to the component table
266 * This fcn iterates over adds all
267 * objects found on this page looking
268 * for components. When it finds a component, it finds all component
269 * attribs and sticks them in the TABLE.
270 * \param obj_list pointer to GList containing objects on this page
272 void s_table_add_toplevel_comp_items_to_comp_table (const GList *obj_list) {
273 gchar *temp_uref;
274 int row, col;
275 gchar *attrib_text;
276 gchar *attrib_name;
277 gchar *attrib_value;
278 const GList *o_iter;
279 GList *a_iter;
280 OBJECT *a_current;
281 gint old_visibility, old_show_name_value;
284 if (verbose_mode) {
285 printf(_("- Starting internal component TABLE creation\n"));
288 #ifdef DEBUG
289 fflush(stderr);
290 fflush(stdout);
291 printf("=========== Just entered s_table_add_toplevel_comp_items_to_comp_table! ==============\n");
292 #endif
294 /* ----- Iterate through all objects found on page ----- */
295 for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
296 OBJECT *o_current = o_iter->data;
298 #ifdef DEBUG
299 printf(" ---> In s_table_add_toplevel_comp_items_to_comp_table, examining o_current->name = %s\n", o_current->name);
300 #endif
302 /* ----- Now process objects found on page ----- */
303 if (o_current->type == OBJ_COMPLEX &&
304 o_current->attribs != NULL) {
306 /* ---- Don't process part if it lacks a refdes ----- */
307 temp_uref = g_strdup(s_attrib_get_refdes(o_current));
308 if (temp_uref) {
310 #if DEBUG
311 printf(" In s_table_add_toplevel_comp_items_to_comp_table, found component on page. Refdes = %s\n", temp_uref);
312 #endif
313 verbose_print(" C");
315 /* Having found a component, we loop over all attribs in this
316 * component, and stick them
317 * into cells in the table. */
318 a_iter = o_current->attribs;
319 while (a_iter != NULL) {
320 a_current = a_iter->data;
321 if (a_current->type == OBJ_TEXT
322 && a_current->text != NULL) { /* found an attribute */
323 /* may need to check more thoroughly here. . . . */
324 attrib_text = g_strdup(a_current->text->string);
325 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
326 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
327 old_visibility = o_is_visible (a_current) ? VISIBLE : INVISIBLE;
328 old_show_name_value = a_current->show_name_value;
330 /* Don't include "refdes" or "slot" because they form the row name. */
331 /* Also don't include "net" per bug found by Steve W. 4.3.2007 -- SDB */
332 if ( (strcmp(attrib_name, "refdes") != 0) &&
333 (strcmp(attrib_name, "net") != 0) &&
334 (strcmp(attrib_name, "slot") != 0) ) {
336 /* Get row and col where to put this attrib */
337 row = s_table_get_index(sheet_head->master_comp_list_head, temp_uref);
338 col = s_table_get_index(sheet_head->master_comp_attrib_list_head, attrib_name);
339 /* Sanity check */
340 if (row == -1 || col == -1) {
341 /* we didn't find the item in the table */
342 fprintf (stderr,
343 _("In s_table_add_toplevel_comp_items_to_comp_table, we didn't find either row or col in the lists!\n"));
344 } else {
346 #if DEBUG
347 printf(" In s_table_add_toplevel_comp_items_to_comp_table, about to add row %d, col %d, attrib_value = %s\n",
348 row, col, attrib_value);
349 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value);
350 #endif
351 /* Is there a compelling reason for me to put this into a separate fcn? */
352 ((sheet_head->component_table)[row][col]).row = row;
353 ((sheet_head->component_table)[row][col]).col = col;
354 ((sheet_head->component_table)[row][col]).row_name = g_strdup(temp_uref);
355 ((sheet_head->component_table)[row][col]).col_name = g_strdup(attrib_name);
356 ((sheet_head->component_table)[row][col]).attrib_value = g_strdup(attrib_value);
357 ((sheet_head->component_table)[row][col]).visibility = old_visibility;
358 ((sheet_head->component_table)[row][col]).show_name_value = old_show_name_value;
361 g_free(attrib_name);
362 g_free(attrib_text);
363 g_free(attrib_value);
365 a_iter = g_list_next (a_iter);
367 } /* while (a_current != NULL) */
368 g_free(temp_uref);
369 } /* if (temp_uref) */
370 } /* if (o_current->type == OBJ_COMPLEX) */
373 verbose_done();
377 #if 0
378 /*------------------------------------------------------------------*/
379 /*! \brief Add nets to net table
381 * This function iterates over adds all
382 * items found on this page looking
383 * for nets and adds them individually to the net table. Looping over
384 * objects occurs here.
386 * \param start_obj Pointer to first object
388 * \todo Why do the calling semantics of this function disagree with
389 * s_table_add_toplevel_pin_items_to_pin_table()? That function
390 * takes a GList, this one takes a pointer to OBJECT.
392 void s_table_add_toplevel_net_items_to_net_table(OBJECT *start_obj) {
393 OBJECT *o_current;
394 char *temp_netname;
395 int row, col;
396 char *attrib_text;
397 char *attrib_name;
398 char *attrib_value;
399 ATTRIB *a_current;
401 /* ----- Iterate through all objects found on page ----- */
402 o_current = start_obj;
403 while (o_current != NULL) {
405 /* ----- Now process objects found on page ----- */
406 if (o_current->type == OBJ_NET) {
407 #if DEBUG
408 fflush(stderr);
409 fflush(stdout);
410 printf("In s_table_add_toplevel_net_items_to_net_table, Found net on page\n");
411 #endif
412 verbose_print(" N");
414 /* Having found a net, we stick it into the table. */
415 a_current = o_current->attribs;
416 while (a_current != NULL) {
417 if (a_current->object->type == OBJ_TEXT
418 && a_current->object->text != NULL) { /* found an attribute */
419 /* may need to check more thoroughly here. . . . */
420 attrib_text = g_strdup(a_current->object->text->string);
421 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
422 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
423 if (strcmp(attrib_name, "netname") != 0) {
424 /* Don't include "netname" */
426 /* Get row and col where to put this attrib */
427 row = s_table_get_index(sheet_head->master_net_list_head, temp_netname);
428 col = s_table_get_index(sheet_head->master_net_attrib_list_head, attrib_name);
429 #if DEBUG
430 fflush(stderr);
431 fflush(stdout);
432 printf("In s_table_add_toplevel_net_items_to_net_table, about to add row %d, col %d, attrib_value = %s\n",
433 row, col, attrib_value);
434 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->net_table)[row][col]).attrib_value);
435 #endif
436 /* Is there a compelling reason for me to put this into a separate fcn? */
437 ((sheet_head->net_table)[row][col]).row = row;
438 ((sheet_head->net_table)[row][col]).col = col;
439 ((sheet_head->net_table)[row][col]).row_name = g_strdup(temp_netname);
440 ((sheet_head->net_table)[row][col]).col_name = g_strdup(attrib_name);
441 ((sheet_head->net_table)[row][col]).attrib_value = g_strdup(attrib_value);
443 g_free(attrib_name);
444 g_free(attrib_text);
445 g_free(attrib_value);
447 a_current = a_current->next;
449 } /* while (a_current != NULL) */
450 g_free(temp_netname);
452 } /*--- if (o_current->type == OBJ_NET) ---*/
455 o_current = o_current->next; /* iterate to next object on page */
456 } /* while o_current != NULL */
458 verbose_done();
460 #if DEBUG
461 fflush(stderr);
462 fflush(stdout);
463 printf("In s_table_add_toplevel_net_items_to_net_table -- we are about to return\n");
464 #endif
467 #endif
470 /*------------------------------------------------------------------*/
471 /*! \brief Add pins to pin table.
473 * This function iterates over adds all items found on this page
474 * looking for pins. WHen it finds a pin, it gathers all
475 * pin attribs and sticks them into the pin table.
476 * \param obj_list List of objects on page
478 void s_table_add_toplevel_pin_items_to_pin_table (const GList *obj_list) {
479 gchar *temp_uref;
480 gchar *pinnumber;
481 gchar *row_label;
482 int row, col;
483 gchar *attrib_text;
484 gchar *attrib_name;
485 gchar *attrib_value;
486 const GList *o_iter;
487 GList *a_iter;
488 GList *o_lower_iter;
489 OBJECT *pin_attrib;
491 if (verbose_mode) {
492 printf(_("- Starting internal pin TABLE creation\n"));
495 #ifdef DEBUG
496 printf("=========== Just entered s_table_add_toplevel_pin_items_to_pin_table! ==============\n");
497 #endif
499 /* ----- Iterate through all objects found on page ----- */
500 for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
501 OBJECT *o_current = o_iter->data;
503 #ifdef DEBUG
504 printf(" ---> In s_table_add_toplevel_pin_items_to_pin_table, examining o_current->name = %s\n", o_current->name);
505 #endif
507 /* ----- Now process objects found on page ----- */
508 if (o_current->type == OBJ_COMPLEX &&
509 o_current->attribs != NULL) {
511 /* ---- Don't process part if it lacks a refdes ----- */
512 temp_uref = s_attrib_get_refdes(o_current);
513 if (temp_uref) {
515 /* ----- Now iterate through lower level objects looking for pins. ----- */
516 for (o_lower_iter = o_current->complex->prim_objs;
517 o_lower_iter != NULL;
518 o_lower_iter = g_list_next (o_lower_iter)) {
519 OBJECT *o_lower_current = o_lower_iter->data;
521 if (o_lower_current->type == OBJ_PIN) {
522 /* ----- Found a pin. First get its pinnumber. then get attrib head and loop on attribs. ----- */
523 pinnumber = o_attrib_search_object_attribs_by_name (o_lower_current, "pinnumber", 0);
524 row_label = g_strconcat(temp_uref, ":", pinnumber, NULL);
526 #if DEBUG
527 printf(" In s_table_add_toplevel_pin_items_to_pin_table, examining pin %s\n", row_label);
528 #endif
530 a_iter = o_lower_current->attribs;
531 while (a_iter != NULL) {
532 pin_attrib = a_iter->data;
533 if (pin_attrib->type == OBJ_TEXT
534 && pin_attrib->text != NULL) { /* found an attribute */
535 attrib_text = g_strdup(pin_attrib->text->string);
536 attrib_name = u_basic_breakup_string(attrib_text, '=', 0);
537 attrib_value = s_misc_remaining_string(attrib_text, '=', 1);
539 if ( (strcmp(attrib_name, "pinnumber") != 0)
540 && (attrib_value != 0) ) {
541 /* Don't include "pinnumber" because it is already in other master list.
542 * Also must ensure that value is non-null; certain symbols are not well formed.
545 /* Get row and col where to put this attrib */
546 row = s_table_get_index(sheet_head->master_pin_list_head, row_label);
547 col = s_table_get_index(sheet_head->master_pin_attrib_list_head, attrib_name);
548 /* Sanity check */
549 if (row == -1 || col == -1) {
550 /* we didn't find the item in the table */
551 fprintf (stderr,
552 _("In s_table_add_toplevel_pin_items_to_pin_table, we didn't find either row or col in the lists!\n"));
553 } else {
555 #if DEBUG
556 printf(" In s_table_add_toplevel_pin_items_to_pin_table, about to add row %d, col %d, attrib_value = %s\n",
557 row, col, attrib_value);
558 printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value);
559 #endif
560 /* Is there a compelling reason for me to put this into a separate fcn? */
561 ((sheet_head->pin_table)[row][col]).row = row;
562 ((sheet_head->pin_table)[row][col]).col = col;
563 ((sheet_head->pin_table)[row][col]).row_name = g_strdup(row_label);
564 ((sheet_head->pin_table)[row][col]).col_name = g_strdup(attrib_name);
565 ((sheet_head->pin_table)[row][col]).attrib_value = g_strdup(attrib_value);
568 g_free(attrib_name);
569 g_free(attrib_text);
570 g_free(attrib_value);
572 a_iter = g_list_next (a_iter);
574 } /* while (pin_attrib != NULL) */
575 g_free(pinnumber);
576 g_free(row_label);
582 g_free(temp_uref);
587 verbose_done();
591 /*------------------------------------------------------------------*/
592 /*! \brief Push spreadsheet data to TABLEs.
594 * This function traverses the spreadsheet,
595 * extracts the attribs from
596 * the cells, and places them back into TABLE. This is the
597 * first step in saving out a project.
599 void s_table_gtksheet_to_all_tables() {
601 int num_rows;
602 int num_cols;
603 STRING_LIST *master_row_list;
604 STRING_LIST *master_col_list;
605 TABLE **local_table;
606 GtkSheet *local_gtk_sheet;
608 /* First handle component sheet */
609 num_rows = sheet_head->comp_count;
610 num_cols = sheet_head->comp_attrib_count;
611 local_gtk_sheet = sheets[0];
612 master_row_list = sheet_head->master_comp_list_head;
613 master_col_list = sheet_head->master_comp_attrib_list_head;
615 local_table = sheet_head->component_table;
617 /* now fill out new table */
618 #ifdef DEBUG
619 printf("In s_table_gtksheet_to_all_tables, now about to fill out new component table.\n");
620 #endif
621 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
622 master_col_list, local_table,
623 num_rows, num_cols);
625 #if 0
626 /* Next handle net sheet */
627 num_rows = sheet_head->net_count;
628 num_cols = sheet_head->net_attrib_count;
629 local_gtk_sheet = sheets[1];
630 master_row_list = sheet_head->master_net_list_head;
631 master_col_list = sheet_head->master_net_attrib_list_head;
632 local_table = sheet_head->net_table;
634 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
635 master_col_list, local_table,
636 num_rows, num_cols);
637 #endif
639 #ifdef UNIMPLEMENTED_FEATURES
640 /* Finally, handle component pin sheet */
641 num_rows = sheet_head->pin_count;
642 num_cols = sheet_head->pin_attrib_count;
643 local_gtk_sheet = sheets[2];
644 master_row_list = sheet_head->master_pin_list_head;
645 master_col_list = sheet_head->master_pin_attrib_list_head;
646 /* local_table = s_table_new(num_rows, num_cols); */
647 local_table = sheet_head->pin_table;
649 s_table_gtksheet_to_table(local_gtk_sheet, master_row_list,
650 master_col_list, local_table,
651 num_rows, num_cols);
652 #endif
654 return;
658 /* =================== Private Functions ====================== */
659 /*------------------------------------------------------------------*/
660 /*! \brief Extract attributes from gtksheet into TABLE
662 * This function does the actual heavy lifting of looping
663 * through the spreadsheet, extracting the attribs from
664 * the cells, and placing them back into TABLE. This is the
665 * first step in saving out a project.
667 * \param local_gtk_sheet GtkSheet to save
668 * \param master_row_list STRING_LIST of rows
669 * \param master_col_list STRING_LIST of columns
670 * \param local_table TABLE structure to fill
671 * \param num_rows Number of rows in table
672 * \param num_cols Number of columns in table
674 void s_table_gtksheet_to_table(GtkSheet *local_gtk_sheet, STRING_LIST *master_row_list,
675 STRING_LIST *master_col_list, TABLE **local_table,
676 int num_rows, int num_cols)
678 int row, col;
680 STRING_LIST *row_list_item;
681 gchar *row_title;
683 STRING_LIST *col_list_item;
684 gchar *col_title;
686 gchar *attrib_value;
688 #ifdef DEBUG
689 printf("********** Entering s_table_gtksheet_to_table ******************\n");
690 #endif
693 row_list_item = master_row_list;
694 for (row = 0; row < num_rows; row++) {
695 row_title = (gchar *) g_strdup(row_list_item->data);
697 col_list_item = master_col_list;
698 for (col = 0; col < num_cols; col++) {
699 col_title = (gchar *) g_strdup(col_list_item->data);
701 /* get value of attrib in cell */
702 attrib_value = (gchar *) gtk_sheet_cell_get_text(GTK_SHEET(local_gtk_sheet), row, col);
704 #if 0
705 if (strlen(attrib_value) == 0) {
706 /* g_free(attrib_value); */ /* sometimes we have spurious, zero length strings creep */
707 attrib_value = NULL; /* into the GtkSheet */
709 #endif
712 #ifdef DEBUG
713 printf("In s_table_gtksheet_to_table, found attrib_value = %s in cell row=%d, col=%d\n",
714 attrib_value, row, col);
715 #endif
717 /* first handle attrib value in cell */
718 #ifdef DEBUG
719 printf(" Updating attrib_value %s\n", attrib_value);
720 #endif
721 g_free( local_table[row][col].attrib_value );
722 if (attrib_value != NULL) {
723 local_table[row][col].attrib_value = (gchar *) g_strdup(attrib_value);
724 } else {
725 local_table[row][col].attrib_value = NULL;
728 /* next handle name of row (also held in TABLE cell) */
729 #ifdef DEBUG
730 printf(" Updating row_name %s\n", row_title);
731 #endif
732 g_free( local_table[row][col].row_name );
733 if (row_title != NULL) {
734 local_table[row][col].row_name = (gchar *) g_strdup(row_title);
735 } else {
736 local_table[row][col].row_name = NULL;
739 /* finally handle name of col */
740 #ifdef DEBUG
741 printf(" Updating col_name %s\n", col_title);
742 #endif
743 g_free( local_table[row][col].col_name );
744 if (col_title != NULL) {
745 local_table[row][col].col_name = (gchar *) g_strdup(col_title);
746 } else {
747 local_table[row][col].col_name = NULL;
750 /* get next col list item and then iterate. */
751 col_list_item = col_list_item->next;
754 row_list_item = row_list_item->next;
757 return;