name change
[metze/wireshark/wip.git] / gtk / recent.c
1 /* recent.c
2  * Recent "preference" handling routines
3  * Copyright 2004, Ulf Lamping <ulf.lamping@web.de>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #include "recent.h"
36 #include <epan/epan.h>
37 #include <epan/filesystem.h>
38 #include "menu.h"
39 #include "main.h"
40 #include <epan/prefs.h>
41 #include <epan/prefs-int.h>
42 #include "gui_utils.h"
43 #if 0
44 #include "dlg_utils.h"
45 #endif
46 #include "file_dlg.h"
47 #include "cfilter_combo_utils.h"
48 #include "simple_dialog.h"
49 #include "file_util.h"
50
51 #define RECENT_KEY_MAIN_TOOLBAR_SHOW        "gui.toolbar_main_show"
52 #define RECENT_KEY_FILTER_TOOLBAR_SHOW      "gui.filter_toolbar_show"
53 #define RECENT_KEY_PACKET_LIST_SHOW         "gui.packet_list_show"
54 #define RECENT_KEY_TREE_VIEW_SHOW           "gui.tree_view_show"
55 #define RECENT_KEY_BYTE_VIEW_SHOW           "gui.byte_view_show"
56 #define RECENT_KEY_STATUSBAR_SHOW           "gui.statusbar_show"
57 #define RECENT_KEY_PACKET_LIST_COLORIZE     "gui.packet_list_colorize"
58 #define RECENT_GUI_TIME_FORMAT              "gui.time_format"
59 #define RECENT_GUI_TIME_PRECISION           "gui.time_precision"
60 #define RECENT_GUI_ZOOM_LEVEL               "gui.zoom_level"
61 #define RECENT_GUI_GEOMETRY_MAIN_X          "gui.geometry_main_x"
62 #define RECENT_GUI_GEOMETRY_MAIN_Y          "gui.geometry_main_y"
63 #define RECENT_GUI_GEOMETRY_MAIN_WIDTH      "gui.geometry_main_width"
64 #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT     "gui.geometry_main_height"
65 #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED  "gui.geometry_main_maximized"
66 #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
67 #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
68 #define RECENT_GUI_GEOMETRY_STATUS_PANE     "gui.geometry_status_pane"
69 #define RECENT_GUI_FILEOPEN_REMEMBERED_DIR  "gui.fileopen_remembered_dir"
70 #define RECENT_GUI_GEOMETRY "gui.geom."
71
72 #define RECENT_FILE_NAME "recent"
73
74 recent_settings_t recent;
75
76 static const char *ts_type_text[] =
77         { "RELATIVE", "ABSOLUTE", "ABSOLUTE_WITH_DATE", "DELTA", NULL };
78
79 static const char *ts_precision_text[] =
80         { "AUTO", "SEC", "DSEC", "CSEC", "MSEC", "USEC", "NSEC", NULL };
81
82 /* Takes an string and a pointer to an array of strings, and a default int value.
83  * The array must be terminated by a NULL string. If the string is found in the array
84  * of strings, the index of that string in the array is returned. Otherwise, the
85  * default value that was passed as the third argument is returned.
86  */
87 static int
88 find_index_from_string_array(const char *needle, const char **haystack, int default_value)
89 {
90         int i = 0;
91
92         while (haystack[i] != NULL) {
93                 if (strcmp(needle, haystack[i]) == 0) {
94                         return i;
95                 }
96                 i++;
97         }
98         return default_value;
99 }
100
101 /* Attempt to Write out "recent" to the user's recent file.
102    If we got an error report it with a dialog box and return FALSE,
103    otherwise return TRUE. */
104 gboolean
105 write_recent(void)
106 {
107   char        *pf_dir_path;
108   char        *rf_path;
109   FILE        *rf;
110
111   /* To do:
112    * - Split output lines longer than MAX_VAL_LEN
113    * - Create a function for the preference directory check/creation
114    *   so that duplication can be avoided with filter.c
115    */
116
117   /* Create the directory that holds personal configuration files, if
118      necessary.  */
119   if (create_persconffile_dir(&pf_dir_path) == -1) {
120      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
121       "Can't create directory\n\"%s\"\nfor recent file: %s.", pf_dir_path,
122       strerror(errno));
123      g_free(pf_dir_path);
124      return FALSE;
125   }
126
127   rf_path = get_persconffile_path(RECENT_FILE_NAME, TRUE);
128   if ((rf = eth_fopen(rf_path, "w")) == NULL) {
129      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
130       "Can't open recent file\n\"%s\": %s.", rf_path,
131       strerror(errno));
132     g_free(rf_path);
133     return FALSE;
134   }
135
136   fputs("# Recent settings file for Ethereal " VERSION ".\n"
137     "#\n"
138     "# This file is regenerated each time Ethereal is quit.\n"
139     "# So be careful, if you want to make manual changes here.\n"
140     "\n"
141     "######## Recent capture files (latest last), cannot be altered through command line ########\n"
142     "\n", rf);
143
144   menu_recent_file_write_all(rf);
145
146   fputs("\n"
147     "######## Recent capture filters (latest last), cannot be altered through command line ########\n"
148     "\n", rf);
149
150   cfilter_combo_recent_write_all(rf);
151
152   fputs("\n"
153     "######## Recent display filters (latest last), cannot be altered through command line ########\n"
154     "\n", rf);
155
156   dfilter_recent_combo_write_all(rf);
157
158   fprintf(rf, "\n# Main Toolbar show (hide).\n");
159   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
160   fprintf(rf, RECENT_KEY_MAIN_TOOLBAR_SHOW ": %s\n",
161                   recent.main_toolbar_show == TRUE ? "TRUE" : "FALSE");
162
163   fprintf(rf, "\n# Filter Toolbar show (hide).\n");
164   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
165   fprintf(rf, RECENT_KEY_FILTER_TOOLBAR_SHOW ": %s\n",
166                   recent.filter_toolbar_show == TRUE ? "TRUE" : "FALSE");
167
168   fprintf(rf, "\n# Packet list show (hide).\n");
169   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
170   fprintf(rf, RECENT_KEY_PACKET_LIST_SHOW ": %s\n",
171                   recent.packet_list_show == TRUE ? "TRUE" : "FALSE");
172
173   fprintf(rf, "\n# Tree view show (hide).\n");
174   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
175   fprintf(rf, RECENT_KEY_TREE_VIEW_SHOW ": %s\n",
176                   recent.tree_view_show == TRUE ? "TRUE" : "FALSE");
177
178   fprintf(rf, "\n# Byte view show (hide).\n");
179   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
180   fprintf(rf, RECENT_KEY_BYTE_VIEW_SHOW ": %s\n",
181                   recent.byte_view_show == TRUE ? "TRUE" : "FALSE");
182
183   fprintf(rf, "\n# Statusbar show (hide).\n");
184   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
185   fprintf(rf, RECENT_KEY_STATUSBAR_SHOW ": %s\n",
186                   recent.statusbar_show == TRUE ? "TRUE" : "FALSE");
187
188   fprintf(rf, "\n# Packet list colorize (hide).\n");
189   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
190   fprintf(rf, RECENT_KEY_PACKET_LIST_COLORIZE ": %s\n",
191                   recent.packet_list_colorize == TRUE ? "TRUE" : "FALSE");
192
193   fprintf(rf, "\n# Timestamp display format.\n");
194   fprintf(rf, "# One of: RELATIVE, ABSOLUTE, ABSOLUTE_WITH_DATE, DELTA\n");
195   fprintf(rf, RECENT_GUI_TIME_FORMAT ": %s\n",
196           ts_type_text[recent.gui_time_format]);
197
198   fprintf(rf, "\n# Timestamp display precision.\n");
199   fprintf(rf, "# One of: AUTO, SEC, DSEC, CSEC, MSEC, USEC, NSEC\n");
200   fprintf(rf, RECENT_GUI_TIME_PRECISION ": %s\n",
201           ts_precision_text[recent.gui_time_precision]);
202
203   fprintf(rf, "\n# Zoom level.\n");
204   fprintf(rf, "# A decimal number.\n");
205   fprintf(rf, RECENT_GUI_ZOOM_LEVEL ": %d\n",
206                   recent.gui_zoom_level);
207
208   fprintf(rf, "\n# Main window geometry.\n");
209   fprintf(rf, "# Decimal numbers.\n");
210   fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_X ": %d\n", recent.gui_geometry_main_x);
211   fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_Y ": %d\n", recent.gui_geometry_main_y);
212   fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_WIDTH ": %d\n",
213                   recent.gui_geometry_main_width);
214   fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_HEIGHT ": %d\n",
215                   recent.gui_geometry_main_height);
216   
217   fprintf(rf, "\n# Main window maximized (GTK2 only!).\n");
218   fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
219   fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED ": %s\n",
220                   recent.gui_geometry_main_maximized == TRUE ? "TRUE" : "FALSE");
221
222   fprintf(rf, "\n# Main window upper (or leftmost) pane size.\n");
223   fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
224   fprintf(rf, "# Decimal number.\n");
225   if (recent.gui_geometry_main_upper_pane != 0) {
226     fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE ": %d\n",
227                   recent.gui_geometry_main_upper_pane);
228   }
229   fprintf(rf, "\n# Main window middle pane size.\n");
230   fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
231   fprintf(rf, "# Decimal number.\n");
232   if (recent.gui_geometry_main_lower_pane != 0) {
233     fprintf(rf, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE ": %d\n",
234                   recent.gui_geometry_main_lower_pane);
235   }
236   fprintf(rf, "\n# Statusbar left pane size.\n");
237   fprintf(rf, "# (GTK1: has no effect here, command line -o usage only).\n");
238   fprintf(rf, "# Decimal number.\n");
239   if (recent.gui_geometry_status_pane != 0) {
240     fprintf(rf, RECENT_GUI_GEOMETRY_STATUS_PANE ": %d\n",
241                   recent.gui_geometry_status_pane);
242   }
243
244   if (get_last_open_dir() != NULL) {
245     fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
246     fprintf(rf, RECENT_GUI_FILEOPEN_REMEMBERED_DIR ": %s\n", get_last_open_dir());
247   }
248
249   window_geom_recent_write_all(rf);
250
251   fclose(rf);
252
253   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
254      an error indication, or maybe write to a new recent file and
255      rename that file on top of the old one only if there are not I/O
256      errors. */
257   return TRUE;
258 }
259
260
261 /* write the geometry values of a window to recent file */
262 void 
263 write_recent_geom(gpointer key _U_, gpointer value, gpointer rf)
264 {
265     window_geometry_t *geom = value;
266
267     fprintf(rf, "\n# Geometry and maximized state (GTK2 only) of %s window.\n", geom->key);
268     fprintf(rf, "# Decimal integers.\n");
269     fprintf(rf, RECENT_GUI_GEOMETRY "%s.x: %d\n", geom->key, geom->x);
270     fprintf(rf, RECENT_GUI_GEOMETRY "%s.y: %d\n", geom->key, geom->y);
271     fprintf(rf, RECENT_GUI_GEOMETRY "%s.width: %d\n", geom->key,
272               geom->width);
273     fprintf(rf, RECENT_GUI_GEOMETRY "%s.height: %d\n", geom->key,
274               geom->height);
275
276     fprintf(rf, "# TRUE or FALSE (case-insensitive).\n");
277     fprintf(rf, RECENT_GUI_GEOMETRY "%s.maximized: %s\n", geom->key,
278               geom->maximized == TRUE ? "TRUE" : "FALSE");
279
280 }
281
282
283 /* set one user's recent file key/value pair */
284 static int
285 read_set_recent_pair_static(gchar *key, gchar *value)
286 {
287   long num;
288   char *p;
289
290   if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
291     if (strcasecmp(value, "true") == 0) {
292         recent.main_toolbar_show = TRUE;
293     }
294     else {
295         recent.main_toolbar_show = FALSE;
296     }
297   } else if (strcmp(key, RECENT_KEY_FILTER_TOOLBAR_SHOW) == 0) {
298     if (strcasecmp(value, "true") == 0) {
299         recent.filter_toolbar_show = TRUE;
300     }
301     else {
302         recent.filter_toolbar_show = FALSE;
303     }
304   } else if (strcmp(key, RECENT_KEY_PACKET_LIST_SHOW) == 0) {
305     if (strcasecmp(value, "true") == 0) {
306         recent.packet_list_show = TRUE;
307     }
308     else {
309         recent.packet_list_show = FALSE;
310     }
311   } else if (strcmp(key, RECENT_KEY_TREE_VIEW_SHOW) == 0) {
312     if (strcasecmp(value, "true") == 0) {
313         recent.tree_view_show = TRUE;
314     }
315     else {
316         recent.tree_view_show = FALSE;
317     }
318   } else if (strcmp(key, RECENT_KEY_BYTE_VIEW_SHOW) == 0) {
319     if (strcasecmp(value, "true") == 0) {
320         recent.byte_view_show = TRUE;
321     }
322     else {
323         recent.byte_view_show = FALSE;
324     }
325   } else if (strcmp(key, RECENT_KEY_STATUSBAR_SHOW) == 0) {
326     if (strcasecmp(value, "true") == 0) {
327         recent.statusbar_show = TRUE;
328     }
329     else {
330         recent.statusbar_show = FALSE;
331     }
332   } else if (strcmp(key, RECENT_KEY_PACKET_LIST_COLORIZE) == 0) {
333     if (strcasecmp(value, "true") == 0) {
334         recent.packet_list_colorize = TRUE;
335     }
336     else {
337         recent.packet_list_colorize = FALSE;
338     }
339   } else if (strcmp(key, RECENT_GUI_TIME_FORMAT) == 0) {
340     recent.gui_time_format =
341         find_index_from_string_array(value, ts_type_text, TS_RELATIVE);
342   } else if (strcmp(key, RECENT_GUI_TIME_PRECISION) == 0) {
343     recent.gui_time_precision =
344         find_index_from_string_array(value, ts_precision_text, TS_PREC_AUTO);
345   } else if (strcmp(key, RECENT_GUI_ZOOM_LEVEL) == 0) {
346     num = strtol(value, &p, 0);
347     if (p == value || *p != '\0')
348       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
349     recent.gui_zoom_level = num;
350   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
351     if (strcasecmp(value, "true") == 0) {
352         recent.gui_geometry_main_maximized = TRUE;
353     }
354     else {
355         recent.gui_geometry_main_maximized = FALSE;
356     }
357
358   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
359     num = strtol(value, &p, 0);
360     if (p == value || *p != '\0')
361       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
362     recent.gui_geometry_main_x = num;
363   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_Y) == 0) {
364     num = strtol(value, &p, 0);
365     if (p == value || *p != '\0')
366       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
367     recent.gui_geometry_main_y = num;
368   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_WIDTH) == 0) {
369     num = strtol(value, &p, 0);
370     if (p == value || *p != '\0')
371       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
372     if (num <= 0)
373       return PREFS_SET_SYNTAX_ERR;      /* number must be positive */
374     recent.gui_geometry_main_width = num;
375   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {
376     num = strtol(value, &p, 0);
377     if (p == value || *p != '\0')
378       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
379     if (num <= 0)
380       return PREFS_SET_SYNTAX_ERR;      /* number must be positive */
381     recent.gui_geometry_main_height = num;
382   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE) == 0) {
383     num = strtol(value, &p, 0);
384     if (p == value || *p != '\0')
385       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
386     if (num <= 0)
387       return PREFS_SET_SYNTAX_ERR;      /* number must be positive */
388     recent.gui_geometry_main_upper_pane = num;
389     recent.has_gui_geometry_main_upper_pane = TRUE;
390   } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE) == 0) {
391     num = strtol(value, &p, 0);
392     if (p == value || *p != '\0')
393       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
394     if (num <= 0)
395       return PREFS_SET_SYNTAX_ERR;      /* number must be positive */
396     recent.gui_geometry_main_lower_pane = num;
397     recent.has_gui_geometry_main_lower_pane = TRUE;
398   } else if (strcmp(key, RECENT_GUI_GEOMETRY_STATUS_PANE) == 0) {
399     num = strtol(value, &p, 0);
400     if (p == value || *p != '\0')
401       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
402     if (num <= 0)
403       return PREFS_SET_SYNTAX_ERR;      /* number must be positive */
404     recent.gui_geometry_status_pane = num;
405     recent.has_gui_geometry_status_pane = TRUE;
406   } else if (strcmp(key, RECENT_GUI_FILEOPEN_REMEMBERED_DIR) == 0) {
407     set_last_open_dir(value);
408   } else if (strncmp(key, RECENT_GUI_GEOMETRY, sizeof(RECENT_GUI_GEOMETRY)-1) == 0) {
409     /* now have something like "gui.geom.main.x", split it into win and sub_key */
410     char *win = &key[sizeof(RECENT_GUI_GEOMETRY)-1];
411     char *sub_key = strchr(win, '.');
412     if(sub_key) {
413       *sub_key = '\0';
414       sub_key++;
415       window_geom_recent_read_pair(win, sub_key, value);
416     }
417   }
418
419   return PREFS_SET_OK;
420 }
421
422
423 /* set one user's recent file key/value pair */
424 static int
425 read_set_recent_pair_dynamic(gchar *key, gchar *value)
426 {
427   if (strcmp(key, RECENT_KEY_CAPTURE_FILE) == 0) {
428         add_menu_recent_capture_file(value);
429   } else if (strcmp(key, RECENT_KEY_DISPLAY_FILTER) == 0) {
430         dfilter_combo_add_recent(value);
431   } else if (strcmp(key, RECENT_KEY_CAPTURE_FILTER) == 0) {
432         cfilter_combo_add_recent(value);
433   }
434
435   return PREFS_SET_OK;
436 }
437
438
439 /*
440  * Given a string of the form "<recent name>:<recent value>", as might appear
441  * as an argument to a "-o" option, parse it and set the recent value in
442  * question.  Return an indication of whether it succeeded or failed
443  * in some fashion.
444  */
445 int
446 recent_set_arg(char *prefarg)
447 {
448         guchar *p, *colonp;
449         int ret;
450
451         colonp = strchr(prefarg, ':');
452         if (colonp == NULL)
453                 return PREFS_SET_SYNTAX_ERR;
454
455         p = colonp;
456         *p++ = '\0';
457
458         /*
459          * Skip over any white space (there probably won't be any, but
460          * as we allow it in the preferences file, we might as well
461          * allow it here).
462          */
463         while (isspace(*p))
464                 p++;
465         if (*p == '\0') {
466                 /*
467                  * Put the colon back, so if our caller uses, in an
468                  * error message, the string they passed us, the message
469                  * looks correct.
470                  */
471                 *colonp = ':';
472                 return PREFS_SET_SYNTAX_ERR;
473         }
474
475         ret = read_set_recent_pair_static(prefarg, p);
476         *colonp = ':';  /* put the colon back */
477         return ret;
478 }
479
480
481 /* opens the user's recent file and read the first part */
482 void
483 recent_read_static(char **rf_path_return, int *rf_errno_return)
484 {
485   char       *rf_path;
486   FILE       *rf;
487
488
489   /* set defaults */
490   recent.main_toolbar_show      = TRUE;
491   recent.filter_toolbar_show    = TRUE;
492   recent.packet_list_show       = TRUE;
493   recent.tree_view_show         = TRUE;
494   recent.byte_view_show         = TRUE;
495   recent.statusbar_show         = TRUE;
496   recent.packet_list_colorize   = TRUE;
497   recent.gui_time_format        = TS_RELATIVE;
498   recent.gui_time_precision     = TS_PREC_AUTO;
499   recent.gui_zoom_level         = 0;
500
501   recent.gui_geometry_main_x        =        20;
502   recent.gui_geometry_main_y        =        20;
503   recent.gui_geometry_main_width    = DEF_WIDTH;
504   recent.gui_geometry_main_height   = DEF_HEIGHT;
505   recent.gui_geometry_main_maximized=     FALSE;
506
507   /* pane size of zero will autodetect */
508   recent.gui_geometry_main_upper_pane   = 0;
509   recent.gui_geometry_main_lower_pane   = 0;
510   recent.gui_geometry_status_pane       = 0;
511
512   /* the following are only used if GTK2 is used (as GTK1 cannot read these geometry values) */
513   /* or if set through command line */
514 #if GTK_MAJOR_VERSION >= 2
515   recent.has_gui_geometry_main_upper_pane = TRUE;
516   recent.has_gui_geometry_main_lower_pane = TRUE;
517   recent.has_gui_geometry_status_pane = TRUE;
518 #else
519   recent.has_gui_geometry_main_upper_pane = FALSE;
520   recent.has_gui_geometry_main_lower_pane = FALSE;
521   recent.has_gui_geometry_status_pane = FALSE;
522 #endif
523
524   /* Construct the pathname of the user's recent file. */
525   rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
526
527   /* Read the user's recent file, if it exists. */
528   *rf_path_return = NULL;
529   if ((rf = eth_fopen(rf_path, "r")) != NULL) {
530     /* We succeeded in opening it; read it. */
531     read_prefs_file(rf_path, rf, read_set_recent_pair_static);
532     fclose(rf);
533     g_free(rf_path);
534     rf_path = NULL;
535   } else {
536     /* We failed to open it.  If we failed for some reason other than
537        "it doesn't exist", return the errno and the pathname, so our
538        caller can report the error. */
539     if (errno != ENOENT) {
540       *rf_errno_return = errno;
541       *rf_path_return = rf_path;
542     }
543   }
544 }
545
546
547
548 /* opens the user's recent file and read it out */
549 void
550 recent_read_dynamic(char **rf_path_return, int *rf_errno_return)
551 {
552   char       *rf_path;
553   FILE       *rf;
554
555
556   /* Construct the pathname of the user's recent file. */
557   rf_path = get_persconffile_path(RECENT_FILE_NAME, FALSE);
558
559   /* Read the user's recent file, if it exists. */
560   *rf_path_return = NULL;
561   if ((rf = eth_fopen(rf_path, "r")) != NULL) {
562     /* We succeeded in opening it; read it. */
563     read_prefs_file(rf_path, rf, read_set_recent_pair_dynamic);
564         /* set dfilter combobox to have an empty line */
565     dfilter_combo_add_empty();
566     fclose(rf);
567     g_free(rf_path);
568     rf_path = NULL;
569   } else {
570     /* We failed to open it.  If we failed for some reason other than
571        "it doesn't exist", return the errno and the pathname, so our
572        caller can report the error. */
573     if (errno != ENOENT) {
574       *rf_errno_return = errno;
575       *rf_path_return = rf_path;
576     }
577   }
578 }
579
580