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

Reply via email to