1 /*
2 * xnec2c - GTK2-based version of nec2c, the C translation of NEC2
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /* nec2_model.c
20 *
21 * Structure modelling functions for xnec2c
22 */
23
24 #include "nec2_model.h"
25 #include "shared.h"
26
27 /*------------------------------------------------------------------------*/
28
29 /* Nec2_Input_File_Treeview()
30 *
31 * Reads a NEC2 input file and renders it in a tree view
32 */
33 void
Nec2_Input_File_Treeview(int action)34 Nec2_Input_File_Treeview( int action )
35 {
36 /* Abort if editor window is not opened */
37 if( nec2_edit_window == NULL ) return;
38
39 /* Signal save of edited file */
40 SetFlag( NEC2_EDIT_SAVE );
41
42 /* Implement user action */
43 switch( action )
44 {
45 case NEC2_EDITOR_REVERT: /* Revert editor to file contents */
46 /* Clear all tree view list stores */
47 gtk_list_store_clear( cmnt_store );
48 gtk_list_store_clear( geom_store );
49 gtk_list_store_clear( cmnd_store );
50 break;
51
52 case NEC2_EDITOR_NEW: /* Create new default input file */
53 /* If tree view stores are already
54 * created, just make the new file */
55 Create_List_Stores(); /* Only done if needed */
56 Create_Default_File();
57 return;
58
59 case NEC2_EDITOR_RELOAD: /* Just reload input file */
60 Create_List_Stores(); /* Only done if needed */
61 break;
62
63 } /* switch( action ) */
64
65 /* Rewind NEC2 input file */
66 rewind( input_fp );
67
68 /*** List Comment cards ***/
69 List_Comments();
70
71 /*** List Geometry cards ***/
72 List_Geometry();
73
74 /*** Read Command cards ***/
75 List_Commands();
76
77 return;
78 } /* Nec2_Input_File_Treeview() */
79
80 /*------------------------------------------------------------------------*/
81
82 /* Create_List_Stores()
83 *
84 * Create stores needed for the treeview
85 */
86 void
Create_List_Stores(void)87 Create_List_Stores( void )
88 {
89 /* Comments column names */
90 char *cmnt_col_name[CMNT_NUM_COLS] =
91 { _("Card"), _("Comments") };
92
93 /* Geometry column names */
94 char *geom_col_name[GEOM_NUM_COLS] =
95 { _("Card"), "I1", "I2", "F1", "F2", "F3", "F4", "F5", "F6", "F7" };
96
97 /* Command column names */
98 char *cmnd_col_name[CMND_NUM_COLS] =
99 { _("Card"), "I1", "I2", "I3", "I4", "F1", "F2", "F3", "F4", "F5", "F6" };
100
101
102 /* Create list stores only if needed */
103 if( cmnt_store != NULL ) return;
104
105 /* Create comments list store */
106 cmnt_store = gtk_list_store_new(
107 CMNT_NUM_COLS, G_TYPE_STRING, G_TYPE_STRING );
108
109 /* Create geometry data list store */
110 geom_store = gtk_list_store_new(
111 GEOM_NUM_COLS, G_TYPE_STRING,
112 G_TYPE_STRING, G_TYPE_STRING,
113 G_TYPE_STRING, G_TYPE_STRING,
114 G_TYPE_STRING, G_TYPE_STRING,
115 G_TYPE_STRING, G_TYPE_STRING,
116 G_TYPE_STRING );
117
118 /* Create control commands data list store */
119 cmnd_store = gtk_list_store_new(
120 CMND_NUM_COLS, G_TYPE_STRING,
121 G_TYPE_STRING, G_TYPE_STRING,
122 G_TYPE_STRING, G_TYPE_STRING,
123 G_TYPE_STRING, G_TYPE_STRING,
124 G_TYPE_STRING, G_TYPE_STRING,
125 G_TYPE_STRING, G_TYPE_STRING );
126
127 /* Insert comment columns */
128 Insert_Columns(
129 nec2_edit_window, "nec2_cmnt_treeview",
130 cmnt_store, CMNT_NUM_COLS, cmnt_col_name );
131
132 /* Insert geometry columns */
133 Insert_Columns(
134 nec2_edit_window, "nec2_geom_treeview",
135 geom_store, GEOM_NUM_COLS, geom_col_name );
136
137 /* Insert command columns */
138 Insert_Columns(
139 nec2_edit_window, "nec2_cmnd_treeview",
140 cmnd_store, CMND_NUM_COLS, cmnd_col_name );
141
142 /* Set models to treviews */
143 gtk_tree_view_set_model(
144 GTK_TREE_VIEW(lookup_widget(
145 nec2_edit_window, "nec2_cmnt_treeview")),
146 GTK_TREE_MODEL(cmnt_store) );
147 gtk_tree_view_set_model(
148 GTK_TREE_VIEW(lookup_widget(
149 nec2_edit_window, "nec2_geom_treeview")),
150 GTK_TREE_MODEL(geom_store) );
151 gtk_tree_view_set_model(
152 GTK_TREE_VIEW(lookup_widget(
153 nec2_edit_window, "nec2_cmnd_treeview")),
154 GTK_TREE_MODEL(cmnd_store) );
155
156 } /* Create_List_Stores() */
157
158 /*------------------------------------------------------------------------*/
159
160 /* Create_Default_File()
161 *
162 * Creates a default NEC2 file if needed
163 */
164 void
Create_Default_File(void)165 Create_Default_File( void )
166 {
167 GtkTreeIter iter;
168 int idx, idi;
169 char str[64];
170 size_t s = sizeof( str );
171
172
173 /* Clear all tree views */
174 gtk_list_store_clear( cmnt_store );
175 gtk_list_store_clear( geom_store );
176 gtk_list_store_clear( cmnd_store );
177
178 /* Append a default comment row */
179 Strlcpy( str, _("--- NEC2 Input File created or edited by "), s );
180 Strlcat( str, PACKAGE_STRING, s );
181 Strlcat( str, " ---", s );
182 gtk_list_store_append( cmnt_store, &iter );
183 gtk_list_store_set(
184 cmnt_store, &iter,
185 CMNT_COL_NAME, "CM",
186 CMNT_COL_COMMENT, str, -1 );
187
188 /* Append a default CE card */
189 gtk_list_store_append( cmnt_store, &iter );
190 gtk_list_store_set(
191 cmnt_store, &iter,
192 CMNT_COL_NAME, "CE",
193 CMNT_COL_COMMENT,
194 _("--- End Comments ---"),
195 -1 );
196
197 /* Append a dipole wire (GW) card */
198 gtk_list_store_append( geom_store, &iter );
199 gtk_list_store_set( geom_store, &iter,
200 GEOM_COL_NAME, "GW",
201 GEOM_COL_I1, "1",
202 GEOM_COL_I2, "15",
203 GEOM_COL_F1, "0.0",
204 GEOM_COL_F2, "0.0",
205 GEOM_COL_F3, "-1.0",
206 GEOM_COL_F4, "0.0",
207 GEOM_COL_F5, "0.0",
208 GEOM_COL_F6, "1.0",
209 GEOM_COL_F7, "0.015",
210 -1 );
211
212 /* Append a geometry end (GE) card */
213 gtk_list_store_append( geom_store, &iter );
214 gtk_list_store_set( geom_store,
215 &iter, GEOM_COL_NAME, "GE", -1 );
216 for( idx = GEOM_COL_I1; idx < GEOM_NUM_COLS; idx++ )
217 gtk_list_store_set( geom_store, &iter, idx, "0", -1 );
218
219 /* Append an excitation (EX) card */
220 gtk_list_store_append( cmnd_store, &iter );
221 gtk_list_store_set( cmnd_store, &iter,
222 CMND_COL_NAME, "EX",
223 CMND_COL_I1, "0",
224 CMND_COL_I2, "1",
225 CMND_COL_I3, "8",
226 CMND_COL_I4, "0",
227 CMND_COL_F1, "1.0",
228 CMND_COL_F2, "0.0",
229 CMND_COL_F3, "0.0",
230 CMND_COL_F4, "0.0",
231 CMND_COL_F5, "0.0",
232 CMND_COL_F6, "0.0",
233 -1 );
234
235 /* Append a frequency (FR) card */
236 gtk_list_store_append( cmnd_store, &iter );
237 gtk_list_store_set( cmnd_store, &iter,
238 CMND_COL_NAME, "FR",
239 CMND_COL_I1, "0",
240 CMND_COL_I2, "11",
241 CMND_COL_I3, "0",
242 CMND_COL_I4, "0",
243 CMND_COL_F1, "50.0",
244 CMND_COL_F2, "5.0",
245 CMND_COL_F3, "0.0",
246 CMND_COL_F4, "0.0",
247 CMND_COL_F5, "0.0",
248 CMND_COL_F6, "0.0",
249 -1 );
250
251 /* Append a near H field (NH) card */
252 gtk_list_store_append( cmnd_store, &iter );
253 gtk_list_store_set( cmnd_store, &iter,
254 CMND_COL_NAME, "NH",
255 CMND_COL_I1, "0",
256 CMND_COL_I2, "0",
257 CMND_COL_I3, "0",
258 CMND_COL_I4, "0",
259 CMND_COL_F1, "0.0",
260 CMND_COL_F2, "0.0",
261 CMND_COL_F3, "0.0",
262 CMND_COL_F4, "0.0",
263 CMND_COL_F5, "0.0",
264 CMND_COL_F6, "0.0",
265 -1 );
266
267 /* Append a near E field (NE) card */
268 gtk_list_store_append( cmnd_store, &iter );
269 gtk_list_store_set( cmnd_store, &iter,
270 CMND_COL_NAME, "NE",
271 CMND_COL_I1, "0",
272 CMND_COL_I2, "10",
273 CMND_COL_I3, "1",
274 CMND_COL_I4, "10",
275 CMND_COL_F1, "-1.35",
276 CMND_COL_F2, "0.0",
277 CMND_COL_F3, "-1.35",
278 CMND_COL_F4, "0.3",
279 CMND_COL_F5, "0.0",
280 CMND_COL_F6, "0.3",
281 -1 );
282
283 /* Append a radiation pattern (RP) card */
284 gtk_list_store_append( cmnd_store, &iter );
285 gtk_list_store_set( cmnd_store, &iter,
286 CMND_COL_NAME, "RP",
287 CMND_COL_I1, "0",
288 CMND_COL_I2, "19",
289 CMND_COL_I3, "37",
290 CMND_COL_I4, "1000",
291 CMND_COL_F1, "0.0",
292 CMND_COL_F2, "0.0",
293 CMND_COL_F3, "10.0",
294 CMND_COL_F4, "10.0",
295 CMND_COL_F5, "0.0",
296 CMND_COL_F6, "0.0",
297 -1 );
298
299 /* Append a file end (EN) card */
300 gtk_list_store_append( cmnd_store, &iter );
301 gtk_list_store_set( cmnd_store,
302 &iter, CMND_COL_NAME, "EN", -1 );
303 for( idi = CMND_COL_I1; idi < CMND_NUM_COLS; idi++ )
304 gtk_list_store_set( cmnd_store, &iter, idi, "0", -1 );
305
306 } /* Create_Default_File() */
307
308 /*------------------------------------------------------------------------*/
309
310 /* List_Comments()
311 *
312 * Reads comments from file and lists in tree view
313 */
314 void
List_Comments(void)315 List_Comments( void )
316 {
317 GtkTreeIter iter;
318 gboolean ret;
319
320 /* "Card" mnemonic and line buffer */
321 char ain[3], line_buf[LINE_LEN];
322
323 /* Check that store is empty */
324 ret = gtk_tree_model_get_iter_first(
325 GTK_TREE_MODEL(cmnt_store), &iter );
326
327 /* Keep reading till the CE card */
328 do
329 {
330 /* Read a line from input file */
331 if( Load_Line(line_buf, input_fp) == EOF )
332 stop( _("List_Comments():\n"\
333 "Error reading input file\n"\
334 "Unexpected EOF (End of File)"), ERR_OK );
335
336 /* Check for short or missing CM or CE and fix */
337 if( strlen(line_buf) < 2 )
338 {
339 stop( _("List_Comments():\n"\
340 "Error reading input file\n"\
341 "Comment mnemonic short or missing"), ERR_OK );
342 Strlcpy( line_buf, "XX ", sizeof(line_buf) );
343 }
344
345 /* If only mnemonic in card,
346 * "cut" the rest of line buffer */
347 if( strlen(line_buf) == 2 ) line_buf[3] = '\0';
348
349 /* Separate card's id mnemonic */
350 Strlcpy( ain, line_buf, sizeof(ain) );
351
352 /* Append a comment row and fill in text if opening call */
353 if( !ret )
354 gtk_list_store_append( cmnt_store, &iter );
355 gtk_list_store_set(
356 cmnt_store, &iter,
357 CMNT_COL_NAME, ain,
358 CMNT_COL_COMMENT,
359 &line_buf[3], -1 );
360
361 /* Get new row if available */
362 ret = gtk_tree_model_iter_next(
363 GTK_TREE_MODEL(cmnt_store), &iter);
364
365 } /* do */
366 while( strcmp(ain, "CE") != 0 );
367
368 } /* List_Comments() */
369
370 /*------------------------------------------------------------------------*/
371
372 /* List_Geometry()
373 *
374 * Reads geometry cards from file and lists in tree view
375 */
376 void
List_Geometry(void)377 List_Geometry( void )
378 {
379 GtkTreeIter iter;
380
381 /* "Card" mnemonic */
382 char ain[3];
383
384 /* int data from cards */
385 int iv[4];
386
387 /* float data from cards */
388 double fv[7];
389
390 /* For snprintf */
391 char si[4][7], sf[7][13];
392
393 int idx;
394 gboolean ret;
395
396 /* Check that store is empty */
397 ret = gtk_tree_model_get_iter_first(
398 GTK_TREE_MODEL(geom_store), &iter );
399 do
400 {
401 /* Read a geometry card. Errors are handled in readgm() */
402 if( !readgm( ain, &iv[0], &iv[1],
403 &fv[0], &fv[1], &fv[2], &fv[3],
404 &fv[4], &fv[5], &fv[6]) )
405 break;
406
407 /* Ignore in-data (NEC4 style) comments */
408 if( strcmp(ain, "CM") == 0 ) continue;
409
410 /* Format card data and print to string */
411 snprintf( si[0], 6, "%5d", iv[0] );
412 snprintf( si[1], 7, "%5d ", iv[1] );
413 for( idx = GEOM_COL_F1; idx <= GEOM_COL_F7; idx++ )
414 snprintf( sf[idx-GEOM_COL_F1], 13,
415 "%12.5E", (double)fv[idx-GEOM_COL_F1] );
416
417 /* Append a comment row and fill in text if opening call */
418 if( !ret )
419 gtk_list_store_append( geom_store, &iter );
420
421 /* Set data to list store */
422 gtk_list_store_set(
423 geom_store, &iter, GEOM_COL_NAME, ain, -1 );
424 for( idx = GEOM_COL_I1; idx <= GEOM_COL_I2; idx++ )
425 gtk_list_store_set(
426 geom_store, &iter, idx, si[idx-GEOM_COL_I1], -1 );
427 for( idx = GEOM_COL_F1; idx <= GEOM_COL_F7; idx++ )
428 gtk_list_store_set(
429 geom_store, &iter, idx, sf[idx-GEOM_COL_F1], -1 );
430
431 /* Get new row if available */
432 ret = gtk_tree_model_iter_next(
433 GTK_TREE_MODEL(geom_store), &iter);
434 }
435 while( strcmp(ain, "GE") != 0 );
436
437 } /* List_Geometry() */
438
439 /*------------------------------------------------------------------------*/
440
441 /* List_Commands()
442 *
443 * Reads command cards from file and lists in tree view
444 */
445 void
List_Commands(void)446 List_Commands( void )
447 {
448 GtkTreeIter iter;
449
450 /* "Card" mnemonic and line buffer */
451 char ain[3];
452
453 /* int data from cards */
454 int iv[4];
455
456 /* float data from cards */
457 double fv[7];
458
459 /* For snprintf */
460 char si[4][7], sf[7][13];
461
462 int idx;
463 gboolean ret;
464
465 /* Check that store is empty */
466 ret = gtk_tree_model_get_iter_first(
467 GTK_TREE_MODEL(cmnd_store), &iter );
468 do
469 {
470 /* Read a command card. Errors are handled in readmn() */
471 readmn(
472 ain, &iv[0], &iv[1], &iv[2], &iv[3], &fv[0],
473 &fv[1], &fv[2], &fv[3], &fv[4], &fv[5] );
474
475 /* Ignore in-data (NEC4 style) comments */
476 if( strcmp(ain, "CM") == 0 ) continue;
477
478 /* Format card data and print to string */
479 for( idx = CMND_COL_I1; idx < CMND_COL_I4; idx++ )
480 snprintf( si[idx-CMND_COL_I1], 6, "%5d", iv[idx-CMND_COL_I1] );
481
482 /* For alignment of data printed to NEC2 file */
483 snprintf( si[idx-CMND_COL_I1], 7, " %5d", iv[idx-CMND_COL_I1] );
484 for( idx = CMND_COL_F1; idx <= CMND_COL_F6; idx++ )
485 snprintf( sf[idx-CMND_COL_F1], 13,
486 "%12.5E", (double)fv[idx-CMND_COL_F1] );
487
488 /* Append a command row and fill in text if opening call */
489 if( !ret )
490 gtk_list_store_append( cmnd_store, &iter );
491
492 /* Set data to list store */
493 gtk_list_store_set(
494 cmnd_store, &iter, CMND_COL_NAME, ain, -1 );
495 for( idx = CMND_COL_I1; idx <= CMND_COL_I4; idx++ )
496 gtk_list_store_set(
497 cmnd_store, &iter, idx, si[idx-CMND_COL_I1], -1 );
498 for( idx = CMND_COL_F1; idx <= CMND_COL_F6; idx++ )
499 gtk_list_store_set(
500 cmnd_store, &iter, idx, sf[idx-CMND_COL_F1], -1 );
501
502 /* Get new row if available */
503 ret = gtk_tree_model_iter_next(
504 GTK_TREE_MODEL(cmnd_store), &iter);
505 }
506 while( strcmp(ain, "EN") != 0 );
507
508 } /* List_Commands() */
509
510 /*------------------------------------------------------------------------*/
511
512 /* Insert_Columns()
513 *
514 * Inserts columns in a list store
515 */
516 void
Insert_Columns(GtkWidget * window,gchar * treeview,GtkListStore * store,int ncols,char * colname[])517 Insert_Columns( GtkWidget *window, gchar *treeview,
518 GtkListStore* store, int ncols, char *colname[] )
519 {
520 int idx;
521 GtkTreeModel *model;
522 GtkCellRenderer *renderer;
523
524 static GtkWidget *view;
525 view = lookup_widget( window, treeview );
526 for( idx = 0; idx < ncols; idx++ )
527 {
528 renderer = gtk_cell_renderer_text_new();
529 g_object_set(renderer, "editable", TRUE, NULL);
530 g_signal_connect( renderer, "edited",
531 (GCallback)cell_edited_callback, view );
532 g_object_set_data( G_OBJECT(renderer),
533 "column", GUINT_TO_POINTER(idx) );
534 gtk_tree_view_insert_column_with_attributes(
535 GTK_TREE_VIEW(view), -1, colname[idx],
536 renderer, "text", idx, NULL );
537 }
538 model = GTK_TREE_MODEL(store);
539 gtk_tree_view_set_model( GTK_TREE_VIEW (view), model );
540
541 /* Destroy model automatically with view */
542 g_object_unref( model );
543
544 } /* Insert_Columns() */
545
546 /*------------------------------------------------------------------------*/
547
548 /* cell_edited_callback()
549 *
550 * Text cell edited callback
551 */
552 void
cell_edited_callback(GtkCellRendererText * cell,gchar * path,gchar * new_text,gpointer user_data)553 cell_edited_callback(
554 GtkCellRendererText *cell,
555 gchar *path,
556 gchar *new_text,
557 gpointer user_data )
558 {
559 GtkTreeSelection *selection;
560 GtkTreeModel *model;
561 GtkTreeIter iter;
562 guint column;
563
564 column = GPOINTER_TO_UINT(
565 g_object_get_data(G_OBJECT(cell), "column") );
566 selection = gtk_tree_view_get_selection(
567 GTK_TREE_VIEW(user_data) );
568 gtk_tree_selection_get_selected(
569 selection, &model, &iter );
570
571 /* Blank cells cause problems */
572 if( strcmp(new_text, "") == 0 )
573 {
574 gchar *name;
575
576 gtk_tree_model_get( model, &iter, 0, &name, -1 );
577 if( strcmp(name, "CE") == 0 )
578 gtk_list_store_set( GTK_LIST_STORE(model),
579 &iter, column, _("End Comments"), -1 );
580 else
581 gtk_list_store_set( GTK_LIST_STORE(model),
582 &iter, column, "0", -1 );
583 g_free(name);
584 }
585 else
586 gtk_list_store_set( GTK_LIST_STORE(model),
587 &iter, column, new_text, -1 );
588
589 } /* cell_edited_callback() */
590
591 /*------------------------------------------------------------------------*/
592
593 /* Save_Nec2_Input_File()
594 *
595 * Saves the data in a NEC2 input treeview to a given filename
596 */
597 void
Save_Nec2_Input_File(GtkWidget * treeview_window,char * nec2_file)598 Save_Nec2_Input_File( GtkWidget *treeview_window, char *nec2_file )
599 {
600 FILE *nec2_fp = NULL;
601 GtkTreeView *tree_view;
602
603
604 /* Abort if editor window is not opened */
605 if( nec2_edit_window == NULL ) return;
606
607 /* Open NEC2 input file for writing */
608 if( !Open_File(&nec2_fp, nec2_file, "w") ) return;
609
610 /* Save comments to file */
611 tree_view = GTK_TREE_VIEW( lookup_widget(
612 treeview_window, "nec2_cmnt_treeview") );
613 Save_Treeview_Data( tree_view, CMNT_NUM_COLS, nec2_fp );
614
615 /* Save geometry to file */
616 tree_view = GTK_TREE_VIEW( lookup_widget(
617 treeview_window, "nec2_geom_treeview") );
618 Save_Treeview_Data( tree_view, GEOM_NUM_COLS, nec2_fp );
619
620 /* Save commands to file */
621 tree_view = GTK_TREE_VIEW( lookup_widget(
622 treeview_window, "nec2_cmnd_treeview") );
623 Save_Treeview_Data( tree_view, CMND_NUM_COLS, nec2_fp );
624
625 /* Re-open file in read mode */
626 Close_File( &nec2_fp );
627
628 } /* Save_Nec2_Input_File() */
629
630 /*------------------------------------------------------------------------*/
631
632 /* Save_Treeview_Data()
633 *
634 * Saves tree view data to an open NEC2 input file
635 */
636 void
Save_Treeview_Data(GtkTreeView * tree_view,int ncols,FILE * nec2_fp)637 Save_Treeview_Data( GtkTreeView *tree_view, int ncols, FILE *nec2_fp )
638 {
639 GtkTreeModel *list_store;
640 GtkTreeIter iter;
641 gboolean valid;
642 int idx;
643
644 /* Abort if no open file to sane to */
645 if( nec2_fp == NULL )
646 {
647 stop( _("Cannot save treeview data\n"\
648 "Please use the Save button\n"\
649 "to specify a file path"), ERR_STOP );
650 }
651
652 /* Get the first iter in the list */
653 list_store = GTK_TREE_MODEL( gtk_tree_view_get_model(tree_view) );
654 valid = gtk_tree_model_get_iter_first( list_store, &iter );
655
656 /* Walk through all rows and print data to file */
657 while( valid )
658 {
659 gchar *str_data;
660
661 for( idx = 0; idx < ncols; idx++ )
662 {
663 gtk_tree_model_get( list_store, &iter, idx, &str_data, -1 );
664 fprintf( nec2_fp, "%s ", str_data );
665 g_free( str_data );
666 }
667
668 /* Overwrite last space with newline */
669 if( fseek(nec2_fp, -1, SEEK_CUR) == 0 )
670 fprintf( nec2_fp, "\n" );
671
672 valid = gtk_tree_model_iter_next( list_store, &iter );
673 } /* while( valid ) */
674
675 } /* Save_Treeview_Data() */
676
677 /*------------------------------------------------------------------------*/
678
679 /* Helper function */
680 gboolean
gtk_tree_model_iter_previous(GtkTreeModel * tree_model,GtkTreeIter * iter)681 gtk_tree_model_iter_previous(GtkTreeModel *tree_model, GtkTreeIter *iter)
682 {
683 GtkTreePath *path;
684 gboolean ret;
685
686 path = gtk_tree_model_get_path (tree_model, iter);
687 ret = gtk_tree_path_prev (path);
688 if (ret == TRUE)
689 gtk_tree_model_get_iter (tree_model, iter, path);
690 gtk_tree_path_free (path);
691 return ret;
692 }
693
694 /*------------------------------------------------------------------------*/
695
696