This commit is contained in:
Frederick John Milens III 2025-05-03 03:48:14 +00:00 committed by GitHub
commit f16ae209d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 332 additions and 29 deletions

View file

@ -53,6 +53,7 @@
#import "AppKit/NSFont.h"
#import "AppKit/NSFontDescriptor.h"
#import "AppKit/NSFontManager.h"
#import "AppKit/NSTextList.h"
// For the colour name spaces
#import "AppKit/NSGraphics.h"
#import "AppKit/NSTextTable.h"
@ -1095,20 +1096,43 @@ documentAttributes: (NSDictionary **)dict
- (NSInteger) itemNumberInTextList: (NSTextList *)list
atIndex: (NSUInteger)location
{
NSParagraphStyle *style = [self attribute: NSParagraphStyleAttributeName
atIndex: location
effectiveRange: NULL];
if (style != nil)
NSRange listRange = [self rangeOfTextList: list atIndex: location];
if (listRange.location == NSNotFound)
{
NSArray *textLists = [style textLists];
if (textLists != nil)
{
return [textLists indexOfObject: list];
}
return 0;
}
return NSNotFound;
NSRange subRange = NSMakeRange(listRange.location, location-listRange.location+1);
unichar buffer[subRange.length];
[[self string] getCharacters: buffer range: subRange];
NSCharacterSet *newlineCharacterSet = [NSCharacterSet newlineCharacterSet];
NSUInteger itemNumber = 1;
NSUInteger index;
for (index=1; index<subRange.length; index++)
{
if ([newlineCharacterSet characterIsMember: buffer[index-1]])
{
NSParagraphStyle *style = [self attribute: NSParagraphStyleAttributeName
atIndex: subRange.location + index
effectiveRange: NULL];
NSArray *textLists = [style textLists];
if ([list isEqual: [textLists lastObject]])
{
itemNumber++;
}
if (buffer[index-1] == '\r' && buffer[index] == '\n')
{
index++;
}
}
}
return itemNumber;
}
- (NSRange) rangeOfTextBlock: (NSTextBlock *)block
@ -1183,7 +1207,7 @@ documentAttributes: (NSDictionary **)dict
NSRange newEffRange;
NSUInteger len = [self length];
while ((effRange.location > 0) && style && textLists)
while (effRange.location > 0)
{
style = [self attribute: NSParagraphStyleAttributeName
atIndex: effRange.location - 1
@ -1196,11 +1220,13 @@ documentAttributes: (NSDictionary **)dict
{
effRange.location = newEffRange.location;
effRange.length += newEffRange.length;
continue;
}
}
break;
}
while (NSMaxRange(effRange) < len && style && textLists)
while (NSMaxRange(effRange) < len)
{
style = [self attribute: NSParagraphStyleAttributeName
atIndex: NSMaxRange(effRange)
@ -1212,8 +1238,10 @@ documentAttributes: (NSDictionary **)dict
if ((textLists != nil) && [textLists containsObject: list])
{
effRange.length += newEffRange.length;
continue;
}
}
break;
}
return effRange;

View file

@ -303,6 +303,8 @@ static NSParagraphStyle *defaultStyle = nil;
[_tabStops addObject: tab];
RELEASE(tab);
}
ASSIGN(_textLists, [NSArray array]);
}
return self;
}
@ -494,6 +496,9 @@ static NSParagraphStyle *defaultStyle = nil;
[aCoder decodeValueOfObjCType: @encode(float) at: &_paragraphSpacing];
[aCoder decodeValueOfObjCType: @encode(float) at: &_tailIndent];
// Text lists were not included for non-keyed encoding, use a default
ASSIGN(_textLists, [NSArray array]);
/*
* Tab stops don't conform to NSCoding - so we do it the long way.
*/
@ -621,7 +626,12 @@ static NSParagraphStyle *defaultStyle = nil;
C(_headerLevel);
#undef C
return [_tabStops isEqualToArray: other->_tabStops];
#define C(x) if (![x isEqualToArray: other->x]) return NO;
C(_tabStops);
C(_textLists);
#undef C
return YES;
}
- (NSUInteger) hash

View file

@ -51,21 +51,6 @@
[super dealloc];
}
- (BOOL) isEqual: (id)anObject
{
if (anObject == self)
{
return YES;
}
if (anObject == nil || [anObject isKindOfClass: [NSTextList class]] == NO)
{
return NO;
}
return ([anObject listOptions] == _listOptions)
&& [_markerFormat isEqualToString: [anObject markerFormat]];
}
- (unsigned int) listOptions
{
return _listOptions;

View file

@ -0,0 +1,79 @@
#include "Testing.h"
#include <Foundation/NSAutoreleasePool.h>
#include <AppKit/NSAttributedString.h>
#include <AppKit/NSParagraphStyle.h>
#include <AppKit/NSTextList.h>
int main(int argc, char **argv)
{
CREATE_AUTORELEASE_POOL(arp);
START_SET("NSAttributedString itemNumberInTextList:atIndex: category method");
NSTextList *list1 = [[NSTextList alloc] initWithMarkerFormat:@"{decimal}" options:0];
NSTextList *list2 = [[NSTextList alloc] initWithMarkerFormat:@"{box}" options:0];
NSMutableParagraphStyle *style1 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style2 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style1 setTextLists: [NSArray arrayWithObject: list1]];
[style2 setTextLists: [NSArray arrayWithObjects: list1, list2, nil]];
NSDictionary *attrs1 = [NSDictionary dictionaryWithObject: style1
forKey: NSParagraphStyleAttributeName];
NSDictionary *attrs2 = [NSDictionary dictionaryWithObject: style2
forKey: NSParagraphStyleAttributeName];
NSDictionary *attrs3 = [NSDictionary dictionaryWithObject: [NSParagraphStyle defaultParagraphStyle]
forKey: NSParagraphStyleAttributeName];
NSMutableAttributedString *storage = [[NSMutableAttributedString alloc] init];
NSUInteger index1 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"item 1\r\n" attributes: attrs1]];
NSUInteger index2 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"item 2\n" attributes: attrs1]];
NSUInteger index3 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"item 3\n" attributes: attrs1]];
NSUInteger index4 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"subitem 1\n" attributes: attrs2]];
NSUInteger index5 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"subitem 2\n" attributes: attrs2]];
NSUInteger index6 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"item 4\n" attributes: attrs1]];
NSUInteger index7 = [storage length];
[storage appendAttributedString:
[[NSMutableAttributedString alloc] initWithString: @"extra text\n" attributes: attrs3]];
pass([storage itemNumberInTextList: list1 atIndex: index1] == 1, "Index for first list item");
pass([storage itemNumberInTextList: list1 atIndex: index2] == 2, "Index with CR+LF sequence");
pass([storage itemNumberInTextList: list1 atIndex: index3 - 1] == 2, "Index on boundary");
pass([storage itemNumberInTextList: list1 atIndex: index3] == 3, "Index for third list item");
pass([storage itemNumberInTextList: list1 atIndex: index4] == 3, "Index for third list item (sublist 1)");
pass([storage itemNumberInTextList: list1 atIndex: index5] == 3, "Index for third list item (sublist 2");
pass([storage itemNumberInTextList: list1 atIndex: index6] == 4, "Index for fourth list item");
pass([storage itemNumberInTextList: list2 atIndex: index4] == 1, "Index for first sublist item");
pass([storage itemNumberInTextList: list2 atIndex: index5] == 2, "Index for second sublist item");
pass([storage itemNumberInTextList: list2 atIndex: index1] == 0, "Index in other list is zero");
pass([storage itemNumberInTextList: list1 atIndex: index7] == 0, "Index in nonlist is zero");
END_SET("NSAttributedString itemNumberInTextList:atIndex: category method");
DESTROY(arp);
return 0;
}

View file

@ -0,0 +1,73 @@
#include "Testing.h"
#include <Foundation/NSAutoreleasePool.h>
#include <AppKit/NSAttributedString.h>
#include <AppKit/NSParagraphStyle.h>
#include <AppKit/NSTextList.h>
int main(int argc, char **argv)
{
CREATE_AUTORELEASE_POOL(arp);
START_SET("NSAttributedString attribute merging");
NSMutableParagraphStyle *style1 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style2 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style3 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style4 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSTextList *list1 = [[NSTextList alloc] initWithMarkerFormat: @"{box}" options: 0];
NSTextList *list2 = [[NSTextList alloc] initWithMarkerFormat: @"{box}" options: 0];
[style3 setTextLists: [NSArray arrayWithObject: list1]];
[style4 setTextLists: [NSArray arrayWithObject: list2]];
NSAttributedString *str1 = [[NSAttributedString alloc]
initWithString: @"string 1"
attributes: [NSDictionary dictionaryWithObject: style1 forKey: NSParagraphStyleAttributeName]];
NSAttributedString *str2 = [[NSAttributedString alloc]
initWithString: @"string 2"
attributes: [NSDictionary dictionaryWithObject: style2 forKey: NSParagraphStyleAttributeName]];
NSAttributedString *str3 = [[NSAttributedString alloc]
initWithString: @"string 3"
attributes: [NSDictionary dictionaryWithObject: style3 forKey: NSParagraphStyleAttributeName]];
NSAttributedString *str4 = [[NSAttributedString alloc]
initWithString: @"string 4"
attributes: [NSDictionary dictionaryWithObject: style4 forKey: NSParagraphStyleAttributeName]];
NSMutableAttributedString *storage = [[NSMutableAttributedString alloc] init];
NSUInteger pos1 = [storage length];
[storage appendAttributedString: str1];
NSUInteger pos2 = [storage length];
[storage appendAttributedString: str2];
NSUInteger pos3 = [storage length];
[storage appendAttributedString: str3];
NSUInteger pos4 = [storage length];
[storage appendAttributedString: str4];
NSParagraphStyle *result1 = [storage attribute: NSParagraphStyleAttributeName
atIndex: pos1
effectiveRange: NULL];
NSParagraphStyle *result2 = [storage attribute: NSParagraphStyleAttributeName
atIndex: pos2
effectiveRange: NULL];
NSParagraphStyle *result3 = [storage attribute: NSParagraphStyleAttributeName
atIndex: pos3
effectiveRange: NULL];
NSParagraphStyle *result4 = [storage attribute: NSParagraphStyleAttributeName
atIndex: pos4
effectiveRange: NULL];
pass(result1 == result2, "Did merge equal paragraph styles");
pass(result3 != result4, "Did not merge equal paragraph styles with text lists");
END_SET("NSAttributedString attribute merging");
DESTROY(arp);
return 0;
}

View file

@ -0,0 +1,88 @@
#include "Testing.h"
#include <Foundation/NSAutoreleasePool.h>
#include <AppKit/NSAttributedString.h>
#include <AppKit/NSParagraphStyle.h>
#include <AppKit/NSTextList.h>
int main(int argc, char **argv)
{
CREATE_AUTORELEASE_POOL(arp);
START_SET("NSAttributedString rangeOfTextList:atIndex: category method");
NSTextList *list1 = [[NSTextList alloc] initWithMarkerFormat: @"{box}" options: 0];
NSTextList *list2 = [[NSTextList alloc] initWithMarkerFormat: @"{box}" options: 0];
NSTextList *list3 = [[NSTextList alloc] initWithMarkerFormat: @"{box}" options: 0];
NSMutableParagraphStyle *style1 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style2 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style3 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSMutableParagraphStyle *style4 = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style2 setTextLists: [NSArray arrayWithObject: list1]];
[style3 setTextLists: [NSArray arrayWithObjects: list1, list2, nil]];
[style4 setTextLists: [NSArray arrayWithObject: list3]];
NSMutableAttributedString *storage = [[NSMutableAttributedString alloc] init];
NSUInteger pos1 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"before\n"
attributes: [NSDictionary dictionaryWithObject: style1 forKey: NSParagraphStyleAttributeName]]];
NSUInteger pos2 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"list 1\n"
attributes: [NSDictionary dictionaryWithObject: style2 forKey: NSParagraphStyleAttributeName]]];
NSUInteger pos3 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"sublist 1\n"
attributes: [NSDictionary dictionaryWithObject: style3 forKey: NSParagraphStyleAttributeName]]];
NSUInteger pos4 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"list 1\n"
attributes: [NSDictionary dictionaryWithObject: style2 forKey: NSParagraphStyleAttributeName]]];
NSUInteger pos5 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"list 2\n"
attributes: [NSDictionary dictionaryWithObject: style4 forKey: NSParagraphStyleAttributeName]]];
NSUInteger pos6 = [storage length];
[storage appendAttributedString: [[NSAttributedString alloc]
initWithString: @"ending\n"
attributes: [NSDictionary dictionaryWithObject: style1 forKey: NSParagraphStyleAttributeName]]];
NSRange expected, actual;
expected = NSMakeRange(pos3, pos4 - pos3);
actual = [storage rangeOfTextList: list2 atIndex: pos3 + 1];
pass(NSEqualRanges(expected, actual), "Found correct range of nested list");
expected = NSMakeRange(pos2, pos5 - pos2);
actual = [storage rangeOfTextList: list1 atIndex: pos3 + 1];
pass(NSEqualRanges(expected, actual), "Found correct range of enclosing list");
expected = NSMakeRange(pos2, pos5 - pos2);
actual = [storage rangeOfTextList: list1 atIndex: pos2 + 1];
pass(NSEqualRanges(expected, actual), "Found correct range including nested list");
expected = NSMakeRange(pos5, pos6 - pos5);
actual = [storage rangeOfTextList: list3 atIndex: pos5 + 1];
pass(NSEqualRanges(expected, actual), "Found correct range of an adjacent list");
actual = [storage rangeOfTextList: list1 atIndex: pos5];
pass(actual.location == NSNotFound, "Returned not found for location in different list");
actual = [storage rangeOfTextList: list1 atIndex: pos1];
pass(actual.location == NSNotFound, "Returned not found for location not in any list");
END_SET("NSAttributedString rangeOfTextList:atIndex: category method");
DESTROY(arp);
return 0;
}

View file

View file

@ -0,0 +1,40 @@
#include "Testing.h"
#include <Foundation/NSAutoreleasePool.h>
#include <AppKit/NSParagraphStyle.h>
#include <AppKit/NSTextList.h>
int main(int argc, char **argv)
{
CREATE_AUTORELEASE_POOL(arp);
START_SET("NSParagraphStyle equality tests");
NSMutableParagraphStyle *default1 = [NSParagraphStyle defaultParagraphStyle];
NSMutableParagraphStyle *default2 = [NSParagraphStyle defaultParagraphStyle];
PASS_EQUAL(default1, default2, "NSParagraphStyle isEqual: works for default paragraph styles");
NSMutableParagraphStyle *style1 = [[NSMutableParagraphStyle alloc] init];
NSMutableParagraphStyle *style2 = [[NSMutableParagraphStyle alloc] init];
PASS_EQUAL(style1, style2, "NSParagraphStyle isEqual: works for default mutable copies");
NSTextList *textList = [[NSTextList alloc] init];
[style1 setTextLists: [NSArray arrayWithObject: textList]];
[style2 setTextLists: [NSArray arrayWithObject: textList]];
PASS_EQUAL(style1, style2, "NSParagraphStyle isEqual: works for identical textlists");
[style1 setTextLists: [NSArray arrayWithObject: [[NSTextList alloc] init]]];
[style2 setTextLists: [NSArray arrayWithObject: [[NSTextList alloc] init]]];
pass(![style1 isEqual: style2], "NSParagraphStyle isEqual: works for different textlists");
END_SET("NSParagraphStyle equality tests");
DESTROY(arp);
return 0;
}