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 #include <config.h>
49
50 #include <errno.h>
51 #include <limits.h>
52 #include <stdio.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55
56 #include "lib/global.h"
57
58 #include "lib/tty/tty.h"
59 #include "lib/skin.h"
60 #include "lib/strutil.h"
61 #include "lib/fileloc.h"
62 #include "lib/util.h"
63 #include "lib/widget.h"
64 #include "lib/event-types.h"
65
66 #include "keymap.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 void
448 help_show (WDialog *h, const char *paint_start)
449 {
450 gboolean painting = TRUE;
451 gboolean repeat_paint;
452 int active_col, active_line;
453 char buff[MB_LEN_MAX + 1];
454 GString *word;
455
456 word = g_string_sized_new (32);
457
458 tty_setcolor (HELP_NORMAL_COLOR);
459 do
460 {
461 int line = 0;
462 int col = 0;
463 gboolean acs = FALSE;
464 const char *p, *n;
465
466 active_col = 0;
467 active_line = 0;
468
469 repeat_paint = FALSE;
470
471 clear_link_areas ();
472 if ((int) (selected_item - paint_start) < 0)
473 selected_item = NULL;
474
475 p = paint_start;
476 n = paint_start;
477 while ((n[0] != '\0') && (n[0] != CHAR_NODE_END) && (line < help_lines))
478 {
479 int c;
480
481 p = n;
482 n = str_cget_next_char (p);
483 memcpy (buff, p, n - p);
484 buff[n - p] = '\0';
485
486 c = (unsigned char) buff[0];
487 switch (c)
488 {
489 case CHAR_LINK_START:
490 if (selected_item == NULL)
491 selected_item = p;
492 if (p != selected_item)
493 tty_setcolor (HELP_LINK_COLOR);
494 else
495 {
496 tty_setcolor (HELP_SLINK_COLOR);
497
498
499 active_col = col + 2;
500 active_line = line + 2;
501 }
502 start_link_area (col, line, p);
503 break;
504 case CHAR_LINK_POINTER:
505 painting = FALSE;
506 break;
507 case CHAR_LINK_END:
508 painting = TRUE;
509 help_print_word (h, word, &col, &line, FALSE);
510 end_link_area (col - 1, line);
511 tty_setcolor (HELP_NORMAL_COLOR);
512 break;
513 case CHAR_ALTERNATE:
514 acs = TRUE;
515 break;
516 case CHAR_NORMAL:
517 acs = FALSE;
518 break;
519 case CHAR_VERSION:
520 widget_gotoyx (h, line + 2, col + 2);
521 tty_print_string (mc_global.mc_version);
522 col += str_term_width1 (mc_global.mc_version);
523 break;
524 case CHAR_FONT_BOLD:
525 tty_setcolor (HELP_BOLD_COLOR);
526 break;
527 case CHAR_FONT_ITALIC:
528 tty_setcolor (HELP_ITALIC_COLOR);
529 break;
530 case CHAR_FONT_NORMAL:
531 help_print_word (h, word, &col, &line, FALSE);
532 tty_setcolor (HELP_NORMAL_COLOR);
533 break;
534 case '\n':
535 if (painting)
536 help_print_word (h, word, &col, &line, FALSE);
537 line++;
538 col = 0;
539 break;
540 case ' ':
541 case '\t':
542
543 if (painting)
544 {
545 help_print_word (h, word, &col, &line, c == ' ');
546 if (c == '\t')
547 {
548 col = (col / 8 + 1) * 8;
549 if (col >= HELP_WINDOW_WIDTH)
550 {
551 line++;
552 col = 8;
553 }
554 }
555 }
556 break;
557 default:
558 if (painting && (line < help_lines))
559 {
560 if (!acs)
561
562 g_string_append (word, buff);
563 else if (col < HELP_WINDOW_WIDTH)
564 {
565 widget_gotoyx (h, line + 2, col + 2);
566
567 if ((c == ' ') || (c == '.'))
568 tty_print_char (c);
569 else
570 #ifndef HAVE_SLANG
571 tty_print_char (acs_map[c]);
572 #else
573 SLsmg_draw_object (WIDGET (h)->rect.y + line + 2,
574 WIDGET (h)->rect.x + col + 2, c);
575 #endif
576 col++;
577 }
578 }
579 }
580 }
581
582
583 if (n[0] == CHAR_NODE_END)
584 help_print_word (h, word, &col, &line, FALSE);
585
586 last_shown = p;
587 end_of_node = line < help_lines;
588 tty_setcolor (HELP_NORMAL_COLOR);
589 if ((int) (selected_item - last_shown) >= 0)
590 {
591 if ((link_area == NULL) || (link_area->data == NULL))
592 selected_item = NULL;
593 else
594 {
595 selected_item = ((Link_Area *) link_area->data)->link_name;
596 repeat_paint = TRUE;
597 }
598 }
599 }
600 while (repeat_paint);
601
602 g_string_free (word, TRUE);
603
604
605 if (active_col != 0)
606 widget_gotoyx (h, active_line, active_col);
607 }
608
609
610
611
612 static void
613 help_help (WDialog *h)
614 {
615 const char *p;
616
617 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
618 history[history_ptr].page = currentpoint;
619 history[history_ptr].link = selected_item;
620
621 p = search_string (fdata, "[How to use help]");
622 if (p != NULL)
623 {
624 currentpoint = p + 1;
625 selected_item = NULL;
626 widget_draw (WIDGET (h));
627 }
628 }
629
630
631
632 static void
633 help_index (WDialog *h)
634 {
635 const char *new_item;
636
637 new_item = search_string (fdata, "[Contents]");
638
639 if (new_item == NULL)
640 message (D_ERROR, MSG_ERROR, _ ("Cannot find node %s in help file"), "[Contents]");
641 else
642 {
643 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
644 history[history_ptr].page = currentpoint;
645 history[history_ptr].link = selected_item;
646
647 currentpoint = new_item + 1;
648 selected_item = NULL;
649 widget_draw (WIDGET (h));
650 }
651 }
652
653
654
655 static void
656 help_back (WDialog *h)
657 {
658 currentpoint = history[history_ptr].page;
659 selected_item = history[history_ptr].link;
660 history_ptr--;
661 if (history_ptr < 0)
662 history_ptr = HISTORY_SIZE - 1;
663
664 widget_draw (WIDGET (h));
665 }
666
667
668
669 static void
670 help_next_link (gboolean move_down)
671 {
672 const char *new_item;
673
674 new_item = select_next_link (selected_item);
675 if (new_item != NULL)
676 {
677 selected_item = new_item;
678 if ((int) (selected_item - last_shown) >= 0)
679 {
680 if (move_down)
681 move_forward (1);
682 else
683 selected_item = NULL;
684 }
685 }
686 else if (move_down)
687 move_forward (1);
688 else
689 selected_item = NULL;
690 }
691
692
693
694 static void
695 help_prev_link (gboolean move_up)
696 {
697 const char *new_item;
698
699 new_item = select_prev_link (selected_item);
700 selected_item = new_item;
701 if ((selected_item == NULL) || (selected_item < currentpoint))
702 {
703 if (move_up)
704 move_backward (1);
705 else if ((link_area != NULL) && (link_area->data != NULL))
706 selected_item = ((Link_Area *) link_area->data)->link_name;
707 else
708 selected_item = NULL;
709 }
710 }
711
712
713
714 static void
715 help_next_node (void)
716 {
717 const char *new_item;
718
719 new_item = currentpoint;
720 while ((*new_item != '\0') && (*new_item != CHAR_NODE_END))
721 new_item++;
722
723 if (*++new_item == '[')
724 while (*++new_item != '\0')
725 if ((*new_item == ']') && (*++new_item != '\0') && (*++new_item != '\0'))
726 {
727 currentpoint = new_item;
728 selected_item = NULL;
729 break;
730 }
731 }
732
733
734
735 static void
736 help_prev_node (void)
737 {
738 const char *new_item;
739
740 new_item = currentpoint;
741 while (((int) (new_item - fdata) > 1) && (*new_item != CHAR_NODE_END))
742 new_item--;
743 new_item--;
744 while (((int) (new_item - fdata) > 0) && (*new_item != CHAR_NODE_END))
745 new_item--;
746 while (*new_item != ']')
747 new_item++;
748 currentpoint = new_item + 2;
749 selected_item = NULL;
750 }
751
752
753
754 static void
755 help_select_link (void)
756 {
757
758 if (selected_item == NULL)
759 {
760 #ifdef WE_WANT_TO_GO_BACKWARD_ON_KEY_RIGHT
761
762
763
764
765
766 history_ptr--;
767 if (history_ptr < 0)
768 history_ptr = HISTORY_SIZE - 1;
769
770 currentpoint = history[history_ptr].page;
771 selected_item = history[history_ptr].link;
772 #endif
773 }
774 else
775 {
776 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
777 history[history_ptr].page = currentpoint;
778 history[history_ptr].link = selected_item;
779 currentpoint = help_follow_link (currentpoint, selected_item);
780 }
781
782 selected_item = NULL;
783 }
784
785
786
787 static cb_ret_t
788 help_execute_cmd (long command)
789 {
790 cb_ret_t ret = MSG_HANDLED;
791
792 switch (command)
793 {
794 case CK_Help:
795 help_help (whelp);
796 break;
797 case CK_Index:
798 help_index (whelp);
799 break;
800 case CK_Back:
801 help_back (whelp);
802 break;
803 case CK_Up:
804 help_prev_link (TRUE);
805 break;
806 case CK_Down:
807 help_next_link (TRUE);
808 break;
809 case CK_PageDown:
810 move_forward (help_lines - 1);
811 break;
812 case CK_PageUp:
813 move_backward (help_lines - 1);
814 break;
815 case CK_HalfPageDown:
816 move_forward (help_lines / 2);
817 break;
818 case CK_HalfPageUp:
819 move_backward (help_lines / 2);
820 break;
821 case CK_Top:
822 move_to_top ();
823 break;
824 case CK_Bottom:
825 move_to_bottom ();
826 break;
827 case CK_Enter:
828 help_select_link ();
829 break;
830 case CK_LinkNext:
831 help_next_link (FALSE);
832 break;
833 case CK_LinkPrev:
834 help_prev_link (FALSE);
835 break;
836 case CK_NodeNext:
837 help_next_node ();
838 break;
839 case CK_NodePrev:
840 help_prev_node ();
841 break;
842 case CK_Quit:
843 dlg_close (whelp);
844 break;
845 default:
846 ret = MSG_NOT_HANDLED;
847 }
848
849 return ret;
850 }
851
852
853
854 static cb_ret_t
855 help_handle_key (WDialog *h, int key)
856 {
857 Widget *w = WIDGET (h);
858 long command;
859
860 command = widget_lookup_key (w, key);
861 if (command == CK_IgnoreKey)
862 return MSG_NOT_HANDLED;
863
864 return help_execute_cmd (command);
865 }
866
867
868
869 static cb_ret_t
870 help_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
871 {
872 switch (msg)
873 {
874 case MSG_DRAW:
875 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
876 help_show (DIALOG (w->owner), currentpoint);
877 return MSG_HANDLED;
878
879 default:
880 return frame_callback (w, sender, msg, parm, data);
881 }
882 }
883
884
885
886 static cb_ret_t
887 help_resize (WDialog *h)
888 {
889 Widget *w = WIDGET (h);
890 WButtonBar *bb;
891 WRect r = w->rect;
892
893 help_lines = MIN (LINES - 4, MAX (2 * LINES / 3, 18));
894 r.lines = help_lines + 4;
895 r.cols = HELP_WINDOW_WIDTH + 4;
896 dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
897 bb = buttonbar_find (h);
898 widget_set_size (WIDGET (bb), LINES - 1, 0, 1, COLS);
899
900 return MSG_HANDLED;
901 }
902
903
904
905 static cb_ret_t
906 help_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
907 {
908 WDialog *h = DIALOG (w);
909
910 switch (msg)
911 {
912 case MSG_RESIZE:
913 return help_resize (h);
914
915 case MSG_KEY:
916 {
917 cb_ret_t ret;
918
919 ret = help_handle_key (h, parm);
920 if (ret == MSG_HANDLED)
921 widget_draw (w);
922
923 return ret;
924 }
925
926 case MSG_ACTION:
927
928 return help_execute_cmd (parm);
929
930 default:
931 return dlg_default_callback (w, sender, msg, parm, data);
932 }
933 }
934
935
936
937 static void
938 interactive_display_finish (void)
939 {
940 clear_link_areas ();
941 }
942
943
944
945
946 static void
947 translate_file (char *filedata)
948 {
949 GIConv conv;
950
951 conv = str_crt_conv_from ("UTF-8");
952 if (conv != INVALID_CONV)
953 {
954 GString *translated_data;
955 gboolean nok;
956
957 g_free (fdata);
958
959
960 translated_data = g_string_sized_new (32 * 1024);
961 nok = (str_convert (conv, filedata, translated_data) == ESTR_FAILURE);
962 fdata = g_string_free (translated_data, nok);
963
964 str_close_conv (conv);
965 }
966 }
967
968
969
970 static cb_ret_t
971 md_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
972 {
973 switch (msg)
974 {
975 case MSG_RESIZE:
976 widget_default_callback (w, NULL, MSG_RESIZE, 0, data);
977 w->rect.lines = help_lines;
978 return MSG_HANDLED;
979
980 default:
981 return widget_default_callback (w, sender, msg, parm, data);
982 }
983 }
984
985
986
987 static void
988 help_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
989 {
990 int x, y;
991 GSList *current_area;
992
993 if (msg != MSG_MOUSE_CLICK)
994 return;
995
996 if ((event->buttons & GPM_B_RIGHT) != 0)
997 {
998
999 help_back (whelp);
1000 return;
1001 }
1002
1003
1004
1005
1006 x = event->x - 1;
1007 y = event->y - 1;
1008
1009
1010 for (current_area = link_area; current_area != NULL; current_area = g_slist_next (current_area))
1011 {
1012 Link_Area *la = (Link_Area *) current_area->data;
1013
1014
1015 if (y == la->y1 && x >= la->x1 && y == la->y2 && x <= la->x2)
1016 break;
1017
1018
1019 if (la->y1 + 1 == la->y2)
1020 {
1021
1022 if ((y == la->y1 && x >= la->x1) || (y == la->y2 && x <= la->x2))
1023 break;
1024 }
1025
1026 }
1027
1028
1029 if (current_area != NULL)
1030 {
1031 Link_Area *la = (Link_Area *) current_area->data;
1032
1033
1034 history_ptr = (history_ptr + 1) % HISTORY_SIZE;
1035 history[history_ptr].page = currentpoint;
1036 history[history_ptr].link = la->link_name;
1037 currentpoint = help_follow_link (currentpoint, la->link_name);
1038 selected_item = NULL;
1039 }
1040 else if (y < 0)
1041 move_backward (help_lines - 1);
1042 else if (y >= help_lines)
1043 move_forward (help_lines - 1);
1044 else if (y < help_lines / 2)
1045 move_backward (1);
1046 else
1047 move_forward (1);
1048
1049
1050 widget_draw (WIDGET (w->owner));
1051 }
1052
1053
1054
1055 static Widget *
1056 mousedispatch_new (const WRect *r)
1057 {
1058 Widget *w;
1059
1060 w = g_new0 (Widget, 1);
1061 widget_init (w, r, md_callback, help_mouse_callback);
1062 w->options |= WOP_SELECTABLE | WOP_WANT_CURSOR;
1063
1064 return w;
1065 }
1066
1067
1068
1069
1070
1071
1072 gboolean
1073 help_interactive_display (const gchar *event_group_name, const gchar *event_name,
1074 gpointer init_data, gpointer data)
1075 {
1076 const dlg_colors_t help_colors = {
1077 HELP_NORMAL_COLOR,
1078 0,
1079 HELP_BOLD_COLOR,
1080 0,
1081 HELP_TITLE_COLOR
1082 };
1083
1084 Widget *wh;
1085 WGroup *g;
1086 WButtonBar *help_bar;
1087 Widget *md;
1088 char *hlpfile = NULL;
1089 char *filedata;
1090 ev_help_t *event_data = (ev_help_t *) data;
1091 WRect r = { 1, 1, 1, 1 };
1092 int i;
1093
1094 (void) event_group_name;
1095 (void) event_name;
1096 (void) init_data;
1097
1098 if (event_data->filename != NULL)
1099 g_file_get_contents (event_data->filename, &filedata, NULL, NULL);
1100 else
1101 filedata = load_mc_home_file (mc_global.share_data_dir, MC_HELP, &hlpfile, NULL);
1102
1103 if (filedata == NULL)
1104 message (D_ERROR, MSG_ERROR, _ ("Cannot open file %s\n%s"),
1105 event_data->filename ? event_data->filename : hlpfile, unix_error_string (errno));
1106
1107 g_free (hlpfile);
1108
1109 if (filedata == NULL)
1110 return TRUE;
1111
1112 translate_file (filedata);
1113
1114 g_free (filedata);
1115
1116 if (fdata == NULL)
1117 return TRUE;
1118
1119 if ((event_data->node == NULL) || (*event_data->node == '\0'))
1120 event_data->node = "[main]";
1121
1122 main_node = search_string (fdata, event_data->node);
1123
1124 if (main_node == NULL)
1125 {
1126 message (D_ERROR, MSG_ERROR, _ ("Cannot find node %s in help file"), event_data->node);
1127
1128
1129 main_node = search_string (fdata, "[main]");
1130 if (main_node == NULL)
1131 {
1132 interactive_display_finish ();
1133 return TRUE;
1134 }
1135 }
1136
1137 help_lines = MIN (LINES - 4, MAX (2 * LINES / 3, 18));
1138
1139 whelp = dlg_create (TRUE, 0, 0, help_lines + 4, HELP_WINDOW_WIDTH + 4, WPOS_CENTER | WPOS_TRYUP,
1140 FALSE, help_colors, help_callback, NULL, "[Help]", _ ("Help"));
1141 wh = WIDGET (whelp);
1142 g = GROUP (whelp);
1143 wh->keymap = help_map;
1144 widget_want_tab (wh, TRUE);
1145
1146 whelp->bg->callback = help_bg_callback;
1147
1148 selected_item = search_string_node (main_node, STRING_LINK_START) - 1;
1149 currentpoint = main_node + 1;
1150
1151 for (i = HISTORY_SIZE - 1; i >= 0; i--)
1152 {
1153 history[i].page = currentpoint;
1154 history[i].link = selected_item;
1155 }
1156
1157 help_bar = buttonbar_new ();
1158 WIDGET (help_bar)->rect.y -= wh->rect.y;
1159 WIDGET (help_bar)->rect.x -= wh->rect.x;
1160
1161 r.lines = help_lines;
1162 r.cols = HELP_WINDOW_WIDTH - 2;
1163 md = mousedispatch_new (&r);
1164
1165 group_add_widget (g, md);
1166 group_add_widget (g, help_bar);
1167
1168 buttonbar_set_label (help_bar, 1, Q_ ("ButtonBar|Help"), wh->keymap, NULL);
1169 buttonbar_set_label (help_bar, 2, Q_ ("ButtonBar|Index"), wh->keymap, NULL);
1170 buttonbar_set_label (help_bar, 3, Q_ ("ButtonBar|Prev"), wh->keymap, NULL);
1171 buttonbar_set_label (help_bar, 4, "", wh->keymap, NULL);
1172 buttonbar_set_label (help_bar, 5, "", wh->keymap, NULL);
1173 buttonbar_set_label (help_bar, 6, "", wh->keymap, NULL);
1174 buttonbar_set_label (help_bar, 7, "", wh->keymap, NULL);
1175 buttonbar_set_label (help_bar, 8, "", wh->keymap, NULL);
1176 buttonbar_set_label (help_bar, 9, "", wh->keymap, NULL);
1177 buttonbar_set_label (help_bar, 10, Q_ ("ButtonBar|Quit"), wh->keymap, NULL);
1178
1179 dlg_run (whelp);
1180 interactive_display_finish ();
1181 widget_destroy (wh);
1182 return TRUE;
1183 }
1184
1185