diff --git a/Headers/gnustep/gui/NSLayoutManager.h b/Headers/gnustep/gui/NSLayoutManager.h index 6047dbe90..8a1f36be6 100644 --- a/Headers/gnustep/gui/NSLayoutManager.h +++ b/Headers/gnustep/gui/NSLayoutManager.h @@ -41,34 +41,37 @@ #import @class NSTypesetter; -@class NSGlyphGenerator; @class NSTextView; @class NSWindow; -@class NSColor; @class NSRulerView; @class NSParagraphStyle; -@class NSRulerMarker; +@class NSView; + +// These are unclear: @class NSBox; -@class NSTextField; -@class NSMatrix; +@class NSGlyphGenerator; +@class NSSortedArray; @class NSTabWell; @class NSStorage; -@class NSRunStorage; -@class NSSortedArray; -@class NSView; -@class NSEvent; - +@class NSTextField; +@class NSMatrix; // Michael's botch list. :-) @class GSRunStorage; -// These glyph attributes are used only inside the glyph generation machinery, but must be shared between componenets. +/* + These glyph attributes are used only inside the glyph generation machinery, + but must be shared between componenets. +*/ enum _NSGlyphAttribute { NSGlyphAttributeSoft = 0, NSGlyphAttributeElastic = 1, NSGlyphAttributeInscribe = 5, }; -// The inscribe attribute of a glyph determines how it is laid out relative to the previous glyph. +/* + The inscribe attribute of a glyph determines how it is laid out relative to + the previous glyph. +*/ typedef enum { NSGlyphInscribeBase = 0, NSGlyphInscribeBelow = 1, @@ -79,25 +82,35 @@ typedef enum { @interface NSLayoutManager : NSObject { + BOOL _backgroundLayout; + BOOL _showsInvisibleChars; + BOOL _showsControlChars; + float _hyphenationFactor; + BOOL _usesScreenFonts; + BOOL _finished; NSTextStorage *_textStorage; - NSGlyphGenerator *_glyphGenerator; NSTypesetter *_typesetter; + /* + These three arrays must bekeppt in step. The size of all is + _glyph_max_count with _glyph_count used entries. + */ + unsigned _glyph_count; + unsigned _glyph_max_count; + NSGlyph *_glyphs; + unsigned *char_glyph_mapping; + unsigned *glyph_attrs; + + NSGlyphGenerator *_glyphGenerator; NSMutableArray *_textContainers; NSStorage *_containerUsedRects; - NSStorage *_glyphs; // GS data storage. - GSRunStorage *containerRuns; - GSRunStorage *fragmentRuns; - GSRunStorage *locationRuns; + GSRunStorage *_containerRuns; + GSRunStorage *_fragmentRuns; + GSRunStorage *_locationRuns; - NSRunStorage *_containerRuns; - NSRunStorage *_fragmentRuns; - NSRunStorage *_glyphLocations; - NSRunStorage *_glyphRotationRuns; - NSRect _extraLineFragmentRect; NSRect _extraLineFragmentUsedRect; NSTextContainer *_extraLineFragmentContainer; @@ -148,14 +161,6 @@ typedef enum { NSMatrix *_rulerAccViewFixedLineHeightButtons; NSRange _newlyFilledGlyphRange; - -// Michael additions. - BOOL _backgroundLayout; - BOOL _showsInvisibleChars; - BOOL _showsControlChars; - float _hyphenationFactor; - BOOL _usesScreenFonts; - BOOL finished; } /**************************** Initialization ****************************/ @@ -271,10 +276,11 @@ typedef enum { - (void)setIntAttribute:(int)attributeTag value:(int)val forGlyphAtIndex:(unsigned)glyphIndex; // This method is used by the NSGlyphGenerator to set attributes. It is not usually necessary for anyone but the glyph generator (and perhaps the typesetter) to call it. It is provided as a public method so subclassers can extend it to accept other glyph attributes. To add new glyph attributes to the text system you basically need to do two things. You need to write a rulebook which will generate the attributes (in rulebooks attributes are identified by integer tags). Then you need to subclass NSLayoutManager to provide someplace to store the new attribute and to override this method and -attribute:forGlyphAtIndex: to understand the integer tag which your new rulebook is generating. NSLayoutManager's implementation understands the glyph attributes which it is prepared to remember. Your override should pass any glyph attributes it does not understand up to the superclass's implementation. -// This method will cause glyph generation as necessary to answer the question. - (int)intAttribute:(int)attributeTag forGlyphAtIndex:(unsigned)glyphIndex; - // This returns the value for the given glyph attribute at the glyph index specified. Most apps will not have much use for this info but the typesetter and glyph generator might need to know about certain attributes. You can override this method to know how to return any custom glyph attributes you want to support. +// This returns the value for the given glyph attribute at the glyph index specified. Most apps will not have much use for this info but the typesetter and glyph generator might need to know about certain attributes. You can override this method to know how to return any custom glyph attributes you want to support. + +- (void)setAttachmentSize:(NSSize)attachmentSize forGlyphRange:(NSRange)glyphRange; /************************ Set/Get layout attributes ************************/ diff --git a/Source/NSLayoutManager.m b/Source/NSLayoutManager.m index b4a37654f..c920cafa0 100644 --- a/Source/NSLayoutManager.m +++ b/Source/NSLayoutManager.m @@ -298,6 +298,8 @@ static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1) } @end + + @implementation NSLayoutManager - (id) init @@ -308,13 +310,18 @@ static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1) _delegate = nil; _textContainers = [[NSMutableArray alloc] initWithCapacity: 2]; - containerRuns = [GSRunStorage new]; - fragmentRuns = [GSRunStorage new]; - locationRuns = [GSRunStorage new]; + _containerRuns = [GSRunStorage new]; + _fragmentRuns = [GSRunStorage new]; + _locationRuns = [GSRunStorage new]; return self; } +- (void) dealloc +{ + [super dealloc]; +} + // // Setting the text storage // @@ -380,12 +387,21 @@ static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1) changeInLength: (int)lengthChange actualCharacterRange: (NSRange*)actualRange { + // FIXME + + // Currently we don't have context information + if (actualRange) + { + *actualRange = aRange; + } } - (void) invalidateLayoutForCharacterRange: (NSRange)aRange isSoft: (BOOL)flag actualCharacterRange: (NSRange*)actualRange { + + [self _doLayout]; } - (void) invalidateDisplayForCharacterRange: (NSRange)aRange @@ -398,6 +414,15 @@ static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1) - (void) textContainerChangedGeometry: (NSTextContainer*)aContainer { + unsigned first = 0; + + // find the first character in that text container + + // invalidate the layout from here on + [self invalidateLayoutForCharacterRange: + NSMakeRange(first, [_textStorage length] - first) + isSoft: NO + actualCharacterRange: NULL]; } - (void) textContainerChangedTextView: (NSTextContainer*)aContainer @@ -410,28 +435,34 @@ static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1) changeInLength: (int)lengthChange invalidatedRange: (NSRange)invalidatedRange { +/* NSLog(@"NSLayoutManager was just notified that a change in the text storage occured."); NSLog(@"range: (%d, %d) changeInLength: %d invalidatedRange (%d, %d)", range.location, range.length, lengthChange, invalidatedRange.location, invalidatedRange.length); - -/* - if (mask == NSTextStorageEditedCharacters) - { - aLayoutHole = [[NSLayoutHole alloc] -initWithCharacterRange: invalidatedRange isSoft: NO]; - } - else if (mask == NSTextStorageEditedAttributes) - { - } - else if (mask == NSTextStorageEditedCharacters | NSTextStorageEditedAttributes) - { - } */ - // invalidation should occure here. + int delta = 0; + unsigned last = NSMaxRange(invalidatedRange); - [self _doLayout]; + if (mask & NSTextStorageEditedCharacters) + { + delta = lengthChange; + } + + // hard invalidation occures here. + [self invalidateGlyphsForCharacterRange: range + changeInLength: delta + actualCharacterRange: NULL]; + [self invalidateLayoutForCharacterRange: invalidatedRange + isSoft: NO + actualCharacterRange: NULL]; + + // the following range is soft invalidated + [self invalidateLayoutForCharacterRange: + NSMakeRange(last, [_textStorage length] - last) + isSoft: YES + actualCharacterRange: NULL]; } // @@ -543,7 +574,7 @@ initWithCharacterRange: invalidatedRange isSoft: NO]; theLine->glyphRange = glyphRange; ASSIGN(theLine->textContainer, aTextContainer); - [containerRuns insertObject: theLine]; + [_containerRuns insertObject: theLine]; } - (NSRange) glyphRangeForTextContainer: (NSTextContainer*)aTextContainer @@ -551,11 +582,11 @@ initWithCharacterRange: invalidatedRange isSoft: NO]; int i; NSLog(@"glyphRangeForTextContainer: called. There are %d -textContainer(s) in containerRuns.", [containerRuns count]); +textContainer(s) in containerRuns.", [_containerRuns count]); - for (i=0;i<[containerRuns count];i++) + for (i=0;i<[_containerRuns count];i++) { - GSTextContainerLayoutInfo *aNewLine = [containerRuns objectAtIndex: i]; + GSTextContainerLayoutInfo *aNewLine = [_containerRuns objectAtIndex: i]; /* NSLog(@"glyphRangeForTextContainer: (%d, %d)", @@ -582,7 +613,7 @@ aNewLine->glyphRange.length); { GSTextContainerLayoutInfo *theLine; - theLine = [containerRuns objectContainingLocation: glyphIndex]; + theLine = [_containerRuns objectContainingLocation: glyphIndex]; if (theLine) { (NSRange*)effectiveRange = &theLine->glyphRange; @@ -606,7 +637,7 @@ aNewLine->glyphRange.length); aNewLine->lineFragmentRect = fragmentRect; aNewLine->usedRect = usedRect; - [fragmentRuns insertObject: aNewLine]; + [_fragmentRuns insertObject: aNewLine]; } - (NSRect) lineFragmentRectForGlyphAtIndex: (unsigned)glyphIndex @@ -614,7 +645,7 @@ aNewLine->glyphRange.length); { GSLineLayoutInfo *theLine; - theLine = [fragmentRuns objectContainingLocation: glyphIndex]; + theLine = [_fragmentRuns objectContainingLocation: glyphIndex]; if (theLine) { (NSRange*)lineFragmentRange = &theLine->glyphRange; @@ -630,7 +661,7 @@ aNewLine->glyphRange.length); { GSLineLayoutInfo *theLine; - theLine = [fragmentRuns objectContainingLocation: glyphIndex]; + theLine = [_fragmentRuns objectContainingLocation: glyphIndex]; if (theLine) { (NSRange*)lineFragmentRange = &theLine->glyphRange; @@ -684,7 +715,7 @@ forStartOfGlyphRange: (NSRange)glyphRange aNewLine->glyphRange = glyphRange; aNewLine->point = aPoint; - [locationRuns insertObject: aNewLine]; + [_locationRuns insertObject: aNewLine]; } - (NSPoint) locationForGlyphAtIndex: (unsigned)glyphIndex @@ -696,7 +727,7 @@ forStartOfGlyphRange: (NSRange)glyphRange { GSLineLayoutInfo *theLine; - theLine = [locationRuns objectContainingLocation: glyphIndex]; + theLine = [_locationRuns objectContainingLocation: glyphIndex]; if (theLine) { @@ -864,11 +895,21 @@ be redrawn when a range of glyphs changes. */ - (void) getFirstUnlaidCharacterIndex: (unsigned*)charIndex glyphIndex: (unsigned*)glyphIndex { + if (charIndex) + *charIndex = [self firstUnlaidCharacterIndex]; + + if (glyphIndex) + *glyphIndex = [self firstUnlaidGlyphIndex]; } - (unsigned int) firstUnlaidCharacterIndex { - return 0; + return _firstUnlaidCharIndex; +} + +- (unsigned int) firstUnlaidGlyphIndex +{ + return _firstUnlaidGlyphIndex; } // @@ -886,7 +927,18 @@ be redrawn when a range of glyphs changes. */ - (NSFont*) substituteFontForFont: (NSFont*)originalFont { - return originalFont; + NSFont *replaceFont; + + if (_usesScreenFonts) + return originalFont; + + // FIXME: Should check if any NSTextView is scalled or rotated + replaceFont = [originalFont screenFont]; + + if (replaceFont != nil) + return replaceFont; + else + return originalFont; } // @@ -938,9 +990,9 @@ be redrawn when a range of glyphs changes. */ { int firstPosition, lastPosition, i; - for (i=0;i<[fragmentRuns count];i++) + for (i=0;i<[_fragmentRuns count];i++) { - GSLineLayoutInfo *info = [fragmentRuns objectAtIndex: i]; + GSLineLayoutInfo *info = [_fragmentRuns objectAtIndex: i]; /* NSLog(@"i: %d glyphRange: (%d, %d) lineFragmentRect: (%f, %f) (%f, %f)", @@ -954,9 +1006,9 @@ info->lineFragmentRect.size.height); */ } - firstPosition = [fragmentRuns indexOfObjectContainingLocation: glyphRange.location]; - lastPosition = [fragmentRuns -indexOfObjectContainingLocation: (glyphRange.location+glyphRange.length-3)]; + firstPosition = [_fragmentRuns indexOfObjectContainingLocation: glyphRange.location]; + lastPosition = [_fragmentRuns + indexOfObjectContainingLocation: (glyphRange.location+glyphRange.length-3)]; NSLog(@"glyphRange: (%d, %d) position1: %d position2: %d", glyphRange.location, glyphRange.length, firstPosition, lastPosition); @@ -965,13 +1017,13 @@ glyphRange.location, glyphRange.length, firstPosition, lastPosition); { if (lastPosition == -1) { - lastPosition = [fragmentRuns count] - 1; // FIXME + lastPosition = [_fragmentRuns count] - 1; // FIXME NSLog(@"fixed lastPosition: %d", lastPosition); } for (i = firstPosition; i <= lastPosition; i++) { - GSLineLayoutInfo *aLine = [fragmentRuns objectAtIndex: i]; + GSLineLayoutInfo *aLine = [_fragmentRuns objectAtIndex: i]; NSRect aRect = aLine->lineFragmentRect; aRect.size.height -= 4; @@ -1288,4 +1340,5 @@ substringWithRange: ourRange]); startingAtGlyphIndex: gIndex]; } } + @end