/**
NSDataLink
Copyright (C) 1996, 2005 Free Software Foundation, Inc.
Author: Gregory John Casamento
Date: 2005
Author: Scott Christley
Date: 1996
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "config.h"
#import
#import
#import
#import "AppKit/NSDataLink.h"
#import "AppKit/NSDataLinkManager.h"
#import "AppKit/NSPasteboard.h"
#import "AppKit/NSSavePanel.h"
#import "AppKit/NSSelection.h"
@implementation NSDataLink
//
// Class methods
//
+ (void)initialize
{
if (self == [NSDataLink class])
{
// Initial version
[self setVersion: 0];
}
}
//
//
// Instance methods
//
// Initializing a Link
//
- (id)initLinkedToFile:(NSString *)filename
{
if ((self = [self init]) != nil)
{
NSData *data = [NSData dataWithBytes: [filename cString] length: [filename cStringLength]];
NSSelection *selection = [NSSelection selectionWithDescriptionData: data];
ASSIGN(sourceSelection, selection);
}
return self;
}
- (id)initLinkedToSourceSelection:(NSSelection *)selection
managedBy:(NSDataLinkManager *)linkManager
supportingTypes:(NSArray *)newTypes
{
if ((self = [self init]) != nil)
{
ASSIGN(sourceSelection,selection);
ASSIGN(sourceManager,linkManager);
ASSIGN(types,newTypes);
}
return self;
}
- (id)initWithContentsOfFile:(NSString *)filename
{
NSData *data = [[NSData alloc] initWithContentsOfFile: filename];
id object = [NSUnarchiver unarchiveObjectWithData: data];
RELEASE(data);
RELEASE(self);
return RETAIN(object);
}
- (id)initWithPasteboard:(NSPasteboard *)pasteboard
{
NSData *data = [pasteboard dataForType: NSDataLinkPboardType];
id object = [NSUnarchiver unarchiveObjectWithData: data];
RELEASE(self);
return RETAIN(object);
}
//
// Exporting a Link
//
- (BOOL)saveLinkIn:(NSString *)directoryName
{
NSSavePanel *sp;
int result;
sp = [NSSavePanel savePanel];
[sp setRequiredFileType: NSDataLinkFilenameExtension];
result = [sp runModalForDirectory: directoryName file: @""];
if (result == NSOKButton)
{
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *path = [sp filename];
if ([mgr fileExistsAtPath: path] == YES)
{
/* NSSavePanel has already asked if it's ok to replace */
NSString *bPath = [path stringByAppendingString: @"~"];
[mgr removeFileAtPath: bPath handler: nil];
[mgr movePath: path toPath: bPath handler: nil];
}
// save it.
return [self writeToFile: path];
}
return NO;
}
- (BOOL)writeToFile:(NSString *)filename
{
NSString *path = filename;
if ([[path pathExtension] isEqual: NSDataLinkFilenameExtension] == NO)
{
path = [filename stringByAppendingPathExtension: NSDataLinkFilenameExtension];
}
return [NSArchiver archiveRootObject: self toFile: path];
}
- (void)writeToPasteboard:(NSPasteboard *)pasteboard
{
NSData *data = [NSArchiver archivedDataWithRootObject: self];
[pasteboard setData: data forType: NSDataLinkPboardType];
}
//
// Information about the Link
//
- (NSDataLinkDisposition)disposition
{
return disposition;
}
- (NSDataLinkNumber)linkNumber
{
return linkNumber;
}
- (NSDataLinkManager *)manager
{
return sourceManager;
}
//
// Information about the Link's Source
//
- (NSDate *)lastUpdateTime
{
return lastUpdateTime;
}
- (BOOL)openSource
{
return NO;
}
- (NSString *)sourceApplicationName
{
return sourceApplicationName;
}
- (NSString *)sourceFilename
{
return sourceFilename;
}
- (NSSelection *)sourceSelection
{
return sourceSelection;
}
- (NSArray *)types
{
return types;
}
//
// Information about the Link's Destination
//
- (NSString *)destinationApplicationName
{
return destinationApplicationName;
}
- (NSString *)destinationFilename
{
return destinationFilename;
}
- (NSSelection *)destinationSelection
{
return destinationSelection;
}
//
// Changing the Link
//
- (BOOL)break
{
id srcDelegate = [sourceManager delegate];
id dstDelegate = [destinationManager delegate];
// The spec is quite vague here. I don't know under what
// circumstances a link cannot be broken, so this method
// always returns YES.
if ([srcDelegate respondsToSelector: @selector(dataLinkManager:didBreakLink:)])
{
[srcDelegate dataLinkManager: sourceManager didBreakLink: self];
}
if ([dstDelegate respondsToSelector: @selector(dataLinkManager:didBreakLink:)])
{
[dstDelegate dataLinkManager: destinationManager didBreakLink: self];
}
return (_flags.broken = YES);
}
- (void)noteSourceEdited
{
_flags.isDirty = YES;
if (updateMode != NSUpdateNever)
{
[sourceManager noteDocumentEdited];
}
}
- (void)setUpdateMode:(NSDataLinkUpdateMode)mode
{
updateMode = mode;
}
- (BOOL)updateDestination
{
return NO;
}
- (NSDataLinkUpdateMode)updateMode
{
return updateMode;
}
//
// NSCoding protocol
//
- (void) encodeWithCoder: (NSCoder*)aCoder
{
BOOL flag = NO;
if ([aCoder allowsKeyedCoding])
{
[aCoder encodeInt: linkNumber forKey: @"GSLinkNumber"];
[aCoder encodeInt: disposition forKey: @"GSUpdateMode"];
[aCoder encodeInt: updateMode forKey: @"GSLastUpdateMode"];
[aCoder encodeObject: lastUpdateTime forKey: @"GSLastUpdateTime"];
[aCoder encodeObject: sourceApplicationName forKey: @"GSSourceApplicationName"];
[aCoder encodeObject: sourceFilename forKey: @"GSSourceFilename"];
[aCoder encodeObject: sourceSelection forKey: @"GSSourceSelection"];
[aCoder encodeObject: sourceManager forKey: @"GSSourceManager"];
[aCoder encodeObject: destinationApplicationName forKey: @"GSDestinationApplicationName"];
[aCoder encodeObject: destinationFilename forKey: @"GSDestinationFilename"];
[aCoder encodeObject: destinationSelection forKey: @"GSDestinationSelection"];
[aCoder encodeObject: destinationManager forKey: @"GSDestinationManager"];
[aCoder encodeObject: types forKey: @"GSTypes"];
// flags...
flag = _flags.appVerifies;
[aCoder encodeBool: flag forKey: @"GSAppVerifies"];
flag = _flags.canUpdateContinuously;
[aCoder encodeBool: flag forKey: @"GSCanUpdateContinuously"];
flag = _flags.isDirty;
[aCoder encodeBool: flag forKey: @"GSIsDirty"];
flag = _flags.willOpenSource;
[aCoder encodeBool: flag forKey: @"GSWillOpenSource"];
flag = _flags.willUpdate;
[aCoder encodeBool: flag forKey: @"GSWillUpdate"];
}
else
{
[aCoder encodeValueOfObjCType: @encode(int) at: &linkNumber];
[aCoder encodeValueOfObjCType: @encode(int) at: &disposition];
[aCoder encodeValueOfObjCType: @encode(int) at: &updateMode];
[aCoder encodeValueOfObjCType: @encode(id) at: &lastUpdateTime];
[aCoder encodeValueOfObjCType: @encode(id) at: &sourceApplicationName];
[aCoder encodeValueOfObjCType: @encode(id) at: &sourceFilename];
[aCoder encodeValueOfObjCType: @encode(id) at: &sourceSelection];
[aCoder encodeValueOfObjCType: @encode(id) at: &sourceManager];
[aCoder encodeValueOfObjCType: @encode(id) at: &destinationApplicationName];
[aCoder encodeValueOfObjCType: @encode(id) at: &destinationFilename];
[aCoder encodeValueOfObjCType: @encode(id) at: &destinationSelection];
[aCoder encodeValueOfObjCType: @encode(id) at: &destinationManager];
[aCoder encodeValueOfObjCType: @encode(id) at: &types];
// flags...
flag = _flags.appVerifies;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.canUpdateContinuously;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.isDirty;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.willOpenSource;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.willUpdate;
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
}
}
- (id) initWithCoder: (NSCoder*)aCoder
{
if ([aCoder allowsKeyedCoding])
{
id obj;
linkNumber = [aCoder decodeIntForKey: @"GSLinkNumber"];
disposition = [aCoder decodeIntForKey: @"GSDisposition"];
updateMode = [aCoder decodeIntForKey: @"GSUpdateMode"];
obj = [aCoder decodeObjectForKey: @"GSSourceManager"];
ASSIGN(sourceManager,obj);
obj = [aCoder decodeObjectForKey: @"GSDestinationManager"];
ASSIGN(destinationManager,obj);
obj = [aCoder decodeObjectForKey: @"GSLastUpdateTime"];
ASSIGN(lastUpdateTime, obj);
obj = [aCoder decodeObjectForKey: @"GSSourceApplicationName"];
ASSIGN(sourceApplicationName,obj);
obj = [aCoder decodeObjectForKey: @"GSSourceFilename"];
ASSIGN(sourceFilename,obj);
obj = [aCoder decodeObjectForKey: @"GSSourceSelection"];
ASSIGN(sourceSelection,obj);
obj = [aCoder decodeObjectForKey: @"GSSourceManager"];
ASSIGN(sourceManager,obj);
obj = [aCoder decodeObjectForKey: @"GSDestinationApplicationName"];
ASSIGN(destinationApplicationName,obj);
obj = [aCoder decodeObjectForKey: @"GSDestinationFilename"];
ASSIGN(destinationFilename,obj);
obj = [aCoder decodeObjectForKey: @"GSDestinationSelection"];
ASSIGN(destinationSelection,obj);
obj = [aCoder decodeObjectForKey: @"GSDestinationManager"];
ASSIGN(destinationManager,obj);
obj = [aCoder decodeObjectForKey: @"GSTypes"];
ASSIGN(types,obj);
// flags...
_flags.appVerifies = [aCoder decodeBoolForKey: @"GSAppVerifies"];
_flags.canUpdateContinuously = [aCoder decodeBoolForKey: @"GSCanUpdateContinuously"];
_flags.isDirty = [aCoder decodeBoolForKey: @"GSIsDirty"];
_flags.willOpenSource = [aCoder decodeBoolForKey: @"GSWillOpenSource"];
_flags.willUpdate = [aCoder decodeBoolForKey: @"GSWillUpdate"];
}
else
{
int version = [aCoder versionForClassName: @"NSDataLink"];
if (version == 0)
{
BOOL flag = NO;
[aCoder decodeValueOfObjCType: @encode(int) at: &linkNumber];
[aCoder decodeValueOfObjCType: @encode(int) at: &disposition];
[aCoder decodeValueOfObjCType: @encode(int) at: &updateMode];
[aCoder decodeValueOfObjCType: @encode(id) at: &sourceManager];
[aCoder decodeValueOfObjCType: @encode(id) at: &destinationManager];
[aCoder decodeValueOfObjCType: @encode(id) at: &lastUpdateTime];
[aCoder decodeValueOfObjCType: @encode(id) at: &sourceApplicationName];
[aCoder decodeValueOfObjCType: @encode(id) at: &sourceFilename];
[aCoder decodeValueOfObjCType: @encode(id) at: &sourceSelection];
[aCoder decodeValueOfObjCType: @encode(id) at: &sourceManager];
[aCoder decodeValueOfObjCType: @encode(id) at: &destinationApplicationName];
[aCoder decodeValueOfObjCType: @encode(id) at: &destinationFilename];
[aCoder decodeValueOfObjCType: @encode(id) at: &destinationSelection];
[aCoder decodeValueOfObjCType: @encode(id) at: &destinationManager];
[aCoder decodeValueOfObjCType: @encode(id) at: &types];
// flags...
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.appVerifies = flag;
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.canUpdateContinuously = flag;
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.isDirty = flag;
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.willOpenSource = flag;
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.willUpdate = flag;
}
else
return nil;
}
return self;
}
@end