2 * \file LinkBackProxy.m
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Stefan Schimanski
8 * Full author contact details are available in file CREDITS.
13 #include "support/linkback/LinkBackProxy.h"
15 #include "support/linkback/LinkBack.h"
17 ///////////////////////////////////////////////////////////////////////
19 static NSAutoreleasePool * pool = nil;
21 @interface LyXLinkBackClient : NSObject <LinkBackClientDelegate> {
25 - (LyXLinkBackClient *)init;
26 - (BOOL)edit:(NSString *)fileName;
29 @implementation LyXLinkBackClient
31 - (LyXLinkBackClient *)init
35 keys = [[NSMutableSet alloc] init];
41 NSArray * allKeys = [keys allObjects];
43 for (i = 0; i < [allKeys count]; ++i) {
45 = [LinkBack activeLinkBackForItemKey:[allKeys objectAtIndex:i]];
53 - (BOOL)edit:(NSString *)fileName
55 if ([LinkBack activeLinkBackForItemKey:fileName])
59 // get put data, i.e. PDF + LinkBack + 4 bytes PDF-length
60 NSData * data = [NSData dataWithContentsOfFile:fileName];
62 NSLog(@"Cannot read file %@", fileName);
66 // Get linkback data which comes behind the pdf data.
67 // The pdf data length are the last 4 bytes.
69 pdfLen = *(UInt32 const *)(((UInt8 const *)[data bytes]) + [data length] - 4);
70 pdfLen = NSSwapBigLongToHost(pdfLen); // make it big endian
71 if (pdfLen >= [data length] - 4) {
72 NSLog(@"Invalid file %@ for LinkBack", fileName);
77 = [data subdataWithRange:NSMakeRange(pdfLen, [data length] - pdfLen - 4)];
78 if (linkBackData == nil) {
79 NSLog(@"Invalid file %@ for LinkBack", fileName);
83 NSMutableDictionary * linkBackDataDict
84 = [NSUnarchiver unarchiveObjectWithData:linkBackData];
85 if (linkBackDataDict == nil) {
86 NSLog(@"LinkBack data in %@ corrupted", fileName);
90 // create the link to the LinkBack server
91 LinkBack * link = [LinkBack editLinkBackData:linkBackDataDict
92 sourceName:fileName delegate:self itemKey:fileName];
94 NSLog(@"Failed to create LinkBack link for %@", fileName);
97 [keys addObject:fileName];
99 @catch (NSException * exception) {
100 NSLog(@"LinkBack exception: %@", exception);
107 - (void)linkBackDidClose:(LinkBack*)link
109 NSString * fileName = [link itemKey];
111 [keys removeObject:fileName];
112 NSLog(@"LinkBack link for %@ closed", fileName);
116 - (void)linkBackServerDidSendEdit:(LinkBack*)link
119 // get pasteboard and check that linkback and pdf data is available
120 NSPasteboard * pboard = [link pasteboard];
121 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
122 NSArray * pdfType = [NSArray arrayWithObjects: NSPDFPboardType, nil];
123 if ([pboard availableTypeFromArray:linkBackType] == nil
124 || [pboard availableTypeFromArray:pdfType] == nil) {
125 NSLog(@"No PDF or LinkBack data in pasteboard");
129 // get new linkback data
130 id linkBackDataDict = [pboard propertyListForType:LinkBackPboardType];
131 if (linkBackDataDict == nil) {
132 NSLog(@"Cannot get LinkBack data from pasteboard");
135 NSData * linkBackData = [NSArchiver archivedDataWithRootObject:linkBackDataDict];
136 if (linkBackData == nil) {
137 NSLog(@"Cannot archive LinkBack data");
142 NSData * pdfData = [pboard dataForType:NSPDFPboardType];
143 if (pdfData == nil) {
144 NSLog(@"Cannot get PDF data from pasteboard");
149 NSString * fileName = [link itemKey];
150 NSFileHandle * file = [NSFileHandle fileHandleForUpdatingAtPath:fileName];
152 NSLog(@"LinkBack file %@ disappeared.", fileName);
155 [file truncateFileAtOffset:0];
156 [file writeData:pdfData];
157 [file writeData:linkBackData];
159 UInt32 pdfLen = NSSwapHostLongToBig([pdfData length]); // big endian
160 NSData * lenData = [NSData dataWithBytes:&pdfLen length:4];
161 [file writeData:lenData];
164 @catch (NSException * exception) {
165 NSLog(@"LinkBack exception in linkBackServerDidSendEdit: %@", exception);
172 ///////////////////////////////////////////////////////////////////////
174 static LyXLinkBackClient * linkBackClient = nil;
176 void checkAutoReleasePool()
179 pool = [[NSAutoreleasePool alloc] init];
182 int isLinkBackDataInPasteboard()
184 checkAutoReleasePool() ;
186 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
187 NSString * ret = [[NSPasteboard generalPasteboard] availableTypeFromArray:linkBackType];
193 void getLinkBackData(void const * * buf, unsigned * len)
195 checkAutoReleasePool() ;
197 // get linkback data from pasteboard
198 NSPasteboard * pboard = [NSPasteboard generalPasteboard];
199 id linkBackData = [pboard propertyListForType:LinkBackPboardType];
202 = [NSArchiver archivedDataWithRootObject:linkBackData];
209 *buf = [nsdata bytes];
210 *len = [nsdata length];
215 int editLinkBackFile(char const * docName)
217 // setup Obj-C and our client
218 if (linkBackClient == nil)
219 linkBackClient = [[LyXLinkBackClient alloc] init];
220 checkAutoReleasePool() ;
222 // FIXME: really UTF8 here?
223 NSString * nsDocName = [NSString stringWithUTF8String:docName];
224 return [linkBackClient edit:nsDocName] == YES;
228 void closeAllLinkBackLinks()
230 if (linkBackClient != nil) {
231 [linkBackClient release];
232 linkBackClient = nil;