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