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 @interface LyXLinkBackClient : NSObject <LinkBackClientDelegate> {
23 - (LyXLinkBackClient *)init;
24 - (BOOL)edit:(NSString *)fileName;
27 @implementation LyXLinkBackClient
29 - (LyXLinkBackClient *)init
33 keys = [[NSMutableSet alloc] init];
39 NSArray * allKeys = [keys allObjects];
41 for (i = 0; i < [allKeys count]; ++i) {
43 = [LinkBack activeLinkBackForItemKey:[allKeys objectAtIndex:i]];
51 - (BOOL)edit:(NSString *)fileName
53 if ([LinkBack activeLinkBackForItemKey:fileName])
57 // get put data, i.e. PDF + LinkBack + 4 bytes PDF-length
58 NSData * data = [NSData dataWithContentsOfFile:fileName];
60 NSLog(@"Cannot read file %@", fileName);
64 // Get linkback data which comes behind the pdf data.
65 // The pdf data length are the last 4 bytes.
67 pdfLen = *(UInt32 const *)(((UInt8 const *)[data bytes]) + [data length] - 4);
68 pdfLen = NSSwapBigIntToHost(pdfLen); // make it big endian
69 if (pdfLen >= [data length] - 4) {
70 NSLog(@"Invalid file %@ for LinkBack", fileName);
75 = [data subdataWithRange:NSMakeRange(pdfLen, [data length] - pdfLen - 4)];
76 if (linkBackData == nil) {
77 NSLog(@"Invalid file %@ for LinkBack", fileName);
81 NSMutableDictionary * linkBackDataDict
82 = [NSUnarchiver unarchiveObjectWithData:linkBackData];
83 if (linkBackDataDict == nil) {
84 NSLog(@"LinkBack data in %@ corrupted", fileName);
88 // create the link to the LinkBack server
89 LinkBack * link = [LinkBack editLinkBackData:linkBackDataDict
90 sourceName:fileName delegate:self itemKey:fileName];
92 NSLog(@"Failed to create LinkBack link for %@", fileName);
95 [keys addObject:fileName];
97 @catch (NSException * exception) {
98 NSLog(@"LinkBack exception: %@", exception);
105 - (void)linkBackDidClose:(LinkBack*)link
107 NSString * fileName = [link itemKey];
109 [keys removeObject:fileName];
110 NSLog(@"LinkBack link for %@ closed", fileName);
114 - (void)linkBackServerDidSendEdit:(LinkBack*)link
117 // get pasteboard and check that linkback and pdf data is available
118 NSPasteboard * pboard = [link pasteboard];
119 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
120 NSArray * pdfType = [NSArray arrayWithObjects: NSPDFPboardType, nil];
121 if ([pboard availableTypeFromArray:linkBackType] == nil
122 || [pboard availableTypeFromArray:pdfType] == nil) {
123 NSLog(@"No PDF or LinkBack data in pasteboard");
127 // get new linkback data
128 id linkBackDataDict = [pboard propertyListForType:LinkBackPboardType];
129 if (linkBackDataDict == nil) {
130 NSLog(@"Cannot get LinkBack data from pasteboard");
133 NSData * linkBackData = [NSArchiver archivedDataWithRootObject:linkBackDataDict];
134 if (linkBackData == nil) {
135 NSLog(@"Cannot archive LinkBack data");
140 NSData * pdfData = [pboard dataForType:NSPDFPboardType];
141 if (pdfData == nil) {
142 NSLog(@"Cannot get PDF data from pasteboard");
147 NSString * fileName = [link itemKey];
148 NSFileHandle * file = [NSFileHandle fileHandleForUpdatingAtPath:fileName];
150 NSLog(@"LinkBack file %@ disappeared.", fileName);
153 [file truncateFileAtOffset:0];
154 [file writeData:pdfData];
155 [file writeData:linkBackData];
157 UInt32 pdfLen = NSSwapHostIntToBig([pdfData length]); // big endian
158 NSData * lenData = [NSData dataWithBytes:&pdfLen length:4];
159 [file writeData:lenData];
162 @catch (NSException * exception) {
163 NSLog(@"LinkBack exception in linkBackServerDidSendEdit: %@", exception);
170 ///////////////////////////////////////////////////////////////////////
172 static LyXLinkBackClient * linkBackClient = nil;
174 int isLinkBackDataInPasteboard()
176 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
177 NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
178 NSString * ret = [[NSPasteboard generalPasteboard] availableTypeFromArray:linkBackType];
184 void getLinkBackData(void const * * buf, unsigned * len)
186 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
187 // get linkback data from pasteboard
188 NSPasteboard * pboard = [NSPasteboard generalPasteboard];
189 id linkBackData = [pboard propertyListForType:LinkBackPboardType];
191 NSData * nsdata = [NSArchiver archivedDataWithRootObject:linkBackData];
196 *buf = [nsdata bytes];
197 *len = [nsdata length];
203 int editLinkBackFile(char const * docName)
205 // setup Obj-C and our client
206 if (linkBackClient == nil)
207 linkBackClient = [[LyXLinkBackClient alloc] init];
208 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
209 // FIXME: really UTF8 here?
210 NSString * nsDocName = [NSString stringWithUTF8String:docName];
211 int result = [linkBackClient edit:nsDocName] == YES;
217 void closeAllLinkBackLinks()
219 if (linkBackClient != nil) {
220 [linkBackClient release];
221 linkBackClient = nil;