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