mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-05 08:51:33 +00:00
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:
parent
d18dff286c
commit
b5dad7bf50
3 changed files with 270 additions and 124 deletions
|
@ -105,13 +105,12 @@ typedef enum {
|
||||||
float _hyphenationFactor;
|
float _hyphenationFactor;
|
||||||
NSTypesetter *_typesetter;
|
NSTypesetter *_typesetter;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -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,9 +1631,13 @@ _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.
|
||||||
*/
|
*/
|
||||||
GSIArrayRemoveItemAtIndex((GSIArray)_glyphGaps, 0);
|
while (GSIArrayCount((GSIArray)_glyphGaps) > 0
|
||||||
|
&& GSIArrayItemAtIndex((GSIArray)_glyphGaps, 0).ulng < gap)
|
||||||
|
{
|
||||||
|
GSIArrayRemoveItemAtIndex((GSIArray)_glyphGaps, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
format: @"glyph index out of range"];
|
||||||
}
|
}
|
||||||
[NSException raise: NSRangeException
|
|
||||||
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,78 +2158,131 @@ _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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cRange = NSMakeRange(NSNotFound, 0);
|
||||||
|
gRange = NSMakeRange(NSNotFound, 0);
|
||||||
}
|
}
|
||||||
return NSMakeRange(numGlyphs, 0);
|
|
||||||
}
|
|
||||||
gRange.location = _GlyphIndex(self);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adjust start character if necessary.
|
|
||||||
*/
|
|
||||||
pos = _CharIndex(self);
|
|
||||||
if (pos < cRange.location)
|
|
||||||
{
|
|
||||||
cRange.length += (cRange.location - pos);
|
|
||||||
cRange.location = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (charRange.length == 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* For a zero length range, we don't need to locate an end character.
|
|
||||||
*/
|
|
||||||
gRange.length = 0;
|
|
||||||
}
|
|
||||||
else if (NSMaxRange(charRange) == [_textStorage length])
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Special case - range extends to end of text storage.
|
|
||||||
*/
|
|
||||||
gRange.length = numGlyphs - gRange.location;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
gRange.location = _GlyphIndex(self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate the glyph immediately beyond the range,
|
* Adjust start character if necessary. The glyph may have a lower
|
||||||
* and calculate the length of the range from that.
|
* index if the start char is part of a composed character sequence.
|
||||||
*/
|
*/
|
||||||
_JumpToChar(self, NSMaxRange(charRange));
|
|
||||||
pos = _GlyphIndex(self);
|
|
||||||
gRange.length = pos - gRange.location;
|
|
||||||
pos = _CharIndex(self);
|
pos = _CharIndex(self);
|
||||||
cRange.length = pos - cRange.location;
|
if (pos < cRange.location)
|
||||||
|
{
|
||||||
|
cRange.length += (cRange.location - pos);
|
||||||
|
cRange.location = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (charRange.length == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
else if (NSMaxRange(charRange) == [_textStorage length])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Special case - range extends to end of text storage.
|
||||||
|
*/
|
||||||
|
gRange.length = numGlyphs - gRange.location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Locate the glyph immediately beyond the range,
|
||||||
|
* and calculate the length of the range from that.
|
||||||
|
*/
|
||||||
|
_JumpToChar(self, NSMaxRange(charRange));
|
||||||
|
pos = _GlyphIndex(self);
|
||||||
|
gRange.length = pos - gRange.location;
|
||||||
|
pos = _CharIndex(self);
|
||||||
|
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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue