* Source/NSText.m ([NSText -initWithCoder:]):

Retain the decoded background color.

	* Source/NSTextView.m :
	multiple location: don't ignore textContainer's inset
	([NSTextView -initWithCoder:])
	([NSTextView -encodeWithCoder:])
	Encode caret color, textContainer's size and whether the
	textContainer has widthTracksTextView or heightTracksTextView set.
	([NSTextView -sizeToFit]) Change width (height) only if
	is_horizontally_resizable (is_vertically_resizable).
	([NSTextView -scrollRangeToVisible:]) scrolls to the first char of
	the range.
	([NSTextView -invalidateTextContainerOrigin]): Don't ignore inset,
	set the origin so that the justification is preserved even if the
	textContainer's width is larger that the textview's width.
	([NSTextView -updateInsertionPointStateAndRestartTimer:]):
	update and place the insertion point properly.
	([NSTextView -moveDown:]) & ([NSTextView -moveUp:]):
	Don't ignore inset. Make insertion point visible.

	* Source/NSTextField.m ([NSTextField -acceptsFirstResponder:]):
	responds NO if the editing is still in progrss.

	* Source/NSLayoutManager.m
	([NSLayoutManager -drawBackgroundForGlyphRange:atPoint:]):
	Don't ignore textContainer's inset.

	* Source/GSSimpleLayoutManager.m
	Replaced [-drawLinesInLineRange:] with [-drawLinesInLineRange:atPoint:].
	Replaced [-drawSelectionAsRangeNoCaret:] with
	[-drawSelectionAsRangeNoCaret:atPoint:].
	Those replacements make it easier to take inset into account.
	([-lineFragmentUsedRectForGlyphAtIndex:effectiveRange:])
	([-locationForGlyphAtIndex:])
	([-boundingRectForGlyphRange:inTextContainer:])
	([-rectForCharacterIndex:])
	([-setNeedsDisplayForLineRange:inTextContainer:]):
	Various fixes.
	([-textStorage:edited:range:changeInLength:invalidatedRange:])
	Update insertion point if needed (useful when alignment changes).
	([-rebuildForRange:delta:inTextContainer:]):
	Update layout mechanism.

	* Source/NSCell.m
	([NSCell -highlight:withFrame:inView:]):
	Ask the control to draw the background if we are not opaque.
	([NSCell -editWithFrame:inView:editor:delegate:event:]):
	([NSCell -selectWithFrame:inView:editor:delegate:start:length:]):
	([NSCell -endEditing:]):
	instantiate (and remove) the textview so that it can be scrolled.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@14429 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
pyr 2002-09-11 20:26:27 +00:00
parent 80075ebc40
commit 9ae9ab48a3
7 changed files with 672 additions and 106 deletions

View file

@ -1,3 +1,57 @@
2002-09-11 Pierre-Yves Rivaille <pyrivail@ens-lyon.fr>
* Source/NSText.m ([NSText -initWithCoder:]):
Retain the decoded background color.
* Source/NSTextView.m :
multiple location: don't ignore textContainer's inset
([NSTextView -initWithCoder:])
([NSTextView -encodeWithCoder:])
Encode caret color, textContainer's size and whether the
textContainer has widthTracksTextView or heightTracksTextView set.
([NSTextView -sizeToFit]) Change width (height) only if
is_horizontally_resizable (is_vertically_resizable).
([NSTextView -scrollRangeToVisible:]) scrolls to the first char of
the range.
([NSTextView -invalidateTextContainerOrigin]): Don't ignore inset,
set the origin so that the justification is preserved even if the
textContainer's width is larger that the textview's width.
([NSTextView -updateInsertionPointStateAndRestartTimer:]):
update and place the insertion point properly.
([NSTextView -moveDown:]) & ([NSTextView -moveUp:]):
Don't ignore inset. Make insertion point visible.
* Source/NSTextField.m ([NSTextField -acceptsFirstResponder:]):
responds NO if the editing is still in progrss.
* Source/NSLayoutManager.m
([NSLayoutManager -drawBackgroundForGlyphRange:atPoint:]):
Don't ignore textContainer's inset.
* Source/GSSimpleLayoutManager.m
Replaced [-drawLinesInLineRange:] with [-drawLinesInLineRange:atPoint:].
Replaced [-drawSelectionAsRangeNoCaret:] with
[-drawSelectionAsRangeNoCaret:atPoint:].
Those replacements make it easier to take inset into account.
([-lineFragmentUsedRectForGlyphAtIndex:effectiveRange:])
([-locationForGlyphAtIndex:])
([-boundingRectForGlyphRange:inTextContainer:])
([-rectForCharacterIndex:])
([-setNeedsDisplayForLineRange:inTextContainer:]):
Various fixes.
([-textStorage:edited:range:changeInLength:invalidatedRange:])
Update insertion point if needed (useful when alignment changes).
([-rebuildForRange:delta:inTextContainer:]):
Update layout mechanism.
* Source/NSCell.m
([NSCell -highlight:withFrame:inView:]):
Ask the control to draw the background if we are not opaque.
([NSCell -editWithFrame:inView:editor:delegate:event:]):
([NSCell -selectWithFrame:inView:editor:delegate:start:length:]):
([NSCell -endEditing:]):
instantiate (and remove) the textview so that it can be scrolled.
2002-09-09 Adam Fedor <fedor@gnu.org> 2002-09-09 Adam Fedor <fedor@gnu.org>
* configure.ac: Switch to disaple gsnd. * configure.ac: Switch to disaple gsnd.

View file

@ -15,6 +15,9 @@
Date: September 2000 Date: September 2000
Extracted from NSText, reorganised to specification Extracted from NSText, reorganised to specification
Author: Pierre-Yves Rivaille <pyrivail@ens-lyon.fr>
Date: September 2002
This file is part of the GNUstep GUI Library. This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@ -47,6 +50,7 @@
#include <AppKit/NSTextStorage.h> #include <AppKit/NSTextStorage.h>
#include <AppKit/NSTextContainer.h> #include <AppKit/NSTextContainer.h>
#include <AppKit/NSStringDrawing.h> #include <AppKit/NSStringDrawing.h>
#include <AppKit/NSParagraphStyle.h>
#include "GSSimpleLayoutManager.h" #include "GSSimpleLayoutManager.h"
@ -309,6 +313,35 @@ static inline float defaultFontHeight ()
return currentInfo->lineFragmentRect; return currentInfo->lineFragmentRect;
} }
- (NSRect)lineFragmentUsedRectForGlyphAtIndex: (unsigned)index
effectiveRange: (NSRange *)lineFragmentRange
{
_GNULineLayoutInfo *currentInfo;
if (![_textStorage length] || ![_lineLayoutInformation count])
{
// we return the line fragment from the virtual newline
// that we added at the end of the empty text
if (lineFragmentRange)
{
lineFragmentRange->location=0;
lineFragmentRange->length=0;
}
return ((_GNULineLayoutInfo *)[_lineLayoutInformation lastObject])->usedRect;
}
currentInfo = [_lineLayoutInformation
objectAtIndex: [self lineLayoutIndexForGlyphIndex:
index]];
if (lineFragmentRange)
{
*lineFragmentRange = currentInfo->glyphRange;
}
return currentInfo->usedRect;
}
- (NSPoint)locationForGlyphAtIndex:(unsigned)index - (NSPoint)locationForGlyphAtIndex:(unsigned)index
{ {
float x; float x;
@ -325,7 +358,8 @@ static inline float defaultFontHeight ()
index]]; index]];
if (index >= NSMaxRange (currentInfo->glyphRange)) if (index >= NSMaxRange (currentInfo->glyphRange))
{ {
return NSMakePoint (NSMaxX (currentInfo->usedRect), 0); x = [self _sizeOfRange: currentInfo->glyphRange].width;
return NSMakePoint (x, 0);
} }
start = currentInfo->glyphRange.location; start = currentInfo->glyphRange.location;
@ -341,7 +375,9 @@ static inline float defaultFontHeight ()
{ {
_GNULineLayoutInfo *currentInfo; _GNULineLayoutInfo *currentInfo;
unsigned i1, i2; unsigned i1, i2;
NSRect rect1; NSRect rect1, rect2;
NSSize size;
NSRect rect;
if (![_textStorage length] || ![_lineLayoutInformation count]) if (![_textStorage length] || ![_lineLayoutInformation count])
{ {
@ -351,22 +387,72 @@ static inline float defaultFontHeight ()
i1 = [self lineLayoutIndexForGlyphIndex: aRange.location]; i1 = [self lineLayoutIndexForGlyphIndex: aRange.location];
i2 = [self lineLayoutIndexForGlyphIndex: NSMaxRange(aRange)]; i2 = [self lineLayoutIndexForGlyphIndex: NSMaxRange(aRange)];
// This is not exacty what we need, but should be correct enough
currentInfo = [_lineLayoutInformation objectAtIndex: i1];
rect1 = currentInfo->lineFragmentRect;
if (i1 != i2) if (i1 == i2)
{ {
// the range is not multiline.
currentInfo = [_lineLayoutInformation objectAtIndex: i1];
rect1 = currentInfo->usedRect;
size = [self _sizeOfRange:
NSMakeRange
(currentInfo->glyphRange.location,
aRange.location -
currentInfo->glyphRange.location)];
rect1.origin.x += size.width;
rect1.size.width = [self _sizeOfRange:
NSMakeRange
(aRange.location -
currentInfo->glyphRange.location, 1)].width;
// rect1 is the rect for the first glyph in the range
currentInfo = [_lineLayoutInformation objectAtIndex: i2]; currentInfo = [_lineLayoutInformation objectAtIndex: i2];
rect1 = NSUnionRect(rect1, currentInfo->lineFragmentRect); rect2 = currentInfo->usedRect;
size = [self _sizeOfRange:
NSMakeRange
(currentInfo->glyphRange.location,
NSMaxRange(aRange) -
currentInfo->glyphRange.location)];
rect2.origin.x += size.width;
rect2.size.width = [self _sizeOfRange:
NSMakeRange
(NSMaxRange(aRange) -
currentInfo->glyphRange.location, 1)].width;
// rect2 is the rect for the last glyph in the range
// TODO: it might not work if some glyph draw out of the usedRect.
// (is this really possible ?)
} }
else else
{ {
//float width = [aTextContainer containerSize].width; // this is a multiline range, therefore the bounding rect goes
// FIXME: When we are on one line we may need only part of it // from the beginning of a line till the end
// getting the lineFragmentRects will give the correct result
currentInfo = [_lineLayoutInformation objectAtIndex: i1];
rect1 = currentInfo->lineFragmentRect;
currentInfo = [_lineLayoutInformation objectAtIndex: i2];
rect2 = currentInfo->lineFragmentRect;
} }
return rect1;
// this does compute the smallest rect enclosing
// rect1 (or rect1.origin if rect1 is empty)
// and rect2 (or rect2.origin if rect1 is empty)
rect = NSMakeRect(MIN(NSMinX(rect1), NSMinX(rect2)),
MIN(NSMinY(rect1), NSMinY(rect2)), 0, 0);
rect = NSMakeRect(NSMinX(rect),
NSMinY(rect),
MAX(NSMaxX(rect1), NSMaxX(rect2)) - NSMinX(rect),
MAX(NSMaxY(rect1), NSMaxY(rect2)) - NSMinY(rect));
return rect;
} }
- (NSRange)glyphRangeForBoundingRect:(NSRect)aRect - (NSRange)glyphRangeForBoundingRect:(NSRect)aRect
@ -492,9 +578,21 @@ static inline float defaultFontHeight ()
lineRange = [self rebuildForRange: aRange lineRange = [self rebuildForRange: aRange
delta: delta delta: delta
inTextContainer: aTextContainer]; inTextContainer: aTextContainer];
[[aTextContainer textView] sizeToFit]; [[aTextContainer textView] sizeToFit];
[[aTextContainer textView] invalidateTextContainerOrigin]; [[aTextContainer textView] invalidateTextContainerOrigin];
{
NSRange sr = [[aTextContainer textView] selectedRange];
if (sr.length == 0
&& aRange.location <= sr.location
&& aRange.location + aRange.length >= sr.location)
{
[[aTextContainer textView]
updateInsertionPointStateAndRestartTimer: YES];
}
}
/* FIXME - it was reported that at this point lineRange is no longer /* FIXME - it was reported that at this point lineRange is no longer
* correct ... looks like sizeToFit / invalidateTextContainerOrigin * correct ... looks like sizeToFit / invalidateTextContainerOrigin
* migth cause additional relayout. */ * migth cause additional relayout. */
@ -511,7 +609,8 @@ static inline float defaultFontHeight ()
unsigned end = [self lineLayoutIndexForGlyphIndex: NSMaxRange(glyphRange)]; unsigned end = [self lineLayoutIndexForGlyphIndex: NSMaxRange(glyphRange)];
NSRange lineRange = NSMakeRange(start, end + 1 - start); NSRange lineRange = NSMakeRange(start, end + 1 - start);
[self drawLinesInLineRange: lineRange]; [self drawLinesInLineRange: lineRange
atPoint: containerOrigin];
// We have to redraw the part of the selection that is inside // We have to redraw the part of the selection that is inside
// the redrawn lines // the redrawn lines
@ -520,7 +619,8 @@ static inline float defaultFontHeight ()
if ((selectedRange.length && if ((selectedRange.length &&
NSLocationInRange(newRange.location, selectedRange))) NSLocationInRange(newRange.location, selectedRange)))
{ {
[self drawSelectionAsRangeNoCaret: newRange]; [self drawSelectionAsRangeNoCaret: newRange
atPoint: containerOrigin];
} }
} }
@ -705,7 +805,7 @@ forStartOfGlyphRange: (NSRange)glyphRange
currentInfo = [_lineLayoutInformation lastObject]; currentInfo = [_lineLayoutInformation lastObject];
if (index >= NSMaxRange(currentInfo->glyphRange)) if (index >= NSMaxRange(currentInfo->glyphRange))
{ {
NSRect rect = currentInfo->lineFragmentRect; NSRect rect = currentInfo->usedRect;
return NSMakeRect(NSMaxX (rect), rect.origin.y, return NSMakeRect(NSMaxX (rect), rect.origin.y,
width - NSMaxX (rect), width - NSMaxX (rect),
@ -717,7 +817,7 @@ forStartOfGlyphRange: (NSRange)glyphRange
objectAtIndex: [self lineLayoutIndexForGlyphIndex: objectAtIndex: [self lineLayoutIndexForGlyphIndex:
index]]; index]];
start = currentInfo->glyphRange.location; start = currentInfo->glyphRange.location;
rect = currentInfo->lineFragmentRect; rect = currentInfo->usedRect;
x = rect.origin.x + [self _sizeOfRange: NSMakeRange(start, index-start)].width; x = rect.origin.x + [self _sizeOfRange: NSMakeRange(start, index-start)].width;
return NSMakeRect(x, rect.origin.y, NSMaxX (rect) - x, return NSMakeRect(x, rect.origin.y, NSMaxX (rect) - x,
@ -725,6 +825,7 @@ forStartOfGlyphRange: (NSRange)glyphRange
} }
- (void) drawSelectionAsRangeNoCaret: (NSRange)aRange - (void) drawSelectionAsRangeNoCaret: (NSRange)aRange
atPoint: (NSPoint)containerOrigin
{ {
unsigned i, count; unsigned i, count;
NSTextContainer *aTextContainer; NSTextContainer *aTextContainer;
@ -739,6 +840,8 @@ forStartOfGlyphRange: (NSRange)glyphRange
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
rects[i].origin.x += containerOrigin.x;
rects[i].origin.y += containerOrigin.y;
NSHighlightRect (rects[i]); NSHighlightRect (rects[i]);
} }
} }
@ -758,7 +861,8 @@ forStartOfGlyphRange: (NSRange)glyphRange
} }
// relies on _lineLayoutInformation // relies on _lineLayoutInformation
- (void) drawLinesInLineRange: (NSRange)aRange; - (void) drawLinesInLineRange: (NSRange)aRange
atPoint: (NSPoint)containerOrigin
{ {
NSArray *linesToDraw; NSArray *linesToDraw;
NSEnumerator *lineEnum; NSEnumerator *lineEnum;
@ -774,8 +878,12 @@ forStartOfGlyphRange: (NSRange)glyphRange
for ((lineEnum = [linesToDraw objectEnumerator]); for ((lineEnum = [linesToDraw objectEnumerator]);
(currentInfo = [lineEnum nextObject]);) (currentInfo = [lineEnum nextObject]);)
{ {
NSRect rect;
rect = currentInfo->lineFragmentRect;
rect.origin.x += containerOrigin.x;
rect.origin.y += containerOrigin.y;
[_textStorage drawRange: currentInfo->glyphRange [_textStorage drawRange: currentInfo->glyphRange
inRect: currentInfo->lineFragmentRect]; inRect: rect];
} }
} }
@ -792,14 +900,17 @@ forStartOfGlyphRange: (NSRange)glyphRange
float width = 0; float width = 0;
if (aTextContainer) if (aTextContainer)
width = [aTextContainer containerSize].width; width = [aTextContainer containerSize].width;
if (redrawLineRange.length > 1) if (redrawLineRange.length > 1)
displayRect = NSUnionRect(displayRect, displayRect = NSUnionRect(displayRect,
[[_lineLayoutInformation [[_lineLayoutInformation
objectAtIndex: objectAtIndex:
(int)NSMaxRange(redrawLineRange) - 1] lineFragmentRect]); (int)NSMaxRange(redrawLineRange) - 1] lineFragmentRect]);
displayRect.size.width = width - displayRect.origin.x; displayRect.size.width = width;
displayRect.origin.x +=
[[aTextContainer textView] textContainerInset].width;
displayRect.origin.y +=
[[aTextContainer textView] textContainerInset].height;
[[aTextContainer textView] setNeedsDisplayInRect: displayRect]; [[aTextContainer textView] setNeedsDisplayInRect: displayRect];
} }
} }
@ -908,10 +1019,11 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet)
{ {
_GNULineLayoutInfo *lastValidLineInfo = [_lineLayoutInformation _GNULineLayoutInfo *lastValidLineInfo = [_lineLayoutInformation
objectAtIndex: aLine - 1]; objectAtIndex: aLine - 1];
NSRect aRect = lastValidLineInfo->lineFragmentRect; NSRect aRect = lastValidLineInfo->usedRect;
startingIndex = NSMaxRange(lastValidLineInfo->glyphRange); startingIndex = NSMaxRange(lastValidLineInfo->glyphRange);
drawingPoint = aRect.origin; drawingPoint.x = 0;
drawingPoint.y = aRect.origin.y;
drawingPoint.y += aRect.size.height; drawingPoint.y += aRect.size.height;
} }
@ -927,11 +1039,39 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet)
// FIXME: This should be done via extra line fragment // FIXME: This should be done via extra line fragment
// If there is no text add one empty box // If there is no text add one empty box
[_lineLayoutInformation {
addObject: [_GNULineLayoutInfo NSParagraphStyle *style =
lineLayoutWithRange: NSMakeRange (0, 0) (NSParagraphStyle*)[_textStorage
rect: NSMakeRect (0, 0, width, defaultFontHeight ()) attribute: NSParagraphStyleAttributeName
usedRect: NSMakeRect (0, 0, 1, defaultFontHeight ())]]; atIndex: 0
effectiveRange: NULL];
if ([style alignment] == NSRightTextAlignment)
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (0, 0)
rect: NSMakeRect (0, 0, width, defaultFontHeight ())
usedRect: NSMakeRect (width-1, 0, 1, defaultFontHeight ())]];
}
else if ([style alignment] == NSCenterTextAlignment)
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (0, 0)
rect: NSMakeRect (0, 0, width, defaultFontHeight ())
usedRect: NSMakeRect ((int) width/2, 0, 1, defaultFontHeight ())]];
}
else
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (0, 0)
rect: NSMakeRect (0, 0, width, defaultFontHeight ())
usedRect: NSMakeRect (0, 0, 1, defaultFontHeight ())]];
}
}
return NSMakeRange(0,1); return NSMakeRange(0,1);
} }
@ -1012,7 +1152,7 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet)
width = fragmentRect.size.width - 2 * padding; width = fragmentRect.size.width - 2 * padding;
usedLineRect = fragmentRect; usedLineRect = fragmentRect;
usedLineRect.origin.x += padding; // usedLineRect.origin.x += padding;
usedLineRect.size = NSZeroSize; usedLineRect.size = NSZeroSize;
// scan the individual words to the end of the line // scan the individual words to the end of the line
@ -1129,6 +1269,29 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet)
// the to big // the to big
fragmentRect.size.height = usedLineRect.size.height; fragmentRect.size.height = usedLineRect.size.height;
// adjust the usedLineRect depending on the justification
{
NSParagraphStyle *style =
(NSParagraphStyle*)[_textStorage
attribute: NSParagraphStyleAttributeName
atIndex: startingLineCharIndex
effectiveRange: NULL];
if ([style alignment] == NSLeftTextAlignment)
{
}
else if ([style alignment] == NSRightTextAlignment)
{
usedLineRect.origin.x +=
fragmentRect.size.width - usedLineRect.size.width - padding;
}
else if ([style alignment] == NSCenterTextAlignment)
{
usedLineRect.origin.x +=
(int) (fragmentRect.size.width - usedLineRect.size.width) / 2;
}
}
// This range is to small, as there are more lines that fit // This range is to small, as there are more lines that fit
// into the container // into the container
[self setTextContainer: aTextContainer [self setTextContainer: aTextContainer
@ -1190,17 +1353,58 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet)
if (aTextContainer) if (aTextContainer)
width = [aTextContainer containerSize].width; width = [aTextContainer containerSize].width;
[_lineLayoutInformation {
addObject: [_GNULineLayoutInfo NSParagraphStyle *style =
lineLayoutWithRange: NSMakeRange (length, 0) (NSParagraphStyle*)[_textStorage
rect: NSMakeRect (drawingPoint.x, drawingPoint.y, attribute: NSParagraphStyleAttributeName
width, defaultFontHeight ()) atIndex: length - 1
usedRect: NSMakeRect (drawingPoint.x, drawingPoint.y, effectiveRange: NULL];
1, defaultFontHeight ())]];
if ([style alignment] == NSRightTextAlignment)
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (length, 0)
rect:
NSMakeRect (drawingPoint.x
+ (width - drawingPoint.x),
drawingPoint.y,
1, defaultFontHeight ())
usedRect:
NSMakeRect (drawingPoint.x
+ (width - drawingPoint.x),
drawingPoint.y,
1, defaultFontHeight ())]];
}
else if ([style alignment] == NSCenterTextAlignment)
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (length, 0)
rect:
NSMakeRect (drawingPoint.x
+ (int)(width - drawingPoint.x) / 2,
drawingPoint.y,
1, defaultFontHeight ())
usedRect:
NSMakeRect (drawingPoint.x
+ (int)(width - drawingPoint.x) / 2,
drawingPoint.y,
1, defaultFontHeight ())]];
}
else
{
[_lineLayoutInformation
addObject: [_GNULineLayoutInfo
lineLayoutWithRange: NSMakeRange (length, 0)
rect: NSMakeRect (drawingPoint.x, drawingPoint.y,
width, defaultFontHeight ())
usedRect: NSMakeRect (drawingPoint.x, drawingPoint.y,
1, defaultFontHeight ())]];
}
}
} }
// lines actually updated (optimized drawing) // lines actually updated (optimized drawing)
return NSMakeRange(aLine, MAX(1, [_lineLayoutInformation count] - aLine)); return NSMakeRange(aLine, MAX(1, [_lineLayoutInformation count] - aLine));
} }

View file

@ -54,6 +54,8 @@
#include <AppKit/PSOperators.h> #include <AppKit/PSOperators.h>
#include <AppKit/NSAttributedString.h> #include <AppKit/NSAttributedString.h>
#include <AppKit/NSClipView.h>
static Class colorClass; static Class colorClass;
static Class cellClass; static Class cellClass;
static Class fontClass; static Class fontClass;
@ -1692,7 +1694,11 @@ static NSColor *shadowCol;
* NSCell simply draws border+text/image and makes no highlighting, * NSCell simply draws border+text/image and makes no highlighting,
* for easier subclassing. * for easier subclassing.
*/ */
[self drawWithFrame: cellFrame inView: controlView]; if ([self isOpaque] == NO)
{
[controlView displayRect: cellFrame];
}
[self drawWithFrame: cellFrame inView: controlView];
} }
} }
@ -1708,8 +1714,32 @@ static NSColor *shadowCol;
if (!controlView || !textObject || (_cell.type != NSTextCellType)) if (!controlView || !textObject || (_cell.type != NSTextCellType))
return; return;
[textObject setFrame: [self titleRectForBounds: aRect]]; {
[controlView addSubview: textObject]; NSClipView *cv = [[NSClipView alloc]
initWithFrame:
[self titleRectForBounds: aRect]];
[controlView addSubview: cv];
RELEASE(cv);
[cv setAutoresizesSubviews: NO];
[cv setDocumentView: textObject];
[textObject setFrame: [cv bounds]];
[textObject setHorizontallyResizable: YES];
[textObject setVerticallyResizable: NO];
[textObject
setMaxSize:
NSMakeSize (3000,
[self titleRectForBounds: aRect].size.height)];
[textObject
setMinSize:
[self titleRectForBounds: aRect].size];
[[textObject textContainer]
setContainerSize:
NSMakeSize (3000,
[self titleRectForBounds: aRect].size.height)];
[[textObject textContainer] setHeightTracksTextView: NO];
[[textObject textContainer] setWidthTracksTextView: NO];
}
if (_formatter != nil) if (_formatter != nil)
{ {
@ -1734,6 +1764,7 @@ static NSColor *shadowCol;
[textObject setText: [(NSAttributedString *)_contents string]]; [textObject setText: [(NSAttributedString *)_contents string]];
} }
} }
[textObject sizeToFit];
[textObject setDelegate: anObject]; [textObject setDelegate: anObject];
[[controlView window] makeFirstResponder: textObject]; [[controlView window] makeFirstResponder: textObject];
@ -1748,8 +1779,11 @@ static NSColor *shadowCol;
- (void) endEditing: (NSText*)textObject - (void) endEditing: (NSText*)textObject
{ {
NSClipView *cv;
[textObject setDelegate: nil]; [textObject setDelegate: nil];
cv = (NSClipView*)[textObject superview];
[textObject removeFromSuperview]; [textObject removeFromSuperview];
[cv removeFromSuperview];
} }
- (void) selectWithFrame: (NSRect)aRect - (void) selectWithFrame: (NSRect)aRect
@ -1762,17 +1796,61 @@ static NSColor *shadowCol;
if (!controlView || !textObject || (_cell.type != NSTextCellType)) if (!controlView || !textObject || (_cell.type != NSTextCellType))
return; return;
[textObject setFrame: [self titleRectForBounds: aRect]]; {
[controlView addSubview: textObject]; NSClipView *cv = [[NSClipView alloc]
if (_cell.contents_is_attributed_string == NO) initWithFrame:
[self titleRectForBounds: aRect]];
[controlView addSubview: cv];
RELEASE(cv);
[cv setAutoresizesSubviews: NO];
[cv setDocumentView: textObject];
[textObject setFrame: [cv bounds]];
[textObject setHorizontallyResizable: YES];
[textObject setVerticallyResizable: NO];
[textObject
setMaxSize:
NSMakeSize (3000,
[self titleRectForBounds: aRect].size.height)];
[textObject
setMinSize:
[self titleRectForBounds: aRect].size];
[[textObject textContainer]
setContainerSize:
NSMakeSize (3000,
[self titleRectForBounds: aRect].size.height)];
[[textObject textContainer] setWidthTracksTextView: NO];
[[textObject textContainer] setWidthTracksTextView: NO];
}
if (_formatter != nil)
{ {
[textObject setText: _contents]; NSString *contents;
contents = [_formatter editingStringForObjectValue: _objectValue];
if (contents == nil)
{
contents = _contents;
}
[textObject setText: contents];
} }
else else
{ {
/* FIXME/TODO make sure this is correct. */ if (_cell.contents_is_attributed_string == NO)
[textObject setText: [(NSAttributedString *)_contents string]]; {
[textObject setText: _contents];
}
else
{
/* FIXME/TODO make sure this is correct. */
[textObject setText: [(NSAttributedString *)_contents string]];
}
} }
[textObject sizeToFit];
[textObject setDelegate: anObject];
[[controlView window] makeFirstResponder: textObject];
[textObject setSelectedRange: NSMakeRange (selStart, selLength)]; [textObject setSelectedRange: NSMakeRange (selStart, selLength)];
[textObject setDelegate: anObject]; [textObject setDelegate: anObject];
[[controlView window] makeFirstResponder: textObject]; [[controlView window] makeFirstResponder: textObject];

View file

@ -2762,14 +2762,18 @@ forStartOfGlyphRange: (NSRange)glyphRange
atPoint: (NSPoint)containerOrigin atPoint: (NSPoint)containerOrigin
{ {
NSTextContainer *aTextContainer; NSTextContainer *aTextContainer;
NSRect rect;
aTextContainer = [self textContainerForGlyphAtIndex: glyphRange.location aTextContainer = [self textContainerForGlyphAtIndex: glyphRange.location
effectiveRange: NULL]; effectiveRange: NULL];
[[[aTextContainer textView] backgroundColor] set]; [[[aTextContainer textView] backgroundColor] set];
NSRectFill ([self boundingRectForGlyphRange: glyphRange rect = [self boundingRectForGlyphRange: glyphRange
inTextContainer: aTextContainer]); inTextContainer: aTextContainer];
rect.origin.x += containerOrigin.x;
rect.origin.x += containerOrigin.y;
NSRectFill (rect);
} }
- (void) drawGlyphsForGlyphRange: (NSRange)glyphRange - (void) drawGlyphsForGlyphRange: (NSRange)glyphRange

View file

@ -715,7 +715,7 @@ static Class concrete;
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tf.is_ruler_visible = flag; _tf.is_ruler_visible = flag;
_background_color = [aDecoder decodeObject]; _background_color = RETAIN([aDecoder decodeObject]);
[aDecoder decodeValueOfObjCType: @encode(NSSize) at: &_minSize]; [aDecoder decodeValueOfObjCType: @encode(NSSize) at: &_minSize];
[aDecoder decodeValueOfObjCType: @encode(NSSize) at: &_maxSize]; [aDecoder decodeValueOfObjCType: @encode(NSSize) at: &_maxSize];

View file

@ -282,7 +282,9 @@ static Class textFieldCellClass;
/* This could happen if someone pressed the mouse on the borders. */ /* This could happen if someone pressed the mouse on the borders. */
if (_text_object) if (_text_object)
return; {
return;
}
t = [_window fieldEditor: YES forObject: self]; t = [_window fieldEditor: YES forObject: self];
@ -297,7 +299,6 @@ static Class textFieldCellClass;
// [NSCursor hide]; // [NSCursor hide];
_text_object = [_cell setUpFieldEditorAttributes: t]; _text_object = [_cell setUpFieldEditorAttributes: t];
[_cell editWithFrame: _bounds [_cell editWithFrame: _bounds
inView: self inView: self
@ -313,7 +314,10 @@ static Class textFieldCellClass;
- (BOOL) acceptsFirstResponder - (BOOL) acceptsFirstResponder
{ {
return [self isSelectable]; // we do not accept first responder if there is already a
// _text_object, else it would make the _text_object resign
// and end editing
return (_text_object == nil) && [self isSelectable];
} }
- (BOOL) becomeFirstResponder - (BOOL) becomeFirstResponder

View file

@ -20,6 +20,9 @@
Author: Nicola Pero <n.pero@mi.flashnet.it> Author: Nicola Pero <n.pero@mi.flashnet.it>
Date: 2000, 2001, 2002 Date: 2000, 2001, 2002
Author: Pierre-Yves Rivaille <pyrivail@ens-lyon.fr>
Date: September 2002
This file is part of the GNUstep GUI Library. This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@ -63,6 +66,8 @@
#include <AppKit/NSColorPanel.h> #include <AppKit/NSColorPanel.h>
#include <AppKit/NSAttributedString.h> #include <AppKit/NSAttributedString.h>
static const int currentVersion = 2;
#define HUGE 1e7 #define HUGE 1e7
/* not the same as NSMakeRange! */ /* not the same as NSMakeRange! */
@ -154,7 +159,7 @@ static NSNotificationCenter *nc;
{ {
if ([self class] == [NSTextView class]) if ([self class] == [NSTextView class])
{ {
[self setVersion: 1]; [self setVersion: currentVersion];
nc = [NSNotificationCenter defaultCenter]; nc = [NSNotificationCenter defaultCenter];
[self registerForServices]; [self registerForServices];
} }
@ -266,7 +271,8 @@ static NSNotificationCenter *nc;
- (void) encodeWithCoder: (NSCoder *)aCoder - (void) encodeWithCoder: (NSCoder *)aCoder
{ {
BOOL flag; BOOL flag;
NSSize containerSize = [_textContainer containerSize];
[super encodeWithCoder: aCoder]; [super encodeWithCoder: aCoder];
@ -274,28 +280,71 @@ static NSNotificationCenter *nc;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _tvf.allows_undo; flag = _tvf.allows_undo;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
[aCoder encodeObject: _caret_color];
[aCoder encodeValueOfObjCType: @encode(NSSize) at: &containerSize];
flag = [_textContainer widthTracksTextView];
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = [_textContainer heightTracksTextView];
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
} }
- (id) initWithCoder: (NSCoder *)aDecoder - (id) initWithCoder: (NSCoder *)aDecoder
{ {
NSTextContainer *aTextContainer; int version = [aDecoder versionForClassName:
BOOL flag; @"NSTextView"];
self = [super initWithCoder: aDecoder]; if (version == currentVersion)
{
NSTextContainer *aTextContainer;
BOOL flag;
NSSize containerSize;
self = [super initWithCoder: aDecoder];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.smart_insert_delete = flag;
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.allows_undo = flag;
_caret_color = RETAIN([aDecoder decodeObject]);
[aDecoder decodeValueOfObjCType: @encode(NSSize) at: &containerSize];
/* build up the rest of the text system, which doesn't get stored
<doesn't even implement the Coding protocol>. */
aTextContainer = [self buildUpTextNetwork: _frame.size];
[aTextContainer setTextView: (NSTextView*)self];
[aTextContainer setContainerSize: containerSize];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.smart_insert_delete = flag; [aTextContainer setWidthTracksTextView: flag];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.allows_undo = flag; [aTextContainer setHeightTracksTextView: flag];
/* build up the rest of the text system, which doesn't get stored
<doesn't even implement the Coding protocol>. */
aTextContainer = [self buildUpTextNetwork: _frame.size];
[aTextContainer setTextView: (NSTextView*)self];
/* See initWithFrame: for comments on this RELEASE */
RELEASE (self);
[self setSelectedRange: NSMakeRange (0, 0)]; /* See initWithFrame: for comments on this RELEASE */
RELEASE (self);
[self setSelectedRange: NSMakeRange (0, 0)];
}
else if (version == 1)
{
NSTextContainer *aTextContainer;
BOOL flag;
self = [super initWithCoder: aDecoder];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.smart_insert_delete = flag;
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_tvf.allows_undo = flag;
/* build up the rest of the text system, which doesn't get stored
<doesn't even implement the Coding protocol>. */
aTextContainer = [self buildUpTextNetwork: _frame.size];
[aTextContainer setTextView: (NSTextView*)self];
/* See initWithFrame: for comments on this RELEASE */
RELEASE (self);
[self setSelectedRange: NSMakeRange (0, 0)];
}
return self; return self;
} }
@ -363,11 +412,50 @@ static NSNotificationCenter *nc;
this case. So we set the attributes manually. */ this case. So we set the attributes manually. */
NSAttributedString *as; NSAttributedString *as;
as = AUTORELEASE ([[NSAttributedString alloc] if ([aString length] == 0)
initWithString: aString {
attributes: _typingAttributes]); as = AUTORELEASE ([[NSAttributedString alloc]
[self replaceRange: aRange withAttributedString: as]; initWithString: @" "
attributes: _typingAttributes]);
[self replaceRange: aRange withAttributedString: as];
as = AUTORELEASE ([[NSAttributedString alloc]
initWithString: aString
attributes: _typingAttributes]);
[self replaceRange: NSMakeRange(0, 1) withAttributedString: as];
}
else
{
as = AUTORELEASE ([[NSAttributedString alloc]
initWithString: aString
attributes: _typingAttributes]);
[self replaceRange: aRange withAttributedString: as];
}
} }
// BEGIN: following code added by pyr
else if ([_textStorage length] == 0)
{
NSAttributedString *as;
if ([aString length] == 0)
{
as = AUTORELEASE ([[NSAttributedString alloc]
initWithString: @" "
attributes: _typingAttributes]);
[_textStorage replaceCharactersInRange: aRange withAttributedString: as];
as = AUTORELEASE ([[NSAttributedString alloc]
initWithString: aString
attributes: _typingAttributes]);
[_textStorage replaceCharactersInRange: NSMakeRange(0, 1) withAttributedString: as];
}
else
{
as = AUTORELEASE ([[NSAttributedString alloc]
initWithString: aString
attributes: _typingAttributes]);
[_textStorage replaceCharactersInRange: aRange
withAttributedString: as];
}
}
// END
else else
{ {
[_textStorage replaceCharactersInRange: aRange withString: aString]; [_textStorage replaceCharactersInRange: aRange withString: aString];
@ -837,18 +925,24 @@ static NSNotificationCenter *nc;
- (void) sizeToFit - (void) sizeToFit
{ {
NSSize size;
if (_tf.is_horizontally_resizable || _tf.is_vertically_resizable) if (_tf.is_horizontally_resizable || _tf.is_vertically_resizable)
{ size = [_layoutManager usedRectForTextContainer: _textContainer].size;
NSSize size;
if (!_tf.is_horizontally_resizable)
size = [_layoutManager usedRectForTextContainer: _textContainer].size; size.width = _bounds.size.width;
size.width += 2 * _textContainerInset.width; else
size.height += 2 * _textContainerInset.height; size.width += 2 * _textContainerInset.width;
[self setConstrainedFrameSize: size]; if (!_tf.is_vertically_resizable)
} size.height = _bounds.size.height;
else
size.height += 2 * _textContainerInset.height;
[self setConstrainedFrameSize: size];
} }
/* /*
* [NSText] Spelling * [NSText] Spelling
*/ */
@ -897,11 +991,42 @@ static NSNotificationCenter *nc;
*/ */
- (void) scrollRangeToVisible: (NSRange)aRange - (void) scrollRangeToVisible: (NSRange)aRange
{ {
// Don't try scrolling an ancestor clipview if we are field editor. if (aRange.length > 0)
// This makes things so much simpler and stabler for now.
if (_tf.is_field_editor == NO)
{ {
[self scrollRectToVisible: [self rectForCharacterRange: aRange]]; aRange.length = 1;
[self scrollRectToVisible:
[self rectForCharacterRange: aRange]];
}
else
{
/* Update insertion point rect */
NSRange charRange;
NSRange glyphRange;
unsigned glyphIndex;
NSRect rect;
charRange = NSMakeRange (aRange.location, 0);
glyphRange = [_layoutManager glyphRangeForCharacterRange: charRange
actualCharacterRange: NULL];
glyphIndex = glyphRange.location;
rect = [_layoutManager lineFragmentUsedRectForGlyphAtIndex: glyphIndex
effectiveRange: NULL];
rect.origin.x += _textContainerOrigin.x;
rect.origin.y += _textContainerOrigin.y;
if ([self selectionAffinity] != NSSelectionAffinityUpstream)
{
/* Standard case - draw the insertion point just before the
associated glyph index */
NSPoint loc = [_layoutManager locationForGlyphAtIndex: glyphIndex];
rect.origin.x += loc.x;
}
rect.size.width = 1;
[self scrollRectToVisible: rect];
} }
} }
@ -1015,6 +1140,8 @@ static NSNotificationCenter *nc;
{ {
_textContainerInset = inset; _textContainerInset = inset;
[self invalidateTextContainerOrigin]; [self invalidateTextContainerOrigin];
[nc postNotificationName: NSViewFrameDidChangeNotification
object: self];
} }
- (NSSize) textContainerInset - (NSSize) textContainerInset
@ -1042,19 +1169,60 @@ static NSNotificationCenter *nc;
information is used when we ask the layout manager to draw - the information is used when we ask the layout manager to draw - the
base point is precisely this `text container origin', which is base point is precisely this `text container origin', which is
the origin of the used rect in our own coordinate system. */ the origin of the used rect in our own coordinate system. */
/* It seems like the `text container origin' is the origin
of the text container rect so that the used rect
is "well positionned" within the textview */
if (usedRect.size.width - _bounds.size.width < 0.0001)
{
NSRect rect;
float diff;
float ratio;
rect.origin = NSMakePoint(0, 0);
rect.size = textContainerSize;
diff = rect.size.width - usedRect.size.width;
_textContainerOrigin.x = NSMinX(_bounds);
_textContainerOrigin.x += _textContainerInset.width;
if (diff)
{
ratio = (_bounds.size.width - usedRect.size.width)
/ diff;
if (NSMaxX(rect) == NSMaxX(usedRect))
{
_textContainerOrigin.x -= rect.size.width - _bounds.size.width;
}
else
{
_textContainerOrigin.x -=
(int) (usedRect.origin.x * (1 - ratio ));
}
}
else
{
}
}
else
{
/* First get the pure text container origin */
_textContainerOrigin.x = NSMinX (_bounds);
_textContainerOrigin.x += _textContainerInset.width;
/* Then move to the used rect origin */
_textContainerOrigin.x -= usedRect.origin.x;
}
/* First get the pure text container origin */ /* First get the pure text container origin */
_textContainerOrigin.x = NSMinX (_bounds); _textContainerOrigin.y = NSMinY (_bounds);
_textContainerOrigin.x += _textContainerInset.width; _textContainerOrigin.y += _textContainerInset.height;
// _textContainerOrigin.y -= textContainerSize.height;
/* Then move to the used rect origin */ /* Then move to the used rect origin */
_textContainerOrigin.x += usedRect.origin.x; _textContainerOrigin.y -= usedRect.origin.y;
/* First get the pure text container origin */
_textContainerOrigin.y = NSMaxY (_bounds);
_textContainerOrigin.y -= _textContainerInset.height;
_textContainerOrigin.y -= textContainerSize.height;
/* Then move to the used rect origin */
_textContainerOrigin.y += usedRect.origin.y;
} }
- (NSLayoutManager*) layoutManager - (NSLayoutManager*) layoutManager
@ -1427,8 +1595,13 @@ static NSNotificationCenter *nc;
if (flag == NO) if (flag == NO)
{ {
/* Make the selected range visible */ // FIXME
[self scrollRangeToVisible: range]; // Make the selected range visible
// We do not always want to scroll to the beginning of the
// selection
// however we do for sure if the selection's length is 0
if (range.length == 0 && _tf.is_editable )
[self scrollRangeToVisible: range];
} }
/* Try to optimize for overlapping ranges */ /* Try to optimize for overlapping ranges */
@ -1518,6 +1691,7 @@ static NSNotificationCenter *nc;
NSRange glyphRange; NSRange glyphRange;
unsigned glyphIndex; unsigned glyphIndex;
NSRect rect; NSRect rect;
NSRect oldInsertionPointRect;
/* Simple case - no insertion point */ /* Simple case - no insertion point */
if ((_selected_range.length > 0) || _selected_range.location == NSNotFound) if ((_selected_range.length > 0) || _selected_range.location == NSNotFound)
@ -1526,7 +1700,6 @@ static NSNotificationCenter *nc;
{ {
[_insertionPointTimer invalidate]; [_insertionPointTimer invalidate];
DESTROY (_insertionPointTimer); DESTROY (_insertionPointTimer);
_drawInsertionPointNow = YES;
} }
/* FIXME: horizontal position of insertion point */ /* FIXME: horizontal position of insertion point */
@ -1539,9 +1712,11 @@ static NSNotificationCenter *nc;
actualCharacterRange: NULL]; actualCharacterRange: NULL];
glyphIndex = glyphRange.location; glyphIndex = glyphRange.location;
rect = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex rect = [_layoutManager lineFragmentUsedRectForGlyphAtIndex: glyphIndex
effectiveRange: NULL]; effectiveRange: NULL];
rect.origin.x += _textContainerOrigin.x;
rect.origin.y += _textContainerOrigin.y;
if ([self selectionAffinity] != NSSelectionAffinityUpstream) if ([self selectionAffinity] != NSSelectionAffinityUpstream)
{ {
/* Standard case - draw the insertion point just before the /* Standard case - draw the insertion point just before the
@ -1549,6 +1724,7 @@ static NSNotificationCenter *nc;
NSPoint loc = [_layoutManager locationForGlyphAtIndex: glyphIndex]; NSPoint loc = [_layoutManager locationForGlyphAtIndex: glyphIndex];
rect.origin.x += loc.x; rect.origin.x += loc.x;
} }
else /* _affinity == NSSelectionAffinityUpstream - non standard */ else /* _affinity == NSSelectionAffinityUpstream - non standard */
{ {
@ -1580,8 +1756,10 @@ static NSNotificationCenter *nc;
} }
} }
rect.size.width = 1; rect.size.width = 1;
oldInsertionPointRect = _insertionPointRect;
_insertionPointRect = rect; _insertionPointRect = rect;
/* Remember horizontal position of insertion point */ /* Remember horizontal position of insertion point */
@ -1592,6 +1770,22 @@ static NSNotificationCenter *nc;
/* Start blinking timer if not yet started */ /* Start blinking timer if not yet started */
if (_insertionPointTimer == nil && [self shouldDrawInsertionPoint]) if (_insertionPointTimer == nil && [self shouldDrawInsertionPoint])
{ {
_drawInsertionPointNow = NO;
[self _blink: nil];
_insertionPointTimer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(_blink:)
userInfo: nil
repeats: YES];
RETAIN (_insertionPointTimer);
}
else if (_insertionPointTimer != nil)
{
[_insertionPointTimer invalidate];
DESTROY (_insertionPointTimer);
[self setNeedsDisplayInRect: oldInsertionPointRect];
_drawInsertionPointNow = NO;
[self _blink: nil];
_insertionPointTimer = [NSTimer scheduledTimerWithTimeInterval: 0.5 _insertionPointTimer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self target: self
selector: @selector(_blink:) selector: @selector(_blink:)
@ -1610,8 +1804,10 @@ static NSNotificationCenter *nc;
{ {
if (_insertionPointTimer != nil) if (_insertionPointTimer != nil)
{ {
[self setNeedsDisplayInRect: oldInsertionPointRect];
[_insertionPointTimer invalidate]; [_insertionPointTimer invalidate];
DESTROY (_insertionPointTimer); DESTROY (_insertionPointTimer);
} }
} }
} }
@ -2067,6 +2263,7 @@ replacing the selection.
- (void) didChangeText - (void) didChangeText
{ {
[self sizeToFit];
[nc postNotificationName: NSTextDidChangeNotification [nc postNotificationName: NSTextDidChangeNotification
object: _notifObject]; object: _notifObject];
} }
@ -2467,6 +2664,7 @@ afterString in order over charRange. */
- (void) moveUp: (id)sender - (void) moveUp: (id)sender
{ {
float originalInsertionPoint; float originalInsertionPoint;
float savedOriginalInsertionPoint;
float startingY; float startingY;
unsigned newLocation; unsigned newLocation;
@ -2481,10 +2679,16 @@ afterString in order over charRange. */
/* Read from memory the horizontal position we aim to move the cursor /* Read from memory the horizontal position we aim to move the cursor
at on the next line */ at on the next line */
savedOriginalInsertionPoint = _originalInsertPoint;
originalInsertionPoint = _originalInsertPoint; originalInsertionPoint = _originalInsertPoint;
/* Ask the layout manager to compute where to go */ /* Ask the layout manager to compute where to go */
startingY = NSMidY (_insertionPointRect); startingY = NSMidY (_insertionPointRect);
/* consider textContainerInset */
startingY -= _textContainerInset.height;
originalInsertionPoint -= _textContainerInset.width;
newLocation = [_layoutManager newLocation = [_layoutManager
_charIndexForInsertionPointMovingFromY: startingY _charIndexForInsertionPointMovingFromY: startingY
bestX: originalInsertionPoint bestX: originalInsertionPoint
@ -2497,12 +2701,13 @@ afterString in order over charRange. */
/* Restore the _originalInsertPoint (which was changed /* Restore the _originalInsertPoint (which was changed
by setSelectedRange:) because we don't want it to change between by setSelectedRange:) because we don't want it to change between
moveUp:/moveDown: operations. */ moveUp:/moveDown: operations. */
_originalInsertPoint = originalInsertionPoint; _originalInsertPoint = savedOriginalInsertionPoint;
} }
- (void) moveDown: (id)sender - (void) moveDown: (id)sender
{ {
float originalInsertionPoint; float originalInsertionPoint;
float savedOriginalInsertionPoint;
float startingY; float startingY;
unsigned newLocation; unsigned newLocation;
@ -2517,10 +2722,16 @@ afterString in order over charRange. */
/* Read from memory the horizontal position we aim to move the cursor /* Read from memory the horizontal position we aim to move the cursor
at on the next line */ at on the next line */
savedOriginalInsertionPoint = _originalInsertPoint;
originalInsertionPoint = _originalInsertPoint; originalInsertionPoint = _originalInsertPoint;
/* Ask the layout manager to compute where to go */ /* Ask the layout manager to compute where to go */
startingY = NSMidY (_insertionPointRect); startingY = NSMidY (_insertionPointRect);
/* consider textContainerInset */
startingY -= _textContainerInset.height;
originalInsertionPoint -= _textContainerInset.width;
newLocation = [_layoutManager newLocation = [_layoutManager
_charIndexForInsertionPointMovingFromY: startingY _charIndexForInsertionPointMovingFromY: startingY
bestX: originalInsertionPoint bestX: originalInsertionPoint
@ -2533,7 +2744,7 @@ afterString in order over charRange. */
/* Restore the _originalInsertPoint (which was changed /* Restore the _originalInsertPoint (which was changed
by setSelectedRange:) because we don't want it to change between by setSelectedRange:) because we don't want it to change between
moveUp:/moveDown: operations. */ moveUp:/moveDown: operations. */
_originalInsertPoint = originalInsertionPoint; _originalInsertPoint = savedOriginalInsertionPoint;
} }
- (void) moveLeft: (id)sender - (void) moveLeft: (id)sender
@ -3027,8 +3238,12 @@ afterString in order over charRange. */
- (void) drawRect: (NSRect)rect - (void) drawRect: (NSRect)rect
{ {
/* TODO: Only do relayout if needed */ /* TODO: Only do relayout if needed */
NSRange drawnRange = [_layoutManager glyphRangeForBoundingRect: rect NSRange drawnRange;
inTextContainer: _textContainer]; NSRect containerRect = rect;
containerRect.origin.x -= _textContainerOrigin.x;
containerRect.origin.y -= _textContainerOrigin.y;
drawnRange = [_layoutManager glyphRangeForBoundingRect: containerRect
inTextContainer: _textContainer];
if (_tf.draws_background) if (_tf.draws_background)
{ {
/* First paint the background with the color. This is necessary /* First paint the background with the color. This is necessary
@ -3043,6 +3258,7 @@ afterString in order over charRange. */
/* Then draw the special background of the new glyphs. */ /* Then draw the special background of the new glyphs. */
[_layoutManager drawBackgroundForGlyphRange: drawnRange [_layoutManager drawBackgroundForGlyphRange: drawnRange
atPoint: _textContainerOrigin]; atPoint: _textContainerOrigin];
} }
[_layoutManager drawGlyphsForGlyphRange: drawnRange [_layoutManager drawGlyphsForGlyphRange: drawnRange
@ -3934,6 +4150,9 @@ other than copy/paste or dragging. */
unsigned index; unsigned index;
float fraction; float fraction;
point.x -= _textContainerOrigin.x;
point.y -= _textContainerOrigin.y;
index = [_layoutManager glyphIndexForPoint: point index = [_layoutManager glyphIndexForPoint: point
inTextContainer: _textContainer inTextContainer: _textContainer
fractionOfDistanceThroughGlyph: &fraction]; fractionOfDistanceThroughGlyph: &fraction];
@ -4122,12 +4341,15 @@ other than copy/paste or dragging. */
- (NSRect) rectForCharacterRange: (NSRange)aRange - (NSRect) rectForCharacterRange: (NSRange)aRange
{ {
NSRange glyphRange; NSRange glyphRange;
NSRect rect;
glyphRange = [_layoutManager glyphRangeForCharacterRange: aRange glyphRange = [_layoutManager glyphRangeForCharacterRange: aRange
actualCharacterRange: NULL]; actualCharacterRange: NULL];
rect = [_layoutManager boundingRectForGlyphRange: glyphRange
return [_layoutManager boundingRectForGlyphRange: glyphRange
inTextContainer: _textContainer]; inTextContainer: _textContainer];
rect.origin.x += _textContainerOrigin.x;
rect.origin.y += _textContainerOrigin.y;
return rect;
} }
/** Extension method that copies the current selected text to the /** Extension method that copies the current selected text to the