Modifications for text storage system

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4594 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-07-15 05:52:55 +00:00
parent d86fed1d3a
commit 81b4f0f80c
8 changed files with 678 additions and 58 deletions

View file

@ -1,3 +1,14 @@
Thu Jul 15 6:55:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Headers/AppKit/NSAttributedString.h: new file
* Headers/AppKit/NSStringDrawing.h: Move some stuff to
NSAttributedString.h
* Headers/AppKit/AppKit.h: include NSAttributedString.h
* Source/GSTextStorage.m: new file
* Source/GNUmakefile: update for new source
* Source/NSTextStorage.m: Make instances of GSTextStorage
* Source/externs.m: Add new string constant for text links.
Wed Jul 14 19:18:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/GNUmakefile: Install NSMenuItemCell.h and NSMenuView.h

View file

@ -72,6 +72,7 @@
#include <AppKit/NSActionCell.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSApplication.h>
#include <AppKit/NSAttributedString.h>
#include <AppKit/NSBitmapImageRep.h>
#include <AppKit/NSBox.h>
#include <AppKit/NSBrowser.h>

View file

@ -0,0 +1,100 @@
/*
NSAttributedString.h
Categories which add capabilities to NSAttributedString
Copyright (C) 1999 Free Software Foundation, Inc.
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: July 1999
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _GNUstep_H_NSAttributedString
#define _GNUstep_H_NSAttributedString
#import <Foundation/Foundation.h>
#import <AppKit/NSFileWrapper.h>
#import <AppKit/NSFontManager.h>
#import <AppKit/NSText.h>
// global NSString attribute names used in accessing
// the respective property in a text attributes
// dictionary. if the key is not in the dictionary
// the default value is assumed
extern NSString *NSFontAttributeName;
extern NSString *NSParagraphStyleAttributeName;
extern NSString *NSForegroundColorAttributeName;
extern NSString *NSUnderlineStyleAttributeName;
extern NSString *NSSuperscriptAttributeName;
extern NSString *NSBackgroundColorAttributeName;
extern NSString *NSAttachmentAttributeName;
extern NSString *NSLigatureAttributeName;
extern NSString *NSBaselineOffsetAttributeName;
extern NSString *NSKernAttributeName;
extern NSString *NSLinkAttributeName;
// Currently supported values for NSUnderlineStyleAttributeName
enum
{
GSNoUnderlineStyle = 0,
NSSingleUnderlineStyle = 1
};
@interface NSAttributedString (AppKit)
- (BOOL) containsAttachments;
- (NSDictionary*) fontAttributesInRange: (NSRange)range;
- (NSDictionary*) rulerAttributesInRange: (NSRange)range;
- (unsigned) lineBreakBeforeIndex: (unsigned)location
withinRange: (NSRange)aRange;
- (NSRange) doubleClickAtIndex: (unsigned)location;
- (unsigned) nextWordFromIndex: (unsigned)location forward: (BOOL)isForward;
- (id) initWithRTF: (NSData*)data documentAttributes: (NSDictionary**)dict;
- (id) initWithRTFD: (NSData*)data documentAttributes: (NSDictionary**)dict;
- (id) initWithPath: (NSString*)path documentAttributes: (NSDictionary**)dict;
- (id) initWithURL: (NSURL*)url documentAttributes: (NSDictionary**)dict;
- (id) initWithRTFDFileWrapper: (NSFileWrapper*)wrapper
documentAttributes: (NSDictionary**)dict;
- (id) initWithHTML: (NSData*)data documentAttributes: (NSDictionary**)dict;
- (id) initWithHTML: (NSData*)data baseURL: (NSURL*)base
documentAttributes: (NSDictionary**)dict;
- (NSData*) RTFFromRange: (NSRange)range
documentAttributes: (NSDictionary*)dict;
- (NSData*) RTFDFromRange: (NSRange)range
documentAttributes: (NSDictionary*)dict;
- (NSFileWrapper*) RTFDFileWrapperFromRange: (NSRange)range
documentAttributes: (NSDictionary*)dict;
@end
@interface NSMutableAttributedString (AppKit)
- (void) superscriptRange: (NSRange)range;
- (void) subscriptRange: (NSRange)range;
- (void) unscriptRange: (NSRange)range;
- (void) applyFontTraits: (NSFontTraitMask)traitMask range: (NSRange)range;
- (void) setAlignment: (NSTextAlignment)alignment range: (NSRange)range;
- (void) fixAttributesInRange: (NSRange)range;
- (void) fixFontAttributeInRange: (NSRange)range;
- (void) fixParagraphStyleAttributeInRange: (NSRange)range;
- (void) fixAttachmentAttributeInRange: (NSRange)range;
@end
#endif

View file

@ -35,29 +35,7 @@
#include <Foundation/NSString.h>
#include <Foundation/NSAttributedString.h>
#include <Foundation/NSGeometry.h>
// global NSString attribute names used in accessing
// the respective property in a text attributes
// dictionary. if the key is not in the dictionary
// the default value is assumed
extern NSString *NSFontAttributeName;
extern NSString *NSParagraphStyleAttributeName;
extern NSString *NSForegroundColorAttributeName;
extern NSString *NSUnderlineStyleAttributeName;
extern NSString *NSSuperscriptAttributeName;
extern NSString *NSBackgroundColorAttributeName;
extern NSString *NSAttachmentAttributeName;
extern NSString *NSLigatureAttributeName;
extern NSString *NSBaselineOffsetAttributeName;
extern NSString *NSKernAttributeName;
// Currently supported values for NSUnderlineStyleAttributeName
enum
{
GSNoUnderlineStyle = 0,
NSSingleUnderlineStyle = 1
};
#include <AppKit/NSAttributedString.h>
@interface NSString (NSStringDrawing)

View file

@ -115,6 +115,7 @@ NSTextView.m \
NSView.m \
NSWindow.m \
NSWorkspace.m \
GSTextStorage.m \
GSTrackingRect.m \
GSServicesManager.m \
tiff.m \
@ -132,6 +133,7 @@ AppKit/AppKit.h \
AppKit/NSActionCell.h \
AppKit/NSAffineTransform.h \
AppKit/NSApplication.h \
AppKit/NSAttributedString.h \
AppKit/NSBitmapImageRep.h \
AppKit/NSBox.h \
AppKit/NSBrowser.h \

492
Source/GSTextStorage.m Normal file
View file

@ -0,0 +1,492 @@
/*
GSTextStorage.m
Implementation of concrete subclass of a string class with attributes
Copyright (C) 1999 Free Software Foundation, Inc.
Based on code by: ANOQ of the sun <anoq@vip.cybercity.dk>
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: July 1999
This file is part of GNUStep-gui
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Warning - [-initWithString:attributes:] is the designated initialiser,
* but it doesn't provide any way to perform the function of the
* [-initWithAttributedString:] initialiser.
* In order to work youd this, the string argument of the
* designated initialiser has been overloaded such that it
* is expected to accept an NSAttributedString here instead of
* a string. If you create an NSAttributedString subclass, you
* must make sure that your implementation of the initialiser
* copes with either an NSString or an NSAttributedString.
* If it receives an NSAttributedString, it should ignore the
* attributes argument and use the values from the string.
*/
#include <Foundation/NSAttributedString.h>
#include <Foundation/NSException.h>
#include <Foundation/NSRange.h>
#include <Foundation/NSGArray.h>
#include <AppKit/NSTextStorage.h>
@interface GSTextStorage : NSTextStorage
{
NSMutableString *textChars;
NSMutableArray *infoArray;
}
@end
@interface GSTextInfo : NSObject
{
@public
unsigned loc;
NSDictionary *attrs;
}
+ (GSTextInfo*) newWithZone: (NSZone*)z value: (NSDictionary*)a at: (unsigned)l;
@end
@implementation GSTextInfo
+ (GSTextInfo*) newWithZone: (NSZone*)z value: (NSDictionary*)a at: (unsigned)l;
{
GSTextInfo *info = (GSTextInfo*)NSAllocateObject(self, 0, z);
info->loc = l;
info->attrs = [a copy];
return info;
}
- (void) dealloc
{
RELEASE(attrs);
NSDeallocateObject(self);
}
- (Class) classForPortCoder
{
return [self class];
}
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
{
return self;
}
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[super encodeWithCoder: aCoder];
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &loc];
[aCoder encodeValueOfObjCType: @encode(id) at: &attrs];
}
- (id) initWithCoder: (NSCoder*)aCoder
{
self = [super initWithCoder: aCoder];
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &loc];
[aCoder decodeValueOfObjCType: @encode(id) at: &attrs];
return self;
}
@end
static Class infCls = 0;
static SEL infSel = @selector(newWithZone:value:at:);
static IMP infImp = 0;
static SEL addSel = @selector(addObject:);
static void (*addImp)() = 0;
static SEL cntSel = @selector(count);
static unsigned (*cntImp)() = 0;
static SEL insSel = @selector(insertObject:atIndex:);
static void (*insImp)() = 0;
static SEL oatSel = @selector(objectAtIndex:);
static IMP oatImp = 0;
static SEL remSel = @selector(removeObjectAtIndex:);
static void (*remImp)() = 0;
#define NEWINFO(Z,O,L) ((*infImp)(infCls, infSel, (Z), (O), (L)))
#define ADDOBJECT(O) ((*addImp)(infoArray, addSel, (O)))
#define INSOBJECT(O,I) ((*insImp)(infoArray, insSel, (O), (I)))
#define OBJECTAT(I) ((*oatImp)(infoArray, oatSel, (I)))
#define REMOVEAT(I) ((*remImp)(infoArray, remSel, (I)))
static void _setup()
{
if (infCls == 0)
{
Class c = [NSGMutableArray class];
infCls = [GSTextInfo class];
infImp = [infCls methodForSelector: infSel];
addImp = (void (*)())[c instanceMethodForSelector: addSel];
cntImp = (unsigned (*)())[c instanceMethodForSelector: cntSel];
insImp = (void (*)())[c instanceMethodForSelector: insSel];
oatImp = [c instanceMethodForSelector: oatSel];
remImp = (void (*)())[c instanceMethodForSelector: remSel];
}
}
static void
_setAttributesFrom(
NSAttributedString *attributedString,
NSRange aRange,
NSMutableArray *infoArray)
{
NSZone *z = [infoArray zone];
NSRange range;
NSDictionary *attr;
GSTextInfo *info;
unsigned loc;
/*
* remove any old attributes of the string.
*/
[infoArray removeAllObjects];
if (aRange.length <= 0)
return;
attr = [attributedString attributesAtIndex: aRange.location
effectiveRange: &range];
info = [GSTextInfo newWithZone: z value: attr at: 0];
ADDOBJECT(info);
RELEASE(info);
while ((loc = NSMaxRange(range)) < NSMaxRange(aRange))
{
attr = [attributedString attributesAtIndex: loc
effectiveRange: &range];
info = [GSTextInfo newWithZone: z value: attr at: loc - aRange.location];
ADDOBJECT(info);
RELEASE(info);
}
}
inline static NSDictionary*
_attributesAtIndexEffectiveRange(
unsigned int index,
NSRange *aRange,
unsigned int tmpLength,
NSMutableArray *infoArray,
unsigned int *foundIndex)
{
unsigned low, high, used, cnt, nextLoc;
GSTextInfo *found = nil;
if (index >= tmpLength)
{
[NSException raise: NSRangeException
format: @"index is out of range in function "
@"_attributesAtIndexEffectiveRange()"];
}
used = (*cntImp)(infoArray, cntSel);
/*
* Binary search for efficiency in huge attributed strings
*/
low = 0;
high = used - 1;
while (low <= high)
{
cnt = (low + high) / 2;
found = OBJECTAT(cnt);
if (found->loc > index)
{
high = cnt - 1;
}
else
{
if (cnt >= used - 1)
{
nextLoc = tmpLength;
}
else
{
GSTextInfo *inf = OBJECTAT(cnt + 1);
nextLoc = inf->loc;
}
if (found->loc == index || index < nextLoc)
{
//Found
if (aRange)
{
aRange->location = found->loc;
aRange->length = nextLoc - found->loc;
}
if (foundIndex)
{
*foundIndex = cnt;
}
return found->attrs;
}
else
{
low = cnt + 1;
}
}
}
NSCAssert(NO,@"Error in binary search algorithm");
return nil;
}
@implementation GSTextStorage
+ (void) initialize
{
_setup();
}
- (Class) classForPortCoder
{
return [self class];
}
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
{
return self;
}
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[super encodeWithCoder: aCoder];
[aCoder encodeValueOfObjCType: @encode(id) at: &textChars];
[aCoder encodeValueOfObjCType: @encode(id) at: &infoArray];
}
- (id) initWithCoder: (NSCoder*)aCoder
{
self = [super initWithCoder: aCoder];
[aCoder decodeValueOfObjCType: @encode(id) at: &textChars];
[aCoder decodeValueOfObjCType: @encode(id) at: &infoArray];
return self;
}
- (id) initWithString: (NSString*)aString
attributes: (NSDictionary*)attributes
{
NSZone *z = [self zone];
self = [super initWithString: aString attributes: attributes];
infoArray = [[NSGMutableArray allocWithZone: z] initWithCapacity: 1];
if (aString != nil && [aString isKindOfClass: [NSAttributedString class]])
{
NSAttributedString *as = (NSAttributedString*)aString;
aString = [as string];
_setAttributesFrom(as, NSMakeRange(0, [aString length]), infoArray);
}
else
{
GSTextInfo *info;
info = NEWINFO(z, attributes, 0);
ADDOBJECT(info);
RELEASE(info);
}
if (aString == nil)
textChars = [[NSGMutableString allocWithZone: z] init];
else
textChars = [aString mutableCopyWithZone: z];
return self;
}
- (NSString*) string
{
return textChars;
}
- (NSDictionary*) attributesAtIndex: (unsigned)index
effectiveRange: (NSRange*)aRange
{
return _attributesAtIndexEffectiveRange(
index, aRange, [textChars length], infoArray, NULL);
}
- (void) setAttributes: (NSDictionary*)attributes
range: (NSRange)range
{
unsigned tmpLength, arrayIndex, arraySize, location;
NSRange effectiveRange;
unsigned afterRangeLoc, beginRangeLoc;
NSDictionary *attrs;
NSZone *z = [self zone];
GSTextInfo *info;
if (!attributes)
attributes = [NSDictionary dictionary];
tmpLength = [textChars length];
GS_RANGE_CHECK(range, tmpLength);
arraySize = (*cntImp)(infoArray, cntSel);
if (NSMaxRange(range) < tmpLength)
{
attrs = _attributesAtIndexEffectiveRange(
NSMaxRange(range), &effectiveRange, tmpLength, infoArray, &arrayIndex);
afterRangeLoc = NSMaxRange(range);
if (effectiveRange.location > range.location)
{
info = OBJECTAT(arrayIndex);
info->loc = afterRangeLoc;
}
else
{
info = NEWINFO(z, attrs, afterRangeLoc);
arrayIndex++;
INSOBJECT(info, arrayIndex);
RELEASE(info);
}
arrayIndex--;
}
else
{
arrayIndex = arraySize - 1;
}
while (arrayIndex > 0)
{
info = OBJECTAT(arrayIndex-1);
if (info->loc < range.location)
break;
REMOVEAT(arrayIndex);
arrayIndex--;
}
beginRangeLoc = range.location;
info = OBJECTAT(arrayIndex);
location = info->loc;
if (location >= range.location)
{
if (location > range.location)
{
info->loc = beginRangeLoc;
}
ASSIGN(info->attrs, attributes);
}
else
{
arrayIndex++;
info = NEWINFO(z, attributes, beginRangeLoc);
INSOBJECT(info, arrayIndex);
RELEASE(info);
}
/*
* Primitive method! Sets attributes and values for a given range of
* characters, replacing any previous attributes and values for that
* range.
*/
/*
* Sets the attributes for the characters in aRange to attributes.
* These new attributes replace any attributes previously associated
* with the characters in aRange. Raises an NSRangeException if any
* part of aRange lies beyond the end of the receiver's characters.
* See also: - addAtributes: range: , - removeAttributes: range:
*/
}
- (void) replaceCharactersInRange: (NSRange)range
withString: (NSString*)aString
{
unsigned tmpLength, arrayIndex, arraySize, cnt, moveLocations;
NSRange effectiveRange;
NSDictionary *attrs;
unsigned afterRangeLoc;
GSTextInfo *info;
NSZone *z = [self zone];
if (!aString)
aString = @"";
tmpLength = [textChars length];
GS_RANGE_CHECK(range, tmpLength);
arraySize = (*cntImp)(infoArray, cntSel);
if (NSMaxRange(range) < tmpLength)
{
attrs = _attributesAtIndexEffectiveRange(
NSMaxRange(range), &effectiveRange, tmpLength, infoArray, &arrayIndex);
moveLocations = [aString length] - range.length;
afterRangeLoc = NSMaxRange(range) + moveLocations;
if (effectiveRange.location > range.location)
{
info = OBJECTAT(arrayIndex);
info->loc = afterRangeLoc;
}
else
{
info = NEWINFO(z, attrs, afterRangeLoc);
arrayIndex++;
INSOBJECT(info, arrayIndex);
arraySize++;
RELEASE(info);
}
/*
* Everything after our modified range need to be shifted.
*/
if (arrayIndex + 1 < arraySize)
{
unsigned l = arraySize - arrayIndex - 1;
NSRange r = NSMakeRange(arrayIndex + 1, l);
GSTextInfo *objs[l];
[infoArray getObjects: objs range: r];
for (cnt = 0; cnt < l; cnt++)
{
objs[cnt]->loc += moveLocations;
}
}
arrayIndex--;
}
else
{
arrayIndex = arraySize - 1;
}
while (arrayIndex > 0)
{
info = OBJECTAT(arrayIndex);
if (info->loc <= range.location)
break;
REMOVEAT(arrayIndex);
arrayIndex--;
}
[textChars replaceCharactersInRange: range withString: aString];
}
- (void) dealloc
{
RELEASE(textChars);
RELEASE(infoArray);
[super dealloc];
}
@end

View file

@ -25,19 +25,45 @@
*/
#include <Foundation/Foundation.h>
#include <AppKit/NSAttributedString.h>
#include <AppKit/NSTextStorage.h>
@implementation NSTextStorage
@class GSTextStorage;
static Class abstract;
static Class concrete;
+ (void) initialize
{
if (self == [NSTextStorage class])
{
abstract = self;
concrete = [GSTextStorage class];
}
}
+ (id) allocWithZone: (NSZone*)zone
{
if (self == abstract)
return NSAllocateObject(concrete, 0, zone);
else
return NSAllocateObject(self, 0, zone);
}
- (void) dealloc
{
[layoutManagers release];
RELEASE(layoutManagers);
[super dealloc];
}
- (id) init
/*
* The designated intialiser
*/
- (id) initWithString: (NSString*)aString
attributes: (NSDictionary*)attributes
{
self = [super init];
layoutManagers = [[NSMutableArray alloc] initWithCapacity: 2];
return self;
}

View file

@ -7,8 +7,6 @@
Author: Scott Christley <scottc@net-community.com>
Date: August 1997
Author: Felipe A. Rodriguez <far@ix.netcom.com>
Date: Aug 1998
This file is part of the GNUstep GUI Library.
@ -316,19 +314,31 @@ NSString *NSWorkspaceWillPowerOffNotification =
NSString *NSWorkspaceWillUnmountNotification =
@"NSWorkspaceWillUnmountNotification";
//
// NSStringDrawing NSString additions
//
NSString *NSFontAttributeName = @"NSFontAttributeName";
NSString *NSParagraphStyleAttributeName = @"NSParagraphStyleAttributeName";
NSString *NSForegroundColorAttributeName = @"NSForegroundColorAttributeName";
NSString *NSUnderlineStyleAttributeName = @"NSUnderlineStyleAttributeName";
NSString *NSSuperscriptAttributeName = @"NSSuperscriptAttributeName";
NSString *NSBackgroundColorAttributeName = @"NSBackgroundColorAttributeName";
NSString *NSAttachmentAttributeName = @"NSAttachmentAttributeName";
NSString *NSLigatureAttributeName = @"NSLigatureAttributeName";
NSString *NSBaselineOffsetAttributeName = @"NSBaselineOffsetAttributeName";
NSString *NSKernAttributeName = @"NSKernAttributeName";
/*
* NSStringDrawing NSString additions
*/
NSString *NSFontAttributeName
= @"NSFontAttributeName";
NSString *NSParagraphStyleAttributeName
= @"NSParagraphStyleAttributeName";
NSString *NSForegroundColorAttributeName
= @"NSForegroundColorAttributeName";
NSString *NSUnderlineStyleAttributeName
= @"NSUnderlineStyleAttributeName";
NSString *NSSuperscriptAttributeName
= @"NSSuperscriptAttributeName";
NSString *NSBackgroundColorAttributeName
= @"NSBackgroundColorAttributeName";
NSString *NSAttachmentAttributeName
= @"NSAttachmentAttributeName";
NSString *NSLigatureAttributeName
= @"NSLigatureAttributeName";
NSString *NSBaselineOffsetAttributeName
= @"NSBaselineOffsetAttributeName";
NSString *NSKernAttributeName
= @"NSKernAttributeName";
NSString *NSLinkAttributeName
= @"NSLinkAttributeName";
/* NSFont matrix */
const float NSFontIdentityMatrix[] = {1, 0, 0, 1, 0, 0};