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