[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Texinfo 4.5: info: select reference wrapped over line -> wrong node
From: |
Karl Berry |
Subject: |
Re: Texinfo 4.5: info: select reference wrapped over line -> wrong node |
Date: |
Fri, 7 Mar 2003 07:53:37 -0500 |
if a reference wraps over onto a line which also has a
reference on it and I select the wrapped reference at the start of a line,
then it goes to wrong node.
This was more painful to fix. Here's a patch. Please try it if you
can. Although it fixes the stated problem for me, I'm not 100% sure
there are no unwanted side effects. I had a lot of memory corruption
problems while I was debugging the new code.
Thanks for the report.
Index: info-utils.c
===================================================================
RCS file: /cvsroot/texinfo/texinfo/info/info-utils.c,v
retrieving revision 1.1
diff -c -2 -r1.1 info-utils.c
*** info-utils.c 25 Aug 2002 23:38:38 -0000 1.1
--- info-utils.c 6 Mar 2003 23:18:50 -0000
***************
*** 2,6 ****
$Id: info-utils.c,v 1.1 2002/08/25 23:38:38 karl Exp $
! Copyright (C) 1993, 98 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
--- 2,6 ----
$Id: info-utils.c,v 1.1 2002/08/25 23:38:38 karl Exp $
! Copyright (C) 1993, 1998, 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
***************
*** 356,359 ****
--- 356,380 ----
}
+
+
+ /* Copy a reference structure. Since we tend to free everything at
+ every opportunity, we don't share any points, but copy everything into
+ new memory. */
+ REFERENCE *
+ info_copy_reference (src)
+ REFERENCE *src;
+ {
+ REFERENCE *dest = xmalloc (sizeof (REFERENCE));
+ dest->label = src->label ? xstrdup (src->label) : NULL;
+ dest->filename = src->filename ? xstrdup (src->filename) : NULL;
+ dest->nodename = src->nodename ? xstrdup (src->nodename) : NULL;
+ dest->start = src->start;
+ dest->end = src->end;
+
+ return dest;
+ }
+
+
+
/* Free the data associated with REFERENCES. */
void
Index: info-utils.h
===================================================================
RCS file: /cvsroot/texinfo/texinfo/info/info-utils.h,v
retrieving revision 1.1
diff -c -2 -r1.1 info-utils.h
*** info-utils.h 25 Aug 2002 23:38:38 -0000 1.1
--- info-utils.h 6 Mar 2003 23:18:50 -0000
***************
*** 2,6 ****
$Id: info-utils.h,v 1.1 2002/08/25 23:38:38 karl Exp $
! Copyright (C) 1993, 1996, 1998, 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
--- 2,6 ----
$Id: info-utils.h,v 1.1 2002/08/25 23:38:38 karl Exp $
! Copyright (C) 1993, 1996, 1998, 2002, 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
***************
*** 83,86 ****
--- 83,89 ----
and REF2 arrays are freed, but their contents are not. */
REFERENCE **info_concatenate_references ();
+
+ /* Copy an existing reference into new memory. */
+ extern REFERENCE *info_copy_reference ();
/* Free the data associated with REFERENCES. */
Index: session.c
===================================================================
RCS file: /cvsroot/texinfo/texinfo/info/session.c,v
retrieving revision 1.5
diff -c -2 -r1.5 session.c
*** session.c 11 Feb 2003 16:39:06 -0000 1.5
--- session.c 6 Mar 2003 23:19:18 -0000
***************
*** 2009,2012 ****
--- 2009,2082 ----
}
+
+
+ /* Return a pointer to the xref in XREF_LIST that is nearest to POS, or
+ NULL if XREF_LIST is empty. That is, if POS is within any of the
+ given xrefs, return that one. Otherwise, return the one with the
+ nearest beginning or end. If there are two that are equidistant,
+ prefer the one forward. The return is in newly-allocated memory,
+ since the caller frees it.
+
+ This is called from info_menu_or_ref_item with XREF_LIST being all
+ the xrefs in the node, and POS being point. The ui function that
+ starts it all off is select-reference-this-line.
+
+ This is not the same logic as in info.el. Info-get-token prefers
+ searching backwards to searching forwards, and has a hardwired search
+ limit of 200 chars (in Emacs 21.2). */
+
+ /* We don't need anything fancy. */
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+ static REFERENCE **
+ nearest_xref (xref_list, pos)
+ REFERENCE **xref_list;
+ long pos;
+ {
+ int this_xref;
+ int nearest = -1;
+ long best_delta = -1;
+
+ for (this_xref = 0; xref_list[this_xref]; this_xref++)
+ {
+ long delta;
+ REFERENCE *xref = xref_list[this_xref];
+ if (xref->start <= pos && pos <= xref->end)
+ { /* POS is within this xref, we're done */
+ nearest = this_xref;
+ break;
+ }
+
+ /* See how far POS is from this xref. Take into account the
+ `*Note' that begins the xref, since as far as the user is
+ concerned, that's where it starts. */
+ delta = MIN (labs (pos - (xref->start - strlen (INFO_XREF_LABEL))),
+ labs (pos - xref->end));
+
+ /* It's the <= instead of < that makes us choose the forward xref
+ of POS if two are equidistant. Of course, because of all the
+ punctuation surrounding xrefs, it's not necessarily obvious
+ where one ends. */
+ if (delta <= best_delta || best_delta < 0)
+ {
+ nearest = this_xref;
+ best_delta = delta;
+ }
+ }
+
+ /* Maybe there was no list to search through. */
+ if (nearest < 0)
+ return NULL;
+
+ /* Ok, we have a nearest xref, make a list of it. */
+ {
+ REFERENCE **ret = xmalloc (sizeof (REFERENCE *) * 2);
+ ret[0] = info_copy_reference (xref_list[nearest]);
+ ret[1] = NULL;
+ return ret;
+ }
+ }
+
+
/* Read a menu or followed reference from the user defaulting to the
reference found on the current line, and select that node. The
***************
*** 2022,2029 ****
int ask_p;
{
- REFERENCE **menu, *entry, *defentry = (REFERENCE *)NULL;
char *line;
!
! menu = (*builder) (window->node);
if (!menu)
--- 2092,2099 ----
int ask_p;
{
char *line;
! REFERENCE *entry;
! REFERENCE *defentry = NULL;
! REFERENCE **menu = (*builder) (window->node);
if (!menu)
***************
*** 2039,2046 ****
point is in. */
{
! REFERENCE **refs = (REFERENCE **)NULL;
! int point_line;
!
! point_line = window_line_of_point (window);
if (point_line != -1)
--- 2109,2114 ----
point is in. */
{
! REFERENCE **refs = NULL;
! int point_line = window_line_of_point (window);
if (point_line != -1)
***************
*** 2071,2098 ****
else
#endif /* HANDLE_MAN_PAGES */
! {
! refs = info_xrefs (&binding);
! if (!refs && point_line > 0)
! {
! /* People get annoyed that Info cannot find an xref
! which starts on a previous line and ends on this
! one. So if we fail to find a reference on this
! line, let's try the one before. */
! binding.start =
! window->line_starts[point_line - 1] - binding.buffer;
! refs = info_xrefs (&binding);
! }
! }
}
! if (refs)
{
! if ((strcmp (refs[0]->label, "Menu") != 0) ||
! (builder == info_xrefs_of_node))
{
int which = 0;
! /* Find the closest reference to point. */
! if (builder == info_xrefs_of_node)
{
int closest = -1;
--- 2139,2158 ----
else
#endif /* HANDLE_MAN_PAGES */
! refs = nearest_xref (menu, window->point);
}
! if (refs && refs[0])
{
! if (strcmp (refs[0]->label, "Menu") != 0
! || builder == info_xrefs_of_node)
{
int which = 0;
! /* For xrefs, find the closest reference to point,
! unless we only have one reference (as we will if
! we've called nearest_xref above). It would be better
! to have only one piece of code, but the conditions
! when we call this are tangled. */
! if (builder == info_xrefs_of_node && refs[1])
{
int closest = -1;
***************
*** 2100,2105 ****
for (; refs[which]; which++)
{
! if ((window->point >= refs[which]->start) &&
! (window->point <= refs[which]->end))
{
closest = which;
--- 2160,2165 ----
for (; refs[which]; which++)
{
! if (window->point >= refs[which]->start
! && window->point <= refs[which]->end)
{
closest = which;
***************
*** 2107,2113 ****
}
else if (window->point < refs[which]->start)
! {
! break;
! }
}
if (closest == -1)
--- 2167,2171 ----
}
else if (window->point < refs[which]->start)
! break;
}
if (closest == -1)
***************
*** 2139,2145 ****
/* Build the prompt string. */
if (defentry)
! prompt = (char *)xmalloc (20 + strlen (defentry->label));
else
! prompt = (char *)xmalloc (20);
if (builder == info_menu_of_node)
--- 2197,2203 ----
/* Build the prompt string. */
if (defentry)
! prompt = (char *)xmalloc (99 + strlen (defentry->label));
else
! prompt = (char *)xmalloc (99);
if (builder == info_menu_of_node)