some possibility for bug 24069

View: New views
2 Messages — Rating Filter:   Alert me  

some possibility for bug 24069

by Bernhard R. Link-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I've taken a look at the problem with the overlong scrolled Vlists.
As gv seems to implement its own, changing is relatively easy.

Attached is a try to work around the problem by moving the vertical
scrolling into the vlist. This has the disadvantage that it can only
scroll whole entries and perhaps a couple of more.

Beware that it is quite untested and not very deeply thought about,
but it seems to do something for the TOC.

(File lists and other lists having the same problem would need similar
modifications to make use of this scrolling mechanism. They might
benefit of this to show more of the early entries but it cannot help
with the entries at the end unless the handling of those lists is also
changed to use the new mechanism).

I deem it quite possible that it might have all funny kinds of
side-effects so handle with care, this is mostly some proof-of-concept
so someone else perhaps finds the ideas to implement it properly...

Hochachtungsvoll,
        Bernhard R. Link

Index: src/Vlist.c
===================================================================
RCS file: /sources/gv/gv/src/Vlist.c,v
retrieving revision 1.7
diff -u -r1.7 Vlist.c
--- src/Vlist.c 8 Jun 2008 14:08:31 -0000 1.7
+++ src/Vlist.c 20 Nov 2008 17:13:19 -0000
@@ -4,6 +4,7 @@
 **
 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
 ** Copyright (C) 2004 Jose E. Marchesi
+** modified 2008 by Bernhard R. Link
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 /*
 #define MESSAGES
 */
@@ -68,6 +70,8 @@
 
 #define offset(field) XtOffsetOf(VlistRec, field)
 static XtResource resources[] = {
+   {XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer),
+ offset(vlist.report_callbacks), XtRCallback, (XtPointer) NULL },
    {XtNselectedShadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
  offset(vlist.selected_shadow_width), XtRImmediate, (XtPointer) 1},
    {XtNmarkShadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
@@ -193,6 +197,7 @@
   if (vw->vlist.vlist) s = vw->vlist.vlist;
   vw->vlist.vlist = GV_XtNewString(s);
   c = vw->vlist.vlist;
+  vw->vlist.firstVisible = 0;
   vw->vlist.selected = -1;
   vw->vlist.highlighted = -1;
   vw->vlist.entries = (int)strlen(vw->vlist.vlist);
@@ -214,6 +219,17 @@
   values.graphics_exposures = False;
   vw->vlist.background_GC = XtGetGC((Widget)vw,(unsigned) GCForeground | GCGraphicsExposures,&values);
 
+  /* TODO: check if this works here in international mode, or if it has
+   * to be moved to Realize... */
+  if( vw->simple.international == True ) {
+    XFontSetExtents *ext = XExtentsOfFontSet(vw->label.fontset);
+    vw->vlist.yofs = (ext->max_ink_extent.y<0)?-ext->max_ink_extent.y:ext->max_ink_extent.y;
+    vw->vlist.ydelta = ext->max_ink_extent.height;
+  } else {
+    vw->vlist.yofs = vw->label.font->max_bounds.ascent;
+    vw->vlist.ydelta = vw->label.font->max_bounds.ascent + vw->label.font->max_bounds.descent;
+  }
+
   ENDMESSAGE(Initialize)
 }
 
@@ -318,16 +334,9 @@
   VlistWidget vw = (VlistWidget)w;
   char * s;
   int i;
-  int yofs, ydelta;
+  int yofs = vw->vlist.yofs, ydelta = vw->vlist.ydelta;
 
-  if( vw->simple.international == True ) {
-    XFontSetExtents *ext = XExtentsOfFontSet(vw->label.fontset);
-    yofs = (ext->max_ink_extent.y<0)?-ext->max_ink_extent.y:ext->max_ink_extent.y;
-    ydelta = ext->max_ink_extent.height;
-  } else {
-    yofs = vw->label.font->max_bounds.ascent;
-    ydelta = vw->label.font->max_bounds.ascent + vw->label.font->max_bounds.descent;
-  }
+  yofs -= ydelta * vw->vlist.firstVisible;
 
   BEGINMESSAGE1(PaintEntryString)
   s = vw->label.label;
@@ -378,6 +387,10 @@
     ENDMESSAGE(PaintMark)
     return(ret);
   }
+  if (entry < vw->vlist.firstVisible) {
+    ENDMESSAGE(PaintMark)
+    return 0;
+  }
   if (style<0) { /* highlighted */
     INFMESSAGE(highlighted entry)
     ulx = vw->vlist.hulx;
@@ -397,11 +410,10 @@
   }
   x = (Position) ulx;
   y = (Position) (((int) vw->label.label_y) +
-  (entry*(vw->label.label_height))/vw->vlist.entries +
+  ((entry - vw->vlist.firstVisible)*vw->vlist.ydelta) +
   uly);
   width = (Dimension)((int) vw->core.width - ulx + lrx);
-  height= (Dimension)(((int) vw->label.label_height)/vw->vlist.entries +
-      - uly + lry + .5);
+  height= (Dimension)(vw->vlist.ydelta - uly + lry + .5);
   ss = XawSUNKEN;
   if (region == NULL || XRectInRegion(region,x,y,width,height) != RectangleOut) {
     if (erase) {
@@ -487,14 +499,17 @@
     char *vlist = vw->vlist.vlist;
     Boolean paint=False;
 
+    if (entry < vw->vlist.firstVisible)
+      return;
+
     if (vlist[entry] == '*') paint = True;
     if (paint || erase) {
       x = (Position) (VLIST_MARK_LEFT_INDENT);
       y = (Position) (((int) vw->label.label_y) +
       VLIST_MARK_VERTICAL_INDENT +
-      (entry*(vw->label.label_height))/vw->vlist.entries);
+      ((entry-vw->vlist.firstVisible)*vw->vlist.ydelta));
       width = (Dimension) (VLIST_MARK_WIDTH);
-      height= (Dimension)(((int) vw->label.label_height)/vw->vlist.entries + 0.5 - 2*VLIST_MARK_VERTICAL_INDENT);
+      height= (Dimension)(vw->vlist.ydelta + 0.5 - 2*VLIST_MARK_VERTICAL_INDENT);
       ss = XawSUNKEN;
       if (region == NULL || XRectInRegion(region,x,y,width,height) != RectangleOut) {
  if (paint) {
@@ -530,7 +545,7 @@
   BEGINMESSAGE(PaintMarksOfEntries)
   PaintMarkOfEntry(w, region, vw->vlist.highlighted,-1, False);
   if (vw->vlist.allow_marks) {
-    int i=0;
+    int i= vw->vlist.firstVisible;
     while (i < vw->vlist.entries) {
       if (i != vw->vlist.highlighted)
  PaintMarkMarkOfEntry(w, region, i, False);
@@ -553,14 +568,67 @@
 Region region;
 {
   Dimension width;
+  char *s, *o;
+  int i, y;
   VlistWidget vw = (VlistWidget)w;
+  XRectangle rectangle;
+
   BEGINMESSAGE(PaintVlistWidget)
+  /* better not allow the widget to grow that large, but that needs fixing
+   * of the Clip widget */
   shiftLabel(vw);
   PaintMarksOfEntries(w, event, region);
   width = vw->threeD.shadow_width;
+  o = vw->label.label;
+  s = vw->label.label;
+  i = vw->vlist.firstVisible;
+  if (s) while (i > 0 && (s = strchr(s,'\n'))) { s++; i--; }
+  /* This still fails when the list is too long and does not print anything.
+   * Though that is perhaps best fixed by making Clip to enforce a real window
+   * height...
+  vw->label.label = s;
   vw->threeD.shadow_width = 0;
   (*SuperClass->core_class.expose) (w, event, region);
-  vw->threeD.shadow_width =  width;
+  vw->threeD.shadow_width =  width;
+  vw->label.label = o;
+  until Clip is extended, just manually draw each line:
+  */
+  if (region)
+    XClipBox(region, &rectangle);
+  else {
+    rectangle.x = 0;
+    rectangle.y = 0;
+    rectangle.width = vw->core.width;
+    rectangle.height = vw->core.height;
+    if( rectangle.height >= 0x4000 )
+    rectangle.height = 0x3fff;
+  }
+  y = vw->label.label_y + vw->vlist.yofs;
+  i = 0;
+
+  while (s != NULL) {
+    char *nl = strchr(s, '\n');
+    int len;
+    if (nl)
+      len = nl - s;
+    else
+      len = strlen(s);
+    if (y - vw->vlist.yofs > rectangle.y + rectangle.height)
+      break;
+    if (y + (vw->vlist.ydelta - vw->vlist.yofs) >= rectangle.y) {
+      if( vw->simple.international == True )
+ XmbDrawString(XtDisplay(w), XtWindow(w), vw->label.fontset,
+      vw->label.normal_GC, vw->label.label_x, y, s, len);
+      else
+ XDrawString(XtDisplay(w), XtWindow(w), vw->label.normal_GC,
+    vw->label.label_x, y, s, len);
+    }
+    if (nl)
+      s = nl + 1;
+    else
+      s = NULL;
+    y += vw->vlist.ydelta;
+  }
   ENDMESSAGE(PaintVlistWidget)
 }
 
@@ -644,12 +712,14 @@
 
   BEGINMESSAGE(VlistEntryOfPosition)
   y = y - (int) vw->label.label_y;
-  if (vw->label.label_height > 0) {
+  if (vw->vlist.ydelta > 0) {
     if (y < 0) entry = -1;
-    else       entry = (vw->vlist.entries*y)/(int)vw->label.label_height;
+    else       entry = y/vw->vlist.ydelta;
   }
   if (entry >= vw->vlist.entries)
   entry = vw->vlist.entries-1;
+  if (entry >= 0)
+    entry += vw->vlist.firstVisible;
   IMESSAGE(entry)
   ENDMESSAGE(VlistEntryOfPosition)
   return(entry);
@@ -670,8 +740,9 @@
   float h;
   BEGINMESSAGE(VlistPositionOfEntry)
   *yuP = *ylP = (int) vw->label.label_y;
-  if (e>=0 && vw->vlist.entries > 0) {
-    h = (float)vw->label.label_height/(float)vw->vlist.entries;
+  if (e >= vw->vlist.firstVisible && vw->vlist.entries > 0) {
+    e -= vw->vlist.firstVisible;
+    h = vw->vlist.ydelta;
     *yuP += (int)((float)e*h);
     *ylP += (int)((float)(e+1)*h);
   }
@@ -828,3 +899,78 @@
   vlist_change_mark(w,entry,change,-1);
   ENDMESSAGE(VlistChangeHighlighted)
 }
+
+/*###################################################*/
+/* VlistGetFirstVisible */
+/*###################################################*/
+
+int VlistGetFirstVisible(Widget w)
+{
+  VlistWidget vw = (VlistWidget)w;
+
+  return vw->vlist.firstVisible;
+}
+
+/*###################################################*/
+/* VlistSetFirstVisible */
+/*###################################################*/
+
+void VlistSetFirstVisible(Widget w, int newf)
+{
+  VlistWidget vw = (VlistWidget)w;
+  unsigned int height;
+
+  BEGINMESSAGE(VlistSetFirstVisible)
+  if (newf < 0)
+    newf = 0;
+  else if (newf >= vw->vlist.entries)
+    newf = vw->vlist.entries - 1;
+  if (newf == -1)
+    return;
+  if (newf != vw->vlist.firstVisible) {
+    vw->vlist.firstVisible = newf;
+    /* better not allow the widget to grow that large, but that needs fixing
+     * of the Clip widget */
+    height = vw->core.height;
+    if( height >= 0x8000 )
+    height = 0x3fff;
+    XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), vw->vlist.background_GC,
+    vw->core.x, vw->core.y, vw->core.width, height);
+    Redisplay(w, NULL, NULL);
+    if (vw->vlist.report_callbacks)
+      XtCallCallbackList (w, vw->vlist.report_callbacks, (XtPointer)0);
+  }
+  ENDMESSAGE(VlistMoveFirstVisible)
+}
+/*###################################################*/
+/* VlistMoveFirstVisible */
+/*###################################################*/
+
+void VlistMoveFirstVisible(Widget w, int start, int ydiff)
+{
+  VlistWidget vw = (VlistWidget)w;
+  int ly;
+  int newf;
+
+  BEGINMESSAGE(VlistMoveFirstVisible)
+  ly = vw->vlist.ydelta;
+  fprintf(stderr, "move: start=%d ydiff=%d ly=%d\n", start, ydiff, ly);
+  if (ydiff >= 0)
+  ydiff += ly/2;
+  else
+  ydiff -= ly/2;
+  newf = start + ydiff/ly;
+  VlistSetFirstVisible(w, newf);
+  ENDMESSAGE(VlistMoveFirstVisible)
+}
+
+/*###################################################*/
+/* VlistScrollPosition */
+/*###################################################*/
+
+float VlistScrollPosition(Widget w)
+{
+  VlistWidget vw = (VlistWidget)w;
+
+  return vw->vlist.firstVisible/(float)vw->vlist.entries;
+}
Index: src/Vlist.h
===================================================================
RCS file: /sources/gv/gv/src/Vlist.h,v
retrieving revision 1.3
diff -u -r1.3 Vlist.h
--- src/Vlist.h 7 Jun 2008 18:39:19 -0000 1.3
+++ src/Vlist.h 20 Nov 2008 17:13:19 -0000
@@ -35,6 +35,7 @@
 
 #include "paths.h"
 #include INC_XAW(Label.h)
+#include INC_XAW(Reports.h)
 
 #define XawVlistAll     -13
 #define XawVlistEven    -12
@@ -131,5 +132,9 @@
     int
 #endif
 );
+extern int VlistGetFirstVisible(Widget);
+extern void VlistSetFirstVisible(Widget, int);
+extern void VlistMoveFirstVisible(Widget, int, int);
+float VlistScrollPosition(Widget);
 
 #endif /* _Vlist_h_ */
Index: src/VlistP.h
===================================================================
RCS file: /sources/gv/gv/src/VlistP.h,v
retrieving revision 1.3
diff -u -r1.3 VlistP.h
--- src/VlistP.h 7 Jun 2008 18:39:19 -0000 1.3
+++ src/VlistP.h 20 Nov 2008 17:13:19 -0000
@@ -69,6 +69,7 @@
   GC mark_background_GC;
   GC selected_background_GC;
   GC highlighted_background_GC;
+  int firstVisible;
   int selected;
   int highlighted;
   int hulx;
@@ -79,6 +80,9 @@
   int suly;
   int slrx;
   int slry;
+  int ydelta;
+  int yofs;
+  XtCallbackList report_callbacks;
 } VlistPart;
 
 typedef struct _VlistRec {
Index: src/actions.c
===================================================================
RCS file: /sources/gv/gv/src/actions.c,v
retrieving revision 1.17
diff -u -r1.17 actions.c
--- src/actions.c 2 Aug 2008 16:48:10 -0000 1.17
+++ src/actions.c 20 Nov 2008 17:13:19 -0000
@@ -379,6 +379,7 @@
 {
   static int xf,yf,xo,yo,xp,yp,dyo;
   static Boolean scroll_initialized=False;
+  static int startvisible;
   static Boolean scrolling=False;
   static int entryo = -1;
   Boolean toggle_mark=False;
@@ -397,8 +398,7 @@
     if (!app_res.reverse_scrolling) dy = -dy;
     m  = 1.3*((float)slider->core.height/(float)ph);
     if (m<=1) m = 1;
-    y = yp +(int)(m*dy);
-    if (y<dh) y=dh; if (y>0) y=0;
+    y = yp -(int)(m*dy);
     yo = (int) event->xbutton.y_root;
 
     ph = (int)panner->core.width; if (ph<1) ph = 1;
@@ -411,9 +411,12 @@
     if (x<dh) x=dh; if (x>0) x=0;
     xo = (int) event->xbutton.x_root;
 
-    if (x!=xp || y!=yp) {
-      ClipWidgetSetCoordinates(panner,x,y);
+    if (x!=xp) {
+      ClipWidgetSetCoordinates(panner,x,0);
       xp = x;
+    }
+    if (y!=yp) {
+      VlistMoveFirstVisible(newtoc, startvisible, y);
       yp = y;
     }
     if (abs(xf-xo) > 6 || abs(yf-yo) > 6) scrolling = True;
@@ -422,7 +425,8 @@
     scroll_initialized = True;
     scrolling = False;
     xp = (int) slider->core.x; xf = xo = (int) event->xbutton.x_root;
-    yp = (int) slider->core.y; yf = yo = (int) event->xbutton.y_root;
+    yp = 0; yf = yo = (int) event->xbutton.y_root;
+    startvisible = VlistGetFirstVisible(newtoc);
   }
   else if (!strcmp(params[0],"scrolloff")) {
     scroll_initialized = False;
Index: src/callbacks.c
===================================================================
RCS file: /sources/gv/gv/src/callbacks.c,v
retrieving revision 1.21
diff -u -r1.21 callbacks.c
--- src/callbacks.c 2 Sep 2008 11:42:43 -0000 1.21
+++ src/callbacks.c 20 Nov 2008 17:13:19 -0000
@@ -156,32 +156,36 @@
   Widget w;
   XtPointer client_data, call_data;
 {
-  int x,y;
-
   BEGINMESSAGE(cb_newtocScrollbar)
-  x = (int) newtocControl->core.x;
   if (((int)(intptr_t)client_data)==1) {
     int dy = (int)(intptr_t)call_data;
-    y = (int) newtocControl->core.y - dy;
+    VlistMoveFirstVisible(newtoc, VlistGetFirstVisible(newtoc), dy);
   } else {
     float *percent = (float *) call_data;
-    y = (int)(-*percent * newtocControl->core.height);
+    VlistSetFirstVisible(newtoc, (int)(VlistEntries(newtoc)**percent));
   }
-  ClipWidgetSetCoordinates(newtocClip, x, y);
   ENDMESSAGE(cb_newtocScrollbar)
 }
 
 /*##################################################################*/
-/* cb_newtocClipAdjust */
+/* cb_newtocVisibleAdjust */
 /*##################################################################*/
 
-void cb_newtocClipAdjust(w, client_data, call_data)
+void cb_newtocVisibleAdjust(w, client_data, call_data)
   Widget w;
   XtPointer client_data, call_data;
 {
+  int entries;
+
   BEGINMESSAGE(cb_newtocClipAdjust)
-  XawScrollbarSetThumb(newtocScroll,
-       -(float)newtocControl->core.y/(float)newtocControl->core.height,
+
+  entries = VlistEntries(newtoc);
+
+  if (entries <= 0)
+    XawScrollbarSetThumb(newtocScroll, 0.0, 1.0);
+  else
+    XawScrollbarSetThumb(newtocScroll,
+ VlistScrollPosition(newtoc),
        (float)newtocClip->core.height/(float)newtocControl->core.height);
   ENDMESSAGE(cb_newtocClipAdjust)
 }
Index: src/callbacks.h
===================================================================
RCS file: /sources/gv/gv/src/callbacks.h,v
retrieving revision 1.5
diff -u -r1.5 callbacks.h
--- src/callbacks.h 23 Aug 2008 18:18:55 -0000 1.5
+++ src/callbacks.h 20 Nov 2008 17:13:19 -0000
@@ -49,7 +49,7 @@
 #endif
 );
 
-extern void cb_newtocClipAdjust (
+extern void cb_newtocVisibleAdjust (
 #if NeedFunctionPrototypes
    Widget,
    XtPointer,
Index: src/main.c
===================================================================
RCS file: /sources/gv/gv/src/main.c,v
retrieving revision 1.44
diff -u -r1.44 main.c
--- src/main.c 24 Aug 2008 10:33:48 -0000 1.44
+++ src/main.c 20 Nov 2008 17:13:19 -0000
@@ -1128,11 +1128,11 @@
           cont_child[cont_child_num] = newtocFrame; cont_child_num++;
    n=0;
           newtocClip = XtCreateManagedWidget("newtocClip", clipWidgetClass,newtocFrame, args, n);
-     XtAddCallback(newtocClip, XtNreportCallback,cb_newtocClipAdjust, (XtPointer)NULL);
    n=0;
           newtocControl = XtCreateManagedWidget("newtocControl", aaaWidgetClass,newtocClip, args, n);
                n=0;
           newtoc = XtCreateManagedWidget("newtoc", vlistWidgetClass,newtocControl, args, n);
+  XtAddCallback(newtoc, XtNreportCallback,cb_newtocVisibleAdjust, (XtPointer)NULL);
  n=0;
           newtocScroll = XtCreateWidget("newtocScroll", scrollbarWidgetClass,control, args, n);
      XtAddCallback(newtocScroll, XtNscrollProc,cb_newtocScrollbar, (XtPointer)1);
Index: src/misc.c
===================================================================
RCS file: /sources/gv/gv/src/misc.c,v
retrieving revision 1.26
diff -u -r1.26 misc.c
--- src/misc.c 9 Sep 2008 17:11:04 -0000 1.26
+++ src/misc.c 20 Nov 2008 17:13:19 -0000
@@ -303,41 +303,43 @@
   XEvent *event;
   Boolean check_toc;
 {
-  int x,y,yl,yu,ny=99999;
+  int firstvisible, lastvisible;
   Boolean b = False;
   INFMESSAGE(misc_setPageMarker)
   if (toc_text && (entry >= 0)) {
-    if (kind == 0 && VlistSelected(newtoc) != entry)  
+    if (kind == 0 && VlistSelected(newtoc) != entry)
       VlistChangeSelected(newtoc,entry,XawVlistSet);
-    else if (kind == 1 && VlistHighlighted(newtoc) != entry)  
+    else if (kind == 1 && VlistHighlighted(newtoc) != entry)
       VlistChangeHighlighted(newtoc,entry,XawVlistSet);
     else if (kind == 2) {
       entry=VlistSelected(newtoc);
       if (entry<0) return;
     }
-    VlistPositionOfEntry(newtoc,entry,&yu,&yl);
-    x = newtocControl->core.x;
-    y = newtocControl->core.y;
-    IIMESSAGE(x,y)
-    IIMESSAGE(yu,yl)
-    IIMESSAGE(y,newtoc->core.y)
-    if (yu != yl) {
-      ny = -((int)newtoc->core.y + yu) + 14;
-      if (y<0 && y < ny) b = True;
-      if (!b) {
- ny = (int)newtocClip->core.height - ((int)newtoc->core.y + yl + 14);
-        if (y>ny) b = True;
+    firstvisible = VlistGetFirstVisible(newtoc);
+    if (firstvisible > entry || (entry > 0 && firstvisible >= entry)) {
+      if (entry > 0)
+ VlistSetFirstVisible(newtoc, entry - 1);
+      else
+ VlistSetFirstVisible(newtoc, entry);
+      b = True;
+    } else {
+      /* sadly newtoc does not know it's height, so it cannot be told
+       * to made an item visible and we need to trick: */
+      lastvisible = VlistEntryOfPosition(newtoc, newtocClip->core.height);
+      if (entry > firstvisible && entry >= lastvisible) {
+ VlistSetFirstVisible(newtoc, entry - (lastvisible - firstvisible - 1));
+ b = True;
       }
-      if (b) {
- INFIMESSAGE(jumping to,ny)
- ClipWidgetSetCoordinates(newtocClip,x,ny);
- if (event)
+    }
+    /* if this happened by mouse, we have the information to get the
+     * highlight up to date again: */
+    if (b) {
+      if (event)
  {
-   entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y+(y-ny));
-   if (entry != VlistHighlighted(newtoc) && check_toc)
- VlistChangeHighlighted(newtoc,entry,XawVlistSet);
-        }
-      }
+  entry = VlistEntryOfPosition(newtoc, (int)event->xbutton.y);
+  if (entry != VlistHighlighted(newtoc) && check_toc)
+    VlistChangeHighlighted(newtoc,entry,XawVlistSet);
+ }
     }
   }
 }

Re: some possibility for bug 24069

by Markus Steinborn-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Bernhard R. Link schrieb:
> I've taken a look at the problem with the overlong scrolled Vlists.
> As gv seems to implement its own, changing is relatively easy.
>
> Attached is a try to work around the problem by moving the vertical
> scrolling into the vlist.
Thank you for the patch.
> This has the disadvantage that it can only
> scroll whole entries
IMHO that would be ok.
> and perhaps a couple of more.
>
> Beware that it is quite untested and not very deeply thought about,
> but it seems to do something for the TOC.
>  

> I deem it quite possible that it might have all funny kinds of
> side-effects so handle with care, this is mostly some proof-of-concept
> so someone else perhaps finds the ideas to implement it properly...
>  
I noticed that by a quick test: Viewing a document with only a handfull
pages (in order to give an example let's say four pages) has the side
effect when switching to the last page the page selection panel is
scrolled down without any need.

As I am not sure if the patch is suitable for a release, I attached at
to the savannah bug report. Furthermore I'll install a GNU gv with this
patch to get information about it's problems and to see whether it is
fit enough to be released.

Greetings

Markus Steinborn