bug-texinfo
[Top][All Lists]
Advanced

[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)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]