~ubuntu-branches/ubuntu/maverick/texinfo/maverick

« back to all changes in this revision

Viewing changes to info/infodoc.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2005-10-28 15:10:30 UTC
  • mto: (2.1.1 dapper) (3.1.4 hardy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051028151030-9nsf2s2k2z3fktjt
Tags: upstream-4.8
ImportĀ upstreamĀ versionĀ 4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* infodoc.c -- Functions which build documentation nodes.
2
 
   $Id: infodoc.c,v 1.28 2002/02/27 13:37:33 karl Exp $
 
1
/* infodoc.c -- functions which build documentation nodes.
 
2
   $Id: infodoc.c,v 1.8 2004/04/11 17:56:45 karl Exp $
3
3
 
4
 
   Copyright (C) 1993, 97, 98, 99, 2001, 02 Free Software Foundation, Inc.
 
4
   Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software
 
5
   Foundation, Inc.
5
6
 
6
7
   This program is free software; you can redistribute it and/or modify
7
8
   it under the terms of the GNU General Public License as published by
36
37
static char *internal_info_help_node_contents = (char *)NULL;
37
38
 
38
39
/* The (more or less) static text which appears in the internal info
39
 
   help node.  The actual key bindings are inserted.  Keep the 
 
40
   help node.  The actual key bindings are inserted.  Keep the
40
41
   underlines (****, etc.) in the same N_ call as  the text lines they
41
42
   refer to, so translations can make the number of *'s or -'s match.  */
42
43
#if defined(INFOKEY)
66
67
  "\n",
67
68
  N_("Moving within a node:\n\
68
69
---------------------\n"),
 
70
  N_("\\%-10[beginning-of-node]  Go to the beginning of this node.\n"),
 
71
  N_("\\%-10[end-of-node]  Go to the end of this node.\n"),
 
72
  N_("\\%-10[next-line]  Scroll forward 1 line.\n"),
 
73
  N_("\\%-10[prev-line]  Scroll backward 1 line.\n"),
69
74
  N_("\\%-10[scroll-forward]  Scroll forward a page.\n"),
70
75
  N_("\\%-10[scroll-backward]  Scroll backward a page.\n"),
71
 
  N_("\\%-10[beginning-of-node]  Go to the beginning of this node.\n"),
72
 
  N_("\\%-10[end-of-node]  Go to the end of this node.\n"),
73
 
  N_("\\%-10[scroll-forward]  Scroll forward 1 line.\n"),
74
 
  N_("\\%-10[scroll-backward]  Scroll backward 1 line.\n"),
75
76
  "\n",
76
77
  N_("Other commands:\n\
77
78
---------------\n"),
184
185
 
185
186
#endif /* !INFOKEY */
186
187
 
187
 
static char *where_is_internal ();
 
188
static char *where_is_internal (Keymap map, InfoCommand *cmd);
188
189
 
189
190
void
190
 
dump_map_to_message_buffer (prefix, map)
191
 
     char *prefix;
192
 
     Keymap map;
 
191
dump_map_to_message_buffer (char *prefix, Keymap map)
193
192
{
194
193
  register int i;
195
194
  unsigned prefix_len = strlen (prefix);
225
224
 
226
225
          if (last - 1 != i)
227
226
            {
228
 
              printf_to_message_buffer ("%s .. ", pretty_keyseq (new_prefix));
229
 
              new_prefix[prefix_len] = last - 1;
230
 
              printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix));
 
227
              printf_to_message_buffer ("%s .. ", pretty_keyseq (new_prefix),
 
228
                  NULL, NULL);
 
229
              new_prefix[prefix_len] = last - 1;
 
230
              printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix),
 
231
                  NULL, NULL);
231
232
              i = last - 1;
232
233
            }
233
234
          else
234
 
            printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix));
 
235
            printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix),
 
236
                NULL, NULL);
235
237
 
236
238
#if defined (NAMED_FUNCTIONS)
237
239
          /* Print the name of the function, and some padding before the
240
242
            int length_so_far;
241
243
            int desired_doc_start = 40; /* Must be multiple of 8. */
242
244
 
243
 
            printf_to_message_buffer ("(%s)", name);
 
245
            printf_to_message_buffer ("(%s)", name, NULL, NULL);
244
246
            length_so_far = message_buffer_length_this_line ();
245
247
 
246
 
            if ((desired_doc_start + strlen (doc)) >= the_screen->width)
247
 
              printf_to_message_buffer ("\n     ");
 
248
            if ((desired_doc_start + strlen (doc))
 
249
                >= (unsigned int) the_screen->width)
 
250
              printf_to_message_buffer ("\n     ", NULL, NULL, NULL);
248
251
            else
249
252
              {
250
253
                while (length_so_far < desired_doc_start)
251
254
                  {
252
 
                    printf_to_message_buffer ("\t");
 
255
                    printf_to_message_buffer ("\t", NULL, NULL, NULL);
253
256
                    length_so_far += character_width ('\t', length_so_far);
254
257
                  }
255
258
              }
256
259
          }
257
260
#endif /* NAMED_FUNCTIONS */
258
 
          printf_to_message_buffer ("%s\n", doc);
 
261
          printf_to_message_buffer ("%s\n", doc, NULL, NULL);
259
262
        }
260
263
    }
261
264
  free (new_prefix);
268
271
   make q do the right thing in both cases.  */
269
272
 
270
273
static void
271
 
create_internal_info_help_node (help_is_only_window_p)
272
 
     int help_is_only_window_p;
 
274
create_internal_info_help_node (int help_is_only_window_p)
273
275
{
274
276
  register int i;
275
277
  NODE *node;
290
292
      for (i = 0; info_internal_help_text[i]; i++)
291
293
        {
292
294
#ifdef INFOKEY
293
 
          printf_to_message_buffer (replace_in_documentation (
294
 
           _(info_internal_help_text[i]), help_is_only_window_p));
 
295
          printf_to_message_buffer (replace_in_documentation
 
296
              ((char *) _(info_internal_help_text[i]), help_is_only_window_p),
 
297
              NULL, NULL, NULL);
295
298
#else
296
299
          /* Don't translate blank lines, gettext outputs the po file
297
300
             header in that case.  We want a blank line.  */
299
302
                      ? _(info_internal_help_text[i])
300
303
                      : info_internal_help_text[i];
301
304
          char *key = info_help_keys_text[i][vi_keys_p];
302
 
          
 
305
 
303
306
          /* If we have only one window (because the window size was too
304
307
             small to split it), CTRL-x 0 doesn't work to `quit' help.  */
305
308
          if (STREQ (key, "CTRL-x 0") && help_is_only_window_p)
306
309
            key = "l";
307
310
 
308
 
          printf_to_message_buffer (msg, key);
 
311
          printf_to_message_buffer (msg, key, NULL, NULL);
309
312
#endif /* !INFOKEY */
310
313
        }
311
314
 
312
 
      printf_to_message_buffer ("---------------------\n\n");
313
 
      printf_to_message_buffer (_("The current search path is:\n"));
314
 
      printf_to_message_buffer ("  %s\n", infopath);
315
 
      printf_to_message_buffer ("---------------------\n\n");
316
 
      printf_to_message_buffer (_("Commands available in Info windows:\n\n"));
 
315
      printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
 
316
      printf_to_message_buffer ((char *) _("The current search path is:\n"),
 
317
          NULL, NULL, NULL);
 
318
      printf_to_message_buffer ("  %s\n", infopath, NULL, NULL);
 
319
      printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
 
320
      printf_to_message_buffer ((char *) _("Commands available in Info windows:\n\n"),
 
321
          NULL, NULL, NULL);
317
322
      dump_map_to_message_buffer ("", info_keymap);
318
 
      printf_to_message_buffer ("---------------------\n\n");
319
 
      printf_to_message_buffer (_("Commands available in the echo area:\n\n"));
 
323
      printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
 
324
      printf_to_message_buffer ((char *) _("Commands available in the echo area:\n\n"),
 
325
          NULL, NULL, NULL);
320
326
      dump_map_to_message_buffer ("", echo_area_keymap);
321
327
 
322
328
#if defined (NAMED_FUNCTIONS)
328
334
        {
329
335
          InfoCommand *cmd = DocInfoCmd(&function_doc_array[i]);
330
336
 
331
 
          if (InfoFunction(cmd) != info_do_lowercase_version
332
 
              && !where_is_internal (info_keymap, cmd)
 
337
          if (InfoFunction(cmd) != (VFunction *) info_do_lowercase_version
 
338
              && !where_is_internal (info_keymap, cmd)
333
339
              && !where_is_internal (echo_area_keymap, cmd))
334
340
            {
335
341
              if (!printed_one_mx)
336
342
                {
337
 
                  printf_to_message_buffer ("---------------------\n\n");
338
 
                  if (exec_keys && exec_keys[0])
339
 
                      printf_to_message_buffer
340
 
                        (_("The following commands can only be invoked via %s:\n\n"), exec_keys);
341
 
                  else
342
 
                      printf_to_message_buffer
343
 
                        (_("The following commands cannot be invoked at all:\n\n"));
 
343
                  printf_to_message_buffer ("---------------------\n\n",
 
344
                      NULL, NULL, NULL);
 
345
                  if (exec_keys && exec_keys[0])
 
346
                      printf_to_message_buffer
 
347
                        ((char *) _("The following commands can only be invoked via %s:\n\n"),
 
348
                         exec_keys, NULL, NULL);
 
349
                  else
 
350
                      printf_to_message_buffer
 
351
                        ((char *) _("The following commands cannot be invoked at all:\n\n"),
 
352
                         NULL, NULL, NULL);
344
353
                  printed_one_mx = 1;
345
354
                }
346
355
 
347
356
              printf_to_message_buffer
348
357
                ("%s %s\n     %s\n",
349
 
                 exec_keys,
 
358
                 exec_keys,
350
359
                 function_doc_array[i].func_name,
351
360
                 replace_in_documentation (strlen (function_doc_array[i].doc)
352
 
                                           ? _(function_doc_array[i].doc)
353
 
                                           : "")
354
 
                );
 
361
                   ? (char *) _(function_doc_array[i].doc) : "", 0)
 
362
                );
355
363
 
356
364
            }
357
365
        }
358
366
 
359
367
      if (printed_one_mx)
360
 
        printf_to_message_buffer ("\n");
 
368
        printf_to_message_buffer ("\n", NULL, NULL, NULL);
361
369
 
362
370
      maybe_free (exec_keys);
363
371
#endif /* NAMED_FUNCTIONS */
364
372
 
365
373
      printf_to_message_buffer
366
374
        ("%s", replace_in_documentation
367
 
         (_("--- Use `\\[history-node]' or `\\[kill-node]' to exit ---\n")));
 
375
         ((char *) _("--- Use `\\[history-node]' or `\\[kill-node]' to exit ---\n"), 0),
 
376
         NULL, NULL);
368
377
      node = message_buffer_to_node ();
369
378
      internal_info_help_node_contents = node->contents;
370
379
    }
403
412
#define HELP_SPLIT_SIZE 24
404
413
 
405
414
static WINDOW *
406
 
info_find_or_create_help_window ()
 
415
info_find_or_create_help_window (void)
407
416
{
408
417
  int help_is_only_window_p;
409
418
  WINDOW *eligible = NULL;
437
446
     argument is false if help will be the only window (so l must be used
438
447
     to quit help), true if help will be one of several visible windows
439
448
     (so CTRL-x 0 must be used to quit help).  */
440
 
  help_is_only_window_p
441
 
     = (help_window && !windows->next
442
 
        || !help_window && eligible->height < HELP_SPLIT_SIZE);
 
449
  help_is_only_window_p = ((help_window && !windows->next)
 
450
        || (!help_window && eligible->height < HELP_SPLIT_SIZE));
443
451
  create_internal_info_help_node (help_is_only_window_p);
444
452
 
445
453
  /* Either use the existing window to display the help node, or create
486
494
    }
487
495
  else
488
496
    {
489
 
      info_error (msg_cant_make_help);
 
497
      info_error ((char *) msg_cant_make_help, NULL, NULL);
490
498
    }
491
499
}
492
500
 
528
536
  if (!node)
529
537
    {
530
538
      if (info_recent_file_error)
531
 
        info_error (info_recent_file_error);
 
539
        info_error (info_recent_file_error, NULL, NULL);
532
540
      else
533
 
        info_error (msg_cant_file_node, "Info", nodename);
 
541
        info_error ((char *) msg_cant_file_node, "Info", nodename);
534
542
    }
535
543
  else
536
544
    {
558
566
 
559
567
/* Return the documentation associated with the Info command FUNCTION. */
560
568
char *
561
 
function_documentation (cmd)
562
 
     InfoCommand *cmd;
 
569
function_documentation (InfoCommand *cmd)
563
570
{
564
571
  char *doc;
565
572
 
579
586
 
580
587
#endif /* !INFOKEY */
581
588
 
582
 
  return replace_in_documentation ((strlen (doc) == 0) ? doc : _(doc));
 
589
  return replace_in_documentation ((strlen (doc) == 0) ? doc : (char *) _(doc), 0);
583
590
}
584
591
 
585
592
#if defined (NAMED_FUNCTIONS)
586
593
/* Return the user-visible name of the function associated with the
587
594
   Info command FUNCTION. */
588
595
char *
589
 
function_name (cmd)
590
 
     InfoCommand *cmd;
 
596
function_name (InfoCommand *cmd)
591
597
{
592
598
#if defined (INFOKEY)
593
599
 
608
614
 
609
615
/* Return a pointer to the info command for function NAME. */
610
616
InfoCommand *
611
 
named_function (name)
612
 
     char *name;
 
617
named_function (char *name)
613
618
{
614
619
  register int i;
615
620
 
623
628
 
624
629
/* Return the documentation associated with KEY in MAP. */
625
630
char *
626
 
key_documentation (key, map)
627
 
     char key;
628
 
     Keymap map;
 
631
key_documentation (char key, Keymap map)
629
632
{
630
633
  InfoCommand *function = map[key].function;
631
634
 
647
650
 
648
651
  for (;;)
649
652
    {
650
 
      message_in_echo_area (_("Describe key: %s"), pretty_keyseq (keys));
 
653
      message_in_echo_area ((char *) _("Describe key: %s"),
 
654
          pretty_keyseq (keys), NULL);
651
655
      keystroke = info_get_input_char ();
652
656
      unmessage_in_echo_area ();
653
657
 
661
665
              return;
662
666
            }
663
667
 
664
 
          *k++ = '\e';
 
668
          *k++ = '\e';
665
669
          keystroke = UnMeta (keystroke);
666
670
          map = (Keymap)map[ESC].function;
667
671
        }
673
677
 
674
678
      if (map[keystroke].function == (InfoCommand *)NULL)
675
679
        {
676
 
          message_in_echo_area (_("%s is undefined."), pretty_keyseq (keys));
 
680
          message_in_echo_area ((char *) _("%s is undefined."),
 
681
              pretty_keyseq (keys), NULL);
677
682
          return;
678
683
        }
679
684
      else if (map[keystroke].type == ISKMAP)
686
691
          char *keyname, *message, *fundoc, *funname = "";
687
692
 
688
693
#if defined (INFOKEY)
689
 
          /* If the key is bound to do-lowercase-version, but its
690
 
             lower-case variant is undefined, say that this key is
691
 
             also undefined.  This is especially important for unbound
692
 
             edit keys that emit an escape sequence: it's terribly
693
 
             confusing to see a message "Home (do-lowercase-version)"
694
 
             or some such when Home is unbound.  */
695
 
          if (InfoFunction(map[keystroke].function) == info_do_lowercase_version)
696
 
            {
697
 
              unsigned char lowerkey = Meta_p(keystroke)
698
 
                                       ? Meta (tolower (UnMeta (keystroke)))
699
 
                                       : tolower (keystroke);
 
694
          /* If the key is bound to do-lowercase-version, but its
 
695
             lower-case variant is undefined, say that this key is
 
696
             also undefined.  This is especially important for unbound
 
697
             edit keys that emit an escape sequence: it's terribly
 
698
             confusing to see a message "Home (do-lowercase-version)"
 
699
             or some such when Home is unbound.  */
 
700
          if (InfoFunction(map[keystroke].function)
 
701
              == (VFunction *) info_do_lowercase_version)
 
702
            {
 
703
              unsigned char lowerkey = Meta_p(keystroke)
 
704
                                       ? Meta (tolower (UnMeta (keystroke)))
 
705
                                       : tolower (keystroke);
700
706
 
701
 
              if (map[lowerkey].function == (InfoCommand *)NULL)
702
 
                {
703
 
                  message_in_echo_area (_("%s is undefined."),
704
 
                                        pretty_keyseq (keys));
705
 
                  return;
706
 
                }
707
 
            }
 
707
              if (map[lowerkey].function == (InfoCommand *)NULL)
 
708
                {
 
709
                  message_in_echo_area ((char *) _("%s is undefined."),
 
710
                                        pretty_keyseq (keys), NULL);
 
711
                  return;
 
712
                }
 
713
            }
708
714
#endif
709
715
 
710
 
          keyname = pretty_keyseq (keys);
 
716
          keyname = pretty_keyseq (keys);
711
717
 
712
718
#if defined (NAMED_FUNCTIONS)
713
719
          funname = function_name (map[keystroke].function);
724
730
          sprintf (message, _("%s is defined to %s."), keyname, fundoc);
725
731
#endif /* !NAMED_FUNCTIONS */
726
732
 
727
 
          window_message_in_echo_area ("%s", message);
 
733
          window_message_in_echo_area ("%s", message, NULL);
728
734
          free (message);
729
735
          break;
730
736
        }
733
739
 
734
740
/* Return the pretty printable name of a single character. */
735
741
char *
736
 
pretty_keyname (key)
737
 
     unsigned char key;
 
742
pretty_keyname (unsigned char key)
738
743
{
739
744
  static char rep_buffer[30];
740
745
  char *rep;
784
789
 
785
790
/* Return the pretty printable string which represents KEYSEQ. */
786
791
 
787
 
static void pretty_keyseq_internal ();
 
792
static void pretty_keyseq_internal (char *keyseq, char *rep);
788
793
 
789
794
char *
790
 
pretty_keyseq (keyseq)
791
 
     char *keyseq;
 
795
pretty_keyseq (char *keyseq)
792
796
{
793
797
  static char keyseq_rep[200];
794
798
 
799
803
}
800
804
 
801
805
static void
802
 
pretty_keyseq_internal (keyseq, rep)
803
 
     char *keyseq, *rep;
 
806
pretty_keyseq_internal (char *keyseq, char *rep)
804
807
{
805
808
  if (term_kP && strncmp(keyseq, term_kP, strlen(term_kP)) == 0)
806
809
    {
868
871
 
869
872
/* Return a pointer to the last character in s that is found in f. */
870
873
static char *
871
 
strrpbrk (s, f)
872
 
     const char *s, *f;
 
874
strrpbrk (const char *s, const char *f)
873
875
{
874
876
  register const char *e = s + strlen(s);
875
877
  register const char *t;
878
880
    {
879
881
      for (t = f; *t; t++)
880
882
        if (*e == *t)
881
 
          return (char *)e;
 
883
          return (char *)e;
882
884
    }
883
885
  return NULL;
884
886
}
885
887
 
886
888
/* Replace the names of functions with the key that invokes them. */
887
889
char *
888
 
replace_in_documentation (string, help_is_only_window_p)
889
 
     char *string;
890
 
     int help_is_only_window_p;
 
890
replace_in_documentation (char *string, int help_is_only_window_p)
891
891
{
892
892
  unsigned reslen = strlen (string);
893
893
  register int i, start, next;
905
905
 
906
906
      /* Is this the start of a replaceable function name? */
907
907
      if (string[i] == '\\')
908
 
        {
909
 
          char *fmt = NULL;
910
 
          unsigned min = 0;
911
 
          unsigned max = 0;
912
 
 
913
 
          if(string[j] == '%')
914
 
            {
915
 
              if (string[++j] == '-')
916
 
                j++;
917
 
              if (isdigit(string[j]))
918
 
                {
919
 
                  min = atoi(string + j);
920
 
                  while (isdigit(string[j]))
921
 
                    j++;
922
 
                  if (string[j] == '.' && isdigit(string[j + 1]))
923
 
                    {
924
 
                      j += 1;
925
 
                      max = atoi(string + j);
926
 
                      while (isdigit(string[j]))
927
 
                        j++;
928
 
                    }
929
 
                  fmt = (char *)xmalloc (j - i + 2);
930
 
                  strncpy (fmt, string + i + 1, j - i);
931
 
                  fmt[j - i - 1] = 's';
932
 
                  fmt[j - i] = '\0';
933
 
                }
934
 
              else
935
 
                j = i + 1;
936
 
            }
937
 
          if (string[j] == '[')
938
 
            {
939
 
              unsigned arg = 0;
940
 
              char *argstr = NULL;
941
 
              char *rep_name, *fun_name, *rep;
942
 
              InfoCommand *command;
943
 
              char *repstr = NULL;
944
 
              unsigned replen;
945
 
 
946
 
              /* Copy in the old text. */
947
 
              strncpy (result + next, string + start, i - start);
948
 
              next += (i - start);
949
 
              start = j + 1;
950
 
 
951
 
              /* Look for an optional numeric arg. */
952
 
              i = start;
953
 
              if (isdigit(string[i])
954
 
                  || (string[i] == '-' && isdigit(string[i + 1])) )
955
 
                {
956
 
                  arg = atoi(string + i);
957
 
                  if (string[i] == '-')
958
 
                    i++;
959
 
                  while (isdigit(string[i]))
960
 
                    i++;
961
 
                }
962
 
              start = i;
963
 
 
964
 
              /* Move to the end of the function name. */
965
 
              for (i = start; string[i] && (string[i] != ']'); i++);
966
 
 
967
 
              rep_name = (char *)xmalloc (1 + i - start);
968
 
              strncpy (rep_name, string + start, i - start);
969
 
              rep_name[i - start] = '\0';
970
 
 
971
 
            /* If we have only one window (because the window size was too
972
 
               small to split it), we have to quit help by going back one
973
 
               noew in the history list, not deleting the window.  */
974
 
              if (strcmp (rep_name, "quit-help") == 0)
975
 
                fun_name = help_is_only_window_p ? "history-node"
976
 
                                                 : "delete-window";
977
 
              else
978
 
                fun_name = rep_name;
979
 
 
980
 
              /* Find a key which invokes this function in the info_keymap. */
981
 
              command = named_function (fun_name);
982
 
 
983
 
              free (rep_name);
984
 
 
985
 
              /* If the internal documentation string fails, there is a
986
 
                 serious problem with the associated command's documentation.
987
 
                 We croak so that it can be fixed immediately. */
988
 
              if (!command)
989
 
                abort ();
990
 
 
991
 
              if (arg)
992
 
                {
993
 
                  char *argrep, *p;
994
 
 
995
 
                  argrep = where_is (info_keymap, InfoCmd(info_add_digit_to_numeric_arg));
996
 
                  p = argrep ? strrpbrk (argrep, "0123456789-") : NULL;
997
 
                  if (p)
998
 
                    {
999
 
                      argstr = (char *)xmalloc (p - argrep + 21);
1000
 
                      strncpy (argstr, argrep, p - argrep);
1001
 
                      sprintf (argstr + (p - argrep), "%d", arg);
1002
 
                    }
1003
 
                  else
1004
 
                    command = NULL;
1005
 
                }
1006
 
              rep = command ? where_is (info_keymap, command) : NULL;
1007
 
              if (!rep)
1008
 
                rep = "N/A";
1009
 
              replen = (argstr ? strlen (argstr) + 1 : 0) + strlen (rep);
1010
 
              repstr = (char *)xmalloc (replen);
1011
 
              repstr[0] = '\0';
1012
 
              if (argstr)
1013
 
                {
1014
 
                  strcat(repstr, argstr);
1015
 
                  strcat(repstr, " ");
1016
 
                  free (argstr);
1017
 
                }
1018
 
              strcat(repstr, rep);
1019
 
 
1020
 
              if (fmt)
1021
 
                {
1022
 
                  if (replen > max)
1023
 
                    replen = max;
1024
 
                  if (replen < min)
1025
 
                    replen = min;
1026
 
                }
1027
 
              if (next + replen > reslen)
1028
 
                {
1029
 
                  reslen = next + replen + 1;
1030
 
                  result = (char *)xrealloc (result, reslen + 1);
1031
 
                }
1032
 
 
1033
 
              if (fmt)
1034
 
                  sprintf (result + next, fmt, repstr);
1035
 
              else
1036
 
                  strcpy (result + next, repstr);
1037
 
 
1038
 
              next = strlen (result);
1039
 
              free (repstr);
1040
 
 
1041
 
              start = i;
1042
 
              if (string[i])
1043
 
                start++;
1044
 
            }
1045
 
 
1046
 
          maybe_free (fmt);
1047
 
        }
 
908
        {
 
909
          char *fmt = NULL;
 
910
          unsigned min = 0;
 
911
          unsigned max = 0;
 
912
 
 
913
          if(string[j] == '%')
 
914
            {
 
915
              if (string[++j] == '-')
 
916
                j++;
 
917
              if (isdigit(string[j]))
 
918
                {
 
919
                  min = atoi(string + j);
 
920
                  while (isdigit(string[j]))
 
921
                    j++;
 
922
                  if (string[j] == '.' && isdigit(string[j + 1]))
 
923
                    {
 
924
                      j += 1;
 
925
                      max = atoi(string + j);
 
926
                      while (isdigit(string[j]))
 
927
                        j++;
 
928
                    }
 
929
                  fmt = (char *)xmalloc (j - i + 2);
 
930
                  strncpy (fmt, string + i + 1, j - i);
 
931
                  fmt[j - i - 1] = 's';
 
932
                  fmt[j - i] = '\0';
 
933
                }
 
934
              else
 
935
                j = i + 1;
 
936
            }
 
937
          if (string[j] == '[')
 
938
            {
 
939
              unsigned arg = 0;
 
940
              char *argstr = NULL;
 
941
              char *rep_name, *fun_name, *rep;
 
942
              InfoCommand *command;
 
943
              char *repstr = NULL;
 
944
              unsigned replen;
 
945
 
 
946
              /* Copy in the old text. */
 
947
              strncpy (result + next, string + start, i - start);
 
948
              next += (i - start);
 
949
              start = j + 1;
 
950
 
 
951
              /* Look for an optional numeric arg. */
 
952
              i = start;
 
953
              if (isdigit(string[i])
 
954
                  || (string[i] == '-' && isdigit(string[i + 1])) )
 
955
                {
 
956
                  arg = atoi(string + i);
 
957
                  if (string[i] == '-')
 
958
                    i++;
 
959
                  while (isdigit(string[i]))
 
960
                    i++;
 
961
                }
 
962
              start = i;
 
963
 
 
964
              /* Move to the end of the function name. */
 
965
              for (i = start; string[i] && (string[i] != ']'); i++);
 
966
 
 
967
              rep_name = (char *)xmalloc (1 + i - start);
 
968
              strncpy (rep_name, string + start, i - start);
 
969
              rep_name[i - start] = '\0';
 
970
 
 
971
            /* If we have only one window (because the window size was too
 
972
               small to split it), we have to quit help by going back one
 
973
               noew in the history list, not deleting the window.  */
 
974
              if (strcmp (rep_name, "quit-help") == 0)
 
975
                fun_name = help_is_only_window_p ? "history-node"
 
976
                                                 : "delete-window";
 
977
              else
 
978
                fun_name = rep_name;
 
979
 
 
980
              /* Find a key which invokes this function in the info_keymap. */
 
981
              command = named_function (fun_name);
 
982
 
 
983
              free (rep_name);
 
984
 
 
985
              /* If the internal documentation string fails, there is a
 
986
                 serious problem with the associated command's documentation.
 
987
                 We croak so that it can be fixed immediately. */
 
988
              if (!command)
 
989
                abort ();
 
990
 
 
991
              if (arg)
 
992
                {
 
993
                  char *argrep, *p;
 
994
 
 
995
                  argrep = where_is (info_keymap, InfoCmd(info_add_digit_to_numeric_arg));
 
996
                  p = argrep ? strrpbrk (argrep, "0123456789-") : NULL;
 
997
                  if (p)
 
998
                    {
 
999
                      argstr = (char *)xmalloc (p - argrep + 21);
 
1000
                      strncpy (argstr, argrep, p - argrep);
 
1001
                      sprintf (argstr + (p - argrep), "%d", arg);
 
1002
                    }
 
1003
                  else
 
1004
                    command = NULL;
 
1005
                }
 
1006
              rep = command ? where_is (info_keymap, command) : NULL;
 
1007
              if (!rep)
 
1008
                rep = "N/A";
 
1009
              replen = (argstr ? strlen (argstr) : 0) + strlen (rep) + 1;
 
1010
              repstr = (char *)xmalloc (replen);
 
1011
              repstr[0] = '\0';
 
1012
              if (argstr)
 
1013
                {
 
1014
                  strcat(repstr, argstr);
 
1015
                  strcat(repstr, " ");
 
1016
                  free (argstr);
 
1017
                }
 
1018
              strcat(repstr, rep);
 
1019
 
 
1020
              if (fmt)
 
1021
                {
 
1022
                  if (replen > max)
 
1023
                    replen = max;
 
1024
                  if (replen < min)
 
1025
                    replen = min;
 
1026
                }
 
1027
              if (next + replen > reslen)
 
1028
                {
 
1029
                  reslen = next + replen + 1;
 
1030
                  result = (char *)xrealloc (result, reslen + 1);
 
1031
                }
 
1032
 
 
1033
              if (fmt)
 
1034
                  sprintf (result + next, fmt, repstr);
 
1035
              else
 
1036
                  strcpy (result + next, repstr);
 
1037
 
 
1038
              next = strlen (result);
 
1039
              free (repstr);
 
1040
 
 
1041
              start = i;
 
1042
              if (string[i])
 
1043
                start++;
 
1044
            }
 
1045
 
 
1046
          maybe_free (fmt);
 
1047
        }
1048
1048
    }
1049
1049
  strcpy (result + next, string + start);
1050
1050
  return (result);
1057
1057
static int where_is_rep_size = 0;
1058
1058
 
1059
1059
char *
1060
 
where_is (map, cmd)
1061
 
     Keymap map;
1062
 
     InfoCommand *cmd;
 
1060
where_is (Keymap map, InfoCommand *cmd)
1063
1061
{
1064
1062
  char *rep;
1065
1063
 
1076
1074
 
1077
1075
      name = function_name (cmd);
1078
1076
      if (!name)
1079
 
        return NULL; /* no such function */
 
1077
        return NULL; /* no such function */
1080
1078
 
1081
1079
      rep = where_is_internal (map, InfoCmd(info_execute_command));
1082
1080
      if (!rep)
1092
1090
/* Return the printed rep of the keystrokes that invoke FUNCTION,
1093
1091
   as found in MAP, or NULL. */
1094
1092
static char *
1095
 
where_is_internal (map, cmd)
1096
 
     Keymap map;
1097
 
     InfoCommand *cmd;
 
1093
where_is_internal (Keymap map, InfoCommand *cmd)
1098
1094
{
1099
1095
#if defined(INFOKEY)
1100
1096
 
1107
1103
  return NULL;
1108
1104
 
1109
1105
#else /* !INFOKEY */
 
1106
  /* There is a bug in that create_internal_info_help_node calls
 
1107
     where_is_internal without setting where_is_rep_index to zero.  This
 
1108
     was found by Mandrake and reported by Thierry Vignaud
 
1109
     <tvignaud@mandrakesoft.com> around April 24, 2002.
1110
1110
 
 
1111
     I think the best fix is to make where_is_rep_index another
 
1112
     parameter to this recursively-called function, instead of a static
 
1113
     variable.  But this [!INFOKEY] branch of the code is not enabled
 
1114
     any more, so let's just skip the whole thing.  --karl, 28sep02.  */
1111
1115
  register int i;
1112
1116
 
1113
1117
  /* If the function is directly invokable in MAP, return the representation
1145
1149
#endif /* INFOKEY */
1146
1150
}
1147
1151
 
1148
 
extern char *read_function_name ();
1149
 
 
1150
1152
DECLARE_INFO_COMMAND (info_where_is,
1151
1153
   _("Show what to type to execute a given command"))
1152
1154
{
1153
1155
  char *command_name;
1154
1156
 
1155
 
  command_name = read_function_name (_("Where is command: "), window);
 
1157
  command_name = read_function_name ((char *) _("Where is command: "), window);
1156
1158
 
1157
1159
  if (!command_name)
1158
1160
    {
1174
1176
 
1175
1177
          if (!location || !location[0])
1176
1178
            {
1177
 
              info_error (_("`%s' is not on any keys"), command_name);
 
1179
              info_error ((char *) _("`%s' is not on any keys"),
 
1180
                  command_name, NULL);
1178
1181
            }
1179
1182
          else
1180
1183
            {
1181
1184
              if (strstr (location, function_name (command)))
1182
1185
                window_message_in_echo_area
1183
 
                  (_("%s can only be invoked via %s."), command_name, location);
 
1186
                  ((char *) _("%s can only be invoked via %s."),
 
1187
                   command_name, location);
1184
1188
              else
1185
1189
                window_message_in_echo_area
1186
 
                  (_("%s can be invoked via %s."), command_name, location);
 
1190
                  ((char *) _("%s can be invoked via %s."),
 
1191
                   command_name, location);
1187
1192
            }
1188
1193
        }
1189
1194
      else
1190
 
        info_error (_("There is no function named `%s'"), command_name);
 
1195
        info_error ((char *) _("There is no function named `%s'"),
 
1196
            command_name, NULL);
1191
1197
    }
1192
1198
 
1193
1199
  free (command_name);