#include "WikiTextView.h" #include "GNUstep.h" @implementation WikiTextView - (NSDragOperation) draggingEntered: (id ) sender { NSPasteboard *pboard; NSDragOperation sourceDragMask; sourceDragMask = [sender draggingSourceOperationMask]; pboard = [sender draggingPasteboard]; [NSApp activateIgnoringOtherApps: YES]; if ([[pboard types] containsObject: NSStringPboardType]) { ASSIGN(pboardType, NSStringPboardType); dragOperation = [super draggingEntered: sender]; } else if ([[pboard types] containsObject: NSFilenamesPboardType]) { ASSIGN(pboardType, NSFilenamesPboardType); if (sourceDragMask & NSDragOperationCopy) { dragOperation = NSDragOperationCopy; } else if (sourceDragMask & NSDragOperationMove) { dragOperation = NSDragOperationMove; } else if (sourceDragMask & NSDragOperationLink) { dragOperation = NSDragOperationLink; } else if (sourceDragMask & NSDragOperationGeneric) { dragOperation = NSDragOperationGeneric; } else { dragOperation = NSDragOperationNone; } } else { dragOperation = NSDragOperationNone; } return dragOperation; } - (NSDragOperation) draggingUpdated: (id ) sender { if ([pboardType isEqualToString: NSStringPboardType]) { return [super draggingUpdated: sender]; } else if ([pboardType isEqualToString: NSFilenamesPboardType]) { NSLayoutManager *layoutManager = [self layoutManager]; NSTextContainer *textContainer = [self textContainer]; unsigned int glyphIndex; float partialFraction; NSRange charRange, glyphRange;; //NSLog(@"%@", NSStringFromPoint([sender draggingLocation])); NSPoint point = [self convertPoint: [sender draggingLocation] fromView: nil]; //NSLog(@"%@", NSStringFromPoint(point)); glyphIndex = [layoutManager glyphIndexForPoint: point inTextContainer: textContainer fractionOfDistanceThroughGlyph: &partialFraction]; glyphRange = NSMakeRange(glyphIndex, 0); charRange = [layoutManager characterRangeForGlyphRange: glyphRange actualGlyphRange: NULL/*nil*/]; //NSLog(@"charRange %@", NSStringFromRange(charRange)); if (partialFraction > 0.5) charRange.location++; insertPosition = charRange.location; [self setSelectedRange: NSMakeRange(charRange.location, 0) affinity: NSSelectionAffinityUpstream stillSelecting: YES]; } return dragOperation; } - (BOOL) copyOrMoveFiles: (NSArray *) files { // Copy files into MWK directory; //NSLog(@"copyOrMoveFiles"); NSEnumerator *e; NSString *filepath, *lastPathComponent, *insertion; int result; NSSavePanel *savePanel = [NSSavePanel savePanel]; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL succeed = NO; [savePanel setTreatsFilePackagesAsDirectories: YES]; documentPath = [[self window] representedFilename]; if ((documentPath == nil) || [documentPath isEqualToString: @""]) return NO; e = [files objectEnumerator]; while((filepath = [e nextObject])) { lastPathComponent = [filepath lastPathComponent]; result = [savePanel runModalForDirectory: [[self window] representedFilename] file: lastPathComponent]; if (result == NSFileHandlingPanelOKButton) { NSString *destination = [savePanel filename]; BOOL continueToNextFile = NO; while ([destination hasPrefix: [[self window] representedFilename]] == NO) { // Only allow to save in file packages result = NSRunAlertPanel(@"Unacceptable directory", [NSString stringWithFormat: @"Files are only allowed to be save under %@", [[self window] representedFilename]], @"Save again", @"Cancel", nil, nil); if (result == NSAlertDefaultReturn) { continueToNextFile = NO; result = [savePanel runModalForDirectory: [[self window] representedFilename] file: lastPathComponent]; if (result == NSFileHandlingPanelCancelButton) { continueToNextFile = YES; break; } destination = [savePanel filename]; } else { continueToNextFile = YES; break; } } if (continueToNextFile == YES) continue; //NSLog(@"filename %@", destination); if ([fileManager fileExistsAtPath: destination]) { succeed = [fileManager removeFileAtPath: destination handler: nil]; if (succeed == NO) { NSRunAlertPanel(@"File Error", [NSString stringWithFormat: @"Cannot replace %@", filepath], @"OK", nil, nil, nil); continue; } } // Check whether the directory exist. If not, create one NSString *relativePath; lastPathComponent = [destination lastPathComponent]; relativePath = [destination substringFromIndex: [[[self window] representedFilename] length]+1]; NSArray *pathComponents = [[relativePath stringByDeletingLastPathComponent] pathComponents]; NSString *testPath = [[self window] representedFilename]; NSEnumerator *components = [pathComponents objectEnumerator]; id object; while ((object = [components nextObject])) { testPath = [testPath stringByAppendingPathComponent: object]; if ([fileManager fileExistsAtPath: testPath] == NO) { succeed = [fileManager createDirectoryAtPath: testPath attributes: nil]; if (succeed == NO) { NSRunAlertPanel(@"File Error", [NSString stringWithFormat: @"Cannot create directory %@", testPath], @"OK", nil, nil, nil); break; } } } if (dragOperation == NSDragOperationCopy) { succeed = [fileManager copyPath: filepath toPath: destination handler: nil]; } else { succeed = [fileManager movePath: filepath toPath: destination handler: nil]; } if (succeed == NO) { NSRunAlertPanel(@"File Error", [NSString stringWithFormat: @"Cannot copy or move %@", filepath], @"OK", nil, nil, nil); continue; } insertion = [NSString stringWithFormat: @"%@", relativePath, lastPathComponent]; [[self textStorage] insertAttributedString: [[NSAttributedString alloc] initWithString: insertion] atIndex: insertPosition]; insertPosition += [insertion length]; } } return YES; } - (BOOL) performDragOperation: (id ) sender { if ([pboardType isEqualToString: NSStringPboardType]) return [super performDragOperation: sender]; else if ([pboardType isEqualToString: NSFilenamesPboardType]) { NSPasteboard *pboard = [sender draggingPasteboard]; NSArray *files = [pboard propertyListForType: NSFilenamesPboardType]; NSEnumerator *e; NSString *filepath; NSString *insertion; NSString *lastPathComponent; int result; if ((dragOperation == NSDragOperationCopy) || (dragOperation == NSDragOperationMove) || (dragOperation == NSDragOperationGeneric)) { //NSLog(@"Copy or move"); NSSavePanel *savePanel = [NSSavePanel savePanel]; documentPath = [[self window] representedFilename]; if ((documentPath == nil) || ([documentPath isEqualToString: @""])) { // File is not saved result = NSRunInformationalAlertPanel(@"File is not saved", @"You have to save this document before dropping a file", @"Save File", @"Cancel", nil, nil); if (result == NSAlertDefaultReturn) { //NSLog(@"Save files %@", files); RETAIN(files); [[[[self window] windowController] document] saveDocumentWithDelegate: self didSaveSelector: @selector(document:didSave:contextInfo:) contextInfo: (void *)files]; return YES; } else { // Stop dropping return NO; } } return [self copyOrMoveFiles: files]; } else if (dragOperation == NSDragOperationLink) { //NSLog(@"Link"); e = [files objectEnumerator]; while((filepath = [e nextObject])) { lastPathComponent = [filepath lastPathComponent]; insertion = [NSString stringWithFormat: @"%@", filepath, lastPathComponent]; [[self textStorage] insertAttributedString: [[NSAttributedString alloc] initWithString: insertion] atIndex: insertPosition]; insertPosition += [insertion length]; } } else return NO; return YES; } else return NO; } - (void) concludeDragOperation: (id ) sender { if ([pboardType isEqualToString: NSStringPboardType]) [super concludeDragOperation: sender]; } - (void) document: (NSDocument *) doc didSave: (BOOL) didSave contextInfo: (void *) contextInfo { if (didSave == YES) { [self copyOrMoveFiles: (NSArray *)contextInfo]; AUTORELEASE((NSArray *)contextInfo); } } @end