Remove some unnecessary includes: a lot of things don't need globals.h and register.h
[obnox/wireshark/wip.git] / gtk / about_dlg.c
1 /* about_dlg.c
2  *
3  * $Id$
4  *
5  * Ulf Lamping <ulf.lamping@web.de>
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31
32 #include <string.h>
33
34 #include <epan/filesystem.h>
35 #include <epan/plugins.h>
36 #ifdef HAVE_LIBSMI
37 #include <epan/oids.h>
38 #endif
39 #ifdef HAVE_GEOIP
40 #include <epan/geoip_db.h>
41 #endif
42
43 #include "../log.h"
44 #include "../version_info.h"
45
46 #include "gtk/about_dlg.h"
47 #include "gtk/gui_utils.h"
48 #include "gtk/dlg_utils.h"
49 #include "gtk/file_dlg.h"
50 #include "gtk/text_page_utils.h"
51 #include "gtk/gtkglobals.h"
52 #include "gtk/main.h"
53 #include "gtk/plugins_dlg.h"
54
55 #include "../image/wssplash-dev.xpm"
56 #include "webbrowser.h"
57
58 /*
59  * Update frequence for the splash screen, given in milliseconds.
60  */
61 int info_update_freq = 100;
62
63 static void about_wireshark_destroy_cb(GtkWidget *, gpointer);
64
65
66 /*
67  * Keep a static pointer to the current "About Wireshark" window, if any, so
68  * that if somebody tries to do "About Wireshark" while there's already an
69  * "About Wireshark" window up, we just pop up the existing one, rather than
70  * creating a new one.
71  */
72 static GtkWidget *about_wireshark_w;
73
74
75 static void
76 about_wireshark(GtkWidget *parent, GtkWidget *main_vb)
77 {
78   GtkWidget   *msg_label, *icon;
79   gchar       *message;
80   const char  *title = "Network Protocol Analyzer";
81
82   icon = xpm_to_widget_from_parent(parent, wssplash_xpm);
83   gtk_container_add(GTK_CONTAINER(main_vb), icon);
84
85   msg_label = gtk_label_new(title);
86   message = g_strdup_printf("<span size=\"x-large\" weight=\"bold\">%s</span>", title);
87   gtk_label_set_markup(GTK_LABEL(msg_label), message);
88   g_free(message);
89   gtk_container_add(GTK_CONTAINER(main_vb), msg_label);
90 }
91
92 static void
93 splash_update_label(GtkWidget *win, const char *message)
94 {
95     GtkWidget *main_lb;
96
97     if (win == NULL) return;
98
99     main_lb = g_object_get_data(G_OBJECT(win), "splash_label");
100     gtk_label_set_text(GTK_LABEL(main_lb), message);
101
102     /* Process all pending GUI events before continuing, so that
103        the splash screen window gets updated. */
104     while (gtk_events_pending()) gtk_main_iteration();
105 }
106
107 GtkWidget*
108 splash_new(const char *message)
109 {
110     GtkWidget *win;
111     GtkWidget *main_lb;
112
113     GtkWidget *main_vb;
114     GtkWidget *percentage_hb;
115     GtkWidget *prog_bar;
116     GtkWidget *percentage_lb;
117
118     win = splash_window_new();
119
120     /* When calling about_wireshark(), we must realize the top-level
121        widget for the window, otherwise GTK will throw a warning
122        because we don't have a colormap associated with that window and
123        can't handle the pixmap. */
124     gtk_widget_realize(win);
125
126     main_vb = gtk_vbox_new(FALSE, 6);
127     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 24);
128     gtk_container_add(GTK_CONTAINER(win), main_vb);
129
130     about_wireshark(win, main_vb);
131
132     main_lb = gtk_label_new(message);
133     gtk_container_add(GTK_CONTAINER(main_vb), main_lb);
134     g_object_set_data(G_OBJECT(win), "splash_label", main_lb);
135
136     main_lb = gtk_label_new("");
137     gtk_container_add(GTK_CONTAINER(main_vb), main_lb);
138     g_object_set_data(G_OBJECT(win), "protocol_label", main_lb);
139
140     percentage_hb = gtk_hbox_new(FALSE, 1);
141     gtk_box_pack_start(GTK_BOX(main_vb), percentage_hb, TRUE, TRUE, 3);
142
143     prog_bar = gtk_progress_bar_new();
144     gtk_box_pack_start(GTK_BOX(percentage_hb), prog_bar, TRUE, TRUE, 3);
145     g_object_set_data(G_OBJECT(win), "progress_bar", prog_bar);
146
147     percentage_lb = gtk_label_new("  0%");
148     gtk_misc_set_alignment(GTK_MISC(percentage_lb), 0.0f, 0.0f);
149     gtk_box_pack_start(GTK_BOX(percentage_hb), percentage_lb, FALSE, TRUE, 3);
150     g_object_set_data(G_OBJECT(win), "percentage_label", percentage_lb);
151
152     gtk_widget_show_all(win);
153
154     splash_update_label(win, message);
155
156     return win;
157 }
158
159 void
160 splash_update(register_action_e action, const char *message, gpointer client_data)
161 {
162     GtkWidget  *win;
163     GtkWidget  *main_lb;
164     GtkWidget  *prog_bar;
165     GtkWidget  *percentage_lb;
166     gfloat     percentage;
167     gulong     ul_percentage;
168     gchar      tmp[100];
169     const char *action_msg;
170
171     static gulong ul_sofar = 0;
172     static gulong ul_count = 0;
173
174     static register_action_e last_action = RA_NONE;
175
176     static GTimeVal cur_tv;
177     static GTimeVal next_tv = {0, 0};
178
179     win = (GtkWidget *)client_data;
180
181     if (win == NULL) return;
182
183     g_get_current_time(&cur_tv);
184     if (cur_tv.tv_sec <= next_tv.tv_sec && cur_tv.tv_usec <= next_tv.tv_usec && ul_sofar < ul_count - 1) {
185       /* Only update every splash_register_freq milliseconds */
186       ul_sofar++;
187       return;
188     }
189     memcpy(&next_tv, &cur_tv, sizeof(next_tv));
190     next_tv.tv_usec += info_update_freq * 1000;
191     if (next_tv.tv_usec >= 1000000) {
192         next_tv.tv_sec++;
193         next_tv.tv_usec -= 1000000;
194     }
195
196     if(last_action != action) {
197       /* the action has changed */
198       switch(action) {
199       case RA_DISSECTORS:
200         action_msg = "Initializing dissectors ...";
201         break;
202       case RA_LISTENERS:
203         action_msg = "Initializing tap listeners ...";
204         break;
205       case RA_REGISTER:
206         action_msg = "Registering dissector ...";
207         break;
208       case RA_PLUGIN_REGISTER:
209         action_msg = "Registering plugins ...";
210         break;
211       case RA_HANDOFF:
212         action_msg = "Handing off dissector ...";
213         break;
214       case RA_PLUGIN_HANDOFF:
215         action_msg = "Handing off plugins ...";
216         break;
217       case RA_PREFERENCES:
218         action_msg = "Loading module preferences ...";
219         break;
220       case RA_CONFIGURATION:
221         action_msg = "Loading configuration files ...";
222         break;
223       default:
224         action_msg = "(Unknown action)";;
225         break;
226       }
227       splash_update_label(win, action_msg);
228       last_action = action;
229     }
230
231     if(ul_count == 0) /* get the count of dissectors */
232       ul_count = register_count() + 6; /* additional 6 for:
233                                           dissectors, listeners,
234                                           registering plugins, handingoff plugins,
235                                           preferences and configuration */
236
237     main_lb = g_object_get_data(G_OBJECT(win), "protocol_label");
238     /* make_dissector_reg.py changed -
239        so we need to strip off the leading elements to get back to the protocol */
240     if(message) {
241       if(!strncmp(message, "proto_register_", 15))
242         message += 15;
243       else if(!strncmp(message, "proto_reg_handoff_", 18))
244         message += 18;
245     }
246     gtk_label_set_text(GTK_LABEL(main_lb), message ? message : "");
247
248     ul_sofar++;
249
250     g_assert (ul_sofar <= ul_count);
251
252     percentage = (gfloat)ul_sofar/(gfloat)ul_count;
253     ul_percentage = (gulong)(percentage * 100);
254
255     /* update progress bar */
256     prog_bar = g_object_get_data(G_OBJECT(win), "progress_bar");
257     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prog_bar), percentage);
258
259     percentage_lb = g_object_get_data(G_OBJECT(win), "percentage_label");
260     g_snprintf(tmp, sizeof(tmp), "%lu%%", ul_percentage);
261     gtk_label_set_text((GtkLabel*)percentage_lb, tmp);
262
263     /* Process all pending GUI events before continuing, so that
264        the splash screen window gets updated. */
265     while (gtk_events_pending()) gtk_main_iteration();
266
267 }
268
269 gboolean
270 splash_destroy(GtkWidget *win)
271 {
272     if (win == NULL)
273         return FALSE;
274
275     gtk_widget_destroy(win);
276     return FALSE;
277 }
278
279 static GtkWidget *
280 about_wireshark_page_new(void)
281 {
282   GtkWidget   *main_vb, *msg_label /*, *icon*/;
283   gchar       *message;
284
285   main_vb = gtk_vbox_new(FALSE, 6);
286   gtk_container_set_border_width(GTK_CONTAINER(main_vb), 12);
287
288 #if GTK_CHECK_VERSION(2,9,0)
289   g_object_set(gtk_widget_get_settings(main_vb),
290     "gtk-label-select-on-focus", FALSE, NULL);
291 #endif
292
293   about_wireshark(top_level, main_vb);
294
295   /* Construct the message string */
296   message = g_strdup_printf(
297        "Version " VERSION "%s\n"
298        "\n"
299        "%s"
300        "\n"
301        "%s"
302        "\n"
303        "%s"
304        "\n"
305        "Wireshark is Open Source Software released under the GNU General Public License.\n"
306        "\n"
307        "Check the man page and http://www.wireshark.org for more information.",
308        wireshark_svnversion, get_copyright_info(), comp_info_str->str,
309        runtime_info_str->str);
310
311   msg_label = gtk_label_new(message);
312   g_free(message);
313   gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL);
314   gtk_label_set_selectable(GTK_LABEL(msg_label), TRUE);
315   gtk_container_add(GTK_CONTAINER(main_vb), msg_label);
316
317   return main_vb;
318 }
319
320 static GtkWidget *
321 about_authors_page_new(void)
322 {
323   GtkWidget   *page;
324   char *absolute_path;
325
326   absolute_path = get_datafile_path("AUTHORS-SHORT");
327   page = text_page_new(absolute_path);
328
329   return page;
330 }
331
332 static gboolean about_folders_callback(GtkWidget *widget, GdkEventButton *event, gint id _U_)
333 {
334   GtkTreeSelection *tree_selection;
335   GtkTreeModel *model;
336   GtkTreeIter  iter;
337   gchar        *path;
338
339   tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
340
341   if(gtk_tree_selection_count_selected_rows(tree_selection) == 0)
342     return FALSE;
343
344   if(event->type != GDK_2BUTTON_PRESS)
345     /* not a double click */
346     return FALSE;
347
348   if(gtk_tree_selection_get_selected (tree_selection, &model, &iter)) {
349     gtk_tree_model_get(model, &iter, 1, &path, -1);
350     filemanager_open_directory(path);
351     g_free(path);
352   }
353
354   return TRUE;
355 }
356
357 static void
358 about_folders_row(GtkWidget *table, const char *label, const char *dir, const char *tip)
359 {
360   simple_list_append(table, 0, label, 1, dir, 2, tip, -1);
361 }
362
363 static GtkWidget *
364 about_folders_page_new(void)
365 {
366   GtkWidget   *table;
367   const char *constpath;
368   char *path;
369   const gchar *titles[] = { "Name", "Folder", "Typical Files"};
370   GtkWidget *scrolledwindow;
371 #if defined (HAVE_LIBSMI) || defined (HAVE_GEOIP)
372   gint i;
373   gchar **resultArray;
374 #endif
375
376   scrolledwindow = scrolled_window_new(NULL, NULL);
377   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow),
378                                    GTK_SHADOW_IN);
379
380   /* Container for our data */
381   table = simple_list_new(3, titles);
382
383   /* connect a callback so we can spot a double-click */
384   g_signal_connect(table, "button_press_event",
385                      G_CALLBACK(about_folders_callback), NULL);
386
387   simple_list_url_col(table, 1);
388
389   /* "file open" */
390   about_folders_row(table, "\"File\" dialogs", get_last_open_dir(),
391       "capture files");
392
393   /* temp */
394   path = get_tempfile_path("");
395   about_folders_row(table, "Temp", path,
396       "untitled capture files");
397   g_free(path);
398
399   /* pers conf */
400   path = get_persconffile_path("", FALSE, FALSE);
401   about_folders_row(table, "Personal configuration", path,
402       "\"dfilters\", \"preferences\", \"ethers\", ...");
403   g_free(path);
404
405   /* global conf */
406   constpath = get_datafile_dir();
407   if (constpath != NULL) {
408     about_folders_row(table, "Global configuration", constpath,
409         "\"dfilters\", \"preferences\", \"manuf\", ...");
410   }
411
412   /* system */
413   constpath = get_systemfile_dir();
414   about_folders_row(table, "System", constpath,
415       "\"ethers\", \"ipxnets\"");
416
417   /* program */
418   constpath = get_progfile_dir();
419   about_folders_row(table, "Program", constpath,
420       "program files");
421
422 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
423   /* pers plugins */
424   path = get_plugins_pers_dir();
425   about_folders_row(table, "Personal Plugins", path,
426       "dissector plugins");
427   g_free(path);
428
429   /* global plugins */
430   about_folders_row(table, "Global Plugins", get_plugin_dir(),
431       "dissector plugins");
432 #endif
433
434 #ifdef HAVE_PYTHON
435   /* global python bindings */
436   about_folders_row(table, "Python Bindings", get_wspython_dir(),
437       "python bindings");
438 #endif
439
440 #ifdef HAVE_GEOIP
441   /* GeoIP */
442   path = geoip_db_get_paths();
443
444   resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10);
445
446   for(i = 0; resultArray[i]; i++)
447     about_folders_row(table, "GeoIP path", g_strstrip(resultArray[i]),
448                       "GeoIP database search path");
449   g_strfreev(resultArray);
450   g_free(path);
451 #endif
452
453 #ifdef HAVE_LIBSMI
454   /* SMI MIBs/PIBs */
455   path = oid_get_default_mib_path();
456
457   resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10);
458
459   for(i = 0; resultArray[i]; i++)
460     about_folders_row(table, "MIB/PIB path", g_strstrip(resultArray[i]),
461                       "SMI MIB/PIB search path");
462   g_strfreev(resultArray);
463   g_free(path);
464 #endif
465
466   gtk_container_add(GTK_CONTAINER(scrolledwindow), table);
467
468   return scrolledwindow;
469 }
470
471 static GtkWidget *
472 about_license_page_new(void)
473 {
474   GtkWidget   *page;
475   char *absolute_path;
476
477 #if defined(_WIN32)
478   absolute_path = get_datafile_path("COPYING.txt");
479 #else
480   absolute_path = get_datafile_path("COPYING");
481 #endif
482   page = text_page_new(absolute_path);
483
484   return page;
485 }
486
487 void
488 about_wireshark_cb( GtkWidget *w _U_, gpointer data _U_ )
489 {
490   GtkWidget   *main_vb, *main_nb, *bbox, *ok_btn;
491   GtkWidget   *page_lb, *about_page, *folders_page;
492
493 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
494   GtkWidget   *plugins_page;
495 #endif
496
497   GtkWidget   *authors_page, *license_page;
498
499   if (about_wireshark_w != NULL) {
500     /* There's already an "About Wireshark" dialog box; reactivate it. */
501     reactivate_window(about_wireshark_w);
502     return;
503   }
504
505   /*
506    * XXX - use GtkDialog?  The GNOME 2.x GnomeAbout widget does.
507    * Should we use GtkDialog for simple_dialog() as well?  Or
508    * is the GTK+ 2.x GtkDialog appropriate but the 1.2[.x] one
509    * not?  (The GNOME 1.x GnomeAbout widget uses GnomeDialog.)
510    */
511   about_wireshark_w = dlg_window_new("About Wireshark");
512   /* set the initial position (must be done, before show is called!) */
513   /* default position is not appropriate for the about dialog */
514   gtk_window_set_position(GTK_WINDOW(about_wireshark_w), GTK_WIN_POS_CENTER_ON_PARENT);
515   gtk_window_set_default_size(GTK_WINDOW(about_wireshark_w), 600, 400);
516   gtk_container_set_border_width(GTK_CONTAINER(about_wireshark_w), 6);
517
518   main_vb = gtk_vbox_new(FALSE, 12);
519   gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
520   gtk_container_add(GTK_CONTAINER(about_wireshark_w), main_vb);
521
522   main_nb = gtk_notebook_new();
523   gtk_box_pack_start(GTK_BOX(main_vb), main_nb, TRUE, TRUE, 0);
524
525   about_page = about_wireshark_page_new();
526   page_lb = gtk_label_new("Wireshark");
527   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), about_page, page_lb);
528
529   authors_page = about_authors_page_new();
530   page_lb = gtk_label_new("Authors");
531   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), authors_page, page_lb);
532
533   folders_page = about_folders_page_new();
534   page_lb = gtk_label_new("Folders");
535   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), folders_page, page_lb);
536
537 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
538   plugins_page = about_plugins_page_new();
539   page_lb = gtk_label_new("Plugins");
540   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), plugins_page, page_lb);
541 #endif
542
543   license_page = about_license_page_new();
544   page_lb = gtk_label_new("License");
545   /* set a minmum width to avoid a lot of line breaks at the wrong places */
546   gtk_widget_set_size_request(license_page, 600, -1);
547   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), license_page, page_lb);
548
549   /* Button row */
550   bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
551   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
552
553   ok_btn = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
554   gtk_widget_grab_focus(ok_btn);
555   gtk_widget_grab_default(ok_btn);
556   window_set_cancel_button(about_wireshark_w, ok_btn, window_cancel_button_cb);
557
558   g_signal_connect(about_wireshark_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
559   g_signal_connect(about_wireshark_w, "destroy", G_CALLBACK(about_wireshark_destroy_cb), NULL);
560
561   gtk_widget_show_all(about_wireshark_w);
562   window_present(about_wireshark_w);
563 }
564
565 static void
566 about_wireshark_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
567 {
568   /* Note that we no longer have an "About Wireshark" dialog box. */
569   about_wireshark_w = NULL;
570 }
571