mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-11 13:46:43 +00:00
2d1e0ffabd
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@27627 a592a061-630c-0410-9148-cb99ea01b6c8
242 lines
5.8 KiB
Objective-C
242 lines
5.8 KiB
Objective-C
/**
|
|
* \file LinkBackProxy.mm
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Stefan Schimanski
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "support/linkback/LinkBackProxy.h"
|
|
|
|
#include "support/linkback/LinkBack.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
static NSAutoreleasePool * pool = nil;
|
|
|
|
@interface LyXLinkBackClient : NSObject <LinkBackClientDelegate> {
|
|
NSMutableSet * keys;
|
|
}
|
|
|
|
+ (void)load;
|
|
- (LyXLinkBackClient *)init;
|
|
- (BOOL)edit:(NSString *)fileName;
|
|
@end
|
|
|
|
@implementation LyXLinkBackClient
|
|
|
|
+ (void)load
|
|
{
|
|
pool = [[NSAutoreleasePool alloc] init];
|
|
}
|
|
|
|
- (LyXLinkBackClient *)init
|
|
{
|
|
self = [super init];
|
|
if (self != nil)
|
|
keys = [[NSMutableSet alloc] init];
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
// close all links
|
|
NSArray * allKeys = [keys allObjects];
|
|
unsigned i;
|
|
for (i = 0; i < [allKeys count]; ++i) {
|
|
LinkBack * link
|
|
= [LinkBack activeLinkBackForItemKey:[allKeys objectAtIndex:i]];
|
|
[link closeLink];
|
|
}
|
|
[keys release];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (BOOL)edit:(NSString *)fileName
|
|
{
|
|
if ([LinkBack activeLinkBackForItemKey:fileName])
|
|
return YES;
|
|
|
|
@try {
|
|
// get put data, i.e. PDF + LinkBack + 4 bytes PDF-length
|
|
NSData * data = [NSData dataWithContentsOfFile:fileName];
|
|
if (data == nil) {
|
|
NSLog(@"Cannot read file %@", fileName);
|
|
return NO;
|
|
}
|
|
|
|
// Get linkback data which comes behind the pdf data.
|
|
// The pdf data length are the last 4 bytes.
|
|
UInt32 pdfLen = 0;
|
|
pdfLen = *(UInt32 const *)(((UInt8 const *)[data bytes]) + [data length] - 4);
|
|
pdfLen = NSSwapBigLongToHost(pdfLen); // make it big endian
|
|
if (pdfLen >= [data length] - 4) {
|
|
NSLog(@"Invalid file %@ for LinkBack", fileName);
|
|
return NO;
|
|
}
|
|
|
|
NSData * linkBackData
|
|
= [data subdataWithRange:NSMakeRange(pdfLen, [data length] - pdfLen - 4)];
|
|
if (linkBackData == nil) {
|
|
NSLog(@"Invalid file %@ for LinkBack", fileName);
|
|
return NO;
|
|
}
|
|
|
|
NSMutableDictionary * linkBackDataDict
|
|
= [NSUnarchiver unarchiveObjectWithData:linkBackData];
|
|
if (linkBackDataDict == nil) {
|
|
NSLog(@"LinkBack data in %@ corrupted");
|
|
return NO;
|
|
}
|
|
|
|
// create the link to the LinkBack server
|
|
LinkBack * link = [LinkBack editLinkBackData:linkBackDataDict
|
|
sourceName:fileName delegate:self itemKey:fileName];
|
|
if (link == nil) {
|
|
NSLog(@"Failed to create LinkBack link for %@", fileName);
|
|
return NO;
|
|
}
|
|
[keys addObject:fileName];
|
|
}
|
|
@catch (NSException * exception) {
|
|
NSLog(@"LinkBack exception: %@", exception);
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)linkBackDidClose:(LinkBack*)link
|
|
{
|
|
NSString * fileName = [link itemKey];
|
|
if (fileName) {
|
|
[keys removeObject:fileName];
|
|
NSLog(@"LinkBack link for %@ closed", fileName);
|
|
}
|
|
}
|
|
|
|
- (void)linkBackServerDidSendEdit:(LinkBack*)link
|
|
{
|
|
@try {
|
|
// get pasteboard and check that linkback and pdf data is available
|
|
NSPasteboard * pboard = [link pasteboard];
|
|
NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
|
|
NSArray * pdfType = [NSArray arrayWithObjects: NSPDFPboardType, nil];
|
|
if ([pboard availableTypeFromArray:linkBackType] == nil
|
|
|| [pboard availableTypeFromArray:pdfType] == nil) {
|
|
NSLog(@"No PDF or LinkBack data in pasteboard");
|
|
return;
|
|
}
|
|
|
|
// get new linkback data
|
|
id linkBackDataDict = [pboard propertyListForType:LinkBackPboardType];
|
|
if (linkBackDataDict == nil) {
|
|
NSLog(@"Cannot get LinkBack data from pasteboard");
|
|
return;
|
|
}
|
|
NSData * linkBackData = [NSArchiver archivedDataWithRootObject:linkBackDataDict];
|
|
if (linkBackData == nil) {
|
|
NSLog(@"Cannot archive LinkBack data");
|
|
return;
|
|
}
|
|
|
|
// get pdf
|
|
NSData * pdfData = [pboard dataForType:NSPDFPboardType];
|
|
if (pdfData == nil) {
|
|
NSLog(@"Cannot get PDF data from pasteboard");
|
|
return;
|
|
}
|
|
|
|
// update the file
|
|
NSString * fileName = [link itemKey];
|
|
NSFileHandle * file = [NSFileHandle fileHandleForUpdatingAtPath:fileName];
|
|
if (file == nil) {
|
|
NSLog(@"LinkBack file %@ disappeared.", fileName);
|
|
return;
|
|
}
|
|
[file truncateFileAtOffset:0];
|
|
[file writeData:pdfData];
|
|
[file writeData:linkBackData];
|
|
|
|
UInt32 pdfLen = NSSwapHostLongToBig([pdfData length]); // big endian
|
|
NSData * lenData = [NSData dataWithBytes:&pdfLen length:4];
|
|
[file writeData:lenData];
|
|
[file closeFile];
|
|
}
|
|
@catch (NSException * exception) {
|
|
NSLog(@"LinkBack exception in linkBackServerDidSendEdit: %@", exception);
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
static LyXLinkBackClient * linkBackClient = nil;
|
|
|
|
void checkAutoReleasePool()
|
|
{
|
|
if (pool == nil)
|
|
pool = [[NSAutoreleasePool alloc] init];
|
|
}
|
|
|
|
int isLinkBackDataInPasteboard()
|
|
{
|
|
checkAutoReleasePool() ;
|
|
{
|
|
NSArray * linkBackType = [NSArray arrayWithObjects: LinkBackPboardType, nil];
|
|
NSString * ret = [[NSPasteboard generalPasteboard] availableTypeFromArray:linkBackType];
|
|
return ret != nil;
|
|
}
|
|
}
|
|
|
|
|
|
void getLinkBackData(void const * * buf, unsigned * len)
|
|
{
|
|
checkAutoReleasePool() ;
|
|
{
|
|
// get linkback data from pasteboard
|
|
NSPasteboard * pboard = [NSPasteboard generalPasteboard];
|
|
id linkBackData = [pboard propertyListForType:LinkBackPboardType];
|
|
|
|
NSData * nsdata
|
|
= [NSArchiver archivedDataWithRootObject:linkBackData];
|
|
if (nsdata == nil) {
|
|
*buf = 0;
|
|
*len = 0;
|
|
return;
|
|
}
|
|
|
|
*buf = [nsdata bytes];
|
|
*len = [nsdata length];
|
|
}
|
|
}
|
|
|
|
int editLinkBackFile(char const * docName)
|
|
{
|
|
// setup Obj-C and our client
|
|
if (linkBackClient == nil)
|
|
linkBackClient = [[LyXLinkBackClient alloc] init];
|
|
checkAutoReleasePool() ;
|
|
|
|
// FIXME: really UTF8 here?
|
|
NSString * nsDocName = [NSString stringWithUTF8String:docName];
|
|
return [linkBackClient edit:nsDocName] == YES;
|
|
}
|
|
|
|
|
|
void closeAllLinkBackLinks()
|
|
{
|
|
[linkBackClient release];
|
|
linkBackClient = nil;
|
|
|
|
[pool release];
|
|
pool = nil;
|
|
}
|
|
|