2 Hypertext file browser.
4 Copyright (C) 1994-2017
5 Free Software Foundation, Inc.
7 This file is part of the Midnight Commander.
9 The Midnight Commander is free software: you can redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation, either version 3 of the License,
12 or (at your option) any later version.
14 The Midnight Commander 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, see <http://www.gnu.org/licenses/>.
25 * \brief Source: hypertext file browser
27 * Implements the hypertext file viewer.
28 * The hypertext file is a file that may have one or more nodes. Each
29 * node ends with a ^D character and starts with a bracket, then the
30 * name of the node and then a closing bracket. Right after the closing
31 * bracket a newline is placed. This newline is not to be displayed by
32 * the help viewer and must be skipped - its sole purpose is to faciliate
33 * the work of the people managing the help file template (xnc.hlp) .
35 * Links in the hypertext file are specified like this: the text that
36 * will be highlighted should have a leading ^A, then it comes the
37 * text, then a ^B indicating that highlighting is done, then the name
38 * of the node you want to link to and then a ^C.
40 * The file must contain a ^D at the beginning and at the end of the
41 * file or the program will not be able to detect the end of file.
43 * Lazyness/widgeting attack: This file does use the dialog manager
44 * and uses mainly the dialog to achieve the help work. there is only
45 * one specialized widget and it's only used to forward the mouse messages
46 * to the appropriate routine.
54 #include <sys/types.h>
57 #include "lib/global.h"
59 #include "lib/tty/tty.h"
61 #include "lib/strutil.h"
62 #include "lib/fileloc.h"
64 #include "lib/widget.h"
65 #include "lib/event-types.h"
67 #include "keybind-defaults.h"
70 /*** global variables ****************************************************************************/
72 /*** file scope macro definitions ****************************************************************/
74 #define MAXLINKNAME 80
75 #define HISTORY_SIZE 20
76 #define HELP_WINDOW_WIDTH MIN(80, COLS - 16)
78 #define STRING_LINK_START "\01"
79 #define STRING_LINK_POINTER "\02"
80 #define STRING_LINK_END "\03"
81 #define STRING_NODE_END "\04"
83 /*** file scope type declarations ****************************************************************/
85 /* Link areas for the mouse */
86 typedef struct Link_Area
89 const char *link_name
;
92 /*** file scope variables ************************************************************************/
94 static char *fdata
= NULL
; /* Pointer to the loaded data file */
95 static int help_lines
; /* Lines in help viewer */
96 static int history_ptr
; /* For the history queue */
97 static const char *main_node
; /* The main node */
98 static const char *last_shown
= NULL
; /* Last byte shown in a screen */
99 static gboolean end_of_node
= FALSE
; /* Flag: the last character of the node shown? */
100 static const char *currentpoint
;
101 static const char *selected_item
;
103 /* The widget variables */
104 static WDialog
*whelp
;
108 const char *page
; /* Pointer to the selected page */
109 const char *link
; /* Pointer to the selected link */
110 } history
[HISTORY_SIZE
];
112 static GSList
*link_area
= NULL
;
113 static gboolean inside_link_area
= FALSE
;
115 static cb_ret_t
help_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
);
117 /*** file scope functions ************************************************************************/
118 /* --------------------------------------------------------------------------------------------- */
120 /** returns the position where text was found in the start buffer
124 search_string (const char *start
, const char *text
)
126 const char *result
= NULL
;
127 char *local_text
= g_strdup (text
);
128 char *d
= local_text
;
129 const char *e
= start
;
131 /* fmt sometimes replaces a space with a newline in the help file */
132 /* Replace the newlines in the link name with spaces to correct the situation */
141 for (d
= local_text
; *e
; e
++)
158 /* --------------------------------------------------------------------------------------------- */
159 /** Searches text in the buffer pointed by start. Search ends
160 * if the CHAR_NODE_END is found in the text.
161 * @return NULL on failure
165 search_string_node (const char *start
, const char *text
)
167 const char *d
= text
;
168 const char *e
= start
;
171 for (; *e
&& *e
!= CHAR_NODE_END
; e
++)
184 /* --------------------------------------------------------------------------------------------- */
185 /** Searches the_char in the buffer pointer by start and searches
186 * it can search forward (direction = 1) or backward (direction = -1)
190 search_char_node (const char *start
, char the_char
, int direction
)
194 for (e
= start
; (*e
!= '\0') && (*e
!= CHAR_NODE_END
); e
+= direction
)
201 /* --------------------------------------------------------------------------------------------- */
202 /** Returns the new current pointer when moved lines lines */
205 move_forward2 (const char *c
, int lines
)
211 for (line
= 0, p
= currentpoint
; (*p
!= '\0') && (*p
!= CHAR_NODE_END
); str_cnext_char (&p
))
214 return currentpoint
= p
;
219 return currentpoint
= c
;
222 /* --------------------------------------------------------------------------------------------- */
225 move_backward2 (const char *c
, int lines
)
231 for (line
= 0, p
= currentpoint
; (*p
!= '\0') && ((int) (p
- fdata
) >= 0); str_cprev_char (&p
))
233 if (*p
== CHAR_NODE_END
)
235 /* We reached the beginning of the node */
236 /* Skip the node headers */
239 return currentpoint
= p
+ 2; /* Skip the newline following the start of the node */
242 if (*(p
- 1) == '\n')
245 return currentpoint
= p
;
247 return currentpoint
= c
;
250 /* --------------------------------------------------------------------------------------------- */
256 currentpoint
= move_forward2 (currentpoint
, i
);
259 /* --------------------------------------------------------------------------------------------- */
262 move_backward (int i
)
264 currentpoint
= move_backward2 (currentpoint
, ++i
);
267 /* --------------------------------------------------------------------------------------------- */
272 while (((int) (currentpoint
> fdata
) > 0) && (*currentpoint
!= CHAR_NODE_END
))
275 while (*currentpoint
!= ']')
277 currentpoint
= currentpoint
+ 2; /* Skip the newline following the start of the node */
278 selected_item
= NULL
;
281 /* --------------------------------------------------------------------------------------------- */
284 move_to_bottom (void)
286 while ((*currentpoint
!= '\0') && (*currentpoint
!= CHAR_NODE_END
))
292 /* --------------------------------------------------------------------------------------------- */
295 help_follow_link (const char *start
, const char *lc_selected_item
)
299 if (lc_selected_item
== NULL
)
302 for (p
= lc_selected_item
; *p
&& *p
!= CHAR_NODE_END
&& *p
!= CHAR_LINK_POINTER
; p
++)
304 if (*p
== CHAR_LINK_POINTER
)
307 char link_name
[MAXLINKNAME
];
310 for (i
= 1; *p
!= CHAR_LINK_END
&& *p
&& *p
!= CHAR_NODE_END
&& i
< MAXLINKNAME
- 3;)
311 link_name
[i
++] = *++p
;
312 link_name
[i
- 1] = ']';
314 p
= search_string (fdata
, link_name
);
317 p
+= 1; /* Skip the newline following the start of the node */
322 /* Create a replacement page with the error message */
323 return _("Help file format error\n");
326 /* --------------------------------------------------------------------------------------------- */
329 select_next_link (const char *current_link
)
333 if (current_link
== NULL
)
336 p
= search_string_node (current_link
, STRING_LINK_END
);
339 p
= search_string_node (p
, STRING_LINK_START
);
345 /* --------------------------------------------------------------------------------------------- */
348 select_prev_link (const char *current_link
)
350 return current_link
== NULL
? NULL
: search_char_node (current_link
- 1, CHAR_LINK_START
, -1);
353 /* --------------------------------------------------------------------------------------------- */
356 start_link_area (int x
, int y
, const char *link_name
)
360 if (inside_link_area
)
361 message (D_NORMAL
, _("Warning"), _("Internal bug: Double start of link area"));
363 /* Allocate memory for a new link area */
364 la
= g_new (Link_Area
, 1);
365 /* Save the beginning coordinates of the link area */
368 /* Save the name of the destination anchor */
369 la
->link_name
= link_name
;
370 link_area
= g_slist_prepend (link_area
, la
);
372 inside_link_area
= TRUE
;
375 /* --------------------------------------------------------------------------------------------- */
378 end_link_area (int x
, int y
)
380 if (inside_link_area
)
382 Link_Area
*la
= (Link_Area
*) link_area
->data
;
383 /* Save the end coordinates of the link area */
386 inside_link_area
= FALSE
;
390 /* --------------------------------------------------------------------------------------------- */
393 clear_link_areas (void)
395 g_slist_free_full (link_area
, g_free
);
397 inside_link_area
= FALSE
;
400 /* --------------------------------------------------------------------------------------------- */
403 help_print_word (WDialog
* h
, GString
* word
, int *col
, int *line
, gboolean add_space
)
405 if (*line
>= help_lines
)
406 g_string_set_size (word
, 0);
411 w
= str_term_width1 (word
->str
);
412 if (*col
+ w
>= HELP_WINDOW_WIDTH
)
418 if (*line
>= help_lines
)
419 g_string_set_size (word
, 0);
422 widget_move (h
, *line
+ 2, *col
+ 2);
423 tty_print_string (word
->str
);
424 g_string_set_size (word
, 0);
431 if (*col
< HELP_WINDOW_WIDTH
- 1)
433 tty_print_char (' ');
444 /* --------------------------------------------------------------------------------------------- */
447 help_show (WDialog
* h
, const char *paint_start
)
451 gboolean painting
= TRUE
;
452 gboolean acs
; /* Flag: Alternate character set active? */
453 gboolean repeat_paint
;
454 int active_col
, active_line
; /* Active link position */
455 char buff
[MB_LEN_MAX
+ 1];
458 word
= g_string_sized_new (32);
460 tty_setcolor (HELP_NORMAL_COLOR
);
463 line
= col
= active_col
= active_line
= 0;
464 repeat_paint
= FALSE
;
468 if ((int) (selected_item
- paint_start
) < 0)
469 selected_item
= NULL
;
473 while ((n
[0] != '\0') && (n
[0] != CHAR_NODE_END
) && (line
< help_lines
))
476 n
= str_cget_next_char (p
);
477 memcpy (buff
, p
, n
- p
);
480 c
= (unsigned char) buff
[0];
483 case CHAR_LINK_START
:
484 if (selected_item
== NULL
)
486 if (p
!= selected_item
)
487 tty_setcolor (HELP_LINK_COLOR
);
490 tty_setcolor (HELP_SLINK_COLOR
);
492 /* Store the coordinates of the link */
493 active_col
= col
+ 2;
494 active_line
= line
+ 2;
496 start_link_area (col
, line
, p
);
498 case CHAR_LINK_POINTER
:
503 help_print_word (h
, word
, &col
, &line
, FALSE
);
504 end_link_area (col
- 1, line
);
505 tty_setcolor (HELP_NORMAL_COLOR
);
514 widget_move (h
, line
+ 2, col
+ 2);
515 tty_print_string (VERSION
);
516 col
+= str_term_width1 (VERSION
);
519 tty_setcolor (HELP_BOLD_COLOR
);
521 case CHAR_FONT_ITALIC
:
522 tty_setcolor (HELP_ITALIC_COLOR
);
524 case CHAR_FONT_NORMAL
:
525 help_print_word (h
, word
, &col
, &line
, FALSE
);
526 tty_setcolor (HELP_NORMAL_COLOR
);
530 help_print_word (h
, word
, &col
, &line
, FALSE
);
539 help_print_word (h
, word
, &col
, &line
, c
== ' ');
542 col
= (col
/ 8 + 1) * 8;
543 if (col
>= HELP_WINDOW_WIDTH
)
552 if (painting
&& (line
< help_lines
))
555 /* accumulate symbols in a word */
556 g_string_append (word
, buff
);
557 else if (col
< HELP_WINDOW_WIDTH
)
559 widget_move (h
, line
+ 2, col
+ 2);
561 if ((c
== ' ') || (c
== '.'))
565 tty_print_char (acs_map
[c
]);
567 SLsmg_draw_object (WIDGET (h
)->y
+ line
+ 2, WIDGET (h
)->x
+ col
+ 2,
576 /* print last word */
577 if (n
[0] == CHAR_NODE_END
)
578 help_print_word (h
, word
, &col
, &line
, FALSE
);
581 end_of_node
= line
< help_lines
;
582 tty_setcolor (HELP_NORMAL_COLOR
);
583 if ((int) (selected_item
- last_shown
) >= 0)
585 if ((link_area
== NULL
) || (link_area
->data
== NULL
))
586 selected_item
= NULL
;
589 selected_item
= ((Link_Area
*) link_area
->data
)->link_name
;
594 while (repeat_paint
);
596 g_string_free (word
, TRUE
);
598 /* Position the cursor over a nice link */
600 widget_move (h
, active_line
, active_col
);
603 /* --------------------------------------------------------------------------------------------- */
607 help_help (WDialog
* h
)
611 history_ptr
= (history_ptr
+ 1) % HISTORY_SIZE
;
612 history
[history_ptr
].page
= currentpoint
;
613 history
[history_ptr
].link
= selected_item
;
615 p
= search_string (fdata
, "[How to use help]");
618 currentpoint
= p
+ 1; /* Skip the newline following the start of the node */
619 selected_item
= NULL
;
620 send_message (h
, NULL
, MSG_DRAW
, 0, NULL
);
624 /* --------------------------------------------------------------------------------------------- */
627 help_index (WDialog
* h
)
629 const char *new_item
;
631 new_item
= search_string (fdata
, "[Contents]");
633 if (new_item
== NULL
)
634 message (D_ERROR
, MSG_ERROR
, _("Cannot find node %s in help file"), "[Contents]");
637 history_ptr
= (history_ptr
+ 1) % HISTORY_SIZE
;
638 history
[history_ptr
].page
= currentpoint
;
639 history
[history_ptr
].link
= selected_item
;
641 currentpoint
= new_item
+ 1; /* Skip the newline following the start of the node */
642 selected_item
= NULL
;
643 send_message (h
, NULL
, MSG_DRAW
, 0, NULL
);
647 /* --------------------------------------------------------------------------------------------- */
650 help_back (WDialog
* h
)
652 currentpoint
= history
[history_ptr
].page
;
653 selected_item
= history
[history_ptr
].link
;
656 history_ptr
= HISTORY_SIZE
- 1;
658 send_message (h
, NULL
, MSG_DRAW
, 0, NULL
); /* FIXME: unneeded? */
661 /* --------------------------------------------------------------------------------------------- */
664 help_next_link (gboolean move_down
)
666 const char *new_item
;
668 new_item
= select_next_link (selected_item
);
669 if (new_item
!= NULL
)
671 selected_item
= new_item
;
672 if ((int) (selected_item
- last_shown
) >= 0)
677 selected_item
= NULL
;
683 selected_item
= NULL
;
686 /* --------------------------------------------------------------------------------------------- */
689 help_prev_link (gboolean move_up
)
691 const char *new_item
;
693 new_item
= select_prev_link (selected_item
);
694 selected_item
= new_item
;
695 if ((selected_item
== NULL
) || (selected_item
< currentpoint
))
699 else if ((link_area
!= NULL
) && (link_area
->data
!= NULL
))
700 selected_item
= ((Link_Area
*) link_area
->data
)->link_name
;
702 selected_item
= NULL
;
706 /* --------------------------------------------------------------------------------------------- */
709 help_next_node (void)
711 const char *new_item
;
713 new_item
= currentpoint
;
714 while ((*new_item
!= '\0') && (*new_item
!= CHAR_NODE_END
))
717 if (*++new_item
== '[')
718 while (*++new_item
!= '\0')
719 if ((*new_item
== ']') && (*++new_item
!= '\0') && (*++new_item
!= '\0'))
721 currentpoint
= new_item
;
722 selected_item
= NULL
;
727 /* --------------------------------------------------------------------------------------------- */
730 help_prev_node (void)
732 const char *new_item
;
734 new_item
= currentpoint
;
735 while (((int) (new_item
- fdata
) > 1) && (*new_item
!= CHAR_NODE_END
))
738 while (((int) (new_item
- fdata
) > 0) && (*new_item
!= CHAR_NODE_END
))
740 while (*new_item
!= ']')
742 currentpoint
= new_item
+ 2;
743 selected_item
= NULL
;
746 /* --------------------------------------------------------------------------------------------- */
749 help_select_link (void)
752 if (selected_item
== NULL
)
754 #ifdef WE_WANT_TO_GO_BACKWARD_ON_KEY_RIGHT
755 /* Is there any reason why the right key would take us
756 * backward if there are no links selected?, I agree
757 * with Torben than doing nothing in this case is better
759 /* If there are no links, go backward in history */
762 history_ptr
= HISTORY_SIZE
- 1;
764 currentpoint
= history
[history_ptr
].page
;
765 selected_item
= history
[history_ptr
].link
;
770 history_ptr
= (history_ptr
+ 1) % HISTORY_SIZE
;
771 history
[history_ptr
].page
= currentpoint
;
772 history
[history_ptr
].link
= selected_item
;
773 currentpoint
= help_follow_link (currentpoint
, selected_item
);
776 selected_item
= NULL
;
779 /* --------------------------------------------------------------------------------------------- */
782 help_execute_cmd (long command
)
784 cb_ret_t ret
= MSG_HANDLED
;
798 help_prev_link (TRUE
);
801 help_next_link (TRUE
);
804 move_forward (help_lines
- 1);
807 move_backward (help_lines
- 1);
809 case CK_HalfPageDown
:
810 move_forward (help_lines
/ 2);
813 move_backward (help_lines
/ 2);
825 help_next_link (FALSE
);
828 help_prev_link (FALSE
);
840 ret
= MSG_NOT_HANDLED
;
846 /* --------------------------------------------------------------------------------------------- */
849 help_handle_key (WDialog
* h
, int c
)
853 command
= keybind_lookup_keymap_command (help_map
, c
);
854 if ((command
== CK_IgnoreKey
) || (help_execute_cmd (command
) == MSG_NOT_HANDLED
))
855 return MSG_NOT_HANDLED
;
857 send_message (h
, NULL
, MSG_DRAW
, 0, NULL
);
861 /* --------------------------------------------------------------------------------------------- */
864 help_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
866 WDialog
*h
= DIALOG (w
);
874 help_lines
= MIN (LINES
- 4, MAX (2 * LINES
/ 3, 18));
875 dlg_set_size (h
, help_lines
+ 4, HELP_WINDOW_WIDTH
+ 4);
876 bb
= find_buttonbar (h
);
877 widget_set_size (WIDGET (bb
), LINES
- 1, 0, 1, COLS
);
882 dlg_default_repaint (h
);
883 help_show (h
, currentpoint
);
887 return help_handle_key (h
, parm
);
890 /* Handle shortcuts and buttonbar. */
891 return help_execute_cmd (parm
);
894 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
898 /* --------------------------------------------------------------------------------------------- */
901 interactive_display_finish (void)
906 /* --------------------------------------------------------------------------------------------- */
907 /** translate help file into terminal encoding */
910 translate_file (char *filedata
)
913 GString
*translated_data
;
915 /* initial allocation for largest whole help file */
916 translated_data
= g_string_sized_new (32 * 1024);
918 conv
= str_crt_conv_from ("UTF-8");
920 if (conv
== INVALID_CONV
)
921 g_string_free (translated_data
, TRUE
);
926 if (str_convert (conv
, filedata
, translated_data
) != ESTR_FAILURE
)
927 fdata
= g_string_free (translated_data
, FALSE
);
931 g_string_free (translated_data
, TRUE
);
933 str_close_conv (conv
);
937 /* --------------------------------------------------------------------------------------------- */
940 md_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
945 w
->lines
= help_lines
;
949 return widget_default_callback (w
, sender
, msg
, parm
, data
);
953 /* --------------------------------------------------------------------------------------------- */
956 help_mouse_callback (Widget
* w
, mouse_msg_t msg
, mouse_event_t
* event
)
959 GSList
*current_area
;
961 if (msg
!= MSG_MOUSE_CLICK
)
964 if ((event
->buttons
& GPM_B_RIGHT
) != 0)
966 /* Right button click */
971 /* Left bytton click */
973 /* The event is relative to the dialog window, adjust it: */
977 /* Test whether the mouse click is inside one of the link areas */
978 for (current_area
= link_area
; current_area
!= NULL
; current_area
= g_slist_next (current_area
))
980 Link_Area
*la
= (Link_Area
*) current_area
->data
;
982 /* Test one line link area */
983 if (y
== la
->y1
&& x
>= la
->x1
&& y
== la
->y2
&& x
<= la
->x2
)
986 /* Test two line link area */
987 if (la
->y1
+ 1 == la
->y2
)
989 /* The first line || The second line */
990 if ((y
== la
->y1
&& x
>= la
->x1
) || (y
== la
->y2
&& x
<= la
->x2
))
993 /* Mouse will not work with link areas of more than two lines */
996 /* Test whether a link area was found */
997 if (current_area
!= NULL
)
999 Link_Area
*la
= (Link_Area
*) current_area
->data
;
1001 /* The click was inside a link area -> follow the link */
1002 history_ptr
= (history_ptr
+ 1) % HISTORY_SIZE
;
1003 history
[history_ptr
].page
= currentpoint
;
1004 history
[history_ptr
].link
= la
->link_name
;
1005 currentpoint
= help_follow_link (currentpoint
, la
->link_name
);
1006 selected_item
= NULL
;
1009 move_backward (help_lines
- 1);
1010 else if (y
>= help_lines
)
1011 move_forward (help_lines
- 1);
1012 else if (y
< help_lines
/ 2)
1017 /* Show the new node */
1018 send_message (w
->owner
, NULL
, MSG_DRAW
, 0, NULL
);
1021 /* --------------------------------------------------------------------------------------------- */
1024 mousedispatch_new (int y
, int x
, int yl
, int xl
)
1028 w
= g_new0 (Widget
, 1);
1029 widget_init (w
, y
, x
, yl
, xl
, md_callback
, help_mouse_callback
);
1030 w
->options
|= WOP_SELECTABLE
| WOP_WANT_CURSOR
;
1035 /* --------------------------------------------------------------------------------------------- */
1036 /*** public functions ****************************************************************************/
1037 /* --------------------------------------------------------------------------------------------- */
1039 /* event callback */
1041 help_interactive_display (const gchar
* event_group_name
, const gchar
* event_name
,
1042 gpointer init_data
, gpointer data
)
1044 const dlg_colors_t help_colors
= {
1045 HELP_NORMAL_COLOR
, /* common text color */
1046 0, /* unused in help */
1047 HELP_BOLD_COLOR
, /* bold text color */
1048 0, /* unused in help */
1049 HELP_TITLE_COLOR
/* title color */
1052 WButtonBar
*help_bar
;
1054 char *hlpfile
= NULL
;
1056 ev_help_t
*event_data
= (ev_help_t
*) data
;
1058 (void) event_group_name
;
1062 if (event_data
->filename
!= NULL
)
1063 g_file_get_contents (event_data
->filename
, &filedata
, NULL
, NULL
);
1065 filedata
= load_mc_home_file (mc_global
.share_data_dir
, MC_HELP
, &hlpfile
, NULL
);
1067 if (filedata
== NULL
)
1068 message (D_ERROR
, MSG_ERROR
, _("Cannot open file %s\n%s"),
1069 event_data
->filename
? event_data
->filename
: hlpfile
, unix_error_string (errno
));
1073 if (filedata
== NULL
)
1076 translate_file (filedata
);
1083 if ((event_data
->node
== NULL
) || (*event_data
->node
== '\0'))
1084 event_data
->node
= "[main]";
1086 main_node
= search_string (fdata
, event_data
->node
);
1088 if (main_node
== NULL
)
1090 message (D_ERROR
, MSG_ERROR
, _("Cannot find node %s in help file"), event_data
->node
);
1092 /* Fallback to [main], return if it also cannot be found */
1093 main_node
= search_string (fdata
, "[main]");
1094 if (main_node
== NULL
)
1096 interactive_display_finish ();
1101 help_lines
= MIN (LINES
- 4, MAX (2 * LINES
/ 3, 18));
1104 dlg_create (TRUE
, 0, 0, help_lines
+ 4, HELP_WINDOW_WIDTH
+ 4, WPOS_CENTER
| WPOS_TRYUP
,
1105 FALSE
, help_colors
, help_callback
, NULL
, "[Help]", _("Help"));
1106 widget_want_tab (WIDGET (whelp
), TRUE
);
1108 selected_item
= search_string_node (main_node
, STRING_LINK_START
) - 1;
1109 currentpoint
= main_node
+ 1; /* Skip the newline following the start of the node */
1111 for (history_ptr
= HISTORY_SIZE
; history_ptr
;)
1114 history
[history_ptr
].page
= currentpoint
;
1115 history
[history_ptr
].link
= selected_item
;
1118 help_bar
= buttonbar_new (TRUE
);
1119 WIDGET (help_bar
)->y
-= WIDGET (whelp
)->y
;
1120 WIDGET (help_bar
)->x
-= WIDGET (whelp
)->x
;
1122 md
= mousedispatch_new (1, 1, help_lines
, HELP_WINDOW_WIDTH
- 2);
1124 add_widget (whelp
, md
);
1125 add_widget (whelp
, help_bar
);
1127 buttonbar_set_label (help_bar
, 1, Q_ ("ButtonBar|Help"), help_map
, NULL
);
1128 buttonbar_set_label (help_bar
, 2, Q_ ("ButtonBar|Index"), help_map
, NULL
);
1129 buttonbar_set_label (help_bar
, 3, Q_ ("ButtonBar|Prev"), help_map
, NULL
);
1130 buttonbar_set_label (help_bar
, 4, "", help_map
, NULL
);
1131 buttonbar_set_label (help_bar
, 5, "", help_map
, NULL
);
1132 buttonbar_set_label (help_bar
, 6, "", help_map
, NULL
);
1133 buttonbar_set_label (help_bar
, 7, "", help_map
, NULL
);
1134 buttonbar_set_label (help_bar
, 8, "", help_map
, NULL
);
1135 buttonbar_set_label (help_bar
, 9, "", help_map
, NULL
);
1136 buttonbar_set_label (help_bar
, 10, Q_ ("ButtonBar|Quit"), help_map
, NULL
);
1139 interactive_display_finish ();
1140 dlg_destroy (whelp
);
1144 /* --------------------------------------------------------------------------------------------- */