Add APIs to Wiretap to return the file of the size as supplied by the OS
[obnox/wireshark/wip.git] / gtk / fileset_dlg.c
1 /* fileset_dlg.c
2  * Routines for the file set dialog
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <string.h>
30
31 #ifdef HAVE_IO_H
32 #include <io.h>
33 #endif
34
35 #ifdef HAVE_FCNTL_H
36 #include <fcntl.h>
37 #endif
38
39 #include <gtk/gtk.h>
40
41 #include "globals.h"
42
43
44 #include "compat_macros.h"
45 #include "simple_dialog.h"
46
47 #include "ui_util.h"
48 #include "dlg_utils.h"
49
50 #include "main.h"
51 #include "menu.h"
52 #include "help_dlg.h"
53
54 #include <epan/filesystem.h>
55
56 #include "fileset.h"
57 #include "fileset_dlg.h"
58
59
60
61 /*
62  * Keep a static pointer to the current "File Set" window, if
63  * any, so that if somebody tries to do "File Set" while there's
64  * already a "File Set" window up, we just pop up the existing
65  * one, rather than creating a new one.
66  */
67 static GtkWidget *fs_w;
68
69
70
71 /* various widget related global data */
72 int           row;
73 GtkWidget     *fs_tb;
74 GtkTooltips   *tooltips;
75 GtkWidget     *fs_dir_lb;
76 GtkWidget     *fs_first_rb;
77 GtkWidget     *fs_tb_vb;
78
79
80
81 /* open the file corresponding to the given fileset entry */
82 static void
83 fs_open_entry(fileset_entry *entry)
84 {
85     char            *fname;
86     int             err;
87
88
89     /* make a copy of the filename (cf_close will indirectly destroy it right now) */
90     fname = g_strdup(entry->fullname);
91
92     /* close the old and open the new file */
93     cf_close(&cfile);
94     if (cf_open(&cfile, fname, FALSE, &err) == CF_OK) {
95         cf_read(&cfile);
96     }
97
98     g_free(fname);
99 }
100
101
102 /* radio button was pressed/released */
103 static void
104 fs_rb_cb(GtkWidget *open_bt, gpointer fs_data)
105 {
106     fileset_entry   *entry = fs_data;
107
108     /* button release should have no effect */
109     if(!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(open_bt) )) {
110         return;
111     }
112
113     fs_open_entry(entry);
114 }
115
116
117 /* the window was closed, cleanup things */
118 static void
119 fs_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
120 {
121     /* Note that we no longer have a "File Set" dialog box. */
122     fs_w = NULL;
123 }
124
125
126 /* get creation date (converted from filename) */
127 /* */
128 char *
129 fileset_dlg_name2date_dup(const char * name) {
130     char        *pfx;
131     char        *filename;
132     int         pos;
133
134
135     /* just to be sure ... */
136     g_assert(fileset_filename_match_pattern(name));
137
138     /* find char position behind the last underscore */
139     pfx = strrchr(name, '_');
140     pfx++;
141     pos = pfx - name;
142
143     /* start conversion behind that underscore */
144     filename = g_strdup_printf("%c%c%c%c.%c%c.%c%c %c%c:%c%c:%c%c",
145         /* year  */  name[pos]  ,  name[pos+1], name[pos+2], name[pos+3],
146         /* month */  name[pos+4],  name[pos+5],
147         /* day   */  name[pos+6],  name[pos+7],
148         /* hour */   name[pos+8],  name[pos+9],
149         /* min */    name[pos+10], name[pos+11],
150         /* second */ name[pos+12], name[pos+13]);
151
152     return filename;
153 }
154
155
156 /* this file is a part of the current file set, add it to the dialog */
157 void
158 fileset_dlg_add_file(fileset_entry *entry) {
159     char *created;
160     char *modified;
161     char *size;
162     struct tm *local;
163     GtkWidget     *fs_lb;
164     GtkWidget     *fs_rb;
165     gchar *title;
166
167
168     if (fs_w == NULL) {
169         return;
170     }
171
172     /*local = localtime(&entry->ctime);
173     created = g_strdup_printf("%04u.%02u.%02u %02u:%02u:%02u", 
174         local->tm_year+1900, local->tm_mon+1, local->tm_mday,
175         local->tm_hour, local->tm_min, local->tm_sec);*/
176     created = fileset_dlg_name2date_dup(entry->name);
177
178     local = localtime(&entry->mtime);
179     modified = g_strdup_printf("%04u.%02u.%02u %02u:%02u:%02u", 
180         local->tm_year+1900, local->tm_mon+1, local->tm_mday,
181         local->tm_hour, local->tm_min, local->tm_sec);
182     size = g_strdup_printf("%ld Bytes", entry->size);
183
184     fs_rb = RADIO_BUTTON_NEW_WITH_LABEL(fs_first_rb, entry->name);
185     if(row == 1) {
186         fs_first_rb = fs_rb;
187     }
188     if(entry->current) {
189         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (fs_rb), entry->current);
190     }
191     gtk_tooltips_set_tip(tooltips, fs_rb, "Open this capture file", NULL);
192     gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_rb, 0, 1, row, row+1);
193     SIGNAL_CONNECT(fs_rb, "toggled", fs_rb_cb, entry);
194     gtk_widget_show(fs_rb);
195
196     fs_lb = gtk_label_new(created);
197     gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 1, 2, row, row+1);
198     gtk_widget_set_sensitive(fs_lb, entry->current);
199     gtk_widget_show(fs_lb);
200
201     fs_lb = gtk_label_new(modified);
202     gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 2, 3, row, row+1);
203     gtk_widget_set_sensitive(fs_lb, entry->current);
204     gtk_widget_show(fs_lb);
205
206     fs_lb = gtk_label_new(size);
207     gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 3, 4, row, row+1);
208     gtk_widget_set_sensitive(fs_lb, entry->current);
209     gtk_widget_show(fs_lb);
210
211     title = g_strdup_printf("Ethereal: %u File%s in Set", row, plurality(row, "", "s"));
212     gtk_window_set_title(GTK_WINDOW(fs_w), title);
213     g_free(title);
214
215     title = g_strdup_printf("... in directory: %s", fileset_get_dirname());
216     gtk_label_set(GTK_LABEL(fs_dir_lb), title);
217     g_free(title);
218
219     row++;
220     
221     gtk_widget_show_all(fs_tb);
222
223     g_free(created);
224     g_free(modified);
225     g_free(size);
226 }
227
228
229 /* init the fileset table */
230 static void
231 fileset_init_table(GtkWidget *parent)
232 {
233   GtkWidget     *fs_lb;
234
235   
236   fs_tb = gtk_table_new(6,1, FALSE);
237   gtk_table_set_row_spacings(GTK_TABLE(fs_tb), 1);
238   gtk_table_set_col_spacings(GTK_TABLE(fs_tb), 12);
239   gtk_container_add(GTK_CONTAINER(parent), fs_tb);
240
241   row = 0;
242   fs_first_rb = NULL;
243
244   fs_lb = gtk_label_new("Filename");
245   gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 0, 1, row, row+1);
246
247   fs_lb = gtk_label_new("Created");
248   gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 1, 2, row, row+1);
249
250   fs_lb = gtk_label_new("Last Modified");
251   gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 2, 3, row, row+1);
252
253   fs_lb = gtk_label_new("Size");
254   gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 3, 4, row, row+1);
255
256   gtk_widget_hide(fs_tb);
257
258   gtk_window_set_title(GTK_WINDOW(fs_w), "Ethereal: 0 Files in Set");
259
260   gtk_label_set(GTK_LABEL(fs_dir_lb), "No capture file loaded!");
261
262   row++;
263 }
264
265
266 /* open the fileset dialog */
267 void
268 fileset_cb(GtkWidget *w _U_, gpointer d _U_)
269 {
270   GtkWidget     *main_vb, *bbox, *close_bt, *help_bt;
271 #if GTK_MAJOR_VERSION < 2
272   GtkAccelGroup *accel_group;
273 #endif
274
275
276   if (fs_w != NULL) {
277     /* There's already a "File Set" dialog box; reactivate it. */
278     reactivate_window(fs_w);
279     return;
280   }
281
282   fs_w = window_new(GTK_WINDOW_TOPLEVEL, "");
283
284   tooltips = gtk_tooltips_new();
285
286 #if GTK_MAJOR_VERSION < 2
287   /* Accelerator group for the accelerators (or, as they're called in
288      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
289      Ctrl+<key> is an accelerator). */
290   accel_group = gtk_accel_group_new();
291   gtk_window_add_accel_group(GTK_WINDOW(fs_w), accel_group);
292 #endif
293
294   main_vb = gtk_vbox_new(FALSE, 5);
295   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
296   gtk_container_add(GTK_CONTAINER(fs_w), main_vb);
297
298   /* add a dummy container, so we can replace the table later */
299   fs_tb_vb = gtk_vbox_new(FALSE, 0);
300   gtk_container_add(GTK_CONTAINER(main_vb), fs_tb_vb);
301
302   fs_dir_lb = gtk_label_new("");
303   gtk_container_add(GTK_CONTAINER(main_vb), fs_dir_lb);
304
305   fileset_init_table(fs_tb_vb);
306
307   /* Button row: close button */
308   if(topic_available(HELP_FILESET_DIALOG)) {
309     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
310   } else {
311     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
312   }
313   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
314
315   close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
316   window_set_cancel_button(fs_w, close_bt, window_cancel_button_cb);
317   gtk_tooltips_set_tip(tooltips, close_bt, "Close this window.", NULL);
318
319   if(topic_available(HELP_FILESET_DIALOG)) {
320     help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
321     SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_FILESET_DIALOG);
322   }
323
324   gtk_widget_grab_default(close_bt);
325
326   SIGNAL_CONNECT(fs_w, "delete_event", window_delete_event_cb, NULL);
327   SIGNAL_CONNECT(fs_w, "destroy", fs_destroy_cb, NULL);
328
329   /* init the dialog content */
330   fileset_update_dlg();
331
332   gtk_widget_show_all(fs_w);
333   window_present(fs_w);
334 }
335
336
337 /* open the next file in the file set, or do nothing if already the first file */
338 void
339 fileset_next_cb(GtkWidget *w _U_, gpointer d _U_)
340 {
341     fileset_entry   *entry;
342
343     entry = fileset_get_next();
344
345     if(entry) {
346         fs_open_entry(entry);
347     }
348 }
349
350
351 /* open the previous file in the file set, or do nothing if already the first file */
352 void
353 fileset_previous_cb(GtkWidget *w _U_, gpointer d _U_)
354 {
355     fileset_entry   *entry;
356
357     entry = fileset_get_previous();
358
359     if(entry) {
360         fs_open_entry(entry);
361     }
362 }
363
364
365 /* a new capture file was opened, browse the dir and look for files matching the given file set */
366 void
367 fileset_file_opened(const char *fname) {
368   fileset_add_dir(fname);
369   if(fs_w) {
370     window_present(fs_w);
371   }
372
373   /* update the menu */
374   set_menus_for_file_set(TRUE /* file_set */, 
375       fileset_get_previous() != NULL, fileset_get_next() != NULL );
376 }
377
378
379 /* the capture file was closed */
380 void
381 fileset_file_closed(void)
382 {
383   if(fs_w) {
384     /* reinit the table, title and alike */
385     gtk_widget_ref(fs_tb_vb);
386     gtk_widget_destroy(fs_tb);
387     fileset_delete();
388     fileset_init_table(fs_tb_vb);
389     window_present(fs_w);
390   } else {
391     fileset_delete();
392   }
393
394   /* update the menu */
395   set_menus_for_file_set(FALSE /* file_set */, 
396       fileset_get_previous() != NULL, fileset_get_next() != NULL );
397 }
398