[net.bugs] CURSES - sub-windows bugs and features...

idallen@watmath.UUCP (08/15/84)

These apply to Curses as distributed with 4.2bsd and dated June/July 1983.
They probably also apply to 4.1bsd curses.

>> ONE ------------------------------------------

    If you add text to a sub-window, and refresh the parent window,
    the text in the sub-window is shown correctly.  But, if you then
    clear or erase or insert/delete a character in the sub-window, or
    clear to end of line, or clear to the bottom of the sub-window, 
    and refresh the parent window, nothing happens.  In fact, the only
    change you can make to a sub-window that will be noticed by the
    parent window is to add a character or string.

Is this a bug or a feature?

Analysis:
    When you add a character to a window, the line-by-line change
    flags are updated for all related (by parent or child) windows.
    So, when you refresh any of the related windows, the right thing
    happens.  But when a window is erased, or a line cleared, the
    normal add-character function is bypassed in favour of stomping
    down blanks in a hurry.  Only the change flags for the particular
    window being erased are updated.  Related windows are not told, and
    refreshing them has no effect.  I think this is a bug, not a
    feature.  If you can add text to a sub-window and make it visible
    by refreshing the parent, then you should be able to delete it
    using the same refresh method.  Comments?

>> TWO ------------------------------------------

    Sub-windows don't get told about line movement in their parent
    windows, nor vice versa.  If you insert or delete a line in, or
    scroll, the parent window, the sub-window shows the right lines,
    but in the wrong order.  The same problem is evident in parent
    windows for actions on their sub-windows.  The result is two
    different screen views, when the parent and sub windows are
    alternately touched and refreshed.

This has to be a bug.

Analysis:
    A sub-window is just an edge vector of pointers to positions in the
    parent window's lines.  When the parent shifts the pointers in its
    own edge vector to move or deleta a line, it doesn't tell the
    sub-window.  The sub-window's pointers still point to the same lines
    in the old order.  Refreshing the sub-window puts out the lines in
    the old order.  This has the curious effect of making a blank line
    appear in the middle of the screen when the parent deletes the
    corresponding line, and making the bottom line go blank when the
    parent inserts a line.  Scrolling a parent window has no effect on
    the sub-window, since the sub-window still has the lines in the old
    order.  This can produce delightful (?) effects when the parent
    window and sub-window are alternately touched and refreshed. 
    Conversely, if you scroll a sub-window, or insert or delete lines
    therein, the parent window doesn't get told, and the refreshing of
    the parent and sub windows gives two different views.
------------------------------------------------------------------------------
It looks to me like sub-windows were added to CURSES at the last
minute, and someone forgot to integrate them with all the possible
operations possible on windows.  One slow and expensive fix to the above
would be to make the blank-writing that erases a window use addch().
This won't help the delch() and insch() functions, mind you.
Another (better?) fix would be to make all the routines that set the line
change flags do it for all related windows too, like addch() does.
-- 
        -IAN!  (Ian! D. Allen)      University of Waterloo

laman@sdcsvax.UUCP (Mike Laman) (08/16/84)

>These apply to Curses as distributed with 4.2bsd and dated June/July 1983.
>They probably also apply to 4.1bsd curses.
>
>	:
>	:
>	:
>
>Analysis:
>    A sub-window is just an edge vector of pointers to positions in the
>    parent window's lines.  When the parent shifts the pointers in its
>    own edge vector to move or delete a line, it doesn't tell the
>    sub-window.  The sub-window's pointers still point to the same lines
>    in the old order.  Refreshing the sub-window puts out the lines in
>    the old order.  This has the curious effect of making a blank line
>    appear in the middle of the screen when the parent deletes the
>    corresponding line, and making the bottom line go blank when the
>    parent inserts a line.  Scrolling a parent window has no effect on
>    the sub-window, since the sub-window still has the lines in the old
>    order.  This can produce delightful (?) effects when the parent
>    window and sub-window are alternately touched and refreshed.
>    Conversely, if you scroll a sub-window, or insert or delete lines
>    therein, the parent window doesn't get told, and the refreshing of
>    the parent and sub windows gives two different views.
>
>It looks to me like sub-windows were added to CURSES at the last
>minute, and someone forgot to integrate them with all the possible
>operations possible on windows.  One slow and expensive fix to the above
>would be to make the blank-writing that erases a window use addch().
>This won't help the delch() and insch() functions, mind you.
>Another (better?) fix would be to make all the routines that set the line
>change flags do it for all related windows too, like addch() does.
>--
>        -IAN!  (Ian! D. Allen)      University of Waterloo

I don't know how or why, but I fully agree that sub-windows are NOT properly
implemented in 4.2BSD (& 4.1BSD).  But I think there is a better solution than
the one pointed out.  First of all let me point out that when sub windows are
created, the window's text is SEPARATE from original window.  That is the
real problem.  When you add a character to a sub window, the routine doing
the window updating (how ever it does it -- add characters to the particular
window's line, shuffle lines, ...) would have to update the appropriate
sections of EACH window associated with the given window (original window
and each other sub window, and sub windows of this window, ...).  The
information is available since the WINDOW structure contains pointers to
a linked list of all the related windows (see "_nextp" and "_origp").
As I mentioned earlier, the real killer is that EACH routine would be
responsible for adding the information to each associated window.

This means you would have to modify:
"box()", "wclear()", "wclrtobot()", "wclrtoeol()", "wdelch()",
"wdeleteln()", "werase()", "wgetch()", "winsch()", "winsertln()", "mvprintw()",
"mvwprintw()", "mvscanw()", "mvwscanw()", "overlay()", "overwrite()",
"printw()", "wprintw()", "scanw()", "wscanw()", and "scroll()" [Don't let
the macros "addstr()", ... fool ya.  They reference the above functions.].
Luckily "waddch()" updates associated windows and since "waddstr()" is a loop
of calls to "waddch()", "waddstr()" works too.  I also noticed that
"touchwin()" touches all the associated windows.  This may give a little
glimpse of hope to work around the deficiency of curses.

The reason I enumerated the function requiring changes is to point out two
observations:

	1. The changes will be numerous and painful (Try to imagine adding
	   code to "wdeleteln()" for the case where "wdeleteln()" is called
	   with a window SMALLER than the window of which is a sub window!
	   You can't just shuffle lines on the original window.  VERY PAINFUL.)
	2. The current scheme doesn't seem to offer the correct handling of
	   sub windows.  #1 seems to help illustrate this point.

I suggest the correct solution be to have sub windows SHARE the window text
with the information in the WINDOW header telling what part of the lines it
"owns".  Now we don't have the problem with duplicating data through out all
the associated windows, and we won't have to modify the functions (and any other
functions that get created as time goes by).  Hmmm... "delwin()" would have to
be modified not to free the text area if it were a sub window, but that would
be trivial.

After thinking about this I decided to look at System V.2 curses.  Guess how
"they" do it...  That's right.  They used the scheme I just suggested.
(Well, at least someone else agrees with me on this one.)

As for the problem at hand, I guess you'll have to be happy with "overwrite()"
(and "overlay()"), until you get a System V.2 to use.  I don't even think
"touchwin()" will be much help.  I'm not planning on doing this change to 4.2.
I'm busy this weekend   :-)    and the next weekend...  and the next weekend...

		Mike Laman, NCR Torrey Pines
		UUCP: {ucbvax,philabs,sdcsla}!sdcsvax!laman