Subject: "Scroll" function doesn't wrap correctly

From: [email-masked]
Date: Wed, 24 Feb 1999 20:08:20 -0600 (CST)

Full_Name: Keith Pomakis
Version: 2.2
CVS_Date: 
OS: Linux 2.0.35
X_Server: XFree86
Submission from: (NULL) (207.236.16.95)

The fvwm2 man page states:

    Scroll horizonal vertical
        Scrolls  the virtual desktop's viewport by horizon-
        tal pages in the x-direction and vertical pages  in
        the  y-direction.
        [...]

        If the horizontal and vertical percentages are mul-
        tiplied  by 1000 then scrolling will wrap around at
        the edge of the desktop.

So I decided it would be a great idea to set the following navigation
ability for my 2x2 desktop:

    Mouse 1   A   M   Scroll -100000 0
    Mouse 2   A   M   Scroll 200000 0
    Mouse 3   A   M   Scroll 100000 0

This enables me to get from any page to any other page of my desktop
in just one mouse click.  I find it very convenient.  However, without
the partial fix that I'm supplying below, it doesn't work as expected.
The "Scroll 200000 0" command fails in half of the cases.

    Expected behaviour     Actual behavior
    ------------------     ---------------
    page 1 --> page 3      page 1 --> page 3
    page 2 --> page 4      page 2 --> page 3  *** FAILS ***
    page 3 --> page 1      page 3 --> page 1
    page 4 --> page 2      page 4 --> page 1  *** FAILS ***

This bug has been around for at least a couple of years.  I've finally
decided to go into the code and fix it myself.  The problem is in the
scroll() function of the file "virtual.c".  The following statements are
incorrect:

  if(((val1 <= -100000)||(val1 >= 100000))&&(x>Scr.VxMax))
    {
      x = 0;
      y += Scr.MyDisplayHeight;
      if(y > Scr.VyMax)
        y=0;
    }
  if(((val1 <= -100000)||(val1 >= 100000))&&(x<0))
    {
      x = Scr.VxMax;
      y -= Scr.MyDisplayHeight;
      if(y < 0)
        y=Scr.VyMax;
    }
  if(((val2 <= -100000)||(val2>= 100000))&&(y>Scr.VyMax))
    {
      y = 0;
      x += Scr.MyDisplayWidth;
      if(x > Scr.VxMax)
        x=0;
    }
  if(((val2 <= -100000)||(val2>= 100000))&&(y<0))
    {
      y = Scr.VyMax;
      x -= Scr.MyDisplayWidth;
      if(x < 0)
        x=Scr.VxMax;
    }

They basically say that if a scroll "wraps", it merely sets the coordinate
to zero.  That's not what wrapping is.  Wrapping is a modulus operation.
I've fixed the first and third of these if statements to perform
the correct operation.  See below.  The other two have to be similarly
modified in order for the fix to be considered complete, but I don't have
the spare brainpower at the moment, so I'll leave that to you.

  if(((val1 <= -100000)||(val1 >= 100000))&&(x>Scr.VxMax))
    {
      int xpixels = (Scr.VxMax / Scr.MyDisplayWidth + 1) *
Scr.MyDisplayWidth;
      x %= xpixels;
      y += Scr.MyDisplayHeight * (1+((x-Scr.VxMax-1)/xpixels));
      if(y > Scr.VyMax)
        y %= (Scr.VyMax / Scr.MyDisplayHeight + 1) * Scr.MyDisplayHeight;
    }
  if(((val1 <= -100000)||(val1 >= 100000))&&(x<0))
    {
      x = Scr.VxMax;
      y -= Scr.MyDisplayHeight;
      if(y < 0)
        y=Scr.VyMax;
    }
  if(((val2 <= -100000)||(val2>= 100000))&&(y>Scr.VyMax))
    {
      int ypixels = (Scr.VyMax / Scr.MyDisplayHeight + 1) *
Scr.MyDisplayHeight;
      y %= ypixels;
      x += Scr.MyDisplayWidth * (1+((y-Scr.VyMax-1)/ypixels));
      if(x > Scr.VxMax)
        x %= (Scr.VxMax / Scr.MyDisplayWidth + 1) * Scr.MyDisplayWidth;
    }
  if(((val2 <= -100000)||(val2>= 100000))&&(y<0))
    {
      y = Scr.VyMax;
      x -= Scr.MyDisplayWidth;
      if(x < 0)
        x=Scr.VxMax;
    }

.--------------------+--------------------------------------------.
| Keith Pomakis      | Don't take life too seriously.             |
| [email-masked]  | After all, you'll never make it out alive. |
+--------------------+--------------------------------------------+
|         WWW home page: "http://www.pobox.com/~pomakis/"         |
`-----------------------------------------------------------------'

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]