This source file includes following definitions.
- search_string
- search_string_node
- search_char_node
- move_forward2
- move_backward2
- move_forward
- move_backward
- move_to_top
- move_to_bottom
- help_follow_link
- select_next_link
- select_prev_link
- start_link_area
- end_link_area
- clear_link_areas
- help_print_word
- mc_acs_map
- help_show
- help_help
- help_index
- help_back
- help_next_link
- help_prev_link
- help_next_node
- help_prev_node
- help_select_link
- help_execute_cmd
- help_handle_key
- help_bg_callback
- help_resize
- help_callback
- interactive_display_finish
- translate_file
- md_callback
- help_mouse_callback
- mousedispatch_new
- help_interactive_display
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #include <config.h>
49
50 #include <limits.h>
51 #include <stdio.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54
55 #include "lib/global.h"
56
57 #include "lib/tty/tty.h"
58 #include "lib/skin.h"
59 #include "lib/strutil.h"
60 #include "lib/fileloc.h"
61 #include "lib/util.h"
62 #include "lib/widget.h"
63 #include "lib/event-types.h"
64
65 #include "keymap.h"
66 #include "util.h"
67 #include "help.h"
68
69
70
71
72
73 #define MAXLINKNAME 80
74 #define HISTORY_SIZE 20
75 #define HELP_WINDOW_WIDTH MIN (80, COLS - 16)
76
77 #define STRING_LINK_START "\01"
78 #define STRING_LINK_POINTER "\02"
79 #define STRING_LINK_END "\03"
80 #define STRING_NODE_END "\04"
81
82
83
84
85 typedef struct Link_Area
86 {
87 int x1, y1, x2, y2;
88 const char *link_name;
89 } Link_Area;
90
91
92
93
94
95 static char *fdata = NULL;
96 static int help_lines;
97 static int history_ptr = 0;
98 static const char *main_node;
99 static const char *last_shown = NULL;
100 static gboolean end_of_node = FALSE;
101 static const char *currentpoint;
102 static const char *selected_item;
103
104
105 static WDialog *whelp;
106
107 static struct
108 {
109 const char *page;
110 const char *link;
111 } history[HISTORY_SIZE];
112
113 static GSList *link_area = NULL;
114 static gboolean inside_link_area = FALSE;
115
116
117
118
119
120
121
122
123 static const char *
124 search_string (const char *start, const char *text)
125 {
126 const char *result = NULL;
127 char *local_text;
128 char *d;
129 const char *e = start;
130
131 local_text = g_strdup (text);
132
133
134
135 for (d = local_text; *d != '\0'; str_next_char (&d))
136 if (*d == '\n')
137 *d = ' ';
138
139
140 for (d = local_text; *e != '\0'; e++)
141 {
142 if (*d == *e)
143 d++;
144 else
145 d = local_text;
146 if (*d == '\0')
147 {
148 result = e + 1;
149 break;
150 }
151 }
152
153 g_free (local_text);
154 return result;
155 }
156
157
158
159
160
161
162
163 static const char *
164 search_string_node (const char *start, const char *text)
165 {
166 if (start != NULL)
167 {
168 const char *d = text;
169 const char *e;
170
171 for (e = start; *e != '\0' && *e != CHAR_NODE_END; e++)
172 {
173 if (*d == *e)
174 d++;
175 else
176 d = text;
177 if (*d == '\0')
178 return e + 1;
179 }
180 }
181
182 return NULL;
183 }
184
185
186
187
188
189
190 static const char *
191 search_char_node (const char *start, char the_char, int direction)
192 {
193 const char *e;
194
195 for (e = start; (*e != '\0') && (*e != CHAR_NODE_END); e += direction)
196 if (*e == the_char)
197 return e;
198
199 return NULL;
200 }
201
202
203
204
205 static const char *
206 move_forward2 (const char *c, int lines)
207 {
208 const char *p;
209 int line;
210
211 currentpoint = c;
212 for (line = 0, p = currentpoint; (*p != '\0') && (*p != CHAR_NODE_END); str_cnext_char (&p))
213 {
214 if (line == lines)
215 return currentpoint = p;
216
217 if (*p == '\n')
218 line++;
219 }
220 return currentpoint = c;
221 }
222
223
224
225 static const char *
226 move_backward2 (const char *c, int lines)
227 {
228 const char *p;
229 int line;
230
231 currentpoint = c;
232 for (line = 0, p = currentpoint; (*p != '\0') && ((int) (p - fdata) >= 0); str_cprev_char (&p))
233 {
234 if (*p == CHAR_NODE_END)
235 {
236
237
238 while (*p != ']')
239 str_cnext_char (&p);
240 return currentpoint = p + 2;
241 }
242
243 if (*(p - 1) == '\n')
244 line++;
245 if (line == lines)
246 return currentpoint = p;
247 }
248 return currentpoint = c;
249 }
250
251
252
253 static void
254 move_forward (int i)
255 {
256 if (!end_of_node)
257 currentpoint = move_forward2 (currentpoint, i);
258 }
259
260
261
262 static void
263 move_backward (int i)
264 {
265 currentpoint = move_backward2 (currentpoint, ++i);
266 }
267
268
269
270 static void
271 move_to_top (void)
272 {
273 while (((int) (currentpoint - fdata) > 0) && (*currentpoint != CHAR_NODE_END))
274 currentpoint--;
275
276 while (*currentpoint != ']')
277 currentpoint++;
278 currentpoint = currentpoint + 2;
279 selected_item = NULL;
280 }
281
282
283
284 static void
285 move_to_bottom (void)
286 {
287 while ((*currentpoint != '\0') && (*currentpoint != CHAR_NODE_END))
288 currentpoint++;
289 currentpoint--;
290 move_backward (1);
291 }
292
293
294
295 static const char *
296 help_follow_link (const char *start, const char *lc_selected_item)
297 {
298 const char *p;
299
300 if (lc_selected_item == NULL)
301 return start;
302
303 for (p = lc_selected_item; *p != '\0' && *p != CHAR_NODE_END && *p != CHAR_LINK_POINTER; p++)
304 ;
305 if (*p == CHAR_LINK_POINTER)
306 {
307 int i;
308 char link_name[MAXLINKNAME];
309
310 link_name[0] = '[';
311 for (i = 1;
312 *p != CHAR_LINK_END && *p != '\0' && *p != CHAR_NODE_END && i < MAXLINKNAME - 3;)
313 link_name[i++] = *++p;
314 link_name[i - 1] = ']';
315 link_name[i] = '\0';
316 p = search_string (fdata, link_name);
317 if (p != NULL)
318 {
319 p += 1;
320 return p;
321 }
322 }
323
324
325 return _ ("Help file format error\n");
326 }
327
328
329
330 static const char *
331 select_next_link (const char *current_link)
332 {
333 const char *p;
334
335 if (current_link == NULL)
336 return NULL;
337
338 p = search_string_node (current_link, STRING_LINK_END);
339 if (p == NULL)
340 return NULL;
341 p = search_string_node (p, STRING_LINK_START);
342 if (p == NULL)
343 return NULL;
344 return p - 1;
345 }
346
347
348
349 static const char *
350 select_prev_link (const char *current_link)
351 {
352 return current_link == NULL ? NULL : search_char_node (current_link - 1, CHAR_LINK_START, -1);
353 }
354
355
356
357 static void
358 start_link_area (int x, int y, const char *link_name)
359 {
360 Link_Area *la;
361
362 if (inside_link_area)
363 message (D_NORMAL, _ ("Warning"), "%s", _ ("Internal bug: Double start of link area"));
364
365
366 la = g_new (Link_Area, 1);
367
368 la->x1 = x;
369 la->y1 = y;
370
371 la->link_name = link_name;
372 link_area = g_slist_prepend (link_area, la);
373
374 inside_link_area = TRUE;
375 }
376
377
378
379 static void
380 end_link_area (int x, int y)
381 {
382 if (inside_link_area)
383 {
384 Link_Area *la = (Link_Area *) link_area->data;
385
386 la->x2 = x;
387 la->y2 = y;
388 inside_link_area = FALSE;
389 }
390 }
391
392
393
394 static void
395 clear_link_areas (void)
396 {
397 g_clear_slist (&link_area, g_free);
398 inside_link_area = FALSE;
399 }
400
401
402
403 static void
404 help_print_word (WDialog *h, GString *word, int *col, int *line, gboolean add_space)
405 {
406 if (*line >= help_lines)
407 g_string_set_size (word, 0);
408 else
409 {
410 int w;
411
412 w = str_term_width1 (word->str);
413 if (*col + w >= HELP_WINDOW_WIDTH)
414 {
415 *col = 0;
416 (*line)++;
417 }
418
419 if (*line >= help_lines)
420 g_string_set_size (word, 0);
421 else
422 {
423 widget_gotoyx (h, *line + 2, *col + 2);
424 tty_print_string (word->str);
425 g_string_set_size (word, 0);
426 *col += w;
427 }
428 }
429
430 if (add_space)
431 {
432 if (*col < HELP_WINDOW_WIDTH - 1)
433 {
434 tty_print_char (' ');
435 (*col)++;
436 }
437 else
438 {
439 *col = 0;
440 (*line)++;
441 }
442 }
443 }
444
445
446
447 static mc_tty_char_t
448 mc_acs_map (int c)
449 {
450 switch (c)
451 {
452 case 'q':
453 return mc_global.tty.ugly_line_drawing ? '-'
454 : mc_global.utf8_display ? 0x2500
455 : MC_ACS_HLINE;
456 case 'x':
457 return mc_global.tty.ugly_line_drawing ? '|'
458 : mc_global.utf8_display ? 0x2502
459 : MC_ACS_VLINE;
460 case 'l':
461 return mc_global.tty.ugly_line_drawing ? '+'
462 : mc_global.utf8_display ? 0x250C
463 : MC_ACS_ULCORNER;
464 case 'k':
465 return mc_global.tty.ugly_line_drawing ? '+'
466 : mc_global.utf8_display ? 0x2510
467 : MC_ACS_URCORNER;
468 case 'm':
469 return mc_global.tty.ugly_line_drawing ? '+'
470 : mc_global.utf8_display ? 0x2514
471 : MC_ACS_LLCORNER;
472 case 'j':
473 return mc_global.tty.ugly_line_drawing ? '+'
474 : mc_global.utf8_display ? 0x2518
475 : MC_ACS_LRCORNER;
476 case 't':
477 return mc_global.tty.ugly_line_drawing ? '|'
478 : mc_global.utf8_display ? 0x251C
479 : MC_ACS_LTEE;
480 case 'u':
481 return mc_global.tty.ugly_line_drawing ? '|'
482 : mc_global.utf8_display ? 0x2524
483 : MC_ACS_RTEE;
484 case 'w':
485 return mc_global.tty.ugly_line_drawing ? '-'
486 : mc_global.utf8_display ? 0x252C
487 : MC_ACS_TTEE;
488 case 'v':
489 return mc_global.tty.ugly_line_drawing ? '-'
490 : mc_global.utf8_display ? 0x2534
491 : MC_ACS_BTEE;
492 case 'n':
493 return mc_global.tty.ugly_line_drawing ? '+'
494 : mc_global.utf8_display ? 0x253C
495 : MC_ACS_PLUS;
496
497 default:
498 return c;
499 }
500 }
501
502
503
504 static void
505 help_show (WDialog *h, const char *paint_start)
506 {
507 gboolean painting = TRUE;
508 gboolean repeat_paint;
509 int active_col, active_line;
510 char buff[MB_LEN_MAX + 1];
511 GString *word;
512
513 word = g_string_sized_new (32);
514
515 tty_setcolor (HELP_NORMAL_COLOR);
516 do
517 {
518 int line = 0;
519 int col = 0;
520 gboolean acs = FALSE;
521 const char *p, *n;
522
523 active_col = 0;
524 active_line = 0;
525
526 repeat_paint = FALSE;
527
528 clear_link_areas ();
529 if ((int) (selected_item - paint_start) < 0)
530 selected_item = NULL;
531
532 p = paint_start;
533 n = paint_start;
534 while ((n[0] != '\0') && (n[0] != CHAR_NODE_END) && (line < help_lines))
535 {
536 int c;
537
538 p = n;
539 n = str_cget_next_char (p);
540 memcpy (buff, p, n - p);
541 buff[n - p] = '\0';
542
543 c = (unsigned char) buff[0];
544 switch (c)
545 {
546 case CHAR_LINK_START:
547 if (selected_item == NULL)
548 selected_item = p;
549 if (p != selected_item)
550 tty_setcolor (HELP_LINK_COLOR);
551 else
552 {
553 tty_setcolor (HELP_SLINK_COLOR);
554
555
556 active_col = col + 2;
557 active_line = line + 2;
558 }
559 start_link_area (col, line, p);
560 break;
561 case CHAR_LINK_POINTER:
562 painting = FALSE;
563 break;
564 case CHAR_LINK_END:
565 painting = TRUE;
566 help_print_word (h, word, &col, &line, FALSE);
567 end_link_area (col - 1, line);
568 tty_setcolor (HELP_NORMAL_COLOR);
569 break;
570 case CHAR_ALTERNATE:
571 acs = TRUE;
572 break;
573 case CHAR_NORMAL:
574 acs = FALSE;
575 break;
576 case CHAR_VERSION:
577 widget_gotoyx (h, line + 2, col + 2);
578 tty_print_string (mc_global.mc_version);
579 col += str_term_width1 (mc_global.mc_version);
580 break;
581 case CHAR_FONT_BOLD:
582 tty_setcolor (HELP_BOLD_COLOR);
583 break;
584 case CHAR_FONT_ITALIC:
585 tty_setcolor (HELP_ITALIC_COLOR);
586 break;
587 case CHAR_FONT_NORMAL:
588 help_print_word (h, word, &col, &line, FALSE);
589 tty_setcolor (HELP_NORMAL_COLOR);
590 break;
591 case '\n':
592 if (painting)
593 help_print_word (h, word, &col, &line, FALSE);
594 line++;
595 col = 0;
596 break;
597 case ' ':
598 case '\t':
599
600 if (painting)
601 {
602 help_print_word (h, word, &col, &line, c == ' ');
603 if (c == '\t')
604 {
605 col = (col / 8 + 1) * 8;
606 if (col >= HELP_WINDOW_WIDTH)
607 {
608 line++;
609 col = 8;
610 }
611 }
612 }
613 break;
614 default:
615 if (painting && (line < help_lines))
616 {
617 if (!acs)
618
619 g_string_append (word, buff);
620 else if (col < HELP_WINDOW_WIDTH)
621 {
622 widget_gotoyx (h, line + 2, col + 2);
623 tty_print_char (mc_acs_map (c));
624 col++;
625 }
626 }
627 }
628 }
629
630
631 if (n[0] == CHAR_NODE_END)
632 help_print_word (h, word, &col, &line, FALSE);
633
634 last_shown = p;
635 end_of_node = line < help_lines;
636 tty_setcolor (HELP_NORMAL_COLOR);
637 if ((int) (selected_item - last_shown) >= 0)
638 {
639 if ((link_area == NULL) || (link_area->data == NULL))
640 selected_item = NULL;
641 else
642 {
643 selected_item = ((Link_Area *) link_area->data)->link_name;
644 repeat_paint = TRUE;
645 }
646 }
647 }
648 while (repeat_paint);
649
650 g_string_free (word, TRUE);
651
652
653 if (active_col != 0)
654 widget_gotoyx (h, active_line, active_col);
655 }
656
657
658
659
660 static void
661 help_help (WDialog *h)
662 {
663 const char *p;
664
665 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
666 history[history_ptr].page = currentpoint;
667 history[history_ptr].link = selected_item;
668
669 p = search_string (fdata, "[How to use help]");
670 if (p != NULL)
671 {
672 currentpoint = p + 1;
673 selected_item = NULL;
674 widget_draw (WIDGET (h));
675 }
676 }
677
678
679
680 static void
681 help_index (WDialog *h)
682 {
683 const char *new_item;
684
685 new_item = search_string (fdata, "[Contents]");
686
687 if (new_item == NULL)
688 message (D_ERROR, MSG_ERROR, _ ("Cannot find node %s in help file"), "[Contents]");
689 else
690 {
691 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
692 history[history_ptr].page = currentpoint;
693 history[history_ptr].link = selected_item;
694
695 currentpoint = new_item + 1;
696 selected_item = NULL;
697 widget_draw (WIDGET (h));
698 }
699 }
700
701
702
703 static void
704 help_back (WDialog *h)
705 {
706 currentpoint = history[history_ptr].page;
707 selected_item = history[history_ptr].link;
708 history_ptr--;
709 if (history_ptr < 0)
710 history_ptr = HISTORY_SIZE - 1;
711
712 widget_draw (WIDGET (h));
713 }
714
715
716
717 static void
718 help_next_link (gboolean move_down)
719 {
720 const char *new_item;
721
722 new_item = select_next_link (selected_item);
723 if (new_item != NULL)
724 {
725 selected_item = new_item;
726 if ((int) (selected_item - last_shown) >= 0)
727 {
728 if (move_down)
729 move_forward (1);
730 else
731 selected_item = NULL;
732 }
733 }
734 else if (move_down)
735 move_forward (1);
736 else
737 selected_item = NULL;
738 }
739
740
741
742 static void
743 help_prev_link (gboolean move_up)
744 {
745 const char *new_item;
746
747 new_item = select_prev_link (selected_item);
748 selected_item = new_item;
749 if ((selected_item == NULL) || (selected_item < currentpoint))
750 {
751 if (move_up)
752 move_backward (1);
753 else if ((link_area != NULL) && (link_area->data != NULL))
754 selected_item = ((Link_Area *) link_area->data)->link_name;
755 else
756 selected_item = NULL;
757 }
758 }
759
760
761
762 static void
763 help_next_node (void)
764 {
765 const char *new_item;
766
767 new_item = currentpoint;
768 while ((*new_item != '\0') && (*new_item != CHAR_NODE_END))
769 new_item++;
770
771 if (*++new_item == '[')
772 while (*++new_item != '\0')
773 if ((*new_item == ']') && (*++new_item != '\0') && (*++new_item != '\0'))
774 {
775 currentpoint = new_item;
776 selected_item = NULL;
777 break;
778 }
779 }
780
781
782
783 static void
784 help_prev_node (void)
785 {
786 const char *new_item;
787
788 new_item = currentpoint;
789 while (((int) (new_item - fdata) > 1) && (*new_item != CHAR_NODE_END))
790 new_item--;
791 new_item--;
792 while (((int) (new_item - fdata) > 0) && (*new_item != CHAR_NODE_END))
793 new_item--;
794 while (*new_item != ']')
795 new_item++;
796 currentpoint = new_item + 2;
797 selected_item = NULL;
798 }
799
800
801
802 static void
803 help_select_link (void)
804 {
805
806 if (selected_item == NULL)
807 {
808 #ifdef WE_WANT_TO_GO_BACKWARD_ON_KEY_RIGHT
809
810
811
812
813
814 history_ptr--;
815 if (history_ptr < 0)
816 history_ptr = HISTORY_SIZE - 1;
817
818 currentpoint = history[history_ptr].page;
819 selected_item = history[history_ptr].link;
820 #endif
821 }
822 else
823 {
824 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
825 history[history_ptr].page = currentpoint;
826 history[history_ptr].link = selected_item;
827 currentpoint = help_follow_link (currentpoint, selected_item);
828 }
829
830 selected_item = NULL;
831 }
832
833
834
835 static cb_ret_t
836 help_execute_cmd (long command)
837 {
838 cb_ret_t ret = MSG_HANDLED;
839
840 switch (command)
841 {
842 case CK_Help:
843 help_help (whelp);
844 break;
845 case CK_Index:
846 help_index (whelp);
847 break;
848 case CK_Back:
849 help_back (whelp);
850 break;
851 case CK_Up:
852 help_prev_link (TRUE);
853 break;
854 case CK_Down:
855 help_next_link (TRUE);
856 break;
857 case CK_PageDown:
858 move_forward (help_lines - 1);
859 break;
860 case CK_PageUp:
861 move_backward (help_lines - 1);
862 break;
863 case CK_HalfPageDown:
864 move_forward (help_lines / 2);
865 break;
866 case CK_HalfPageUp:
867 move_backward (help_lines / 2);
868 break;
869 case CK_Top:
870 move_to_top ();
871 break;
872 case CK_Bottom:
873 move_to_bottom ();
874 break;
875 case CK_Enter:
876 help_select_link ();
877 break;
878 case CK_LinkNext:
879 help_next_link (FALSE);
880 break;
881 case CK_LinkPrev:
882 help_prev_link (FALSE);
883 break;
884 case CK_NodeNext:
885 help_next_node ();
886 break;
887 case CK_NodePrev:
888 help_prev_node ();
889 break;
890 case CK_Quit:
891 dlg_close (whelp);
892 break;
893 default:
894 ret = MSG_NOT_HANDLED;
895 }
896
897 return ret;
898 }
899
900
901
902 static cb_ret_t
903 help_handle_key (WDialog *h, int key)
904 {
905 Widget *w = WIDGET (h);
906 long command;
907
908 command = widget_lookup_key (w, key);
909 if (command == CK_IgnoreKey)
910 return MSG_NOT_HANDLED;
911
912 return help_execute_cmd (command);
913 }
914
915
916
917 static cb_ret_t
918 help_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
919 {
920 switch (msg)
921 {
922 case MSG_DRAW:
923 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
924 help_show (DIALOG (w->owner), currentpoint);
925 return MSG_HANDLED;
926
927 default:
928 return frame_callback (w, sender, msg, parm, data);
929 }
930 }
931
932
933
934 static cb_ret_t
935 help_resize (WDialog *h)
936 {
937 Widget *w = WIDGET (h);
938 WButtonBar *bb;
939 WRect r = w->rect;
940
941 help_lines = MIN (LINES - 4, MAX (2 * LINES / 3, 18));
942 r.lines = help_lines + 4;
943 r.cols = HELP_WINDOW_WIDTH + 4;
944 dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
945 bb = buttonbar_find (h);
946 widget_set_size (WIDGET (bb), LINES - 1, 0, 1, COLS);
947
948 return MSG_HANDLED;
949 }
950
951
952
953 static cb_ret_t
954 help_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
955 {
956 WDialog *h = DIALOG (w);
957
958 switch (msg)
959 {
960 case MSG_RESIZE:
961 return help_resize (h);
962
963 case MSG_KEY:
964 {
965 cb_ret_t ret;
966
967 ret = help_handle_key (h, parm);
968 if (ret == MSG_HANDLED)
969 widget_draw (w);
970
971 return ret;
972 }
973
974 case MSG_ACTION:
975
976 return help_execute_cmd (parm);
977
978 default:
979 return dlg_default_callback (w, sender, msg, parm, data);
980 }
981 }
982
983
984
985 static void
986 interactive_display_finish (void)
987 {
988 clear_link_areas ();
989 }
990
991
992
993
994 static void
995 translate_file (char *filedata)
996 {
997 GIConv conv;
998
999 conv = str_crt_conv_from ("UTF-8");
1000 if (conv != INVALID_CONV)
1001 {
1002 GString *translated_data;
1003 gboolean nok;
1004
1005 g_free (fdata);
1006
1007
1008 translated_data = g_string_sized_new (32 * 1024);
1009 nok = (str_convert (conv, filedata, translated_data) == ESTR_FAILURE);
1010 fdata = g_string_free (translated_data, nok);
1011
1012 str_close_conv (conv);
1013 }
1014 }
1015
1016
1017
1018 static cb_ret_t
1019 md_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
1020 {
1021 switch (msg)
1022 {
1023 case MSG_RESIZE:
1024 widget_default_callback (w, NULL, MSG_RESIZE, 0, data);
1025 w->rect.lines = help_lines;
1026 return MSG_HANDLED;
1027
1028 default:
1029 return widget_default_callback (w, sender, msg, parm, data);
1030 }
1031 }
1032
1033
1034
1035 static void
1036 help_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
1037 {
1038 int x, y;
1039 GSList *current_area;
1040
1041 if (msg != MSG_MOUSE_CLICK)
1042 return;
1043
1044 if ((event->buttons & GPM_B_RIGHT) != 0)
1045 {
1046
1047 help_back (whelp);
1048 return;
1049 }
1050
1051
1052
1053
1054 x = event->x - 1;
1055 y = event->y - 1;
1056
1057
1058 for (current_area = link_area; current_area != NULL; current_area = g_slist_next (current_area))
1059 {
1060 Link_Area *la = (Link_Area *) current_area->data;
1061
1062
1063 if (y == la->y1 && x >= la->x1 && y == la->y2 && x <= la->x2)
1064 break;
1065
1066
1067 if (la->y1 + 1 == la->y2)
1068 {
1069
1070 if ((y == la->y1 && x >= la->x1) || (y == la->y2 && x <= la->x2))
1071 break;
1072 }
1073
1074 }
1075
1076
1077 if (current_area != NULL)
1078 {
1079 Link_Area *la = (Link_Area *) current_area->data;
1080
1081
1082 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
1083 history[history_ptr].page = currentpoint;
1084 history[history_ptr].link = la->link_name;
1085 currentpoint = help_follow_link (currentpoint, la->link_name);
1086 selected_item = NULL;
1087 }
1088 else if (y < 0)
1089 move_backward (help_lines - 1);
1090 else if (y >= help_lines)
1091 move_forward (help_lines - 1);
1092 else if (y < help_lines / 2)
1093 move_backward (1);
1094 else
1095 move_forward (1);
1096
1097
1098 widget_draw (WIDGET (w->owner));
1099 }
1100
1101
1102
1103 static Widget *
1104 mousedispatch_new (const WRect *r)
1105 {
1106 Widget *w;
1107
1108 w = g_new0 (Widget, 1);
1109 widget_init (w, r, md_callback, help_mouse_callback);
1110 w->options |= WOP_SELECTABLE | WOP_WANT_CURSOR;
1111
1112 return w;
1113 }
1114
1115
1116
1117
1118
1119
1120 gboolean
1121 help_interactive_display (const gchar *event_group_name, const gchar *event_name,
1122 gpointer init_data, gpointer data)
1123 {
1124 Widget *wh;
1125 WGroup *g;
1126 WButtonBar *help_bar;
1127 Widget *md;
1128 char *hlpfile = NULL;
1129 char *filedata;
1130 ev_help_t *event_data = (ev_help_t *) data;
1131 WRect r = { 1, 1, 1, 1 };
1132 int i;
1133
1134 (void) event_group_name;
1135 (void) event_name;
1136 (void) init_data;
1137
1138 if (event_data->filename != NULL)
1139 g_file_get_contents (event_data->filename, &filedata, NULL, NULL);
1140 else
1141 filedata = load_mc_home_file (mc_global.share_data_dir, MC_HELP, &hlpfile, NULL);
1142
1143 if (filedata == NULL)
1144 file_error_message (_ ("Cannot open file\n%s"),
1145 event_data->filename ? event_data->filename : hlpfile);
1146
1147 g_free (hlpfile);
1148
1149 if (filedata == NULL)
1150 return TRUE;
1151
1152 translate_file (filedata);
1153
1154 g_free (filedata);
1155
1156 if (fdata == NULL)
1157 return TRUE;
1158
1159 if ((event_data->node == NULL) || (*event_data->node == '\0'))
1160 event_data->node = "[main]";
1161
1162 main_node = search_string (fdata, event_data->node);
1163
1164 if (main_node == NULL)
1165 {
1166 message (D_ERROR, MSG_ERROR, _ ("Cannot find node %s in help file"), event_data->node);
1167
1168
1169 main_node = search_string (fdata, "[main]");
1170 if (main_node == NULL)
1171 {
1172 interactive_display_finish ();
1173 return TRUE;
1174 }
1175 }
1176
1177 help_lines = MIN (LINES - 4, MAX (2 * LINES / 3, 18));
1178
1179 whelp = dlg_create (TRUE, 0, 0, help_lines + 4, HELP_WINDOW_WIDTH + 4, WPOS_CENTER | WPOS_TRYUP,
1180 FALSE, help_colors, help_callback, NULL, "[Help]", _ ("Help"));
1181 wh = WIDGET (whelp);
1182 g = GROUP (whelp);
1183 wh->keymap = help_map;
1184 widget_want_tab (wh, TRUE);
1185
1186 whelp->bg->callback = help_bg_callback;
1187
1188 selected_item = search_string_node (main_node, STRING_LINK_START) - 1;
1189 currentpoint = main_node + 1;
1190
1191 for (i = HISTORY_SIZE - 1; i >= 0; i--)
1192 {
1193 history[i].page = currentpoint;
1194 history[i].link = selected_item;
1195 }
1196
1197 help_bar = buttonbar_new ();
1198 WIDGET (help_bar)->rect.y -= wh->rect.y;
1199 WIDGET (help_bar)->rect.x -= wh->rect.x;
1200
1201 r.lines = help_lines;
1202 r.cols = HELP_WINDOW_WIDTH - 2;
1203 md = mousedispatch_new (&r);
1204
1205 group_add_widget (g, md);
1206 group_add_widget (g, help_bar);
1207
1208 buttonbar_set_label (help_bar, 1, Q_ ("ButtonBar|Help"), wh->keymap, NULL);
1209 buttonbar_set_label (help_bar, 2, Q_ ("ButtonBar|Index"), wh->keymap, NULL);
1210 buttonbar_set_label (help_bar, 3, Q_ ("ButtonBar|Prev"), wh->keymap, NULL);
1211 buttonbar_set_label (help_bar, 4, "", wh->keymap, NULL);
1212 buttonbar_set_label (help_bar, 5, "", wh->keymap, NULL);
1213 buttonbar_set_label (help_bar, 6, "", wh->keymap, NULL);
1214 buttonbar_set_label (help_bar, 7, "", wh->keymap, NULL);
1215 buttonbar_set_label (help_bar, 8, "", wh->keymap, NULL);
1216 buttonbar_set_label (help_bar, 9, "", wh->keymap, NULL);
1217 buttonbar_set_label (help_bar, 10, Q_ ("ButtonBar|Quit"), wh->keymap, NULL);
1218
1219 dlg_run (whelp);
1220 interactive_display_finish ();
1221 widget_destroy (wh);
1222 return TRUE;
1223 }
1224
1225