[comp.sys.next] Solution for bug in modifying Text with display disabled

dml@esl.com (Denis Lynch) (03/08/91)

Recently several people have posted comp.sys.next articles about a bug
in Text that I've observed for a long time. (I even reported it to
bug_next). Since this was interfering with performance on a fairly
important app I've been developing, I spent a little more time on it,
and even found an appropriate workaround. (That is, one that's easy,
avoids the problem, and doesn't cost anything.)

So here's the problem:

If you modify text (e.g. with setSelFontStyle:) while the Text's
window's display is disabled, the Text still tries to highlight (or
unhighlight?) the modified text. The visible result of this is
highlighted splotches on whatever view happened to be the last one
drawn in. That frequently turns out to be a menu, in which case the
splotches are there for the rest of the application's life (unless you
happen to do the same thing again and exactly reverse the unwanted
highlighting).

And here's the solution:
1) Before you do disableDisplay to do programmatic things to a Text,
   lock focus on the Text.
2) After you reenableDisplay, unlockFocus on the Text.
3) Ask the Text to display.

If you want to affect scrolling, you can do a scrollSelToVisible while
display is disabled. If you do that, or change the size of the text,
remember to tell the ScrollView to reflectScroll:. And make sure you
do that with display *enabled*.

This seems to work in all the cases we've run into, and has all the
speed advantages that accrue from batching changes with display
disabled.

I presume that if you're going to modify several Text's at once, you
can just pick any one to lockFocus on. Even though the vicimized Text
may get some errant highlights, you're going to completely redisplay
it anyway.

Here's a little sample of what this looks like:

#import <appkit/Text.h>
#import <appkit/Window.h>
#import <appkit/ScrollView.h>

- someMethod
{   /* scrollText is an IB-style scrolling text widget. */
    /* locations is a zero-terminated list of start/end locations to
       bold. (Not a very good way to do this, but fine for the example.
    */
    Text *t = [scrollText docView];
    int *p = locations;

    [t lockFocus];
    [[scrollText window] disableDisplay];
    while (*p) {
	int start = *p++, end = *p++;
	[t setSel: start : end];
	[t setSelFontStyle: NX_BOLD];
    }
    [t scrollSelToVisible];
    [[scrollText window] reenableDisplay];
    [t unlockFocus];
    [t display];
    /* reflectScroll doesn't do anything if display is disabled! */
    [scrollText reflectScroll: [t superview]];
    return self;
}


This little bit works fine as shown, but causes menu splotches if the
lockFocus and unlockFocus are removed.

I hope this helps somebody!

--Denis Lynch, ESL Inc.