2 * \file LinkBackProxy.mm
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> {
26 - (LyXLinkBackClient *)init;
27 - (BOOL)edit:(NSString *)fileName;
30 @implementation LyXLinkBackClient
34 pool = [[NSAutoreleasePool alloc] init];
37 - (LyXLinkBackClient *)init
41 keys = [[NSMutableSet alloc] init];
47 NSArray * allKeys = [keys allObjects];
49 for (i = 0; i < [allKeys count]; ++i) {
51 = [LinkBack activeLinkBackForItemKey:[allKeys objectAtIndex:i]];
59 - (BOOL)edit:(NSString *)fileName
61 if ([LinkBack activeLinkBackForItemKey:fileName])
65 // get put data, i.e. PDF + LinkBack + 4 bytes PDF-length
66 NSData * data = [NSData dataWithContentsOfFile:fileName];
68 NSLog(@"Cannot read file %@", fileName);
72 // Get linkback data which comes behind the pdf data.
73 // The pdf data length are the last 4 bytes.
75 pdfLen = *(UInt32 const *)(((UInt8 const *)[data bytes]) + [data length] - 4);
76 pdfLen = NSSwapBigLongToHost(pdfLen); // make it big endian
77 if (pdfLen >= [data length] - 4) {
78 NSLog(@"Invalid file %@ for LinkBack", fileName);
83 = [data subdataWithRange:NSMakeRange(pdfLen, [data length] - pdfLen - 4)];
84 if (linkBackData == nil) {
85 NSLog(@"Invalid file %@ for LinkBack", fileName);
89 NSMutableDictionary * linkBackDataDict
90 = [NSUnarchiver unarchiveObjectWithData:linkBackData];
91 if (linkBackDataDict == nil) {
92 NSLog(@"LinkBack data in %@ corrupted");
96 // create the link to the LinkBack server
97 LinkBack * link = [LinkBack editLinkBackData:linkBackDataDict
98 sourceName:fileName delegate:self itemKey:fileName];
100 NSLog(@"Failed to create LinkBack link for %@", fileName);
103 [keys addObject:fileName];
105 @catch (NSException * exception) {
106 NSLog(@"LinkBack exception: %@", exception);
113 - (void)linkBackDidClose:(LinkBack*)link
115 NSString * fileName = [link itemKey];
117 [keys removeObject:fileName];
118 NSLog(@"LinkBack link for %@ closed", fileName);
122 - (void)linkBackServerDidSendEdit:(LinkBack*)link
125 // get pasteboard and check that linkback and pdf data is available
126 NSPasteboard * pboard = [link pasteboard];
127 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
128 NSArray * pdfType = [NSArray arrayWithObjects: NSPDFPboardType, nil];
129 if ([pboard availableTypeFromArray:linkBackType] == nil
130 || [pboard availableTypeFromArray:pdfType] == nil) {
131 NSLog(@"No PDF or LinkBack data in pasteboard");
135 // get new linkback data
136 id linkBackDataDict = [pboard propertyListForType:LinkBackPboardType];
137 if (linkBackDataDict == nil) {
138 NSLog(@"Cannot get LinkBack data from pasteboard");
141 NSData * linkBackData = [NSArchiver archivedDataWithRootObject:linkBackDataDict];
142 if (linkBackData == nil) {
143 NSLog(@"Cannot archive LinkBack data");
148 NSData * pdfData = [pboard dataForType:NSPDFPboardType];
149 if (pdfData == nil) {
150 NSLog(@"Cannot get PDF data from pasteboard");
155 NSString * fileName = [link itemKey];
156 NSFileHandle * file = [NSFileHandle fileHandleForUpdatingAtPath:fileName];
158 NSLog(@"LinkBack file %@ disappeared.", fileName);
161 [file truncateFileAtOffset:0];
162 [file writeData:pdfData];
163 [file writeData:linkBackData];
165 UInt32 pdfLen = NSSwapHostLongToBig([pdfData length]); // big endian
166 NSData * lenData = [NSData dataWithBytes:&pdfLen length:4];
167 [file writeData:lenData];
170 @catch (NSException * exception) {
171 NSLog(@"LinkBack exception in linkBackServerDidSendEdit: %@", exception);
178 ///////////////////////////////////////////////////////////////////////
180 static LyXLinkBackClient * linkBackClient = nil;
182 void checkAutoReleasePool()
185 pool = [[NSAutoreleasePool alloc] init];
188 int isLinkBackDataInPasteboard()
190 checkAutoReleasePool() ;
192 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
193 NSString * ret = [[NSPasteboard generalPasteboard] availableTypeFromArray:linkBackType];
199 void getLinkBackData(void const * * buf, unsigned * len)
201 checkAutoReleasePool() ;
203 // get linkback data from pasteboard
204 NSPasteboard * pboard = [NSPasteboard generalPasteboard];
205 id linkBackData = [pboard propertyListForType:LinkBackPboardType];
208 = [NSArchiver archivedDataWithRootObject:linkBackData];
215 *buf = [nsdata bytes];
216 *len = [nsdata length];
220 int editLinkBackFile(char const * docName)
222 // setup Obj-C and our client
223 if (linkBackClient == nil)
224 linkBackClient = [[LyXLinkBackClient alloc] init];
225 checkAutoReleasePool() ;
227 // FIXME: really UTF8 here?
228 NSString * nsDocName = [NSString stringWithUTF8String:docName];
229 return [linkBackClient edit:nsDocName] == YES;
233 void closeAllLinkBackLinks()
235 [linkBackClient release];
236 linkBackClient = nil;