1
/********************************************************************\
2
* window-help.c -- a help window for hypertext help. *
3
* Copyright (C) 1997 Robin D. Clark *
4
* Copyright (C) 1998 Linas Vepstas *
5
* Copyright (C) 1999 Jeremy Collins ( gtk-xmhtml port ) *
6
* Copyright (C) 2000 Dave Peticolas *
7
* Copyright (C) 2000 Bill Gribble *
9
* This program is free software; you can redistribute it and/or *
10
* modify it under the terms of the GNU General Public License as *
11
* published by the Free Software Foundation; either version 2 of *
12
* the License, or (at your option) any later version. *
14
* This program is distributed in the hope that it will be useful, *
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17
* GNU General Public License for more details. *
19
* You should have received a copy of the GNU General Public License*
20
* along with this program; if not, contact: *
22
* Free Software Foundation Voice: +1-617-542-5942 *
23
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
24
* Boston, MA 02111-1307, USA gnu@gnu.org *
26
\********************************************************************/
36
#include <sys/types.h>
39
/* needed for db.h with 'gcc -ansi -pedantic' */
41
# define _BSD_SOURCE 1
67
#include "dialog-utils.h"
68
#include "glade-cb-gnc-dialogs.h"
69
#include "glade-gnc-dialogs.h"
70
#include "gnc-component-manager.h"
71
#include "gnc-engine-util.h"
72
#include "gnc-html-history.h"
74
#include "window-help.h"
76
#define WINDOW_HELP_CM_CLASS "window-help"
78
struct _gnc_help_window {
82
GtkWidget * statusbar;
83
GtkWidget * statusbar_hbox;
84
GtkWidget * html_vbox;
85
GtkWidget * topics_tree;
88
GtkWidget * search_entry;
89
GtkWidget * search_results;
90
GtkWidget * type_pixmap;
96
/* This static indicates the debugging module that this .o belongs to. */
97
static short module = MOD_GUI;
99
static gint last_width = 0;
100
static gint last_height = 0;
103
/********************************************************************
104
* gnc_help_window_check_urltype
105
* is it OK to show a certain URLType in this window?
106
********************************************************************/
109
gnc_help_window_check_urltype(URLType t) {
114
case URL_TYPE_SECURE:
123
/********************************************************************
124
* gnc_help_window_check_urltype
125
* is it OK to show a certain URLType in this window?
126
********************************************************************/
129
gnc_help_window_url_flyover(gnc_html * html, const gchar * url,
131
gnc_help_window * help = (gnc_help_window *)data;
132
gtk_statusbar_pop(GTK_STATUSBAR(help->statusbar), 1);
134
gtk_statusbar_push(GTK_STATUSBAR(help->statusbar),
140
/********************************************************************
141
* after-load cb : enable/disable history buttons
142
********************************************************************/
145
gnc_help_window_set_back_button(gnc_help_window * win, int enabled) {
146
GtkToolbar * tb = GTK_TOOLBAR(win->toolbar);
147
gtk_widget_set_sensitive
148
(GTK_WIDGET(((GtkToolbarChild *)g_list_nth_data(tb->children, 0))->widget),
154
gnc_help_window_set_fwd_button(gnc_help_window * win, int enabled) {
155
GtkToolbar * tb = GTK_TOOLBAR(win->toolbar);
156
gtk_widget_set_sensitive
157
(GTK_WIDGET(((GtkToolbarChild *)g_list_nth_data(tb->children, 1))->widget),
163
compare_locations (gconstpointer a, gconstpointer b)
165
return safe_strcmp (a, b);
169
gnc_help_show_topic (gnc_help_window *help, const char * location)
171
GtkCTreeNode *node, *n;
176
ctree = GTK_CTREE (help->topics_tree);
178
rownum = GTK_CLIST(ctree)->focus_row;
180
node = gtk_ctree_node_nth (ctree, rownum);
186
node_loc = gtk_ctree_node_get_row_data (ctree, node);
188
if (safe_strcmp (location, node_loc) != 0)
192
help_loc = g_strconcat ("gnc-help:", location, NULL);
193
if (safe_strcmp (help_loc, node_loc) != 0)
200
node = gtk_ctree_find_by_row_data_custom (ctree, NULL,
206
char *help_loc = g_strconcat ("gnc-help:", location, NULL);
207
node = gtk_ctree_find_by_row_data_custom (ctree, NULL, help_loc,
214
gtk_ctree_unselect_recursive (ctree, NULL);
219
gtk_signal_handler_block_by_data (GTK_OBJECT (ctree), help);
220
gtk_ctree_select (ctree, node);
221
gtk_signal_handler_unblock_by_data (GTK_OBJECT (ctree), help);
223
/* Expand all the parents */
224
row = GTK_CTREE_ROW (node);
225
while ((n = row->parent) != NULL)
227
gtk_ctree_expand (ctree, n);
228
row = GTK_CTREE_ROW (n);
231
/* Make sure it's visible */
232
if (gtk_ctree_node_is_visible(ctree, node) != GTK_VISIBILITY_FULL)
233
gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0.0);
237
gnc_help_window_load_cb(gnc_html * html, URLType type,
238
const gchar * location, const gchar * label,
240
gnc_help_window * win = data;
242
if(gnc_html_history_forward_p(gnc_html_get_history(win->html))) {
243
gnc_help_window_set_fwd_button(win, TRUE);
246
gnc_help_window_set_fwd_button(win, FALSE);
249
if(gnc_html_history_back_p(gnc_html_get_history(win->html))) {
250
gnc_help_window_set_back_button(win, TRUE);
253
gnc_help_window_set_back_button(win, FALSE);
256
gnc_help_show_topic (win, location);
260
/********************************************************************
262
********************************************************************/
265
gnc_help_window_fwd_cb(GtkWidget * w, gpointer data) {
266
gnc_help_window * help = data;
267
gnc_html_history_node * node;
269
gnc_html_history_forward(gnc_html_get_history(help->html));
270
node = gnc_html_history_get_current(gnc_html_get_history(help->html));
271
gnc_html_show_url(help->html, node->type, node->location, node->label, 0);
276
gnc_help_window_back_cb(GtkWidget * w, gpointer data) {
277
gnc_help_window * help = data;
278
gnc_html_history_node * node;
280
gnc_html_history_back(gnc_html_get_history(help->html));
281
node = gnc_html_history_get_current(gnc_html_get_history(help->html));
282
gnc_html_show_url(help->html, node->type, node->location, node->label, 0);
287
gnc_help_window_stop_button_cb(GtkWidget * w, gpointer data) {
288
gnc_help_window * help = data;
289
gnc_html_cancel(help->html);
294
gnc_help_window_reload_button_cb(GtkWidget * w, gpointer data) {
295
gnc_help_window * help = data;
296
gnc_html_reload(help->html);
301
goto_string_cb(char * string, gpointer data) {
304
*(char **)data = NULL;
307
*(char **)data = g_strdup(string);
312
gnc_help_window_goto_button_cb(GtkWidget * w, gpointer data) {
313
gnc_help_window * help = data;
317
char * location = NULL;
320
GtkWidget * dlg = gnome_request_dialog(FALSE,
321
_("Enter URI to load:"), "", 250,
322
&goto_string_cb, &url,
323
GTK_WINDOW (help->toplevel));
324
retval = gnome_dialog_run_and_close(GNOME_DIALOG(dlg));
326
if((retval == 0) && url && (strlen(url) > 0)) {
327
type = gnc_html_parse_url(help->html, url, &location, &label);
328
gnc_html_show_url(help->html, type, location, label, 0);
341
/********************************************************************
342
* topics-browser callbacks
343
* silly tree building and clicking stuff
344
********************************************************************/
347
gnc_help_window_topic_select_cb(GtkCTree * tree, GtkCTreeNode * row, int col,
348
gpointer user_data) {
349
gnc_help_window * wind = user_data;
351
char * location = NULL;
353
char * url = gtk_ctree_node_get_row_data(tree, row);
355
if(url && strlen(url) > 0) {
356
type = gnc_html_parse_url(wind->html, url, &location, &label);
357
gnc_html_show_url(wind->html, type, location, label, 0);
364
free_url_cb(gpointer user_data) {
365
if(user_data) free(user_data);
369
topics_add_children(SCM topics, GtkCTree * tree, GtkCTreeNode * parent,
370
gnc_help_window * help) {
379
if(!gh_list_p(topics)) return;
381
for(; !gh_null_p(topics); topics = gh_cdr(topics)) {
382
this_topic = gh_car(topics);
384
if(!gh_list_p(this_topic)) continue;
386
if(!gh_null_p(gh_cdr(this_topic)) && !gh_null_p(gh_cddr(this_topic))) {
387
subtopics = gh_caddr(this_topic);
390
subtopics = SCM_BOOL_F;
393
topic_str = gh_scm2newstr(gh_car(this_topic), NULL);
394
ctopics[0] = _(topic_str);
396
if(!gh_null_p(gh_cdr(this_topic))) {
397
curl = gh_scm2newstr(gh_cadr(this_topic), NULL);
400
if(gh_list_p(subtopics)) {
407
node = gtk_ctree_insert_node(GTK_CTREE(tree),
408
GTK_CTREE_NODE(parent), NULL,
410
NULL, NULL, NULL, NULL,
413
gtk_ctree_node_set_row_data_full(GTK_CTREE(tree),
414
GTK_CTREE_NODE(node), curl,
417
if(gh_list_p(subtopics)) {
418
topics_add_children(subtopics, tree, node, help);
424
gnc_help_window_load_topics(gnc_help_window * help, const gchar * file) {
427
SCM load_topics = gh_eval_str("gnc:load-help-topics");
429
topics = gh_call1(load_topics, gh_str02scm(file));
430
topics_add_children(topics, GTK_CTREE(help->topics_tree), NULL, help);
431
gtk_ctree_expand_to_depth (GTK_CTREE(help->topics_tree), NULL, 1);
432
gtk_widget_show_all(help->topics_tree);
437
gnc_help_window_destroy_cb(GtkWidget * w, gpointer data) {
438
gnc_help_window * help = data;
440
gnc_unregister_gui_component_by_data (WINDOW_HELP_CM_CLASS, help);
442
/* close the help index db */
444
help->index_db->close(help->index_db);
447
gnc_html_destroy(help->html);
450
help->toplevel = NULL;
451
help->statusbar = NULL;
452
help->html_vbox = NULL;
453
help->topics_tree = NULL;
459
gnc_help_window_close_cb(GtkWidget * w, gpointer data) {
460
gnc_help_window * help = data;
462
gnc_close_gui_component_by_data (WINDOW_HELP_CM_CLASS, help);
466
gnc_help_window_print_cb(GtkWidget * w, gpointer data) {
467
gnc_help_window * help = data;
469
gnc_html_print(help->html);
474
item_destroy_cb(GtkListItem * li, gpointer user_data) {
475
gpointer x = gtk_object_get_user_data(GTK_OBJECT(li));
481
show_search_results(gnc_help_window * help, const char * matches,
483
const char * current;
485
char * this_link=NULL;
487
GList * results = NULL;
488
GtkWidget * listitem;
491
if(GTK_LIST(help->search_results)->children) {
492
gtk_list_remove_items(GTK_LIST(help->search_results),
493
GTK_LIST(help->search_results)->children);
499
while((end = strchr(current, '\n')) != NULL) {
500
link_len = end - current;
501
this_link = g_new0(char, link_len + 1);
502
strncpy(this_link, current, link_len);
503
listitem = gtk_list_item_new_with_label(this_link);
504
gtk_object_set_user_data(GTK_OBJECT(listitem), this_link);
505
gtk_signal_connect(GTK_OBJECT(listitem), "destroy",
506
GTK_SIGNAL_FUNC(item_destroy_cb), NULL);
508
gtk_widget_show(listitem);
509
results = g_list_append(results, listitem);
513
/* get rid of the old items */
514
if(GTK_LIST(help->search_results)->children) {
515
gtk_list_remove_items(GTK_LIST(help->search_results),
516
GTK_LIST(help->search_results)->children);
519
/* add the new ones */
521
gtk_list_append_items(GTK_LIST(help->search_results),
528
gnc_help_window_search_button_cb(GtkButton * button, gpointer data) {
529
GtkObject * hw = data;
530
gnc_help_window * help = gtk_object_get_data(hw, "help_window_struct");
531
char * search_string =
532
gtk_entry_get_text(GTK_ENTRY(help->search_entry));
536
/* initialize search key/value */
537
memset(&key, 0, sizeof(DBT));
538
memset(&value, 0, sizeof(DBT));
540
key.data = search_string;
541
key.size = strlen(search_string);
545
err = help->index_db->get(help->index_db, &key, &value, 0);
549
/* the data in the DB is a newline-separated list of filenames */
550
show_search_results(help, value.data, value.size);
555
gnc_help_window_search_help_button_cb(GtkButton * button, gpointer data) {
557
GtkObject * hw = data;
558
gnc_help_window * help = gtk_object_get_data(hw, "help_window_struct");
561
printf("help on help\n");
565
gnc_help_window_search_result_select_cb(GtkWidget * list, GtkWidget * child,
566
gpointer user_data) {
567
gnc_help_window * help = user_data;
568
char * helpfile = gtk_object_get_user_data(GTK_OBJECT(child));
569
gnc_help_window_show_help(help, helpfile, NULL);
573
close_handler (gpointer user_data)
575
gnc_help_window *help = user_data;
577
gdk_window_get_geometry (GTK_WIDGET(help->toplevel)->window, NULL, NULL,
578
&last_width, &last_height, NULL);
580
gnc_save_window_size ("help_win", last_width, last_height);
582
gnc_help_window_destroy (help);
585
/********************************************************************
586
* gnc_help_window_new
587
* allocates and opens up a help window
588
********************************************************************/
591
gnc_help_window_new (void) {
593
gnc_help_window * help = g_new0(gnc_help_window, 1);
596
GnomeUIInfo toolbar_data[] =
600
N_("Move back one step in the history"),
601
gnc_help_window_back_cb, help,
603
GNOME_APP_PIXMAP_STOCK,
604
GNOME_STOCK_PIXMAP_BACK,
609
N_("Move forward one step in the history"),
610
gnc_help_window_fwd_cb, help,
612
GNOME_APP_PIXMAP_STOCK,
613
GNOME_STOCK_PIXMAP_FORWARD,
616
GNOMEUIINFO_SEPARATOR,
619
N_("Reload the current document"),
620
gnc_help_window_reload_button_cb, help,
622
GNOME_APP_PIXMAP_STOCK,
623
GNOME_STOCK_PIXMAP_REFRESH,
628
N_("Open a new document"),
629
gnc_help_window_goto_button_cb, help,
631
GNOME_APP_PIXMAP_STOCK,
632
GNOME_STOCK_PIXMAP_OPEN,
637
N_("Cancel outstanding HTML requests"),
638
gnc_help_window_stop_button_cb, help,
640
GNOME_APP_PIXMAP_STOCK,
641
GNOME_STOCK_PIXMAP_STOP,
644
GNOMEUIINFO_SEPARATOR,
647
N_("Print Help window"),
648
gnc_help_window_print_cb, help,
650
GNOME_APP_PIXMAP_STOCK,
651
GNOME_STOCK_PIXMAP_PRINT,
654
GNOMEUIINFO_SEPARATOR,
657
N_("Close this Help window"),
658
gnc_help_window_close_cb, help,
660
GNOME_APP_PIXMAP_STOCK,
661
GNOME_STOCK_PIXMAP_CLOSE,
667
help->toplevel = create_Help_Window();
668
tlo = GTK_OBJECT(help->toplevel);
670
gnc_register_gui_component (WINDOW_HELP_CM_CLASS, NULL, close_handler, help);
672
help->toolbar = gtk_object_get_data(tlo, "help_toolbar");
673
help->statusbar = gtk_object_get_data(tlo, "help_statusbar");
674
help->statusbar_hbox = gtk_object_get_data(tlo, "statusbar_hbox");
675
help->html_vbox = gtk_object_get_data(tlo, "help_html_vbox");
676
help->topics_tree = gtk_object_get_data(tlo, "help_topics_tree");
677
help->paned = gtk_object_get_data(tlo, "help_paned");
678
help->search_entry = gtk_object_get_data(tlo, "help_search_entry");
679
help->search_results = gtk_object_get_data(tlo, "search_results_list");
680
help->type_pixmap = gtk_object_get_data(tlo, "file_type_pixmap");
682
help->html = gnc_html_new();
684
gtk_object_set_data(tlo, "help_window_struct", (gpointer)help);
686
gnome_app_fill_toolbar(GTK_TOOLBAR(help->toolbar), toolbar_data, NULL);
687
gtk_box_pack_start(GTK_BOX(help->html_vbox),
688
gnc_html_get_widget(help->html),
690
gtk_paned_set_position(GTK_PANED(help->paned), 200);
692
gnc_html_set_urltype_cb(help->html, gnc_help_window_check_urltype);
693
gnc_html_set_flyover_cb(help->html, gnc_help_window_url_flyover,
695
gnc_html_set_load_cb(help->html, gnc_help_window_load_cb,
698
gnc_help_window_load_topics(help, "help-topics-index.scm");
700
gtk_signal_connect(GTK_OBJECT(help->toplevel), "destroy",
701
GTK_SIGNAL_FUNC(gnc_help_window_destroy_cb),
704
gtk_signal_connect(GTK_OBJECT(help->topics_tree), "tree_select_row",
705
GTK_SIGNAL_FUNC(gnc_help_window_topic_select_cb),
708
gtk_signal_connect(GTK_OBJECT(help->search_results), "select_child",
709
GTK_SIGNAL_FUNC(gnc_help_window_search_result_select_cb),
712
indexfile = gncFindFile("help-search-index.db");
713
help->index_db = dbopen(indexfile, O_RDONLY, 0644, DB_HASH, NULL);
714
if (!help->index_db) {
715
PERR("Failed to open help index DB '%s' : %s\n",
716
indexfile ? indexfile : "(null)",
717
strerror(errno) ? strerror(errno) : "");
722
gnc_get_window_size("help_win", &last_width, &last_height);
724
gtk_window_set_default_size(GTK_WINDOW(help->toplevel),
725
last_width, last_height);
727
gnc_window_adjust_for_screen (GTK_WINDOW(help->toplevel));
729
gtk_widget_show_all(help->toplevel);
735
/********************************************************************
736
* gnc_help_window_destroy
737
* delete a help window
738
********************************************************************/
741
gnc_help_window_destroy(gnc_help_window * help) {
744
gnc_unregister_gui_component_by_data (WINDOW_HELP_CM_CLASS, help);
746
gtk_signal_disconnect_by_func(GTK_OBJECT(help->toplevel),
747
GTK_SIGNAL_FUNC(gnc_help_window_destroy_cb),
749
/* close the help index db */
751
help->index_db->close(help->index_db);
754
/* take care of the gnc-html object specially */
755
gtk_widget_ref(gnc_html_get_widget(help->html));
756
gnc_html_destroy(help->html);
758
gtk_widget_destroy(GTK_WIDGET(help->toplevel));
762
gnc_help_window_show_help(gnc_help_window * help, const char * location,
763
const char * label) {
764
gnc_html_show_url(help->html, URL_TYPE_FILE, location, label, 0);
768
/********************************************************************
769
* compatibility stuff (temporary)
770
********************************************************************/
773
helpWindow(GtkWidget * parent, const char * title, const char * htmlfile) {
774
gnc_help_window * help = gnc_help_window_new();
775
gnc_help_window_show_help(help, htmlfile, NULL);