[comp.sys.mac.hypercard] How to find the number of lines when they wrap

taylorj@yvax.byu.edu (10/04/90)

The other day when once again faced with the problem that has been plaguing
me and many other HyperCardiacs, namely to figure out how many lines are
actually taken up by the text in a field when it's wrapped, I actually
figured out how to do it!

The problem is that when you ask HyperCard for "the number of lines in
<field>", it tells you the number of lines with returns after them,
regardless of how many times the lines may have been wrapped because they
were too long to fit in the field.

The solution is pretty simple and I can't believe I didn't think of it
before.  The basic idea is to scroll to the end of the field and calculate
the number of lines using the scroll value and the text height:

  select after text of <field>
  get (scroll of <field> + height of <field>) div textHeight of <field>

Here's a complete handler that you can put in the card, background, or stack
script so that you can send a "numLines" message to any field and get the
line count in "the result".  This handler accounts for all possible kinds of
fields.  It temporarily converts non-scrolling fields to scrolling and
adjusts the width to compensate.

on mouseUp
  send numLines to field "Ooglie Booglie"
  put the result
end mouseUp

on numLines
  -- calculates the number of lines in the target field
  -- returns the number of lines in "the result"
  -- counts wrapped lines as separate lines
  -- works with any style of field and with normal or wide margins
  -- the line height must be fixed in HyperCard 2.0
  lock screen
  put the height of the target into oldHeight
  put the style of the target into theStyle
  if theStyle is "scrolling" then
    put the scroll of the target into oldScroll
  else  -- change field to scrolling
    if theStyle is "shadow" then put 13 into extraWidth
    else put 16 into extraWidth
    put the width of the target into oldwidth
    set the width of the target to oldWidth + extraWidth
    set the style of the target to "scrolling"
  end if
  put the textHeight of the target into lineHeight
  set the height of the target to lineHeight
  select after text of the target  -- scroll to end
  put the scroll of the target into scrollCount
  -- put the field back the way it was
  if theStyle is "scrolling" then
    set the scroll of the target to oldScroll
  else
    set the style of the target to theStyle
    set the width of the target to oldwidth
  end if
  set the height of the target to oldHeight
  unlock screen
  return scrollCount div lineHeight + 1
end numLines

In HyperCard 2.0 if text has varying point sizes and the fixedLineHeight is
false you'll get incorrect results.  This can be solved by saving the
fixedLineHeight property and temporarily changing it to true.


Jim Taylor
Microcomputer Support for Curriculum   |
Brigham Young University               |   Bitnet: taylorj@byuvax.bitnet
101 HRCB, Provo, UT  84602             |   Internet: taylorj@yvax.byu.edu

rmh@apple.com (Rick Holzgrafe) (10/06/90)

In article <1627taylorj@yvax.byu.edu> taylorj@yvax.byu.edu writes:
> The basic idea is to scroll to the end of the field and calculate
> the number of lines using the scroll value and the text height

Nifty! But, a warning about a variant that may fail:

I tried this recently but instead of "select after text of <field>" I used 
"set scroll of <field> to 32000". HC 2.0 (I don't know about HC 1.x) pins 
the scroll to reasonable values, so you can then "get scroll" and see what 
the max scroll is. The rub: it doesn't pin the scroll when you lock screen!

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 3-PK |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."