More layout fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@12608 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-02-20 19:39:15 +00:00
parent d18dff286c
commit b5dad7bf50
3 changed files with 270 additions and 124 deletions

View file

@ -107,11 +107,10 @@ typedef enum {
void *_glyphData; // Private glyph storage. void *_glyphData; // Private glyph storage.
void *_currentGlyphs; // Current chunk pointer. void *_currentGlyphs; // Current chunk pointer.
unsigned _currentGlyph; // Current glyph index. unsigned _glyphIndex; // Current glyph index.
void *_glyphGaps; // Gaps in character mapping. void *_glyphGaps; // Gaps in character mapping.
unsigned _chunkIndex; // Current chunk in glyph stream. unsigned _chunkIndex; // Current chunk in glyph stream.
unsigned _glyphIndex; // Current glyph in chunk. unsigned _glyphOffset; // Current glyph in chunk.
unsigned _numberOfGlyphs; // After last generated glyph.
NSGlyphGenerator *_glyphGenerator; NSGlyphGenerator *_glyphGenerator;

View file

@ -36,9 +36,17 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#define USE_GLYPHS 0 #define USE_GLYPHS 0
#define ALL_CHECKS 0
#define BOTH (NSTextStorageEditedCharacters | NSTextStorageEditedAttributes) #define BOTH (NSTextStorageEditedCharacters | NSTextStorageEditedAttributes)
#if ALL_CHECKS
static void missmatch(SEL s)
{
NSLog(@"Missmatch in %@", NSStringFromSelector(s));
}
#endif
/* /*
* Glyph attributes known to the layout manager. * Glyph attributes known to the layout manager.
*/ */
@ -209,8 +217,8 @@ GSCreateGlyphChunk(unsigned glyphIndex, unsigned charIndex)
chunk = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSGlyphChunk)); chunk = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSGlyphChunk));
chunk->charIndex = charIndex; chunk->charIndex = charIndex;
chunk->glyphIndex = glyphIndex; chunk->glyphIndex = glyphIndex;
GSIArrayInitWithZoneAndCapacity(&chunk->glyphs, NSDefaultMallocZone(), 128); GSIArrayInitWithZoneAndCapacity(&chunk->glyphs, NSDefaultMallocZone(), 8);
GSIArrayInitWithZoneAndCapacity(&chunk->attrs, NSDefaultMallocZone(), 128); GSIArrayInitWithZoneAndCapacity(&chunk->attrs, NSDefaultMallocZone(), 8);
return chunk; return chunk;
} }
@ -277,9 +285,9 @@ typedef struct {
#define _chunks ((GSIArray)(((lmDefs)lm)->_glyphData)) #define _chunks ((GSIArray)(((lmDefs)lm)->_glyphData))
#define _chunk ((GSGlyphChunk*)(((lmDefs)lm)->_currentGlyphs)) #define _chunk ((GSGlyphChunk*)(((lmDefs)lm)->_currentGlyphs))
#define _current (((lmDefs)lm)->_currentGlyph) #define _gindex (((lmDefs)lm)->_glyphIndex)
#define _index (((lmDefs)lm)->_chunkIndex) #define _cindex (((lmDefs)lm)->_chunkIndex)
#define _offset (((lmDefs)lm)->_glyphIndex) #define _offset (((lmDefs)lm)->_glyphOffset)
#define _gaps ((GSIArray)(((lmDefs)lm)->_glyphGaps)) #define _gaps ((GSIArray)(((lmDefs)lm)->_glyphGaps))
@ -307,15 +315,15 @@ _Back(NSLayoutManager *lm)
if (_offset > 0) if (_offset > 0)
{ {
_offset--; _offset--;
_current--; _gindex--;
return YES; return YES;
} }
else if (_index > 0) else if (_cindex > 0)
{ {
_index--; _cindex--;
_chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(_chunks, _index).ptr; _chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(_chunks, _cindex).ptr;
_offset = GSIArrayCount(&_chunk->glyphs) - 1; _offset = GSIArrayCount(&_chunk->glyphs) - 1;
_current--; _gindex--;
return YES; return YES;
} }
else else
@ -334,17 +342,17 @@ _Step(NSLayoutManager *lm)
if (_offset < GSIArrayCount(&_chunk->glyphs) - 1) if (_offset < GSIArrayCount(&_chunk->glyphs) - 1)
{ {
_offset++; _offset++;
_current++; _gindex++;
return YES; return YES;
} }
else else
{ {
if (_index < GSIArrayCount(_chunks) - 1) if (_cindex < GSIArrayCount(_chunks) - 1)
{ {
_index++; _cindex++;
_chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(_chunks, _index).ptr; _chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(_chunks, _cindex).ptr;
_offset = 0; _offset = 0;
_current++; _gindex++;
return YES; return YES;
} }
else else
@ -364,7 +372,7 @@ _Adjust(NSLayoutManager *lm, unsigned from, int lengthChange)
if (_JumpToGlyph(lm, from) == YES) if (_JumpToGlyph(lm, from) == YES)
{ {
GSGlyphChunk *chunk = _chunk; GSGlyphChunk *chunk = _chunk;
unsigned index = _index; unsigned index = _cindex;
unsigned offset = _offset; unsigned offset = _offset;
/* /*
@ -511,7 +519,7 @@ _JumpToChar(NSLayoutManager *lm, unsigned charIndex)
* character index we were asked for. If it doesn't we have probably * character index we were asked for. If it doesn't we have probably
* failed to find a glyph matching the character. * failed to find a glyph matching the character.
*/ */
co = (GSIArrayItemAtIndex(&c->attrs, o-1).ext).offset; co = (GSIArrayItemAtIndex(&c->attrs, o).ext).offset;
if (co + c->charIndex != charIndex) if (co + c->charIndex != charIndex)
{ {
if ([((lmDefs)lm)->_textStorage length] > charIndex) if ([((lmDefs)lm)->_textStorage length] > charIndex)
@ -526,6 +534,10 @@ _JumpToChar(NSLayoutManager *lm, unsigned charIndex)
* The requested character is part of a composed character * The requested character is part of a composed character
* sequence whose first character maps on to the glyph we found. * sequence whose first character maps on to the glyph we found.
*/ */
_chunk = c;
_cindex = i;
_offset = o;
_gindex = c->glyphIndex + o;
return YES; return YES;
} }
} }
@ -540,9 +552,9 @@ _JumpToChar(NSLayoutManager *lm, unsigned charIndex)
o--; o--;
} }
_chunk = c; _chunk = c;
_index = i; _cindex = i;
_offset = o; _offset = o;
_current = c->glyphIndex + o; _gindex = c->glyphIndex + o;
return YES; return YES;
} }
@ -565,9 +577,9 @@ _JumpToGlyph(NSLayoutManager *lm, unsigned glyphIndex)
if (GSIArrayCount(&c->glyphs) > 0) if (GSIArrayCount(&c->glyphs) > 0)
{ {
_chunk = c; _chunk = c;
_index = 0; _cindex = 0;
_offset = 0; _offset = 0;
_current = 0; _gindex = 0;
return YES; return YES;
} }
return NO; return NO;
@ -579,9 +591,9 @@ _JumpToGlyph(NSLayoutManager *lm, unsigned glyphIndex)
if (o < GSIArrayCount(&c->glyphs)) if (o < GSIArrayCount(&c->glyphs))
{ {
_chunk = c; _chunk = c;
_index = i; _cindex = i;
_offset = o; _offset = o;
_current = c->glyphIndex + o; _gindex = glyphIndex;
return YES; return YES;
} }
else else
@ -659,26 +671,23 @@ _Sane(NSLayoutManager *lm)
static void static void
_GLog(NSLayoutManager *lm, SEL _cmd) _GLog(NSLayoutManager *lm, SEL _cmd)
{ {
unsigned lastGlyph = 0; #if ALL_CHECKS
unsigned lastChar = 0;
unsigned pos; unsigned pos;
/* /*
* Check gaps. * Check gaps.
*/ */
fprintf(stderr, "%s, %x\ngaps (%u) - ", fprintf(stderr, "%s, %x\ngaps (%u) - ",
sel_get_name(_cmd), (unsigned)lm, GSIArrayCount(_gaps)); _cmd ? sel_get_name(_cmd) : "", (unsigned)lm, GSIArrayCount(_gaps));
for (pos = 0; pos < GSIArrayCount(_gaps); pos++) for (pos = 0; pos < GSIArrayCount(_gaps); pos++)
{ {
unsigned val = GSIArrayItemAtIndex(_gaps, pos).ulng; unsigned val = GSIArrayItemAtIndex(_gaps, pos).ulng;
fprintf(stderr, " %u", val); fprintf(stderr, " %u", val);
lastGlyph = val;
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "chunks (%u) -\n", GSIArrayCount(_chunks)); fprintf(stderr, "chunks (%u) -\n", GSIArrayCount(_chunks));
lastGlyph = 0;
for (pos = 0; pos < GSIArrayCount(_chunks); pos++) for (pos = 0; pos < GSIArrayCount(_chunks); pos++)
{ {
GSGlyphChunk *chunk; GSGlyphChunk *chunk;
@ -699,13 +708,12 @@ _GLog(NSLayoutManager *lm, SEL _cmd)
fprintf(stderr, " %4d %4d %c", fprintf(stderr, " %4d %4d %c",
chunk->glyphIndex + i, chunk->glyphIndex + i,
chunk->charIndex + a.offset, chunk->charIndex + a.offset,
(char)GSIArrayItemAtIndex(&_chunk->glyphs, _offset + i).ulng); (char)GSIArrayItemAtIndex(&chunk->glyphs, i).ulng);
lastChar = chunk->charIndex + a.offset;
} }
lastGlyph = chunk->glyphIndex + count - 1;
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
} }
#endif
} }
#else #else
static inline void static inline void
@ -765,12 +773,13 @@ _GLog(NSLayoutManager *lm, SEL _cmd)
* Initialise glyph storage and ivars to contain 'current' glyph * Initialise glyph storage and ivars to contain 'current' glyph
* location information. * location information.
*/ */
_glyphData = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIArray_t)); a = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIArray_t));
GSIArrayInitWithZoneAndCapacity(glyphChunks, NSDefaultMallocZone(), 8); GSIArrayInitWithZoneAndCapacity(a, NSDefaultMallocZone(), 8);
_glyphData = a;
_currentGlyphs = GSCreateGlyphChunk(0, 0); _currentGlyphs = GSCreateGlyphChunk(0, 0);
GSIArrayInsertItem(glyphChunks, (GSIArrayItem)_currentGlyphs, 0); GSIArrayInsertItem(glyphChunks, (GSIArrayItem)_currentGlyphs, 0);
_chunkIndex = 0; _chunkIndex = 0;
_glyphIndex = 0; _glyphOffset = 0;
/* /*
* Initialise storage of gaps in the glyph stream. * Initialise storage of gaps in the glyph stream.
@ -991,9 +1000,18 @@ _GLog(NSLayoutManager *lm, SEL _cmd)
NSRange cRange; NSRange cRange;
NSRange gRange; NSRange gRange;
_GLog(self,_cmd);
if (actualRange != 0)
{
*actualRange = cRange;
}
if (aRange.length == 0) if (aRange.length == 0)
{ {
return; return; // Empty ... nothing to do.
}
if (aRange.location >= _CharEnd(self))
{
return; // No glyphs generated for that character index.
} }
gRange = [self glyphRangeForCharacterRange: aRange gRange = [self glyphRangeForCharacterRange: aRange
@ -1016,9 +1034,10 @@ _GLog(NSLayoutManager *lm, SEL _cmd)
/* /*
* Unless the 'lengthChange' accounts for the entire character range * Unless the 'lengthChange' accounts for the entire character range
* that we deleted glyphs for, we must note the presence of a gap. * or the deleted glyphs were at the end of the glyph stream, we must
* note the presence of a gap.
*/ */
if (cRange.length + lengthChange > 0) if (cRange.length + lengthChange > -1 && gRange.location < _GlyphEnd(self))
{ {
unsigned count = GSIArrayCount((GSIArray)_glyphGaps); unsigned count = GSIArrayCount((GSIArray)_glyphGaps);
@ -1385,9 +1404,10 @@ _GLog(self,_cmd);
/* /*
* Shall we add to the chunk or is it big enough already? * Shall we add to the chunk or is it big enough already?
*/ */
if (gCount > 100 && gCount == GSIArrayCapacity(&chunk->glyphs)) if (gCount > 4 && gCount == GSIArrayCapacity(&chunk->glyphs))
{ {
GSGlyphChunk *newChunk = 0; GSGlyphChunk *newChunk = 0;
unsigned from;
unsigned pos; unsigned pos;
unsigned splitAt = gCount/2; unsigned splitAt = gCount/2;
unsigned splitChar; unsigned splitChar;
@ -1420,7 +1440,8 @@ _GLog(self,_cmd);
GSIArrayInsertItem(glyphChunks, (GSIArrayItem)(void*)newChunk, GSIArrayInsertItem(glyphChunks, (GSIArrayItem)(void*)newChunk,
chunkIndex+1); chunkIndex+1);
pos = 0; pos = 0;
while (GSIArrayCount(&chunk->glyphs) > splitAt) from = splitAt;
while (from < GSIArrayCount(&chunk->glyphs))
{ {
GSGlyphAttrs attrs; GSGlyphAttrs attrs;
NSGlyph glyph; NSGlyph glyph;
@ -1429,8 +1450,7 @@ _GLog(self,_cmd);
* Remove attributes from old chunk and add to new. * Remove attributes from old chunk and add to new.
* Adjust offset for character index of new chunk. * Adjust offset for character index of new chunk.
*/ */
attrs = GSIArrayItemAtIndex(&chunk->attrs, splitAt).ext; attrs = GSIArrayItemAtIndex(&chunk->attrs, from).ext;
GSIArrayRemoveItemAtIndex(&chunk->attrs, splitAt);
attrs.offset -= splitChar; attrs.offset -= splitChar;
GSIArrayInsertItem(&newChunk->attrs, GSIArrayInsertItem(&newChunk->attrs,
(GSIArrayItem)attrs, pos); (GSIArrayItem)attrs, pos);
@ -1438,13 +1458,15 @@ _GLog(self,_cmd);
/* /*
* Remove glyph from old chunk and add to new. * Remove glyph from old chunk and add to new.
*/ */
glyph = GSIArrayItemAtIndex(&chunk->glyphs, splitAt).ulng; glyph = GSIArrayItemAtIndex(&chunk->glyphs, from).ulng;
GSIArrayRemoveItemAtIndex(&chunk->glyphs, splitAt);
GSIArrayInsertItem(&newChunk->glyphs, GSIArrayInsertItem(&newChunk->glyphs,
(GSIArrayItem)glyph, pos); (GSIArrayItem)glyph, pos);
from++;
pos++; pos++;
} }
GSIArrayRemoveItemsFromIndex(&chunk->glyphs, splitAt);
GSIArrayRemoveItemsFromIndex(&chunk->attrs, splitAt);
/* /*
* And set up so we point at the correct half of the split chunk. * And set up so we point at the correct half of the split chunk.
*/ */
@ -1452,9 +1474,9 @@ _GLog(self,_cmd);
{ {
chunkIndex++; chunkIndex++;
chunk = newChunk; chunk = newChunk;
gCount = GSIArrayCount(&chunk->glyphs);
gOffset = glyphIndex - chunk->glyphIndex; gOffset = glyphIndex - chunk->glyphIndex;
} }
gCount = GSIArrayCount(&chunk->glyphs);
} }
/* /*
@ -1548,6 +1570,7 @@ _Sane(self);
isValidIndex: (BOOL*)flag isValidIndex: (BOOL*)flag
{ {
#if USE_GLYPHS #if USE_GLYPHS
NSGlyph glyph;
NSString *string = nil; NSString *string = nil;
unsigned textLength = [_textStorage length]; unsigned textLength = [_textStorage length];
@ -1573,7 +1596,7 @@ _GLog(self,_cmd);
{ {
/* /*
* Locate the glyph that preceeds the gap, and start with the * Locate the glyph that preceeds the gap, and start with the
* a character one beyond the one that generated the glyph. * a character one beyond the one that generated that glyph.
* This guarantees that we won't try to re-generate the * This guarantees that we won't try to re-generate the
* preceeding glyph. * preceeding glyph.
* FIXME ... probably too simplistic an algorithm if we have * FIXME ... probably too simplistic an algorithm if we have
@ -1608,11 +1631,15 @@ _GLog(self,_cmd);
} }
/* /*
* We have generated glyphs upto or beyond the gap, so we * We have generated glyphs upto or beyond the gap, so we
* can remove this gap entry. * can remove this gap and any others we have gone past.
*/ */
while (GSIArrayCount((GSIArray)_glyphGaps) > 0
&& GSIArrayItemAtIndex((GSIArray)_glyphGaps, 0).ulng < gap)
{
GSIArrayRemoveItemAtIndex((GSIArray)_glyphGaps, 0); GSIArrayRemoveItemAtIndex((GSIArray)_glyphGaps, 0);
} }
} }
}
if (index >= _GlyphEnd(self) && _CharEnd(self) < textLength) if (index >= _GlyphEnd(self) && _CharEnd(self) < textLength)
{ {
@ -1640,13 +1667,31 @@ _Sane(self);
if (_JumpToGlyph(self, index) == YES) if (_JumpToGlyph(self, index) == YES)
{ {
*flag = YES; *flag = YES;
return _Glyph(self); glyph = _Glyph(self);
} }
else else
{ {
*flag = NO; *flag = NO;
return NSNullGlyph; glyph = NSNullGlyph;
} }
#if ALL_CHECKS
if (index >= [_textStorage length])
{
if (glyph != NSNullGlyph)
{
missmatch(_cmd);
*flag = NO;
glyph = NSNullGlyph;
}
}
else if (glyph != (NSGlyph)[[_textStorage string] characterAtIndex: index])
{
missmatch(_cmd);
*flag = YES;
glyph = (NSGlyph)[[_textStorage string] characterAtIndex: index];
}
#endif
return glyph;
#else #else
return (NSGlyph)[[_textStorage string] characterAtIndex: index]; return (NSGlyph)[[_textStorage string] characterAtIndex: index];
#endif #endif
@ -1660,12 +1705,14 @@ _Sane(self);
- (void) replaceGlyphAtIndex: (unsigned)index - (void) replaceGlyphAtIndex: (unsigned)index
withGlyph: (NSGlyph)newGlyph withGlyph: (NSGlyph)newGlyph
{ {
_GLog(self,_cmd);
if (_JumpToGlyph(self, index) == NO) if (_JumpToGlyph(self, index) == NO)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
format: @"glyph index out of range"]; format: @"glyph index out of range"];
} }
_SetGlyph(self, newGlyph); _SetGlyph(self, newGlyph);
_GLog(self,_cmd);
} }
/** /**
@ -1686,6 +1733,7 @@ _Sane(self);
unsigned packed = 0; unsigned packed = 0;
unsigned toFetch = glyphRange.length; unsigned toFetch = glyphRange.length;
_GLog(self,_cmd);
if (toFetch > 0) if (toFetch > 0)
{ {
/* /*
@ -1708,6 +1756,7 @@ _Sane(self);
} }
} }
glyphArray[packed] = 0; glyphArray[packed] = 0;
_GLog(self,_cmd);
return packed; return packed;
} }
@ -1724,6 +1773,7 @@ _Sane(self);
unsigned pos; unsigned pos;
GSGlyphChunk *chunk; GSGlyphChunk *chunk;
_GLog(self,_cmd);
if (aRange.length == 0) if (aRange.length == 0)
{ {
return; // Nothing to delete. return; // Nothing to delete.
@ -1781,10 +1831,10 @@ _Sane(self);
GSIArrayRemoveItemsFromIndex(&chunk->glyphs, offset); GSIArrayRemoveItemsFromIndex(&chunk->glyphs, offset);
GSIArrayRemoveItemsFromIndex(&chunk->attrs, offset); GSIArrayRemoveItemsFromIndex(&chunk->attrs, offset);
} }
chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks, chunkEnd).ptr;
} }
chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks, chunkEnd).ptr; offset = NSMaxRange(aRange) - chunk->glyphIndex;
offset = NSMaxRange(aRange)-1 - chunk->glyphIndex;
if (chunk->glyphIndex < aRange.location) if (chunk->glyphIndex < aRange.location)
{ {
from = aRange.location - chunk->glyphIndex; from = aRange.location - chunk->glyphIndex;
@ -1860,20 +1910,26 @@ _Sane(self);
*/ */
- (unsigned) numberOfGlyphs - (unsigned) numberOfGlyphs
{ {
unsigned result;
#if USE_GLYPHS #if USE_GLYPHS
if (GSIArrayCount((GSIArray)_glyphGaps) > 0)
{
BOOL valid; BOOL valid;
/* /*
* Force generation of all glyphs. * Force generation of all glyphs.
*/ */
[self glyphAtIndex: 0x7fffffff isValidIndex: &valid]; [self glyphAtIndex: 0x7fffffff isValidIndex: &valid];
result = _GlyphEnd(self);
#if ALL_CHECKS
if (result != [_textStorage length])
{
missmatch(_cmd);
result = [_textStorage length];
} }
return _GlyphEnd(self);
#else
return [_textStorage length];
#endif #endif
#else
result = [_textStorage length];
#endif
return result;
} }
/** /**
@ -1886,6 +1942,7 @@ _Sane(self);
GSGlyphAttrs attrs; GSGlyphAttrs attrs;
int diff; int diff;
_GLog(self,_cmd);
if (_JumpToGlyph(self, glyphIndex) == NO) if (_JumpToGlyph(self, glyphIndex) == NO)
{ {
[self glyphAtIndex: glyphIndex]; [self glyphAtIndex: glyphIndex];
@ -1924,7 +1981,7 @@ _Sane(self);
* for the chunk as a whole, then fix each glyph in turn. Otherwise * for the chunk as a whole, then fix each glyph in turn. Otherwise
* we simply adjust the glyph concerned. * we simply adjust the glyph concerned.
*/ */
if (_glyphIndex == 0) if (_glyphOffset == 0)
{ {
GSGlyphChunk *chunk = (GSGlyphChunk*)_currentGlyphs; GSGlyphChunk *chunk = (GSGlyphChunk*)_currentGlyphs;
@ -1954,13 +2011,21 @@ _Sane(self);
*/ */
- (unsigned) characterIndexForGlyphAtIndex: (unsigned)glyphIndex - (unsigned) characterIndexForGlyphAtIndex: (unsigned)glyphIndex
{ {
unsigned result;
#if USE_GLYPHS #if USE_GLYPHS
_GLog(self,_cmd);
if (_JumpToGlyph(self, glyphIndex) == NO) if (_JumpToGlyph(self, glyphIndex) == NO)
{ {
BOOL exists; BOOL exists;
[self glyphAtIndex: glyphIndex isValidIndex: &exists]; [self glyphAtIndex: glyphIndex isValidIndex: &exists];
if (exists == NO) if (exists == YES)
{
_JumpToGlyph(self, glyphIndex);
result = _CharIndex(self);
}
else
{ {
/* /*
* As a special case, the glyph index just beyond the end of * As a special case, the glyph index just beyond the end of
@ -1969,17 +2034,31 @@ _Sane(self);
*/ */
if (glyphIndex == _GlyphEnd(self)) if (glyphIndex == _GlyphEnd(self))
{ {
return [_textStorage length]; result = [_textStorage length];
} }
else
{
[NSException raise: NSRangeException [NSException raise: NSRangeException
format: @"glyph index out of range"]; format: @"glyph index out of range"];
} }
_JumpToGlyph(self, glyphIndex);
} }
return _CharIndex(self); }
#else else
return glyphIndex; {
result = _CharIndex(self);
}
#if ALL_CHECKS
if (result != glyphIndex)
{
missmatch(_cmd);
result = glyphIndex;
}
#endif #endif
_GLog(self,_cmd);
#else
result = glyphIndex;
#endif
return result;
} }
/** /**
@ -1996,12 +2075,13 @@ _Sane(self);
- (NSRange) characterRangeForGlyphRange: (NSRange)glyphRange - (NSRange) characterRangeForGlyphRange: (NSRange)glyphRange
actualGlyphRange: (NSRange*)actualGlyphRange actualGlyphRange: (NSRange*)actualGlyphRange
{ {
#if USE_GLYPHS
NSRange cRange; NSRange cRange;
NSRange gRange = glyphRange; NSRange gRange = glyphRange;
#if USE_GLYPHS
unsigned cEnd; unsigned cEnd;
BOOL exists; BOOL exists;
_GLog(self,_cmd);
/* /*
* Force generation of glyphs to fill gaps. * Force generation of glyphs to fill gaps.
*/ */
@ -2039,17 +2119,28 @@ _Sane(self);
gRange.length++; gRange.length++;
} }
#if ALL_CHECKS
if (NSEqualRanges(cRange, glyphRange) == NO)
{
missmatch(_cmd);
cRange = glyphRange;
}
if (NSEqualRanges(gRange, glyphRange) == NO)
{
missmatch(_cmd);
gRange = glyphRange;
}
#endif
#else
// Currently gyphIndex is the same as character index
gRange = glyphRange;
cRange = glyphRange;
#endif
if (actualGlyphRange != 0) if (actualGlyphRange != 0)
{ {
*actualGlyphRange = gRange; *actualGlyphRange = gRange;
} }
return cRange; return cRange;
#else
// Currently gyphIndex is the same as character index
if (actualGlyphRange != NULL)
*actualGlyphRange = glyphRange;
return glyphRange;
#endif
} }
/** /**
@ -2067,31 +2158,69 @@ _Sane(self);
- (NSRange) glyphRangeForCharacterRange: (NSRange)charRange - (NSRange) glyphRangeForCharacterRange: (NSRange)charRange
actualCharacterRange: (NSRange*)actualCharRange actualCharacterRange: (NSRange*)actualCharRange
{ {
NSRange gRange;
#if USE_GLYPHS #if USE_GLYPHS
unsigned pos; unsigned pos;
NSRange cRange = charRange; NSRange cRange = charRange;
NSRange gRange;
unsigned numGlyphs; unsigned numGlyphs;
BOOL valid;
numGlyphs = [self numberOfGlyphs]; // Force generation of glyphs. /*
* If the range we have been given begins or ends with a composed
* character sequence, we must extend it to encompass the entire
* sequence. We store the actual range in cRange.
*/
if (charRange.length > 0)
{
NSString *s = [_textStorage string];
NSRange r;
r = [s rangeOfComposedCharacterSequenceAtIndex: cRange.location];
if (r.length > 0)
{
cRange.length += (cRange.location - r.location);
cRange.location = r.location;
}
if (NSMaxRange(charRange) > NSMaxRange(r))
{
pos = NSMaxRange(charrange) - 1;
r = [s rangeOfComposedCharacterSequenceAtIndex: pos];
if (r.length > 0)
{
cRange.length += r.length - 1;
}
}
}
_GLog(self,_cmd);
// Force generation of glyphs.
[self glyphAtIndex: NSMaxRange(cRange) - 1 isValidIndex: &valid];
/* /*
* Locate the first glyph corresponding to the start character. * Locate the first glyph corresponding to the start character.
* If we can't find it, we return a zero length range at the end. * If it doesn't exist, we either have a zero length range at the end.
* or we must return a not found marker.
*/ */
if (_JumpToChar(self, charRange.location) == NO) if (_JumpToChar(self, charRange.location) == NO)
{ {
if (actualCharRange != 0) if (charRange.location == _CharEnd(self))
{ {
actualCharRange->location = charRange.location; cRange = NSMakeRange(charRange.location, 0);
actualCharRange->length = 0; gRange = NSMakeRange(numGlyphs, 0);
} }
return NSMakeRange(numGlyphs, 0); else
{
cRange = NSMakeRange(NSNotFound, 0);
gRange = NSMakeRange(NSNotFound, 0);
} }
}
else
{
gRange.location = _GlyphIndex(self); gRange.location = _GlyphIndex(self);
/* /*
* Adjust start character if necessary. * Adjust start character if necessary. The glyph may have a lower
* index if the start char is part of a composed character sequence.
*/ */
pos = _CharIndex(self); pos = _CharIndex(self);
if (pos < cRange.location) if (pos < cRange.location)
@ -2105,6 +2234,7 @@ _Sane(self);
/* /*
* For a zero length range, we don't need to locate an end character. * For a zero length range, we don't need to locate an end character.
*/ */
cRange.length = 0; // May have been lengthened above.
gRange.length = 0; gRange.length = 0;
} }
else if (NSMaxRange(charRange) == [_textStorage length]) else if (NSMaxRange(charRange) == [_textStorage length])
@ -2126,19 +2256,33 @@ _Sane(self);
pos = _CharIndex(self); pos = _CharIndex(self);
cRange.length = pos - cRange.location; cRange.length = pos - cRange.location;
} }
}
#if ALL_CHECKS
if (NSEqualRanges(gRange, charRange) == NO)
{
missmatch(_cmd);
gRange = charRange;
}
if (NSEqualRanges(cRange, charRange) == NO)
{
missmatch(_cmd);
cRange = charRange;
}
#endif
if (actualCharRange != 0) if (actualCharRange != 0)
{ {
*actualCharRange = cRange; *actualCharRange = cRange;
} }
return gRange; _GLog(self,_cmd);
#else #else
// Currently gyphIndex is the same as character index // Currently gyphIndex is the same as character index
if (actualCharRange != NULL) if (actualCharRange != NULL)
{ {
*actualCharRange = charRange; *actualCharRange = charRange;
} }
return charRange; gRange = charRange;
#endif #endif
return gRange;
} }
/** /**
@ -2167,6 +2311,7 @@ _Sane(self);
{ {
GSGlyphAttrs attrs; GSGlyphAttrs attrs;
_GLog(self,_cmd);
if (_JumpToGlyph(self, glyphIndex) == NO) if (_JumpToGlyph(self, glyphIndex) == NO)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
@ -2204,6 +2349,7 @@ _Sane(self);
attrs.inscription = anInt; attrs.inscription = anInt;
} }
_SetAttrs(self, attrs); _SetAttrs(self, attrs);
_GLog(self,_cmd);
} }
/** /**
@ -2218,6 +2364,7 @@ _Sane(self);
{ {
GSGlyphAttrs attrs; GSGlyphAttrs attrs;
_GLog(self,_cmd);
if (_JumpToGlyph(self, glyphIndex) == NO) if (_JumpToGlyph(self, glyphIndex) == NO)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException

View file

@ -1520,7 +1520,7 @@ static NSNotificationCenter *nc;
return; return;
} }
charRange = NSMakeRange (_selected_range.location, 1); charRange = NSMakeRange (_selected_range.location, 0);
glyphRange = [_layoutManager glyphRangeForCharacterRange: charRange glyphRange = [_layoutManager glyphRangeForCharacterRange: charRange
actualCharacterRange: NULL]; actualCharacterRange: NULL];
glyphIndex = glyphRange.location; glyphIndex = glyphRange.location;