Update the download link in the help dialog. More Ethereal -> Wireshark.
[obnox/wireshark/wip.git] / gtk / help_dlg.c
1 /* help_dlg.c
2  *
3  * $Id$
4  *
5  * Laurent Deniel <laurent.deniel@free.fr>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 2000 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 <string.h>
32 #include <stdio.h>
33 #include <errno.h>
34
35 #include "epan/filesystem.h"
36 #include "help_dlg.h"
37 #include "text_page.h"
38 #include <epan/prefs.h>
39 #include "gtkglobals.h"
40 #include "gui_utils.h"
41 #include "compat_macros.h"
42 #include "dlg_utils.h"
43 #include "simple_dialog.h"
44 #include "webbrowser.h"
45 #include "file_util.h"
46
47 #ifdef HHC_DIR
48 #include <windows.h>
49 #include <htmlhelp.h>
50 #include "epan/strutil.h"
51 #endif
52
53
54 #define HELP_DIR        "help"
55
56
57 #define NOTEBOOK_KEY    "notebook_key"
58
59 static void help_destroy_cb(GtkWidget *w, gpointer data);
60
61 /*
62  * Keep a static pointer to the current "Help" window, if any, so that
63  * if somebody tries to do "Help->Help" while there's already a
64  * "Help" window up, we just pop up the existing one, rather than
65  * creating a new one.
66 */
67 static GtkWidget *help_w = NULL;
68
69 /*
70  * Keep a list of text widgets and corresponding file names as well
71  * (for text format changes).
72  */
73 typedef struct {
74   char *topic;
75   char *pathname;
76   GtkWidget *page;
77 } help_page_t;
78
79 static GSList *help_text_pages = NULL;
80
81
82 /*
83  * Helper function to show a simple help text page.
84  */
85 static GtkWidget * help_page(const char *topic, const char *filename)
86 {
87   GtkWidget *text_page;
88   char *relative_path, *absolute_path;
89   help_page_t *page;
90
91   relative_path = g_strconcat(HELP_DIR, G_DIR_SEPARATOR_S, filename, NULL);
92   absolute_path = get_datafile_path(relative_path);
93   text_page = text_page_new(absolute_path);
94   g_free(relative_path);
95   gtk_widget_show(text_page);
96
97   page = g_malloc(sizeof (help_page_t));
98   page->topic = g_strdup(topic);
99   page->pathname = absolute_path;
100   page->page = text_page;
101   help_text_pages = g_slist_append(help_text_pages, page);
102
103   return text_page;
104 }
105
106
107 /*
108  * Create and show help dialog.
109  */
110 static
111 void help_dialog(void)
112 {
113   GtkWidget *main_vb, *bbox, *help_nb, *close_bt, *label, *topic_vb;
114   char line[4096+1];    /* XXX - size? */
115   char *p;
116   char *filename;
117   char *help_toc_file_path;
118   FILE *help_toc_file;
119
120   if (help_w != NULL) {
121     /* There's already a "Help" dialog box; reactivate it. */
122     reactivate_window(help_w);
123     return;
124   }
125
126   help_toc_file_path = get_datafile_path(HELP_DIR G_DIR_SEPARATOR_S "toc");
127   help_toc_file = eth_fopen(help_toc_file_path, "r");
128   if (help_toc_file == NULL) {
129     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not open file \"%s\": %s",
130                   help_toc_file_path, strerror(errno));
131     g_free(help_toc_file_path);
132     return;
133   }
134
135   help_w = window_new_with_geom(GTK_WINDOW_TOPLEVEL, "Wireshark: Help", "help");
136   gtk_window_set_default_size(GTK_WINDOW(help_w), DEF_WIDTH, DEF_HEIGHT);
137   gtk_container_border_width(GTK_CONTAINER(help_w), 2);
138
139   /* Container for each row of widgets */
140   main_vb = gtk_vbox_new(FALSE, 1);
141   gtk_container_border_width(GTK_CONTAINER(main_vb), 1);
142   gtk_container_add(GTK_CONTAINER(help_w), main_vb);
143
144   /* help topics container */
145   help_nb = gtk_notebook_new();
146   gtk_container_add(GTK_CONTAINER(main_vb), help_nb);
147   OBJECT_SET_DATA(help_w, NOTEBOOK_KEY, help_nb);
148
149   /* help topics */
150   while (fgets(line, sizeof line, help_toc_file) != NULL) {
151     /* Strip off line ending. */
152     p = strpbrk(line, "\r\n");
153     if (p == NULL)
154       break;            /* last line has no line ending */
155     *p = '\0';
156     /* {Topic title}:{filename of help file} */
157     p = strchr(line, ':');
158     if (p != NULL) {
159       *p++ = '\0';
160       filename = p;
161
162       /*
163        * "line" refers to the topic now, and "filename" refers to the
164        * file name.
165        */
166       topic_vb = help_page(line, filename);
167       label = gtk_label_new(line);
168       gtk_notebook_append_page(GTK_NOTEBOOK(help_nb), topic_vb, label);
169     }
170   }
171   if(ferror(help_toc_file)) {
172     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Error reading file \"%s\": %s",
173                   help_toc_file_path, strerror(errno));
174   }
175   fclose(help_toc_file);
176
177
178   /* Button row */
179   bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
180   gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
181
182   close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
183   window_set_cancel_button(help_w, close_bt, window_cancel_button_cb);
184
185   SIGNAL_CONNECT(help_w, "delete_event", window_delete_event_cb, NULL);
186   SIGNAL_CONNECT(help_w, "destroy", help_destroy_cb, NULL);
187
188   gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(help_w));
189
190   gtk_widget_show_all(help_w);
191   window_present(help_w);
192 } /* help_dialog */
193
194
195 gboolean topic_available(topic_action_e action) {
196
197 #ifdef WIRESHARK_EUG_DIR
198     if(action == HELP_CAPTURE_INTERFACES_DETAILS_DIALOG) {
199         /* page currently not existing in user's guide */
200         return FALSE;
201     }
202     /* online: we have almost all possible pages available */
203     return TRUE;
204 #else
205     /* offline: we have only some pages available */
206     switch(action) {
207     case(HELP_CONTENT):
208         return TRUE;
209         break;
210     case(HELP_GETTING_STARTED):
211         return TRUE;
212         break;
213     case(HELP_CAPTURE_OPTIONS_DIALOG):
214         return TRUE;
215         break;
216     case(HELP_CAPTURE_FILTERS_DIALOG):
217         return TRUE;
218         break;
219     case(HELP_DISPLAY_FILTERS_DIALOG):
220         return TRUE;
221         break;
222     default:
223         return FALSE;
224     }
225 #endif
226 }
227
228 /*
229  * Open the help dialog and show a specific help page.
230  */
231 static void help_topic(const gchar *topic) {
232
233 #ifdef HHC_DIR
234     HWND hw;
235     GString *url = g_string_new("");
236
237     g_string_append_printf(url, "%s\\user-guide.chm::/%s>Wireshark Help", 
238         get_datafile_dir(), topic);
239
240     hw = HtmlHelpW(NULL, 
241         utf_8to16(url->str), 
242         HH_DISPLAY_TOPIC, 0); 
243
244     if(hw == NULL) {
245         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not open help file: %s\\user-guide.chm",
246             get_datafile_dir());
247     }
248
249     g_string_free(url, TRUE /* free_segment */);
250
251     return;
252 #else
253     gchar       *page_topic;
254     GtkWidget   *help_nb;
255     GSList      *help_page_ent;
256     gint        page_num = 0;
257     help_page_t *page;
258
259
260     /* show help dialog, if not already opened */
261     help_dialog();
262
263     help_nb = OBJECT_GET_DATA(help_w, NOTEBOOK_KEY);
264
265     /* find page to display */
266     for (help_page_ent = help_text_pages; help_page_ent != NULL;
267          help_page_ent = g_slist_next(help_page_ent))
268     {
269         page = (help_page_t *)help_page_ent->data;
270         page_topic = page->topic;
271         if (strcmp (page_topic, topic) == 0) {
272             /* topic page found, switch to notebook page */
273             gtk_notebook_set_page(GTK_NOTEBOOK(help_nb), page_num);
274             return;
275         }
276         page_num++;
277     }
278 #endif
279
280     /* topic page not found, default (first page) will be shown */
281 }
282
283
284 /*
285  * Help dialog is closed now.
286  */
287 static void help_destroy_cb(GtkWidget *w _U_, gpointer data _U_)
288 {
289   GSList *help_page_ent;
290   help_page_t *page;
291
292   /* Free up the list of help pages. */
293   for (help_page_ent = help_text_pages; help_page_ent != NULL;
294        help_page_ent = g_slist_next(help_page_ent)) {
295     page = (help_page_t *)help_page_ent->data;
296     g_free(page->topic);
297     g_free(page->pathname);
298     g_free(page);
299   }
300   g_slist_free(help_text_pages);
301   help_text_pages = NULL;
302
303   /* Note that we no longer have a Help window. */
304   help_w = NULL;
305 }
306
307
308 /**
309  * Redraw all help pages, to use a new font.
310  */
311 void help_redraw(void)
312 {
313   GSList *help_page_ent;
314   help_page_t *help_page;
315
316   if (help_w != NULL) {
317     for (help_page_ent = help_text_pages; help_page_ent != NULL;
318         help_page_ent = g_slist_next(help_page_ent))
319     {
320       help_page = (help_page_t *)help_page_ent->data;
321       text_page_redraw(help_page->page, help_page->pathname);
322     }
323   }
324 }
325
326
327 #ifdef HHC_DIR
328 #define ONLINE_HELP_CALL help_topic
329 #define ONLINE_HELP_PREFIX "wsug_chm/"
330 #else
331 #define ONLINE_HELP_CALL browser_open_data_file
332 #define ONLINE_HELP_PREFIX "wsug_html_chunked/"
333 #endif
334
335 static void
336 topic_action(topic_action_e action)
337 {
338     /* pages online at www.wireshark.org */
339     switch(action) {
340     case(ONLINEPAGE_HOME):
341         browser_open_url ("http://www.wireshark.org");
342         break;
343     case(ONLINEPAGE_WIKI):
344         browser_open_url ("http://wiki.wireshark.org");
345         break;
346     case(ONLINEPAGE_DOWNLOAD):
347         browser_open_url ("http://www.wireshark.org/download/");
348         break;
349     case(ONLINEPAGE_USERGUIDE):
350         browser_open_url ("http://www.wireshark.org/docs/wsug_html_chunked/");
351         break;
352     case(ONLINEPAGE_FAQ):
353         browser_open_url ("http://www.wireshark.org/faq.html");
354         break;
355     case(ONLINEPAGE_SAMPLE_FILES):
356         browser_open_url ("http://wiki.wireshark.org/SampleCaptures");
357         break;
358
359     /* local manual pages */
360     case(LOCALPAGE_MAN_WIRESHARK):
361         browser_open_data_file("wireshark.html");
362         break;
363     case(LOCALPAGE_MAN_WIRESHARK_FILTER):
364         browser_open_data_file("wireshark-filter.html");
365         break;
366     case(LOCALPAGE_MAN_TSHARK):
367         browser_open_data_file("tshark.html");
368         break;
369     case(LOCALPAGE_MAN_DUMPCAP):
370         browser_open_data_file("dumpcap.html");
371         break;
372     case(LOCALPAGE_MAN_MERGECAP):
373         browser_open_data_file("mergecap.html");
374         break;
375     case(LOCALPAGE_MAN_EDITCAP):
376         browser_open_data_file("editcap.html");
377         break;
378     case(LOCALPAGE_MAN_TEXT2PCAP):
379         browser_open_data_file("text2pcap.html");
380         break;
381
382 #ifdef WIRESHARK_EUG_DIR
383     /* local help pages (User's Guide) */
384     case(HELP_CONTENT):
385         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX "index.html");
386         break;
387     case(HELP_CAPTURE_OPTIONS_DIALOG):
388         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX "ChCapCaptureOptions.html");
389         break;
390     case(HELP_CAPTURE_FILTERS_DIALOG):
391         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX "ChWorkDefineFilterSection.html");
392         break;
393     case(HELP_DISPLAY_FILTERS_DIALOG):
394         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX "ChWorkDefineFilterSection.html");
395         break;
396     case(HELP_COLORING_RULES_DIALOG):
397         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCustColorizationSection.html");
398         break;
399     case(HELP_PRINT_DIALOG):
400         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChIOPrintSection.html");
401         break;
402     case(HELP_FIND_DIALOG):
403         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChWorkFindPacketSection.html");
404         break;
405     case(HELP_GOTO_DIALOG):
406         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChWorkGoToPacketSection.html");
407         break;
408     case(HELP_CAPTURE_INTERFACES_DIALOG):
409         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCapInterfaceSection.html");
410         break;
411     case(HELP_ENABLED_PROTOCOLS_DIALOG):
412         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCustProtocolDissectionSection.html");
413         break;
414     case(HELP_DECODE_AS_DIALOG):
415         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCustProtocolDissectionSection.html");
416         break;
417     case(HELP_DECODE_AS_SHOW_DIALOG):
418         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCustProtocolDissectionSection.html");
419         break;
420     case(HELP_FOLLOW_TCP_STREAM_DIALOG):
421         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChAdvFollowTCPSection.html");
422         break;
423     case(HELP_STATS_SUMMARY_DIALOG):
424         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChStatSummary.html");
425         break;
426     case(HELP_STATS_PROTO_HIERARCHY_DIALOG):
427         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChStatHierarchy.html");
428         break;
429     case(HELP_STATS_ENDPOINTS_DIALOG):
430         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChStatEndpoints.html");
431         break;
432     case(HELP_STATS_CONVERSATIONS_DIALOG):
433         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChStatConversations.html");
434         break;
435     case(HELP_STATS_IO_GRAPH_DIALOG):
436         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChStatIOGraphs.html");
437         break;
438     case(HELP_FILESET_DIALOG):
439         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChIOFileSetSection.html");
440         break;
441     case(HELP_CAPTURE_INTERFACES_DETAILS_DIALOG):
442         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCapInterfaceDetailsSection.html");
443         break;
444     case(HELP_PREFERENCES_DIALOG):
445         ONLINE_HELP_CALL(ONLINE_HELP_PREFIX  "ChCustPreferencesSection.html");
446         break;
447 #else
448     /* only some help pages are available for offline reading */
449     case(HELP_CONTENT):
450         help_topic("Overview");
451         break;
452     case(HELP_GETTING_STARTED):
453         help_topic("Getting Started");
454         break;
455     case(HELP_CAPTURE_OPTIONS_DIALOG):
456         help_topic("Capturing");
457         break;
458     case(HELP_CAPTURE_FILTERS_DIALOG):
459         help_topic("Capture Filters");
460         break;
461     case(HELP_DISPLAY_FILTERS_DIALOG):
462         help_topic("Display Filters");
463         break;
464 #endif
465
466     default:
467         g_assert_not_reached();
468     }
469 }
470
471
472 void 
473 topic_cb(GtkWidget *w _U_, topic_action_e action)
474 {
475     topic_action(action);
476 }
477
478 void 
479 topic_menu_cb(GtkWidget *w _U_, gpointer data _U_, topic_action_e action) {
480     topic_action(action);
481 }
482