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

« back to all changes in this revision

Viewing changes to info/info-utils.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
1
/* info-utils.c -- miscellanous.
2
 
   $Id: info-utils.c,v 1.7 1998/08/10 18:07:47 karl Exp $
 
2
   $Id: info-utils.c,v 1.4 2004/04/11 17:56:45 karl Exp $
3
3
 
4
 
   Copyright (C) 1993, 98 Free Software Foundation, Inc.
 
4
   Copyright (C) 1993, 1998, 2003, 2004 Free Software Foundation, Inc.
5
5
 
6
6
   This program is free software; you can redistribute it and/or modify
7
7
   it under the terms of the GNU General Public License as published by
17
17
   along with this program; if not, write to the Free Software
18
18
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
19
 
20
 
   Written by Brian Fox (bfox@ai.mit.edu). */
 
20
   Originally written by Brian Fox (bfox@ai.mit.edu). */
21
21
 
22
22
#include "info.h"
23
23
#include "info-utils.h"
37
37
   calling info_parse_xxx (). */
38
38
char *info_parsed_nodename = (char *)NULL;
39
39
 
 
40
/* Variable which holds the most recent line number parsed as a result of
 
41
   calling info_parse_xxx (). */
 
42
int info_parsed_line_number = 0;
 
43
 
40
44
/* Functions to remember a filename or nodename for later return. */
41
 
static void save_filename (), saven_filename ();
42
 
static void save_nodename (), saven_nodename ();
 
45
static void save_filename (char *filename);
 
46
static void saven_filename (char *filename, int len);
 
47
static void save_nodename (char *nodename);
 
48
static void saven_nodename (char *nodename, int len);
43
49
 
44
50
/* How to get a reference (either menu or cross). */
45
 
static REFERENCE **info_references_internal ();
 
51
static REFERENCE **info_references_internal (char *label,
 
52
    SEARCH_BINDING *binding);
46
53
 
47
54
/* Parse the filename and nodename out of STRING.  If STRING doesn't
48
55
   contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set
50
57
   non-zero, it says to allow the nodename specification to cross a
51
58
   newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */
52
59
void
53
 
info_parse_node (string, newlines_okay)
54
 
     char *string;
55
 
     int newlines_okay;
 
60
info_parse_node (char *string, int newlines_okay)
56
61
{
57
62
  register int i = 0;
58
63
 
96
101
      free (info_parsed_nodename);
97
102
      info_parsed_nodename = (char *)NULL;
98
103
    }
 
104
 
 
105
  /* Parse ``(line ...)'' part of menus, if any.  */
 
106
  {
 
107
    char *rest = string + i;
 
108
 
 
109
    /* Advance only if it's not already at end of string.  */
 
110
    if (*rest)
 
111
      rest++;
 
112
 
 
113
    /* Skip any whitespace first, and then a newline in case the item
 
114
       was so long to contain the ``(line ...)'' string in the same
 
115
       physical line.  */
 
116
    while (whitespace(*rest))
 
117
      rest++;
 
118
    if (*rest == '\n')
 
119
      {
 
120
        rest++;
 
121
        while (whitespace(*rest))
 
122
          rest++;
 
123
      }
 
124
 
 
125
    /* Are we looking at an opening parenthesis?  That can only mean
 
126
       we have a winner. :)  */
 
127
    if (strncmp (rest, "(line ", strlen ("(line ")) == 0)
 
128
      {
 
129
        rest += strlen ("(line ");
 
130
        info_parsed_line_number = strtol (rest, NULL, 0);
 
131
      }
 
132
    else
 
133
      info_parsed_line_number = 0;
 
134
  }
99
135
}
100
136
 
101
137
/* Return the node addressed by LABEL in NODE (usually one of "Prev:",
103
139
   the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain
104
140
   the information. */
105
141
void
106
 
info_parse_label (label, node)
107
 
     char *label;
108
 
     NODE *node;
 
142
info_parse_label (char *label, NODE *node)
109
143
{
110
144
  register int i;
111
145
  char *nodeline;
135
169
/* Return a NULL terminated array of REFERENCE * which represents the menu
136
170
   found in NODE.  If there is no menu in NODE, just return a NULL pointer. */
137
171
REFERENCE **
138
 
info_menu_of_node (node)
139
 
     NODE *node;
 
172
info_menu_of_node (NODE *node)
140
173
{
141
174
  long position;
142
 
  SEARCH_BINDING search;
 
175
  SEARCH_BINDING tmp_search;
143
176
  REFERENCE **menu = (REFERENCE **)NULL;
144
177
 
145
 
  search.buffer = node->contents;
146
 
  search.start = 0;
147
 
  search.end = node->nodelen;
148
 
  search.flags = S_FoldCase;
 
178
  tmp_search.buffer = node->contents;
 
179
  tmp_search.start = 0;
 
180
  tmp_search.end = node->nodelen;
 
181
  tmp_search.flags = S_FoldCase;
149
182
 
150
183
  /* Find the start of the menu. */
151
 
  position = search_forward (INFO_MENU_LABEL, &search);
 
184
  position = search_forward (INFO_MENU_LABEL, &tmp_search);
152
185
 
153
186
  if (position == -1)
154
187
    return ((REFERENCE **) NULL);
155
188
 
156
189
  /* We have the start of the menu now.  Glean menu items from the rest
157
190
     of the node. */
158
 
  search.start = position + strlen (INFO_MENU_LABEL);
159
 
  search.start += skip_line (search.buffer + search.start);
160
 
  search.start--;
161
 
  menu = info_menu_items (&search);
 
191
  tmp_search.start = position + strlen (INFO_MENU_LABEL);
 
192
  tmp_search.start += skip_line (tmp_search.buffer + tmp_search.start);
 
193
  tmp_search.start--;
 
194
  menu = info_menu_items (&tmp_search);
162
195
  return (menu);
163
196
}
164
197
 
166
199
   refrences found in NODE.  If there are no cross references in NODE, just
167
200
   return a NULL pointer. */
168
201
REFERENCE **
169
 
info_xrefs_of_node (node)
170
 
     NODE *node;
 
202
info_xrefs_of_node (NODE *node)
171
203
{
172
 
  SEARCH_BINDING search;
 
204
  SEARCH_BINDING tmp_search;
173
205
 
174
206
#if defined (HANDLE_MAN_PAGES)
175
207
  if (node->flags & N_IsManPage)
176
208
    return (xrefs_of_manpage (node));
177
209
#endif
178
210
 
179
 
  search.buffer = node->contents;
180
 
  search.start = 0;
181
 
  search.end = node->nodelen;
182
 
  search.flags = S_FoldCase;
 
211
  tmp_search.buffer = node->contents;
 
212
  tmp_search.start = 0;
 
213
  tmp_search.end = node->nodelen;
 
214
  tmp_search.flags = S_FoldCase;
183
215
 
184
 
  return (info_xrefs (&search));
 
216
  return (info_xrefs (&tmp_search));
185
217
}
186
218
 
187
219
/* Glean menu entries from BINDING->buffer + BINDING->start until we
188
220
   have looked at the entire contents of BINDING.  Return an array
189
221
   of REFERENCE * that represents each menu item in this range. */
190
222
REFERENCE **
191
 
info_menu_items (binding)
192
 
     SEARCH_BINDING *binding;
 
223
info_menu_items (SEARCH_BINDING *binding)
193
224
{
194
225
  return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding));
195
226
}
198
229
   BINDING->end.  Return an array of REFERENCE * that represents each
199
230
   cross reference in this range. */
200
231
REFERENCE **
201
 
info_xrefs (binding)
202
 
     SEARCH_BINDING *binding;
 
232
info_xrefs (SEARCH_BINDING *binding)
203
233
{
204
234
  return (info_references_internal (INFO_XREF_LABEL, binding));
205
235
}
207
237
/* Glean cross references or menu items from BINDING.  Return an array
208
238
   of REFERENCE * that represents the items found. */
209
239
static REFERENCE **
210
 
info_references_internal (label, binding)
211
 
     char *label;
212
 
     SEARCH_BINDING *binding;
 
240
info_references_internal (char *label, SEARCH_BINDING *binding)
213
241
{
214
 
  SEARCH_BINDING search;
 
242
  SEARCH_BINDING tmp_search;
215
243
  REFERENCE **refs = (REFERENCE **)NULL;
216
244
  int refs_index = 0, refs_slots = 0;
217
245
  int searching_for_menu_items = 0;
218
246
  long position;
219
247
 
220
 
  search.buffer = binding->buffer;
221
 
  search.start = binding->start;
222
 
  search.end = binding->end;
223
 
  search.flags = S_FoldCase | S_SkipDest;
 
248
  tmp_search.buffer = binding->buffer;
 
249
  tmp_search.start = binding->start;
 
250
  tmp_search.end = binding->end;
 
251
  tmp_search.flags = S_FoldCase | S_SkipDest;
224
252
 
225
253
  searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0);
226
254
 
227
 
  while ((position = search_forward (label, &search)) != -1)
 
255
  while ((position = search_forward (label, &tmp_search)) != -1)
228
256
    {
229
257
      int offset, start;
230
258
      char *refdef;
231
259
      REFERENCE *entry;
232
260
 
233
 
      search.start = position;
234
 
      search.start += skip_whitespace (search.buffer + search.start);
235
 
      start = search.start - binding->start;
236
 
      refdef = search.buffer + search.start;
 
261
      tmp_search.start = position;
 
262
      tmp_search.start += skip_whitespace (tmp_search.buffer + tmp_search.start);
 
263
      start = tmp_search.start - binding->start;
 
264
      refdef = tmp_search.buffer + tmp_search.start;
237
265
      offset = string_in_line (":", refdef);
238
266
 
239
267
      /* When searching for menu items, if no colon, there is no
290
318
 
291
319
          if (info_parsed_nodename)
292
320
            entry->nodename = xstrdup (info_parsed_nodename);
 
321
 
 
322
          entry->line_number = info_parsed_line_number;
293
323
        }
294
324
 
295
325
      add_pointer_to_array
301
331
/* Get the entry associated with LABEL in REFERENCES.  Return a pointer
302
332
   to the ENTRY if found, or NULL. */
303
333
REFERENCE *
304
 
info_get_labeled_reference (label, references)
305
 
     char *label;
306
 
     REFERENCE **references;
 
334
info_get_labeled_reference (char *label, REFERENCE **references)
307
335
{
308
336
  register int i;
309
337
  REFERENCE *entry;
320
348
   REFERENCE ** which is the concatenation of REF1 and REF2.  The REF1
321
349
   and REF2 arrays are freed, but their contents are not. */
322
350
REFERENCE **
323
 
info_concatenate_references (ref1, ref2)
324
 
     REFERENCE **ref1, **ref2;
 
351
info_concatenate_references (REFERENCE **ref1, REFERENCE **ref2)
325
352
{
326
353
  register int i, j;
327
354
  REFERENCE **result;
355
382
  return (result);
356
383
}
357
384
 
 
385
 
 
386
 
 
387
/* Copy a reference structure.  Since we tend to free everything at
 
388
   every opportunity, we don't share any points, but copy everything into
 
389
   new memory.  */
 
390
REFERENCE *
 
391
info_copy_reference (REFERENCE *src)
 
392
{
 
393
  REFERENCE *dest = xmalloc (sizeof (REFERENCE));
 
394
  dest->label = src->label ? xstrdup (src->label) : NULL;
 
395
  dest->filename = src->filename ? xstrdup (src->filename) : NULL;
 
396
  dest->nodename = src->nodename ? xstrdup (src->nodename) : NULL;
 
397
  dest->start = src->start;
 
398
  dest->end = src->end;
 
399
  
 
400
  return dest;
 
401
}
 
402
 
 
403
 
 
404
 
358
405
/* Free the data associated with REFERENCES. */
359
406
void
360
 
info_free_references (references)
361
 
     REFERENCE **references;
 
407
info_free_references (REFERENCE **references)
362
408
{
363
409
  register int i;
364
410
  REFERENCE *entry;
382
428
   all such sequences with just a single space.  Remove whitespace from
383
429
   start and end of string. */
384
430
void
385
 
canonicalize_whitespace (string)
386
 
     char *string;
 
431
canonicalize_whitespace (char *string)
387
432
{
388
433
  register int i, j;
389
 
  int len, whitespace_found, whitespace_loc;
 
434
  int len, whitespace_found, whitespace_loc = 0;
390
435
  char *temp;
391
436
 
392
437
  if (!string)
437
482
/* Return a pointer to a string which is the printed representation
438
483
   of CHARACTER if it were printed at HPOS. */
439
484
char *
440
 
printed_representation (character, hpos)
441
 
     unsigned char character;
442
 
     int hpos;
 
485
printed_representation (unsigned char character, int hpos)
443
486
{
444
487
  register int i = 0;
445
488
  int printable_limit = ISO_Latin_p ? 255 : 127;
446
 
    
 
489
 
 
490
  if (raw_escapes_p && character == '\033')
 
491
    the_rep[i++] = character;
447
492
  /* Show CTRL-x as ^X.  */
448
 
  if (iscntrl (character) && character < 127)
 
493
  else if (iscntrl (character) && character < 127)
449
494
    {
450
495
      switch (character)
451
496
        {
501
546
/* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */
502
547
static int parsed_nodename_size = 0;
503
548
 
504
 
static void save_string (), saven_string ();
 
549
static void save_string (char *string, char **string_p, int *string_size_p);
 
550
static void saven_string (char *string, int len, char **string_p,
 
551
    int *string_size_p);
505
552
 
506
553
/* Remember FILENAME in PARSED_FILENAME.  An empty FILENAME is translated
507
554
   to a NULL pointer in PARSED_FILENAME. */
508
555
static void
509
 
save_filename (filename)
510
 
     char *filename;
 
556
save_filename (char *filename)
511
557
{
512
558
  save_string (filename, &info_parsed_filename, &parsed_filename_size);
513
559
}
514
560
 
515
561
/* Just like save_filename (), but you pass the length of the string. */
516
562
static void
517
 
saven_filename (filename, len)
518
 
     char *filename;
519
 
     int len;
 
563
saven_filename (char *filename, int len)
520
564
{
521
565
  saven_string (filename, len,
522
566
                &info_parsed_filename, &parsed_filename_size);
525
569
/* Remember NODENAME in PARSED_NODENAME.  An empty NODENAME is translated
526
570
   to a NULL pointer in PARSED_NODENAME. */
527
571
static void
528
 
save_nodename (nodename)
529
 
     char *nodename;
 
572
save_nodename (char *nodename)
530
573
{
531
574
  save_string (nodename, &info_parsed_nodename, &parsed_nodename_size);
532
575
}
533
576
 
534
577
/* Just like save_nodename (), but you pass the length of the string. */
535
578
static void
536
 
saven_nodename (nodename, len)
537
 
     char *nodename;
538
 
     int len;
 
579
saven_nodename (char *nodename, int len)
539
580
{
540
581
  saven_string (nodename, len,
541
582
                &info_parsed_nodename, &parsed_nodename_size);
545
586
   bytes allocated to it.  An empty STRING is translated to a NULL pointer
546
587
   in STRING_P. */
547
588
static void
548
 
save_string (string, string_p, string_size_p)
549
 
     char *string;
550
 
     char **string_p;
551
 
     int *string_size_p;
 
589
save_string (char *string, char **string_p, int *string_size_p)
552
590
{
553
591
  if (!string || !*string)
554
592
    {
560
598
    }
561
599
  else
562
600
    {
563
 
      if (strlen (string) >= *string_size_p)
 
601
      if (strlen (string) >= (unsigned int) *string_size_p)
564
602
        *string_p = (char *)xrealloc
565
603
          (*string_p, (*string_size_p = 1 + strlen (string)));
566
604
 
570
608
 
571
609
/* Just like save_string (), but you also pass the length of STRING. */
572
610
static void
573
 
saven_string (string, len, string_p, string_size_p)
574
 
     char *string;
575
 
     int len;
576
 
     char **string_p;
577
 
     int *string_size_p;
 
611
saven_string (char *string, int len, char **string_p, int *string_size_p)
578
612
{
579
613
  if (!string)
580
614
    {
596
630
 
597
631
/* Return a pointer to the part of PATHNAME that simply defines the file. */
598
632
char *
599
 
filename_non_directory (pathname)
600
 
     char *pathname;
 
633
filename_non_directory (char *pathname)
601
634
{
602
635
  register char *filename = pathname + strlen (pathname);
603
636
 
612
645
 
613
646
/* Return non-zero if NODE is one especially created by Info. */
614
647
int
615
 
internal_info_node_p (node)
616
 
     NODE *node;
 
648
internal_info_node_p (NODE *node)
617
649
{
618
650
#if defined (NEVER)
619
651
  if (node &&
629
661
 
630
662
/* Make NODE appear to be one especially created by Info. */
631
663
void
632
 
name_internal_node (node, name)
633
 
     NODE *node;
634
 
     char *name;
 
664
name_internal_node (NODE *node, char *name)
635
665
{
636
666
  if (!node)
637
667
    return;
645
675
/* Return the window displaying NAME, the name of an internally created
646
676
   Info window. */
647
677
WINDOW *
648
 
get_internal_info_window (name)
649
 
     char *name;
 
678
get_internal_info_window (char *name)
650
679
{
651
680
  WINDOW *win;
652
681
 
660
689
 
661
690
/* Return a window displaying the node NODE. */
662
691
WINDOW *
663
 
get_window_of_node (node)
664
 
     NODE *node;
 
692
get_window_of_node (NODE *node)
665
693
{
666
694
  WINDOW *win = (WINDOW *)NULL;
667
695