Revision: 4181
http://skim-app.svn.sourceforge.net/skim-app/?rev=4181&view=rev
Author: hofman
Date: 2008-07-10 17:26:38 -0700 (Thu, 10 Jul 2008)
Log Message:
-----------
Rewrite pdfsync code separating out pdfsync specific code. Add separate
parallel methods for synctex support. Currently the actual synctex code is
excluded.
Modified Paths:
--------------
trunk/SKPDFSynchronizer.h
trunk/SKPDFSynchronizer.m
Modified: trunk/SKPDFSynchronizer.h
===================================================================
--- trunk/SKPDFSynchronizer.h 2008-07-10 18:44:31 UTC (rev 4180)
+++ trunk/SKPDFSynchronizer.h 2008-07-11 00:26:38 UTC (rev 4181)
@@ -38,13 +38,20 @@
#import <Cocoa/Cocoa.h>
#import <libkern/OSAtomic.h>
+#ifdef SYNCTEX_FEATURE
+#import "synctex_parser.h"
+#endif
-
@interface SKPDFSynchronizer : NSObject {
NSString *fileName;
+ NSString *syncFileName;
NSDate *lastModDate;
NSMutableArray *pages;
NSMutableDictionary *lines;
+ BOOL isPdfsync;
+#ifdef SYNCTEX_FEATURE
+ synctex_scanner_t scanner;
+#endif
id delegate;
Modified: trunk/SKPDFSynchronizer.m
===================================================================
--- trunk/SKPDFSynchronizer.m 2008-07-10 18:44:31 UTC (rev 4180)
+++ trunk/SKPDFSynchronizer.m 2008-07-11 00:26:38 UTC (rev 4181)
@@ -42,6 +42,8 @@
#import <Carbon/Carbon.h>
#import "Files_SKExtensions.h"
+#define SYNC_TO_PDF(coord) ((float)coord / 65536.0)
+#define PDF_TO_SYNC(coord) (int)(coord * 65536.0)
static NSString *SKPDFSynchronizerRecordIndexKey = @"recordIndex";
static NSString *SKPDFSynchronizerPageKey = @"page";
@@ -50,6 +52,7 @@
static NSString *SKPDFSynchronizerFileKey = @"file";
static NSString *SKPDFSynchronizerLineKey = @"line";
static NSString *SKPDFSynchronizerTexExtension = @"tex";
+static NSString *SKPDFSynchronizerPdfsyncExtension = @"pdfsync";
static NSString *SKTeXSourceFile(NSString *file, NSString *base) {
if ([[file pathExtension]
caseInsensitiveCompare:SKPDFSynchronizerTexExtension] != NSOrderedSame)
@@ -88,16 +91,9 @@
#pragma mark -
@interface SKPDFSynchronizer (Private)
-
-- (NSDate *)lastModDate;
-- (void)setLastModDate:(NSDate *)date;
-
- (void)runDOServerForPorts:(NSArray *)ports;
-
// these following methods only be called on the server thread
-- (BOOL)parsePdfsyncFile;
-- (BOOL)parsePdfsyncFileIfNeeded;
-
+- (BOOL)parseSyncFileIfNeeded;
@end
#pragma mark -
@@ -113,6 +109,7 @@
lines = [[NSMutableDictionary alloc] init];
fileName = nil;
lastModDate = nil;
+ isPdfsync = YES;
NSPort *port1 = [NSPort port];
NSPort *port2 = [NSPort port];
@@ -146,6 +143,7 @@
[pages release];
[lines release];
[fileName release];
+ [syncFileName release];
[lastModDate release];
[super dealloc];
}
@@ -171,7 +169,9 @@
- (void)setFileName:(NSString *)newFileName {
@synchronized(self) {
if (fileName != newFileName) {
- if ([fileName isEqualToString:newFileName] == NO && lastModDate) {
+ if ([fileName isEqualToString:newFileName] == NO) {
+ [syncFileName release];
+ syncFileName = nil;
[lastModDate release];
lastModDate = nil;
}
@@ -181,23 +181,33 @@
}
}
-- (NSDate *)lastModDate {
- NSDate *date = nil;
+- (NSString *)syncFileName {
+ NSString *file = nil;
@synchronized(self) {
- date = [[lastModDate retain] autorelease];
+ file = [[syncFileName retain] autorelease];
}
- return date;
+ return file;
}
-- (void)setLastModDate:(NSDate *)date {
+- (void)setSyncFileName:(NSString *)newSyncFileName {
@synchronized(self) {
- if (date != lastModDate) {
- [lastModDate release];
- lastModDate = [date retain];
+ if (syncFileName != newSyncFileName) {
+ [syncFileName release];
+ syncFileName = [newSyncFileName retain];
}
+ [lastModDate release];
+ lastModDate = [(syncFileName ?
SKFileModificationDateAtPath(syncFileName) : nil) retain];
}
}
+- (NSDate *)lastModDate {
+ NSDate *date = nil;
+ @synchronized(self) {
+ date = [[lastModDate retain] autorelease];
+ }
+ return date;
+}
+
#pragma mark API
#pragma mark | DO server
@@ -266,6 +276,11 @@
[serverOnMainThread release];
serverOnMainThread = nil;
+
+#ifdef SYNCTEX_FEATURE
+ if (scanner)
+ synctex_scanner_free(scanner);
+#endif
}
- (void)runDOServerForPorts:(NSArray *)ports {
@@ -314,32 +329,14 @@
#pragma mark | Parsing and Finding
-- (BOOL)parsePdfsyncFileIfNeeded {
- NSString *theFileName = [self fileName];
-
- if (theFileName == nil || SKFileExistsAtPath(theFileName) == NO)
- return NO;
-
- NSDate *modDate = SKFileModificationDateAtPath(theFileName);
- NSDate *currentModDate = [self lastModDate];
-
- if (currentModDate == nil || [modDate compare:currentModDate] ==
NSOrderedDescending)
- return [self parsePdfsyncFile];
-
- return YES;
-}
+- (BOOL)parsePdfsyncFile:(NSString *)theFileName {
-- (BOOL)parsePdfsyncFile {
- NSString *theFileName = [self fileName];
-
[pages removeAllObjects];
[lines removeAllObjects];
- if (SKFileExistsAtPath(theFileName) == NO)
- return NO;
+ [self setSyncFileName:theFileName];
+ isPdfsync = YES;
- [self setLastModDate:SKFileModificationDateAtPath(theFileName)];
-
NSString *basePath = [theFileName stringByDeletingLastPathComponent];
NSMutableDictionary *records = [NSMutableDictionary dictionary];
NSMutableArray *files = [NSMutableArray array];
@@ -349,18 +346,18 @@
float x, y;
NSMutableDictionary *record;
NSMutableArray *array;
- NSScanner *scanner;
+ NSScanner *sc;
unichar ch;
if ([pdfsyncString length] == 0)
return NO;
- scanner = [[NSScanner alloc] initWithString:pdfsyncString];
- [scanner setCharactersToBeSkipped:[NSCharacterSet whitespaceCharacterSet]];
+ sc = [[NSScanner alloc] initWithString:pdfsyncString];
+ [sc setCharactersToBeSkipped:[NSCharacterSet whitespaceCharacterSet]];
- if ([scanner scanUpToCharactersFromSet:[NSCharacterSet
newlineCharacterSet] intoString:&file] == NO ||
- [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL] == NO) {
- [scanner release];
+ if ([sc scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:&file] == NO ||
+ [sc scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL] == NO) {
+ [sc release];
return NO;
}
@@ -372,21 +369,21 @@
[array release];
// we ignore the version
- if ([scanner scanString:@"version" intoString:NULL] == NO ||
- [scanner scanInt:NULL] == NO) {
- [scanner release];
+ if ([sc scanString:@"version" intoString:NULL] == NO ||
+ [sc scanInt:NULL] == NO) {
+ [sc release];
return NO;
}
- [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL];
+ [sc scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL];
OSMemoryBarrier();
- while (shouldKeepRunning && [scanner scanCharacter:&ch]) {
+ while (shouldKeepRunning && [sc scanCharacter:&ch]) {
if (ch == 'l') {
- if ([scanner scanInt:&recordIndex] && [scanner scanInt:&line]) {
+ if ([sc scanInt:&recordIndex] && [sc scanInt:&line]) {
// we ignore the column
- [scanner scanInt:NULL];
+ [sc scanInt:NULL];
record = SKRecordForRecordIndex(records, recordIndex);
[record setObject:file forKey:SKPDFSynchronizerFileKey];
[record setIntValue:line forKey:SKPDFSynchronizerLineKey];
@@ -394,17 +391,17 @@
}
} else if (ch == 'p') {
// we ignore * and + modifiers
- [scanner scanString:@"*" intoString:NULL] || [scanner
scanString:@"+" intoString:NULL];
- if ([scanner scanInt:&recordIndex] && [scanner scanFloat:&x] &&
[scanner scanFloat:&y]) {
+ [sc scanString:@"*" intoString:NULL] || [sc scanString:@"+"
intoString:NULL];
+ if ([sc scanInt:&recordIndex] && [sc scanFloat:&x] && [sc
scanFloat:&y]) {
record = SKRecordForRecordIndex(records, recordIndex);
[record setIntValue:[pages count] - 1
forKey:SKPDFSynchronizerPageKey];
- [record setFloatValue:x / 65536 + pdfOffset.x
forKey:SKPDFSynchronizerXKey];
- [record setFloatValue:y / 65536 + pdfOffset.y
forKey:SKPDFSynchronizerYKey];
+ [record setFloatValue:SYNC_TO_PDF(x) + pdfOffset.x
forKey:SKPDFSynchronizerXKey];
+ [record setFloatValue:SYNC_TO_PDF(y) + pdfOffset.y
forKey:SKPDFSynchronizerYKey];
[[pages lastObject] addObject:record];
}
} else if (ch == 's') {
// start of a new page, the scanned integer should always equal
[pages count]+1
- if ([scanner scanInt:&pageIndex] == NO) pageIndex = [pages count]
+ 1;
+ if ([sc scanInt:&pageIndex] == NO) pageIndex = [pages count] + 1;
while (pageIndex > (int)[pages count]) {
array = [[NSMutableArray alloc] init];
[pages addObject:array];
@@ -412,7 +409,7 @@
}
} else if (ch == '(') {
// start of a new source file
- if ([scanner scanUpToCharactersFromSet:[NSCharacterSet
newlineCharacterSet] intoString:&file]) {
+ if ([sc scanUpToCharactersFromSet:[NSCharacterSet
newlineCharacterSet] intoString:&file]) {
file = SKTeXSourceFile(file, basePath);
[files addObject:file];
if ([lines objectForKey:file] == nil) {
@@ -429,13 +426,13 @@
}
}
- [scanner scanUpToCharactersFromSet:[NSCharacterSet
newlineCharacterSet] intoString:NULL];
- [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL];
+ [sc scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL];
+ [sc scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:NULL];
OSMemoryBarrier();
}
- [scanner release];
+ [sc release];
NSSortDescriptor *lineSortDescriptor = [[[NSSortDescriptor alloc]
initWithKey:SKPDFSynchronizerLineKey ascending:YES] autorelease];
NSSortDescriptor *xSortDescriptor = [[[NSSortDescriptor alloc]
initWithKey:SKPDFSynchronizerXKey ascending:YES] autorelease];
@@ -452,14 +449,51 @@
return returnValue;
}
-- (oneway void)serverFindLineForLocation:(NSPoint)point inRect:(NSRect)rect
atPageIndex:(unsigned int)pageIndex {
- int foundLine = -1;
- NSString *foundFile = nil;
- NSDictionary *record = nil;
+- (BOOL)parseSynctexFile:(NSString *)theFileName {
+#ifdef SYNCTEX_FEATURE
+ if (scanner)
+ synctex_scanner_free(scanner);
+ scanner = synctex_scanner_new_with_output_file([theFileName
fileSystemRepresentation]);
+ if (scanner) {
+ NSString *theSyncFileName = [NSString
stringWithUTF8String:synctex_scanner_get_synctex(scanner)];
+ [self setSyncFileName:theSyncFileName];
+ isPdfsync = NO;
+ return YES;
+ }
+#endif
+ return NO;
+}
+
+- (BOOL)parseSyncFileIfNeeded {
+ NSString *theFileName = [self fileName];
- OSMemoryBarrier();
- if (shouldKeepRunning && [self parsePdfsyncFileIfNeeded] && pageIndex <
[pages count]) {
+ if (theFileName == nil)
+ return NO;
+
+ NSString *theSyncFileName = [self syncFileName];
+
+ if (theSyncFileName && SKFileExistsAtPath(theSyncFileName)) {
+ NSDate *modDate = SKFileModificationDateAtPath(theFileName);
+ NSDate *currentModDate = [self lastModDate];
+
+ if (currentModDate == nil || [modDate compare:currentModDate] ==
NSOrderedDescending)
+ return isPdfsync ? [self parsePdfsyncFile:theSyncFileName] : [self
parseSynctexFile:theFileName];
+ else
+ return YES;
+ }
+
+ theSyncFileName = [[theFileName stringByDeletingPathExtension]
stringByAppendingPathExtension:SKPDFSynchronizerPdfsyncExtension];
+
+ if (SKFileExistsAtPath(theSyncFileName))
+ return [self parsePdfsyncFile:theSyncFileName];
+ else
+ return [self parseSynctexFile:theFileName];
+}
+
+- (BOOL)pdfsyncFindLine:(int *)line file:(NSString **)file
forLocation:(NSPoint)point inRect:(NSRect)rect atPageIndex:(unsigned
int)pageIndex {
+ if (pageIndex < [pages count]) {
+ NSDictionary *record = nil;
NSDictionary *beforeRecord = nil;
NSDictionary *afterRecord = nil;
NSMutableDictionary *atRecords = [NSMutableDictionary dictionary];
@@ -511,26 +545,18 @@
}
if (record) {
- foundLine = [[record objectForKey:SKPDFSynchronizerLineKey]
intValue];
- foundFile = [record objectForKey:SKPDFSynchronizerFileKey];
+ *line = [[record objectForKey:SKPDFSynchronizerLineKey] intValue];
+ *file = [record objectForKey:SKPDFSynchronizerFileKey];
+ return YES;
}
-
- OSMemoryBarrier();
}
-
- OSMemoryBarrier();
- if (shouldKeepRunning)
- [serverOnMainThread serverFoundLine:foundLine inFile:foundFile];
+ return NO;
}
-- (oneway void)serverFindPageLocationForLine:(int)line inFile:(bycopy NSString
*)file {
- unsigned int foundPageIndex = NSNotFound;
- NSPoint foundPoint = NSZeroPoint;
- NSDictionary *record = nil;
-
- OSMemoryBarrier();
- if (shouldKeepRunning && file && [self parsePdfsyncFileIfNeeded] && [lines
objectForKey:file]) {
+- (BOOL)pdfsyncFindPage:(unsigned int *)pageIndex location:(NSPoint *)point
forLine:(int)line inFile:(NSString *)file {
+ if ([lines objectForKey:file]) {
+ NSDictionary *record = nil;
NSDictionary *beforeRecord = nil;
NSDictionary *afterRecord = nil;
NSDictionary *atRecord = nil;
@@ -567,15 +593,79 @@
}
if (record) {
- foundPageIndex = [[record objectForKey:SKPDFSynchronizerPageKey]
unsignedIntValue];
- foundPoint = NSMakePoint([[record
objectForKey:SKPDFSynchronizerXKey] floatValue], [[record
objectForKey:SKPDFSynchronizerYKey] floatValue]);
+ *pageIndex = [[record objectForKey:SKPDFSynchronizerPageKey]
unsignedIntValue];
+ *point = NSMakePoint([[record objectForKey:SKPDFSynchronizerXKey]
floatValue], [[record objectForKey:SKPDFSynchronizerYKey] floatValue]);
+ return YES;
}
-
+ }
+ return NO;
+}
+
+- (BOOL)synctexFindLine:(int *)line file:(NSString **)file
forLocation:(NSPoint)point inRect:(NSRect)rect atPageIndex:(unsigned
int)pageIndex {
+#ifdef SYNCTEX_FEATURE
+ if (synctex_edit_query(scanner, (int)pageIndex - 1, PDF_TO_SYNC(point.x),
PDF_TO_SYNC(point.y)) > 0) {
+ synctex_node_t node;
+ if (node = synctex_next_result(scanner)) {
+ *line = synctex_node_line(node);
+ *file = [NSString
stringWithUTF8String:synctex_scanner_get_name(scanner, synctex_node_tag(node))];
+ return YES;
+ }
+ }
+#endif
+ return NO;
+}
+
+- (BOOL)synctexFindPage:(unsigned int *)pageIndex location:(NSPoint *)point
forLine:(int)line inFile:(NSString *)file {
+#ifdef SYNCTEX_FEATURE
+ if (synctex_display_query(scanner, [file fileSystemRepresentation], line,
0) > 0) {
+ synctex_node_t node;
+ if ((node = synctex_next_result(scanner))) {
+ *pageIndex = synctex_node_page(node) + 1;
+ *point = NSMakePoint(SYNC_TO_PDF(synctex_node_h(node)),
SYNC_TO_PDF(synctex_node_v(node)));
+ return YES;
+ }
+ }
+#endif
+ return NO;
+}
+
+- (oneway void)serverFindLineForLocation:(NSPoint)point inRect:(NSRect)rect
atPageIndex:(unsigned int)pageIndex {
+ int foundLine = -1;
+ NSString *foundFile = nil;
+
+ OSMemoryBarrier();
+ if (shouldKeepRunning && [self parseSyncFileIfNeeded]) {
OSMemoryBarrier();
+ if (shouldKeepRunning) {
+ if (isPdfsync)
+ [self pdfsyncFindLine:&foundLine file:&foundFile
forLocation:point inRect:rect atPageIndex:pageIndex];
+ else
+ [self synctexFindLine:&foundLine file:&foundFile
forLocation:point inRect:rect atPageIndex:pageIndex];
+ }
}
OSMemoryBarrier();
if (shouldKeepRunning)
+ [serverOnMainThread serverFoundLine:foundLine inFile:foundFile];
+}
+
+- (oneway void)serverFindPageLocationForLine:(int)line inFile:(bycopy NSString
*)file {
+ unsigned int foundPageIndex = NSNotFound;
+ NSPoint foundPoint = NSZeroPoint;
+
+ OSMemoryBarrier();
+ if (shouldKeepRunning && file && [self parseSyncFileIfNeeded] && [lines
objectForKey:file]) {
+ OSMemoryBarrier();
+ if (shouldKeepRunning) {
+ if (isPdfsync)
+ [self pdfsyncFindPage:&foundPageIndex location:&foundPoint
forLine:line inFile:file];
+ else
+ [self synctexFindPage:&foundPageIndex location:&foundPoint
forLine:line inFile:file];
+ }
+ }
+
+ OSMemoryBarrier();
+ if (shouldKeepRunning)
[serverOnMainThread serverFoundLocation:foundPoint
atPageIndex:foundPageIndex];
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit