[net.micro.mac] TextEdit Bugs

dubois@uwmacc.UUCP (Paul DuBois) (09/08/86)

I am going to conjecture that there is a certain bug in TextEdit,
and a depending-on-your-taste-it's-a bug as well.

Both of these relate to the use of word wrap in a TE record
(that is, when (**hTE).crOnly = 0).

Certain bug:  type a few lines into a text window, putting returns
at the end of each line, say

  ________________________________________
  |abc
  |def
  |ghi
  |

You can either put a cr at the end of the last line or not.  Now
click the mouse below the text and swipe up till the mouse is just
after the f or the c - that is, so that all lines below the mouse
are inverted, plus everything *after* the text on the line on which
the mouse is.

Hit backspace (or Cut or Clear).

All the selected text disappears, and you have a blinking caret after
the (now-)last line, which is as it should be.  But the rest of that
same line (where there is no text) remains inverted.  I find this
highly reproducible, both in my own programs, and in other applications
using word wrap in text records (e.g., the STR editing window in ResEdit).
No big deal, right.  Wrong.  I've noticed that this results in later
screwups in the window of caret activating/deactivating - sometimes
two carets appear, or the caret doesn't go away when the window is
deactivated.

Depending-on-taste bug:

It seems to me that the purpose of word wrap is to keep things from
disappearing off the right end of the view rectangle (assuming a
properly set up destination rectangle), and indeed, when you are
typing text words get shoved down to the next line if they'd go
off the right end.  But try this:  type some stuff almost to the
right edge.  Then type spaces.  You caret disappears.  It doesn't
wrap.  Clicking in the text puts the caret at the right spot, clicking
below the text makes it "go away" - it's really at the end of the
line with all the spaces at the end of it.  **That is, it's NOT
in the view rectangle.**

Can anyone confirm this, or (preferably) tell me that I'm doing
something wrong, and what to do instead?

-- 
Paul DuBois     UUCP: {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois    |
                ARPA: dubois@easter                               --+--
                                                                    |
Begin at my sanctuary...                                            |
                          Ezekiel 9:6

dubois@uwmacc.UUCP (Bill Winkle) (09/16/86)

This is a reply to an article on info-mac

> Date: Sun, 14 Sep 86 02:36 N
> From: <INFOEARN%HLERUL5.BITNET@WISCVM.WISC.EDU>
> Subject: RE:TextEdit Bugs


> I also have a third bug to add to the list.  It isn't a serious bug, but it's
> something you have to be aware of when you're programming with TextEdit.
> Several text editors, including MockWrite and MiniEdit from Macintosh Revealed,
> always make sure the edit window is completely filled with text, if possible.
> This means that they scroll their text down whenever empty space appears at
> the bottom after a cut or paste.  Part of checking how far to scroll down is
> looking at the value of nLines which tells you how many lines the TextEdit
> record has.

> However, if the caret is all the way at the end of the text record on an empty
> line, TextEdit doesn't consider this a line and therefore nLines is one too
> little.  This means that our text editor (MockWrite) will not scroll down far
> enough and the caret will be on a nonexisting and invisible line!  As soon as
> you type a character, TextEdit creates the new line, the text editor will see
> scrolling is necessary and your caret comes back into view.  But once you type
> a backspace, the line is destroyed and the caret vanishes again.

I don't think this is a bug in TextEdit, it's a bug in the programs
that use TextEdit.  I know that I consider Chernicoff's code wrong,
from looking at it (I haven't actually used it).  In any case, here's
a function I use to determine the number of display lines a text record
takes.  It may not be intuitive, but it's correct.  Programs that
fiddle with text should make sure to do similar tests.


/*
    Determine number of display lines needed for text record.
    If empty, need one line.  If there's a carriage return at
    the end, then need another line to allow placement of caret
    at beginning of last line plus one.
*/

DisplayCount (te)
TEHandle    te;
{
int        nLines, teLength;

    nLines = (**te).nLines;
    teLength = (**te).teLength;
    if (teLength == 0 || (*((**te).hText))[teLength-1] == '\r')
        ++nLines;
    return (nLines);
}


You run into a similar problem determining which line the caret
is actually in.  Again, it's not a bug in TextEdit, you just have
to be careful.  Again, I think (but cannot verify without testing)
that Chernicoff's code is wrong.  Here's what I use.  (This is a
dumb algorithm; it really should do binary search).


/*
    Return the line number that the caret (or the beginning of
    the currently selected text) is in.  Value returned is in
    the range 0..(**te).nLines.  If = (**te).nLines, the
    caret is past the last line.  The only special case to watch
    out for is at the very end of the text.  If the last character
    is not a carriage return, then the caret is on the (nLines-1)th
    line, not the (nLines)th line.
*/

GetCaretPos (te)
TEHandle    te;
{
int    i;
int    nLines;
int    teLength;
int    selStart;
int    lineStart;

    selStart = (**te).selStart;
    nLines = (**te).nLines;
    teLength = (**te).teLength;

    if (selStart == teLength)
    {
	if (teLength != 0 && (*(**te).hText))[teLength-1] != '\r')
	    return (nLines - 1);
	return (nLines);
    }

    for (i = 0; /* empty */; ++i)
    {
        if ((lineStart = (**te).lineStarts[i]) >= selStart)
            break;    /* succeeds eventually */
    }

    if (lineStart != selStart)
        --i;
    return (i);
}


I hope this saves someone some trouble.
-- 
Paul DuBois     UUCP: {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois    |
                ARPA: dubois@easter                               --+--
                                                                    |
"If it works, I didn't write it."                                   |

dlc@lanl.ARPA (Dale Carstensen) (09/18/86)

> > From: <INFOEARN%HLERUL5.BITNET@WISCVM.WISC.EDU>
> From: dubois@uwmacc.UUCP (Bill Winkle @ Brain-Dead Software)

The above two discussed keeping the TextEdit caret in the visible window
when the caret is on the last line of the TE text.

A simpler way to locate the caret exists.  A TERec field named selRect is a
Rect which contains the caret when no selection is active (selStart is the
same as selEnd).  So all that needs to be done to make sure the caret is
in the visible window, is to make sure that Rect is in the visible window.
A lot of consideration of font size parameters is also not necessary.

Unfortunately, IM doesn't say much about selRect.  There are some strange
special values that appear in it.  So, to figure out how to write your
program, you need to do a lot of peering at selRect with MacsBug or something
that displays it independently.  I think I did a fair job in the Aztec C 
version of SKEL that I submitted to info-mac, available in the Sumex archives.

Anything that keeps track of rectangle coordinates for scrolling in windows
can be confusing, so expect to have to think really hard about how to write
your scrolling routines, and expect a few surprises from the trap handlers.

  Dale Carstensen
  dlc@lanl.arpa
  {cmcl2|ihnp4}!lanl!dlc.uucp