5 * Laurent Deniel <laurent.deniel@free.fr>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 2000 Gerald Combs
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.
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.
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.
35 #include "epan/filesystem.h"
37 #include "text_page.h"
38 #include <epan/prefs.h>
39 #include "gtkglobals.h"
41 #include "compat_macros.h"
42 #include "dlg_utils.h"
43 #include "simple_dialog.h"
44 #include "webbrowser.h"
46 #define HELP_DIR "help"
49 #define NOTEBOOK_KEY "notebook_key"
51 static void help_destroy_cb(GtkWidget *w, gpointer data);
54 * Keep a static pointer to the current "Help" window, if any, so that
55 * if somebody tries to do "Help->Help" while there's already a
56 * "Help" window up, we just pop up the existing one, rather than
59 static GtkWidget *help_w = NULL;
62 * Keep a list of text widgets and corresponding file names as well
63 * (for text format changes).
71 static GSList *help_text_pages = NULL;
75 * Helper function to show a simple help text page.
77 static GtkWidget * help_page(const char *topic, const char *filename)
80 char *relative_path, *absolute_path;
83 relative_path = g_strconcat(HELP_DIR, G_DIR_SEPARATOR_S, filename, NULL);
84 absolute_path = get_datafile_path(relative_path);
85 text_page = text_page_new(absolute_path);
86 g_free(relative_path);
87 gtk_widget_show(text_page);
89 page = g_malloc(sizeof (help_page_t));
90 page->topic = g_strdup(topic);
91 page->pathname = absolute_path;
92 page->page = text_page;
93 help_text_pages = g_slist_append(help_text_pages, page);
100 * Create and show help dialog.
103 void help_dialog(void)
105 GtkWidget *main_vb, *bbox, *help_nb, *close_bt, *label, *topic_vb;
106 char line[4096+1]; /* XXX - size? */
109 char *help_toc_file_path;
112 if (help_w != NULL) {
113 /* There's already a "Help" dialog box; reactivate it. */
114 reactivate_window(help_w);
118 help_toc_file_path = get_datafile_path(HELP_DIR G_DIR_SEPARATOR_S "toc");
119 help_toc_file = fopen(help_toc_file_path, "r");
120 if (help_toc_file == NULL) {
121 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not open file \"%s\": %s",
122 help_toc_file_path, strerror(errno));
123 g_free(help_toc_file_path);
127 help_w = window_new_with_geom(GTK_WINDOW_TOPLEVEL, "Ethereal: Help", "help");
128 gtk_window_set_default_size(GTK_WINDOW(help_w), DEF_WIDTH, DEF_HEIGHT);
129 gtk_container_border_width(GTK_CONTAINER(help_w), 2);
131 /* Container for each row of widgets */
132 main_vb = gtk_vbox_new(FALSE, 1);
133 gtk_container_border_width(GTK_CONTAINER(main_vb), 1);
134 gtk_container_add(GTK_CONTAINER(help_w), main_vb);
136 /* help topics container */
137 help_nb = gtk_notebook_new();
138 gtk_container_add(GTK_CONTAINER(main_vb), help_nb);
139 OBJECT_SET_DATA(help_w, NOTEBOOK_KEY, help_nb);
142 while (fgets(line, sizeof line, help_toc_file) != NULL) {
143 /* Strip off line ending. */
144 p = strpbrk(line, "\r\n");
146 break; /* last line has no line ending */
148 /* {Topic title}:{filename of help file} */
149 p = strchr(line, ':');
155 * "line" refers to the topic now, and "filename" refers to the
158 topic_vb = help_page(line, filename);
159 label = gtk_label_new(line);
160 gtk_notebook_append_page(GTK_NOTEBOOK(help_nb), topic_vb, label);
163 if(ferror(help_toc_file)) {
164 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Error reading file \"%s\": %s",
165 help_toc_file_path, strerror(errno));
167 fclose(help_toc_file);
171 bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
172 gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
174 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
175 window_set_cancel_button(help_w, close_bt, window_cancel_button_cb);
177 SIGNAL_CONNECT(help_w, "delete_event", window_delete_event_cb, NULL);
178 SIGNAL_CONNECT(help_w, "destroy", help_destroy_cb, NULL);
180 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(help_w));
182 gtk_widget_show_all(help_w);
183 window_present(help_w);
187 gboolean topic_available(topic_action_e action) {
189 #ifdef ETHEREAL_EUG_DIR
190 /* online: we have all pages available */
193 /* offline: we have only some pages available */
198 case(HELP_GETTING_STARTED):
201 case(HELP_CAPTURE_OPTIONS_DIALOG):
204 case(HELP_CAPTURE_FILTERS_DIALOG):
207 case(HELP_DISPLAY_FILTERS_DIALOG):
217 * Open the help dialog and show a specific help page.
219 void help_topic(gchar *topic) {
222 GSList *help_page_ent;
227 /* show help dialog, if not already opened */
230 help_nb = OBJECT_GET_DATA(help_w, NOTEBOOK_KEY);
232 /* find page to display */
233 for (help_page_ent = help_text_pages; help_page_ent != NULL;
234 help_page_ent = g_slist_next(help_page_ent))
236 page = (help_page_t *)help_page_ent->data;
237 page_topic = page->topic;
238 if (strcmp (page_topic, topic) == 0) {
239 /* topic page found, switch to notebook page */
240 gtk_notebook_set_page(GTK_NOTEBOOK(help_nb), page_num);
246 /* topic page not found, default (first page) will be shown */
251 * Help dialog is closed now.
253 static void help_destroy_cb(GtkWidget *w _U_, gpointer data _U_)
255 GSList *help_page_ent;
258 /* Free up the list of help pages. */
259 for (help_page_ent = help_text_pages; help_page_ent != NULL;
260 help_page_ent = g_slist_next(help_page_ent)) {
261 page = (help_page_t *)help_page_ent->data;
263 g_free(page->pathname);
266 g_slist_free(help_text_pages);
267 help_text_pages = NULL;
269 /* Note that we no longer have a Help window. */
275 * Redraw all help pages, to use a new font.
277 void help_redraw(void)
279 GSList *help_page_ent;
280 help_page_t *help_page;
282 if (help_w != NULL) {
283 for (help_page_ent = help_text_pages; help_page_ent != NULL;
284 help_page_ent = g_slist_next(help_page_ent))
286 help_page = (help_page_t *)help_page_ent->data;
287 text_page_redraw(help_page->page, help_page->pathname);
294 topic_action(topic_action_e action)
296 /* pages online at www.ethereal.com */
298 case(ONLINEPAGE_HOME):
299 browser_open_url ("http://www.ethereal.com");
301 case(ONLINEPAGE_WIKI):
302 browser_open_url ("http://wiki.ethereal.com");
304 case(ONLINEPAGE_DOWNLOAD):
305 browser_open_url ("http://www.ethereal.com/download.html");
307 case(ONLINEPAGE_USERGUIDE):
308 browser_open_url ("http://www.ethereal.com/docs/user-guide");
310 case(ONLINEPAGE_FAQ):
311 browser_open_url ("http://www.ethereal.com/faq.html");
313 case(ONLINEPAGE_SAMPLE_FILES):
314 browser_open_url ("http://wiki.ethereal.com/SampleCaptures");
317 /* local manual pages */
318 case(LOCALPAGE_MAN_ETHEREAL):
319 browser_open_data_file("ethereal.html");
321 case(LOCALPAGE_MAN_ETHEREAL_FILTER):
322 browser_open_data_file("ethereal-filter.html");
324 case(LOCALPAGE_MAN_TETHEREAL):
325 browser_open_data_file("tethereal.html");
327 case(LOCALPAGE_MAN_MERGECAP):
328 browser_open_data_file("mergecap.html");
330 case(LOCALPAGE_MAN_EDITCAP):
331 browser_open_data_file("editcap.html");
333 case(LOCALPAGE_MAN_TEXT2PCAP):
334 browser_open_data_file("text2pcap.html");
337 #ifdef ETHEREAL_EUG_DIR
338 /* local help pages (User's Guide) */
340 browser_open_data_file("eug_html_chunked/index.html");
342 case(HELP_CAPTURE_OPTIONS_DIALOG):
343 browser_open_data_file("eug_html_chunked/ChCapCaptureOptions.html");
345 case(HELP_CAPTURE_FILTERS_DIALOG):
346 browser_open_data_file("eug_html_chunked/ChWorkDefineFilterSection.html");
348 case(HELP_DISPLAY_FILTERS_DIALOG):
349 browser_open_data_file("eug_html_chunked/ChWorkDefineFilterSection.html");
351 case(HELP_COLORING_RULES_DIALOG):
352 browser_open_data_file("eug_html_chunked/ChCustColorizationSection.html");
354 case(HELP_PRINT_DIALOG):
355 browser_open_data_file("eug_html_chunked/ChIOPrintSection.html");
357 case(HELP_FIND_DIALOG):
358 browser_open_data_file("eug_html_chunked/ChWorkFindPacketSection.html");
360 case(HELP_GOTO_DIALOG):
361 browser_open_data_file("eug_html_chunked/ChWorkGoToPacketSection.html");
363 case(HELP_CAPTURE_INTERFACES_DIALOG):
364 browser_open_data_file("eug_html_chunked/ChCapInterfaceSection.html");
366 case(HELP_ENABLED_PROTOCOLS_DIALOG):
367 browser_open_data_file("eug_html_chunked/ChCustProtocolDissectionSection.html");
369 case(HELP_DECODE_AS_DIALOG):
370 browser_open_data_file("eug_html_chunked/ChCustProtocolDissectionSection.html");
372 case(HELP_DECODE_AS_SHOW_DIALOG):
373 browser_open_data_file("eug_html_chunked/ChCustProtocolDissectionSection.html");
375 case(HELP_FOLLOW_TCP_STREAM_DIALOG):
376 browser_open_data_file("eug_html_chunked/ChAdvFollowTCPSection.html");
378 case(HELP_STATS_SUMMARY_DIALOG):
379 browser_open_data_file("eug_html_chunked/ChStatSummary.html");
381 case(HELP_STATS_PROTO_HIERARCHY_DIALOG):
382 browser_open_data_file("eug_html_chunked/ChStatHierarchy.html");
384 case(HELP_STATS_ENDPOINTS_DIALOG):
385 browser_open_data_file("eug_html_chunked/ChStatEndpoints.html");
387 case(HELP_STATS_CONVERSATIONS_DIALOG):
388 browser_open_data_file("eug_html_chunked/ChStatConversations.html");
390 case(HELP_STATS_IO_GRAPH_DIALOG):
391 browser_open_data_file("eug_html_chunked/ChStatIOGraphs.html");
394 /* only some help pages are available for offline reading */
396 help_topic("Overview");
398 case(HELP_GETTING_STARTED):
399 help_topic("Getting Started");
401 case(HELP_CAPTURE_OPTIONS_DIALOG):
402 help_topic("Capturing");
404 case(HELP_CAPTURE_FILTERS_DIALOG):
405 help_topic("Capture Filters");
407 case(HELP_DISPLAY_FILTERS_DIALOG):
408 help_topic("Display Filters");
413 g_assert_not_reached();
419 topic_cb(GtkWidget *w _U_, topic_action_e action)
421 topic_action(action);
425 topic_menu_cb(GtkWidget *w _U_, gpointer data _U_, topic_action_e action) {
426 topic_action(action);