Re: Word breaks ?
Re: Word breaks ?
- Subject: Re: Word breaks ?
- From: Douglas Davidson <email@hidden>
- Date: Thu, 2 May 2002 09:56:44 -0700
On Thursday, May 2, 2002, at 07:21 AM, RFM wrote:
I haven't been able to find any Cocoa API calls related to word
breaks in a block of text in either NSLayoutManager, NSTextContainer, or
NSTextStorage. I'm trying to get the fragment rectangle for each word in
a block of text without having to scan for blanks in the text or
accumulate rectangles on a character basis. Is there anything available
that allows for obtaining the 'NSRange' of a word(s) in the text and
then from there getting the surrounding rectangle(s) of the word ??
Remember the superclasses...NSTextStorage is a subclass of
NSMutableAttributedString, which in turn is a subclass of
NSAttributedString. The AppKit defines several methods for dealing with
word and line boundaries as categories on NSAttributedString; depending
on what you want, there are
- (unsigned)lineBreakBeforeIndex:(unsigned)location
withinRange:(NSRange)aRange;
- (NSRange)doubleClickAtIndex:(unsigned)location;
- (unsigned)nextWordFromIndex:(unsigned)location forward:(BOOL)isForward;
The first is used by the typesetter to determine appropriate positions
for line breaking when using word wrap mode. The second is used by the
text view for determining the range selected by a double-click. The
third is used by the text view for things like opt-right-arrow == move
word forward. There is also an NSTextView method,
- (NSRange)selectionRangeForProposedRange:(NSRange)proposedCharRange
granularity:(NSSelectionGranularity)granularity;
which, when granularity is NSSelectByWord, will return the corresponding
double-click range.
One thing you will have to remember is that a word may not always lie
entirely on a single line or in a single line fragment. If hyphenation
is on, or if char wrapping is used, or if a word is simply too large to
fit on a line, then a line break can occur in the middle of a word. If
you want a single rectangle, you will need to intersect your word
character ranges with a line character range; otherwise you may need to
use more than one rectangle for a word.
Now, let's turn to the layout manager. One method of interest is
- (NSRect)lineFragmentRectForGlyphAtIndex:(unsigned)glyphIndex
effectiveRange:(NSRangePointer)effectiveRange;
This will get you a rect for the entire line fragment, plus the glyph
range (returned by reference in effectiveRange) for the line. To
convert from a glyph range to a character range, use
- (NSRange)characterRangeForGlyphRange:(NSRange)glyphRange
actualGlyphRange:(NSRangePointer)actualGlyphRange;
When you want to get rects for various ranges, you can use methods like
- (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange
inTextContainer:(NSTextContainer *)container;
- (NSRectArray)rectArrayForCharacterRange:(NSRange)charRange
withinSelectedCharacterRange:(NSRange)selCharRange
inTextContainer:(NSTextContainer *)container rectCount:(unsigned
*)rectCount;
- (NSRectArray)rectArrayForGlyphRange:(NSRange)glyphRange
withinSelectedGlyphRange:(NSRange)selGlyphRange
inTextContainer:(NSTextContainer *)container rectCount:(unsigned
*)rectCount;
The first of these returns a rect that encloses the entire range
specified; thus if you pass it glyphs that lie on more than one line,
the resulting rect will probably be larger than you want. If you pass
it a glyph range that lies entirely in one line, it should do what you
are asking for. The next two are a little more complicated; they are
the methods used for determining the rects used when drawing backgrounds
and especially selections. If you select a range of text, the gray
region will show you graphically the rects that you would get from these
methods. The reason for the selCharRange or selGlyphRange argument is
that when we are drawing the background for a particular range, we may
be dealing with some subrange of the selected range, but in some cases
we need to know what the entire selected range is to draw correctly. If
you're not interested in selected ranges, do as the header suggests and
pass {NSNotFound, 0} for those arguments.
Hope this helps; if you need more information, post another question.
Douglas Davidson
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.