Revision: 4848
http://skim-app.svn.sourceforge.net/skim-app/?rev=4848&view=rev
Author: hofman
Date: 2008-10-22 14:13:25 +0000 (Wed, 22 Oct 2008)
Log Message:
-----------
Allow scriptable selection components for multiple pages.
Modified Paths:
--------------
trunk/PDFSelection_SKExtensions.m
Modified: trunk/PDFSelection_SKExtensions.m
===================================================================
--- trunk/PDFSelection_SKExtensions.m 2008-10-22 12:42:40 UTC (rev 4847)
+++ trunk/PDFSelection_SKExtensions.m 2008-10-22 14:13:25 UTC (rev 4848)
@@ -151,128 +151,158 @@
return range;
}
-static NSArray *characterRangesForSpecifier(NSScriptObjectSpecifier
*specifier, NSScriptObjectSpecifier **containerSpecifier, NSTextStorage
**containerTextStorage) {
+static NSArray
*characterRangesAndContainersForSpecifier(NSScriptObjectSpecifier *specifier) {
if ([specifier isKindOfClass:[NSScriptObjectSpecifier class]] == NO)
return nil;
+ NSMutableArray *rangeDicts = [NSMutableArray array];
+
// we should get ranges of characters, words, or parapgraphs of the
richText of a page
NSString *key = [specifier key];
- NSSet *textKeys = [NSSet setWithObjects:@"characters", @"words",
@"paragraphs", @"attributeRuns", nil];
- if ([textKeys containsObject:key] == NO)
- return nil;
- // get the richText specifier and textStorage
- NSScriptObjectSpecifier *containerSpec = [specifier containerSpecifier];
- NSArray *textRanges = nil;
- NSTextStorage *containerText = nil;
- if ([textKeys containsObject:[containerSpec key]]) {
- textRanges = characterRangesForSpecifier(containerSpec,
containerSpecifier, &containerText);
- if ([textRanges count] == 0)
+ if ([[NSSet setWithObjects:@"characters", @"words", @"paragraphs",
@"attributeRuns", nil] containsObject:key]) {
+
+ // get the richText specifier and textStorage
+ NSArray *dicts = characterRangesAndContainersForSpecifier([specifier
containerSpecifier]);
+ if ([dicts count] == 0)
return nil;
- } else {
- containerText = [containerSpec objectsByEvaluatingSpecifier];
- if ([containerText isKindOfClass:[NSArray class]])
- containerText = [(NSArray *)containerText count] == 1 ? [(NSArray
*)containerText objectAtIndex:0] : nil;
- if ([containerText isKindOfClass:[NSTextStorage class]] == NO)
- return nil;
- textRanges = [NSArray arrayWithObject:[NSValue
valueWithRange:NSMakeRange(0, [containerText length])]];
- *containerSpecifier = containerSpec;
- }
- if (containerTextStorage)
- *containerTextStorage = containerText;
-
- NSEnumerator *rangeEnum = [textRanges objectEnumerator];
- NSValue *value;
- NSMutableArray *rangeValues = [NSMutableArray array];
-
- while (value = [rangeEnum nextObject]) {
- NSRange textRange = [value rangeValue];
- NSTextStorage *textStorage = [[NSTextStorage alloc]
initWithAttributedString:[containerText
attributedSubstringFromRange:textRange]];
- // now get the ranges, which can be any kind of specifier
- int startIndex, endIndex, i, count, *indices;
- NSRange *ranges = NULL;
- int numRanges = 0;
+ NSEnumerator *dictEnum = [dicts objectEnumerator];
+ NSDictionary *dict;
- if ([specifier isKindOfClass:[NSPropertySpecifier class]]) {
- // this should be the full range of characters, words, or
paragraphs
- numRanges = 1;
- ranges = NSZoneRealloc(NSDefaultMallocZone(), ranges,
sizeof(NSRange));
- ranges[0] = NSMakeRange(0, [[textStorage valueForKey:key] count]);
- } else if ([specifier isKindOfClass:[NSRangeSpecifier class]]) {
- // somehow getting the indices as for the general case sometimes
leads to an exception for NSRangeSpecifier, so we get the indices of the
start/endSpecifiers
- NSScriptObjectSpecifier *startSpec = [(NSRangeSpecifier
*)specifier startSpecifier];
- NSScriptObjectSpecifier *endSpec = [(NSRangeSpecifier *)specifier
endSpecifier];
+ while (dict = [dictEnum nextObject]) {
+ NSTextStorage *containerText = [dict objectForKey:@"text"];
+ PDFPage *page = [dict objectForKey:@"page"];
+ NSEnumerator *rangeEnum = [[dict objectForKey:@"ranges"]
objectEnumerator];
+ NSValue *value;
+ NSMutableArray *rangeValues = [[NSMutableArray alloc] init];
- if (startSpec || endSpec) {
- if (startSpec) {
- indices = [startSpec
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
- startIndex = count ? indices[0] : -1;
- } else {
- startIndex = 0;
- }
- if (endSpec) {
- indices = [endSpec
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
- endIndex = count ? indices[count - 1] : -1;
- } else {
- endIndex = [[textStorage valueForKey:key] count];
- }
- if (startIndex >= 0 && endIndex >= 0) {
+ while (value = [rangeEnum nextObject]) {
+ NSRange textRange = [value rangeValue];
+ NSTextStorage *textStorage = [[NSTextStorage alloc]
initWithAttributedString:[containerText
attributedSubstringFromRange:textRange]];
+
+ // now get the ranges, which can be any kind of specifier
+ int startIndex, endIndex, i, count, *indices;
+ NSRange *ranges = NULL;
+ int numRanges = 0;
+
+ if ([specifier isKindOfClass:[NSPropertySpecifier class]]) {
+ // this should be the full range of characters, words, or
paragraphs
numRanges = 1;
ranges = NSZoneRealloc(NSDefaultMallocZone(), ranges,
sizeof(NSRange));
- ranges[0] = NSMakeRange(MIN(startIndex, endIndex),
MAX(startIndex, endIndex) + 1 - MIN(startIndex, endIndex));
+ ranges[0] = NSMakeRange(0, [[textStorage valueForKey:key]
count]);
+ } else if ([specifier isKindOfClass:[NSRangeSpecifier class]])
{
+ // somehow getting the indices as for the general case
sometimes leads to an exception for NSRangeSpecifier, so we get the indices of
the start/endSpecifiers
+ NSScriptObjectSpecifier *startSpec = [(NSRangeSpecifier
*)specifier startSpecifier];
+ NSScriptObjectSpecifier *endSpec = [(NSRangeSpecifier
*)specifier endSpecifier];
+
+ if (startSpec || endSpec) {
+ if (startSpec) {
+ indices = [startSpec
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
+ startIndex = count ? indices[0] : -1;
+ } else {
+ startIndex = 0;
+ }
+ if (endSpec) {
+ indices = [endSpec
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
+ endIndex = count ? indices[count - 1] : -1;
+ } else {
+ endIndex = [[textStorage valueForKey:key] count];
+ }
+ if (startIndex >= 0 && endIndex >= 0) {
+ numRanges = 1;
+ ranges = NSZoneRealloc(NSDefaultMallocZone(),
ranges, sizeof(NSRange));
+ ranges[0] = NSMakeRange(MIN(startIndex, endIndex),
MAX(startIndex, endIndex) + 1 - MIN(startIndex, endIndex));
+ }
+ }
+ } else {
+ // this handles other objectSpecifiers (index, middel,
random, relative, whose). It can contain several ranges, e.g. for aan
NSWhoseSpecifier
+ indices = [specifier
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
+ for (i = 0; i < count; i++) {
+ unsigned int idx = indices[i];
+ if (numRanges == 0 || idx >
NSMaxRange(ranges[numRanges - 1])) {
+ numRanges++;
+ ranges = NSZoneRealloc(NSDefaultMallocZone(),
ranges, numRanges * sizeof(NSRange));
+ ranges[numRanges - 1] = NSMakeRange(idx, 1);
+ } else {
+ ++(ranges[numRanges - 1].length);
+ }
+ }
}
- }
- } else {
- // this handles other objectSpecifiers (index, middel, random,
relative, whose). It can contain several ranges, e.g. for aan NSWhoseSpecifier
- indices = [specifier
indicesOfObjectsByEvaluatingWithContainer:textStorage count:&count];
- for (i = 0; i < count; i++) {
- unsigned int idx = indices[i];
- if (numRanges == 0 || idx > NSMaxRange(ranges[numRanges - 1]))
{
- numRanges++;
- ranges = NSZoneRealloc(NSDefaultMallocZone(), ranges,
numRanges * sizeof(NSRange));
- ranges[numRanges - 1] = NSMakeRange(idx, 1);
+
+ if (numRanges == 0) {
+ } else if ([key isEqualToString:@"characters"]) {
+ for (i = 0; i < numRanges; i++) {
+ NSRange range = ranges[i];
+ range.location += textRange.location;
+ range = NSIntersectionRange(range, textRange);
+ if (range.length)
+ [rangeValues addObject:[NSValue
valueWithRange:range]];
+ }
} else {
- ++(ranges[numRanges - 1].length);
+ // translate from subtext ranges to character ranges
+ NSString *string = [textStorage string];
+ NSArray *substrings = [[textStorage valueForKey:key]
valueForKey:@"string"];
+ for (i = 0; i < numRanges; i++) {
+ startIndex = MIN(ranges[i].location, [substrings
count]);
+ endIndex = MIN(NSMaxRange(ranges[i]) - 1, [substrings
count]);
+ if (endIndex == startIndex) endIndex = -1;
+ NSRange range =
rangeOfSubstringOfStringAtIndex(string, substrings, startIndex);
+ if (range.location == NSNotFound)
+ continue;
+ startIndex = range.location;
+ if (endIndex >= 0) {
+ range = rangeOfSubstringOfStringAtIndex(string,
substrings, endIndex);
+ if (range.location == NSNotFound)
+ continue;
+ }
+ endIndex = NSMaxRange(range) - 1;
+ [rangeValues addObject:[NSValue
valueWithRange:NSMakeRange(textRange.location + startIndex, endIndex + 1 -
startIndex)]];
+ }
}
+
+ if (ranges) NSZoneFree(NSDefaultMallocZone(), ranges);
+ [textStorage release];
}
+
+ if ([rangeValues count]) {
+ dict = [[NSDictionary alloc]
initWithObjectsAndKeys:rangeValues, @"ranges", containerText, @"text", page,
@"page", nil];
+ [rangeDicts addObject:dict];
+ [dict release];
+ }
+ [rangeValues release];
}
- if (numRanges == 0) {
- } else if ([key isEqualToString:@"characters"]) {
- for (i = 0; i < numRanges; i++) {
- NSRange range = ranges[i];
- range.location += textRange.location;
- range = NSIntersectionRange(range, textRange);
- if (range.length)
- [rangeValues addObject:[NSValue valueWithRange:range]];
- }
- } else {
- // translate from subtext ranges to character ranges
- NSString *string = [textStorage string];
- NSArray *substrings = [[textStorage valueForKey:key]
valueForKey:@"string"];
- for (i = 0; i < numRanges; i++) {
- startIndex = MIN(ranges[i].location, [substrings count]);
- endIndex = MIN(NSMaxRange(ranges[i]) - 1, [substrings count]);
- if (endIndex == startIndex) endIndex = -1;
- NSRange range = rangeOfSubstringOfStringAtIndex(string,
substrings, startIndex);
- if (range.location == NSNotFound)
- continue;
- startIndex = range.location;
- if (endIndex >= 0) {
- range = rangeOfSubstringOfStringAtIndex(string,
substrings, endIndex);
- if (range.location == NSNotFound)
- continue;
- }
- endIndex = NSMaxRange(range) - 1;
- [rangeValues addObject:[NSValue
valueWithRange:NSMakeRange(textRange.location + startIndex, endIndex + 1 -
startIndex)]];
- }
+ } else {
+
+ NSArray *pages = nil;
+ if ([key isEqualToString:@"richText"]) {
+ specifier = [specifier containerSpecifier];
+ key = [specifier key];
}
+ if ([key isEqualToString:@"pages"]) {
+ pages = [specifier objectsByEvaluatingSpecifier];
+ if (pages && [pages isKindOfClass:[NSArray class]] == NO)
+ pages = [NSArray arrayWithObject:pages];
+ }
+ if ([pages count] == 0)
+ return nil;
- if (ranges) NSZoneFree(NSDefaultMallocZone(), ranges);
- [textStorage release];
+ NSEnumerator *pageEnum = [pages objectEnumerator];
+ PDFPage *page;
+
+ while (page = [pageEnum nextObject]) {
+ NSTextStorage *containerText = [page richText];
+ NSArray *rangeValues = [[NSArray alloc] initWithObjects:[NSValue
valueWithRange:NSMakeRange(0, [containerText length])], nil];
+ NSDictionary *dict = [[NSDictionary alloc]
initWithObjectsAndKeys:rangeValues, @"ranges", containerText, @"text", page,
@"page", nil];
+ [rangeDicts addObject:dict];
+ [dict release];
+ [rangeValues release];
+ }
+
}
- return rangeValues;
+
+ return rangeDicts;
}
+ (id)selectionWithSpecifier:(id)specifier {
@@ -280,9 +310,7 @@
}
+ (id)selectionWithSpecifier:(id)specifier onPage:(PDFPage *)aPage {
- NSSet *textKeys = [NSSet setWithObjects:@"characters", @"words",
@"paragraphs", @"attributeRuns", nil];
-
- if ([specifier isEqual:[NSNull null]])
+ if (specifier == nil || [specifier isEqual:[NSNull null]])
return nil;
if ([specifier isKindOfClass:[NSArray class]] == NO)
specifier = [NSArray arrayWithObject:specifier];
@@ -290,7 +318,7 @@
NSScriptObjectSpecifier *spec = [specifier objectAtIndex:0];
if ([spec isKindOfClass:[NSPropertySpecifier class]]) {
NSString *key = [spec key];
- if ([textKeys containsObject:key] == NO && [key
isEqualToString:@"richText"] == NO) {
+ if ([[NSSet setWithObjects:@"characters", @"words", @"paragraphs",
@"attributeRuns", @"richText", @"pages", nil] containsObject:key] == NO) {
// this allows to use selection properties directly
specifier = [spec objectsByEvaluatingSpecifier];
if ([specifier isKindOfClass:[NSArray class]] == NO)
@@ -307,41 +335,29 @@
if ([spec isKindOfClass:[NSScriptObjectSpecifier class]] == NO)
continue;
- NSArray *ranges = nil;
- NSScriptObjectSpecifier *textSpec = nil;
- NSString *key = [spec key];
+ NSArray *dicts = characterRangesAndContainersForSpecifier(spec);
+ NSEnumerator *dictEnum = [dicts objectEnumerator];
+ NSDictionary *dict;
+ PDFDocument *doc = nil;
- if ([key isEqualToString:@"richText"]) {
- NSTextStorage *textStorage = [spec objectsByEvaluatingSpecifier];
- if ([textStorage isKindOfClass:[NSArray class]])
- textStorage = [(NSArray *)textStorage count] ? [(NSArray
*)textStorage objectAtIndex:0] : nil;
- if ([textStorage isKindOfClass:[NSTextStorage class]])
+ while (dict = [dictEnum nextObject]) {
+ PDFPage *page = [dict objectForKey:@"page"];
+ if ((aPage && [aPage isEqual:page] == NO) || (doc && [doc
isEqual:[page document]] == NO))
continue;
- ranges = [NSArray arrayWithObjects:[NSValue
valueWithRange:NSMakeRange(0, [textStorage length])], nil];
- textSpec = spec;
- } else if ([textKeys containsObject:key]) {
- ranges = characterRangesForSpecifier(spec, &textSpec, NULL);
- if ([textSpec isKindOfClass:[NSScriptObjectSpecifier class]] == NO
|| [[textSpec key] isEqualToString:@"richText"] == NO)
- continue;
- } else
- continue;
-
- NSScriptObjectSpecifier *pageSpec = [textSpec containerSpecifier];
- PDFPage *page = [pageSpec objectsByEvaluatingSpecifier];
- if ([page isKindOfClass:[NSArray class]])
- page = [(NSArray *)page count] == 1 ? [(NSArray *)page
objectAtIndex:0] : nil;
- if ([page isKindOfClass:[PDFPage class]] == NO || (aPage && [aPage
isEqual:page] == NO))
- continue;
-
- unsigned int i, numRanges = [ranges count];
- for (i = 0; i < numRanges; i++) {
- PDFSelection *sel;
- NSRange range = [[ranges objectAtIndex:i] rangeValue];
- if (range.length && (sel = [page selectionForRange:range])) {
- if (selection == nil)
- selection = sel;
- else
- [selection addSelection:sel];
+
+ NSArray *ranges = [dict objectForKey:@"ranges"];
+ unsigned int i, numRanges = [ranges count];
+
+ for (i = 0; i < numRanges; i++) {
+ PDFSelection *sel;
+ NSRange range = [[ranges objectAtIndex:i] rangeValue];
+ if (range.length && (sel = [page selectionForRange:range])) {
+ doc = [page document];
+ if (selection == nil)
+ selection = sel;
+ else
+ [selection addSelection:sel];
+ }
}
}
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit