diff --git a/ChangeLog b/ChangeLog index 6368f6155..bed893819 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-02-16 04:14 Alexander Malmberg + + * Headers/gnustep/gui/GSLayoutManager.h, Source/GSLayoutManager.m: + Add methods for setting and getting the extra line fragment + information. + + * Source/GSHorizontalTypesetter.m (-layoutLineNewParagraph:): Set + the extra line fragment information as required. + + * Source/NSLayoutManager.m: Use the extra line fragment information + to position the insertion point properly when it's placed after the + last character in the text. + 2003-02-15 18:22 Alexander Malmberg * Headers/gnustep/gui/NSTextView.h, Source/NSLayoutManager.m, diff --git a/Headers/gnustep/gui/GSLayoutManager.h b/Headers/gnustep/gui/GSLayoutManager.h index 3e7ffa7b4..acaa705b2 100644 --- a/Headers/gnustep/gui/GSLayoutManager.h +++ b/Headers/gnustep/gui/GSLayoutManager.h @@ -266,6 +266,21 @@ manager might be substituting screen fonts. */ effectiveRange: (NSRange *)effectiveGlyphRange; +/* +The typesetter may set this to mark where the rectangle the insertion point +is to be placed if the insertion point is beyond the last character of the +text. The extra text container is reset to nil any time layout is +invalidated. +*/ +-(void) setExtraLineFragmentRect: (NSRect)linefrag + usedRect: (NSRect)used + textContainer: (NSTextContainer *)tc; + +-(NSRect) extraLineFragmentRect; +-(NSRect) extraLineFragmentUsedRect; +-(NSTextContainer *) extraLineFragmentTextContainer; + + /* Extension, but without this, there's no way to get the starting locations of the nominally spaced glyphs. */ - (NSRange) rangeOfNominallySpacedGlyphsContainingIndex:(unsigned int)glyphIndex diff --git a/Source/GSHorizontalTypesetter.m b/Source/GSHorizontalTypesetter.m index 5ee2ae27f..39fc01308 100644 --- a/Source/GSHorizontalTypesetter.m +++ b/Source/GSHorizontalTypesetter.m @@ -187,10 +187,10 @@ the last time or not, we wouldn't need to clear the cache every time */ cache = realloc(cache,sizeof(glyph_cache_t) * cache_size); } - for (g = &cache[cache_length];cache_length < new_length;cache_length++,g++) + for (g = &cache[cache_length]; cache_length < new_length; cache_length++, g++) { g->g = [curLayoutManager glyphAtIndex: cache_base + cache_length - isValidIndex: &valid]; + isValidIndex: &valid]; if (!valid) { at_end = YES; @@ -444,9 +444,9 @@ restart: tindent = [curTextContainer containerSize].width + tindent; remain = NSMakeRect(hindent, - curPoint.y, - tindent - hindent, - line_height + [curParagraphStyle lineSpacing]); + curPoint.y, + tindent - hindent, + line_height + [curParagraphStyle lineSpacing]); } /* @@ -518,6 +518,8 @@ restart: /* Main glyph layout loop. */ + /* TODO: handling of newParagraph is ugly. must be set on all exits + from this loop */ while (1) { // printf("at %3i+%3i\n",cache_base,i); @@ -530,10 +532,16 @@ restart: if (i >= cache_length) { if (at_end) - break; + { + newParagraph = NO; + break; + } [self _cacheGlyphs: cache_length + 16]; - if (i == cache_length) - break; + if (i >= cache_length) + { + newParagraph = NO; + break; + } g = cache + i; } @@ -600,7 +608,10 @@ restart: prev_had_non_nominal_width = NO; if (ch == 0xa) - break; + { + newParagraph = YES; + break; + } if (ch == 0x9) { @@ -810,7 +821,10 @@ restart: lf++; lfi++; if (lfi == num_line_frags) - break; + { + newParagraph = NO; + break; + } first_glyph = i; } else @@ -843,8 +857,6 @@ restart: [self rightAlignLine: line_frags : num_line_frags]; else if ([curParagraphStyle alignment] == NSCenterTextAlignment) [self centerAlignLine: line_frags : num_line_frags]; - - newParagraph = YES; } else { @@ -857,7 +869,6 @@ restart: [self centerAlignLine: line_frags : num_line_frags]; lfi--; - newParagraph = NO; } /* Layout is complete. Package it and give it to the layout manager. */ @@ -930,8 +941,52 @@ restart: line_frags = NULL; } - /* TODO: if we're really at the end, we should probably set the extra - line frag stuff here */ + /* Check if we're at the end. */ + { + BOOL valid; + [curLayoutManager glyphAtIndex: curGlyph + isValidIndex: &valid]; + if (!valid) + { + /* + We've typeset all glyphs, and thus return 2. If we ended with a + new-line, we set the extra line frag rect here so the insertion point + will be properly positioned after a trailing newline in the text. + */ + if (newParagraph) + { + NSRect r, r2, remain; + float hindent, tindent; + + hindent = [curParagraphStyle firstLineHeadIndent]; + tindent = [curParagraphStyle tailIndent]; + if (tindent <= 0.0) + tindent = [curTextContainer containerSize].width + tindent; + line_height = [curFont defaultLineHeightForFont]; + + r = NSMakeRect(hindent, + curPoint.y, + tindent - hindent, + line_height + [curParagraphStyle lineSpacing]); + + r = [curTextContainer lineFragmentRectForProposedRect: r + sweepDirection: NSLineSweepRight + movementDirection: NSLineMoveDown + remainingRect: &remain]; + + if (!NSEqualRects(r, NSZeroRect)) + { + r2 = r; + r2.size.width = 1; + [curLayoutManager setExtraLineFragmentRect: r + usedRect: r2 + textContainer: curTextContainer]; + } + } + return 2; + } + } + if (newParagraph) return 3; else diff --git a/Source/GSLayoutManager.m b/Source/GSLayoutManager.m index 7566e767e..bf4091ba6 100644 --- a/Source/GSLayoutManager.m +++ b/Source/GSLayoutManager.m @@ -1901,6 +1901,12 @@ forStartOfGlyphRange: (NSRange)glyphRange used = NSZeroRect; for (i = 0, lf = tc->linefrags; i < tc->num_linefrags; i++, lf++) used = NSUnionRect(used, lf->used_rect); + + if (container == extra_textcontainer) + { + used = NSUnionRect(used, extra_used_rect); + } + return used; } @@ -2024,6 +2030,32 @@ forStartOfGlyphRange: (NSRange)glyphRange *gindex = [self firstUnlaidGlyphIndex]; } + +-(void) setExtraLineFragmentRect: (NSRect)linefrag + usedRect: (NSRect)used + textContainer: (NSTextContainer *)tc +{ + extra_rect = linefrag; + extra_used_rect = used; + extra_textcontainer = tc; +} + +-(NSRect) extraLineFragmentRect +{ + return extra_rect; +} + +-(NSRect) extraLineFragmentUsedRect +{ + return extra_used_rect; +} + +-(NSTextContainer *) extraLineFragmentTextContainer +{ + return extra_textcontainer; +} + + @end diff --git a/Source/NSLayoutManager.m b/Source/NSLayoutManager.m index 5b9e5fcb5..93d8ac71c 100644 --- a/Source/NSLayoutManager.m +++ b/Source/NSLayoutManager.m @@ -589,13 +589,8 @@ Insertion point positioning and movement. { if (cindex == [[_textStorage string] length]) { - if (!cindex) - { - *fraction = 0.0; - return (unsigned int)-1; - } - *fraction = 1.0; - return [self numberOfGlyphs] - 1; + *fraction = 0.0; + return (unsigned int)-1; } else { @@ -639,12 +634,29 @@ has the same y origin and height as the line frag rect it is in. fractionThrough: &fraction_through]; if (glyph_index == (unsigned int)-1) { - if (num_textcontainers > 0) - *textContainer = 0; - else - *textContainer = -1; - /* TODO: use extra rect, etc. */ - return NSMakeRect(1,1,1,13); + /* Need complete layout information. */ + [self _doLayout]; + if (extra_textcontainer) + { + for (tc = textcontainers, i = 0; i < num_textcontainers; i++, tc++) + if (tc == textcontainers) + break; + NSAssert(i < num_textcontainers, @"invalid extraTextContainer"); + *textContainer = i; + r = extra_rect; + r.size.width = 1; + return r; + } + glyph_index = [self numberOfGlyphs] - 1; + if (glyph_index == (unsigned int)-1) + { + /* No information is available. */ + + /* will be -1 if there are no text containers */ + *textContainer = num_textcontainers - 1; + return NSMakeRect(1, 1, 1, 15); + } + fraction_through = 1.0; } [self _doLayoutToGlyph: glyph_index]; @@ -861,6 +873,8 @@ has the same y origin and height as the line frag rect it is in. } else { + if (i == tc->num_linefrags) + i--, lf--; /* Find the target line. Move at least (should be up to?) distance, and at least one line. */ for (; i >= 0; i--, lf--)