[comp.mail.mh] HELP with vmh problem, please

steve@gapos.bt.co.uk (Steve Rooke) (04/25/91)

I have just started to get MH 6.7.1 running under Uniplus+ SVR2 on our
machines here but have hit a problem with vmh.  When I run vmh -vmhproc msh
the screen splits normally, the top window shows a scan of msgbox and I
get the (vmh) prompt in the bottom window okay.  If I scan then the bottom
screen fills up but then immediately clears and I am left with a blank 
bottom window apart from the (top: bottom:) prompt.  A refresh will not
repaint the missing text and I can get the next screen but all I see is
a quick flash of the bottom line of text before it disappears.

I have started to look in vmh.c and think that the problem is somewhere in
the region of linsert (perhaps).  It looks like the screen is written by 
part of the code then a linked list of line structures is read back out
of the curses window, only in my case this seems to read blank strings.
I see the correct display for a quick flash at the time that the first
wrefresh is called in WINloop but, after the lbottom/waddstr bit is run, the
next wrefresh clears the window.

Has anyone else had this problem and can help me please.  If it is covered
in FAQ then please excuse this posting as I have only just started to read
the group and have not seen one yet (if you have a copy, please send it
to me or tell me where I can get a copy, see my other posting).

version: MH 6.7.1 #3[UCI] (azh01) of Tue Apr 23 11:54:41 BST 1991
options: [SYS5] [MORE='"/usr/bin/more"'] [NDIR] [SYSNDIR] [UK] [MHE]
         [SENDMTS] [SPRINTFTYPE=int]

SYSNDIR = local hack for <sys/ndir>

Thanks for your time
Steve
-- 
Steve Rooke  steve@gapos.bt.co.uk  (...mcsun!ukc!gapos!steve)  UK + 394 693595
BT, CS/OPSE, Area 106, Anzani House,  |  Live to Hack -
Trinity Ave, FELIXSTOWE, Suffolk, UK  |       Hack to Live.
#include <std/disclaimer>             |             The_Caged_Lion - DoD #0287

david@cwi.UUCP ("David J. Fiander") (04/26/91)

|From: Steve Rooke  <steve@gapos.bt.co.uk>
|
|I have just started to get MH 6.7.1 running under Uniplus+ SVR2 on our
|machines here but have hit a problem with vmh.  When I run vmh -vmhproc msh
|the screen splits normally, the top window shows a scan of msgbox and I
|get the (vmh) prompt in the bottom window okay.  If I scan then the bottom
|screen fills up but then immediately clears and I am left with a blank 
|bottom window apart from the (top: bottom:) prompt.  A refresh will not
|repaint the missing text and I can get the next screen but all I see is
|a quick flash of the bottom line of text before it disappears.

The problem is that vmh thinks that it knows how curses is implemented,
and insists on "diddling the private bits" of the WIN structure.
Unfortunately it gets it wrong for System V curses.  I have the patches
to MH 6.7.1 lying about somewhere, and should probably post them, or
something.

- David

david@cwi.UUCP ("David J. Fiander") (04/26/91)

Include below, as promised, are my patches to uip/vmh.c so that it will
work with System V curses.  Unfortunately, I don't have a BSD system to
try them on, so I don't know whether I broke anything or not.

I have also included a patch to uip/vmhsbr.c which fixes an off-by-one
allocation error which was walking on the heap.  After this patch has
been applied, you have to rebuild both vmh _and_ msh, since the both use
it.

- David

--------- Cut here ---8<--------

*** vmh.orig.c	Thu Apr 25 20:45:47 1991
--- vmh.c	Sun Mar 10 13:34:44 1991
***************
*** 346,352 ****
      (void) sprintf (bp, "%d %d", RC_VRSN, numwins);
      bp += strlen (bp);
      for (w = windows; *w; w++) {
! 	(void) sprintf (bp, " %d", (*w) -> _maxy);
  	bp += strlen (bp);
      }
  
--- 347,355 ----
      (void) sprintf (bp, "%d %d", RC_VRSN, numwins);
      bp += strlen (bp);
      for (w = windows; *w; w++) {
! 	int x, y;
! 	getmaxyx(*w, y, x);
! 	(void) sprintf (bp, " %d", y);
  	bp += strlen (bp);
      }
  
***************
*** 694,699 ****
--- 697,703 ----
  {
      register int    c;
      register char  *bp;
+     int		   x, y;
  
      bp = buffer;
      *bp = NULL;
***************
*** 712,718 ****
  		*bp = NULL;
  		if (bp > buffer) {
  		    leaveok (curscr, FALSE);
! 		    wmove (w, 0, w -> _curx - (bp - buffer));
  		    wrefresh (w);
  		    leaveok (curscr, TRUE);
  		}
--- 716,723 ----
  		*bp = NULL;
  		if (bp > buffer) {
  		    leaveok (curscr, FALSE);
! 		    getyx(w, y, x);
! 		    wmove (w, 0, x - (bp - buffer));
  		    wrefresh (w);
  		    leaveok (curscr, TRUE);
  		}
***************
*** 736,742 ****
  		if (c == ERASE) {
  		    if (bp <= buffer)
  			continue;
! 		    bp--, w -> _curx--;
  		    wclrtoeol (w);
  		    break;
  		}
--- 741,749 ----
  		if (c == ERASE) {
  		    if (bp <= buffer)
  			continue;
! 		    getyx(w, y, x);
! 		    bp--, x--;
! 		    wmove(w, y, x);
  		    wclrtoeol (w);
  		    break;
  		}
***************
*** 743,749 ****
  		if (c == KILL) {
  		    if (bp <= buffer)
  			continue;
! 		    w -> _curx -= bp - buffer;
  		    bp = buffer;
  		    wclrtoeol (w);
  		    break;
--- 750,757 ----
  		if (c == KILL) {
  		    if (bp <= buffer)
  			continue;
! 		    getyx(w, y, x);
! 		    x -= bp - buffer; wmove(w, y, x);
  		    bp = buffer;
  		    wclrtoeol (w);
  		    break;
***************
*** 751,767 ****
  		if (c == WERASC) {
  		    if (bp <= buffer)
  			continue;
  		    do {
! 			bp--, w -> _curx--;
  		    } while (isspace (*bp) && bp > buffer);
  
  		    if (bp > buffer) {
  			do {
! 			    bp--, w -> _curx--;
  			} while (!isspace (*bp) && bp > buffer);
  			if (isspace (*bp))
! 			    bp++, w -> _curx++;
  		    }
  		    wclrtoeol (w);
  		    break;
  		}
--- 759,777 ----
  		if (c == WERASC) {
  		    if (bp <= buffer)
  			continue;
+ 		    getyx(w, y, x);
  		    do {
! 			bp--, x--;
  		    } while (isspace (*bp) && bp > buffer);
  
  		    if (bp > buffer) {
  			do {
! 			    bp--, x--;
  			} while (!isspace (*bp) && bp > buffer);
  			if (isspace (*bp))
! 			    bp++, x++;
  		    }
+ 		    wmove(w, y, x);
  		    wclrtoeol (w);
  		    break;
  		}
***************
*** 830,835 ****
--- 840,846 ----
              nwait;
      char   *cp;
      register struct line   *lbottom;
+     int x, y;
  
      did_less++;
  
***************
*** 843,848 ****
--- 854,860 ----
      nwait = 0;
      wrefresh (w);
  
+     getmaxyx(w, y, x);
      for (;;) {
  	if (nfresh || nwait) {
  	    nfresh = 0;
***************
*** 856,862 ****
  
  	    if (ltop == NULL)
  		if (fin) {
! 		    (void) lgo (ltail -> l_no - w -> _maxy + 1);
  		    if (ltop == NULL)
  			ltop = lhead;
  		}
--- 868,874 ----
  
  	    if (ltop == NULL)
  		if (fin) {
! 		    (void) lgo (ltail -> l_no - y + 1);
  		    if (ltop == NULL)
  			ltop = lhead;
  		}
***************
*** 961,967 ****
  		break;
  
  	    case 'G': 
! 		if (lgo (n ? n : ltail -> l_no - w -> _maxy + 1))
  		    nfresh++;
  		break;
  
--- 973,979 ----
  		break;
  
  	    case 'G': 
! 		if (lgo (n ? n : ltail -> l_no - y + 1))
  		    nfresh++;
  		break;
  
***************
*** 1027,1032 ****
--- 1039,1048 ----
      register int    x,
                      y;
  
+     register int    maxx,
+ 		    maxy;
+ 
+     getmaxyx(w, maxy, maxx);
      switch (c) {
  	default: 
  	    if (!isascii (c)) {
***************
*** 1050,1057 ****
      if (w != Scan)
  	return waddch (w, c);
  
!     if ((x = w -> _curx) < 0 || x >= w -> _maxx
! 	    || (y = w -> _cury) < 0 || y >= w -> _maxy)
  	return DONE;
  
      switch (c) {
--- 1066,1073 ----
      if (w != Scan)
  	return waddch (w, c);
  
!     getyx(w, y, x);
!     if (x < 0 || x >= maxx || y < 0 || y >= maxy)
  	return DONE;
  
      switch (c) {
***************
*** 1062,1068 ****
  	    break;
  
  	case '\n': 
! 	    if (++y < w -> _maxy) 
  		(void) waddch (w, c);
  	    else
  		wclrtoeol (w);
--- 1078,1084 ----
  	    break;
  
  	case '\n': 
! 	    if (++y < maxy) 
  		(void) waddch (w, c);
  	    else
  		wclrtoeol (w);
***************
*** 1069,1075 ****
  	    break;
  
  	default: 
! 	    if (++x < w -> _maxx) 
  		(void) waddch (w, c);
  	    break;
      }
--- 1085,1091 ----
  	    break;
  
  	default: 
! 	    if (++x < maxx) 
  		(void) waddch (w, c);
  	    break;
      }
***************
*** 1095,1100 ****
--- 1111,1118 ----
  static	linsert (w)
  WINDOW *w;
  {
+     int origx, origy, maxx, maxy; /* origy and maxy are ignored */
+     register int x;
      register char  *cp;
      register struct line   *lp;
  
***************
*** 1101,1108 ****
      if ((lp = (struct line  *) calloc ((unsigned) 1, sizeof *lp)) == NULL)
  	adios (NULLCP, "unable to allocate line storage");
  
      lp -> l_no = (ltail ? ltail -> l_no : 0) + 1;
!     lp -> l_buf = getcpy (w -> _y[w -> _cury]);
      for (cp = lp -> l_buf + strlen (lp -> l_buf) - 1; cp >= lp -> l_buf; cp--)
  	if (isspace (*cp))
  	    *cp = NULL;
--- 1119,1134 ----
      if ((lp = (struct line  *) calloc ((unsigned) 1, sizeof *lp)) == NULL)
  	adios (NULLCP, "unable to allocate line storage");
  
+     getmaxyx(w, maxy, maxx);
+     getyx(w, origy, origx);
      lp -> l_no = (ltail ? ltail -> l_no : 0) + 1;
!     lp -> l_buf = malloc(maxx + 1);
!     if (lp -> l_buf == 0)
! 	adios(NULLCP, "unable to allocate string storage");
!     for (x = 0; x < maxx; ++x)
! 	lp -> l_buf[x] = mvwinch(w, origy, x);
!     lp -> l_buf[maxx] = '\0';
!     wmove(w, origy, origx);
      for (cp = lp -> l_buf + strlen (lp -> l_buf) - 1; cp >= lp -> l_buf; cp--)
  	if (isspace (*cp))
  	    *cp = NULL;
*** vmhsbr.orig.c	Thu Apr 25 20:47:46 1991
--- vmhsbr.c	Sun Mar 10 13:34:44 1991
***************
*** 44,50 ****
  
      if ((cp = getenv ("MHVDEBUG"))
  	    && *cp
! 	    && (fp = fopen (sprintf (buffer, "%s.out", invo_name), "w"))) {
  	(void) fseek (fp, 0L, 2);
  	fprintf (fp, "%d: rcinit (%d, %d)\n", getpid (), rfd, wfd);
  	(void) fflush (fp);
--- 45,52 ----
  
      if ((cp = getenv ("MHVDEBUG"))
  	    && *cp
! 	    && sprintf (buffer, "%s.out", invo_name) > 0
! 	    && (fp = fopen (buffer, "w"))) {
  	(void) fseek (fp, 0L, 2);
  	fprintf (fp, "%d: rcinit (%d, %d)\n", getpid (), rfd, wfd);
  	(void) fflush (fp);
***************
*** 101,107 ****
      if (read (PEERrfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc))
  	return rclose (rc, "read from peer lost(1)");
      if (rc -> rc_len) {
! 	if ((rc -> rc_data = malloc ((unsigned) rc -> rc_len)) == NULL)
  	    return rclose (rc, "malloc of %d lost", rc -> rc_len);
  	if (read (PEERrfd, rc -> rc_data, rc -> rc_len) != rc -> rc_len)
  	    return rclose (rc, "read from peer lost(2)");
--- 103,109 ----
      if (read (PEERrfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc))
  	return rclose (rc, "read from peer lost(1)");
      if (rc -> rc_len) {
! 	if ((rc -> rc_data = malloc ((unsigned) rc -> rc_len + 1)) == NULL)
  	    return rclose (rc, "malloc of %d lost", rc -> rc_len);
  	if (read (PEERrfd, rc -> rc_data, rc -> rc_len) != rc -> rc_len)
  	    return rclose (rc, "read from peer lost(2)");

---------- End of patches

gs@ynetfrsp.inria.fr (gs@ynetfrsp.inria.fr) (04/26/91)

In article <steve.672572789@azh01.gapos.bt.co.uk>, steve@gapos.bt.co.uk
(Steve Rooke) writes:
> 
> I have just started to get MH 6.7.1 running under Uniplus+ SVR2 on our
> machines here but have hit a problem with vmh.  When I run vmh -vmhproc msh
> the screen splits normally, the top window shows a scan of msgbox and I
> get the (vmh) prompt in the bottom window okay.  If I scan then the bottom
> screen fills up but then immediately clears and I am left with a blank 
> bottom window apart from the (top: bottom:) prompt.  A refresh will not
> repaint the missing text and I can get the next screen but all I see is
> a quick flash of the bottom line of text before it disappears.


We had the same problem here (on DPX2000 in SPIX32). The only solution
we have found is
the following correction in the code of vmh.c :

in the routine WINless: 
 
.........

#endif	notdef
		    lbottom = ltail;
		    while (waddstr (w, "~\n") != ERR)
			continue;
		}
		else {
		    wrefresh (w); 
		    return 0;
		}

	    if (!nwait)        <----------   suppress this line
		wrefresh (w);  <----------   suppress this line 
	}

........

steve@gapos.bt.co.uk (Steve Rooke) (04/30/91)

In <2114@seti.inria.fr> gs@ynetfrsp.inria.fr (gs@ynetfrsp.inria.fr) writes:


>In article <steve.672572789@azh01.gapos.bt.co.uk>, steve@gapos.bt.co.uk
>(Steve Rooke) writes:
>> 
>> I have just started to get MH 6.7.1 running under Uniplus+ SVR2 on our
>> machines here but have hit a problem with vmh.  When I run vmh -vmhproc msh
>> the screen splits normally, the top window shows a scan of msgbox and I
>> get the (vmh) prompt in the bottom window okay.  If I scan then the bottom
>> screen fills up but then immediately clears and I am left with a blank 
>> bottom window apart from the (top: bottom:) prompt.  A refresh will not
>> repaint the missing text and I can get the next screen but all I see is
>> a quick flash of the bottom line of text before it disappears.


>We had the same problem here (on DPX2000 in SPIX32). The only solution
>we have found is
>the following correction in the code of vmh.c :

>in the routine WINless: 
> 
>.........

>#endif	notdef
>		    lbottom = ltail;
>		    while (waddstr (w, "~\n") != ERR)
>			continue;
>		}
>		else {
>		    wrefresh (w); 
>		    return 0;
>		}

>	    if (!nwait)        <----------   suppress this line
>		wrefresh (w);  <----------   suppress this line 
>	}

>........

Well does it work okay when you scroll the screen?  I doubt it.  I guess you
have the same problem as me, the original BSD code has a habit of poking
around a the window structure directly.  Unfortunately it assumes that the
characters are stored as char *'s but, as in my case, they are unsigned
short *'s to allow extra room for attributes.  MH initially writes it's
output into the window, then reads it back into a structure (so that it
can scroll the screen), it then writes it's idea of the screen back to the
window and then calls wrefresh (as pointed to above).  If you do not have
char *'s then the read back screen will probably be blank and the screen
will flash initially with the text and then will blank when it calls the
wrefresh.

David Fiander sent some patches to me (and posted them here a day or two ago)
that fix the window dependencies for this problem.  There is also another
problem with long lines wrapping the window.  If you have lines of text
that wrap the window you will only see the tail end when the wrefresh is
called.  You will not see this problem if Show is using an mhl filter as this
splits up long lines so that they show correctly on the screen.  I have some
patches that cure this problem and could post as a diff on David's work
if wanted.

Cheers
Steve
-- 
Steve Rooke  steve@gapos.bt.co.uk  (...mcsun!ukc!gapos!steve)  UK + 394 693595
BT, CS/OPSE, Area 106, Anzani House,  |  Live to Hack -
Trinity Ave, FELIXSTOWE, Suffolk, UK  |       Hack to Live.
#include <std/disclaimer>             |             The_Caged_Lion - DoD #0287