// // FPAppWindow.m // Fuse-PDF-App // // Created by Chris Dolan on 11/29/07. // Copyright 2007, All rights reserved. // #import "AppDelegate.h" #import "BundledTask.h" #import "FPAppWindow.h" @interface NSAttributedString (Hyperlink) +(id)hyperlinkFromString:(NSString*)inString withURL:(NSURL*)aURL; @end @implementation NSAttributedString (Hyperlink) +(id)hyperlinkFromString:(NSString*)inString withURL:(NSURL*)aURL { NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString: inString]; NSRange range = NSMakeRange(0, [attrString length]); [attrString beginEditing]; [attrString addAttribute:NSLinkAttributeName value:[aURL absoluteString] range:range]; // make the text appear in blue [attrString addAttribute:NSForegroundColorAttributeName value:[NSColor blueColor] range:range]; // next make the text appear with an underline [attrString addAttribute: NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:range]; [attrString endEditing]; return [attrString autorelease]; } @end @implementation FPAppWindow static FPAppWindow *sharedController = nil; + (id)sharedController { if (!sharedController) sharedController = [[FPAppWindow allocWithZone:nil] init]; [sharedController showWindow:nil]; return sharedController; } - (id)init { self = [self initWithWindowNibName:@"FPAppWindow"]; return self; } - (void)windowDidLoad { printf("window loaded\n"); [[self window] setExcludedFromWindowsMenu:YES]; [[NSApplication sharedApplication] removeWindowsItem:[self window]]; [super windowDidLoad]; [self setup]; } -(void) parseVersion: (NSString*)result { //printf("result: %s\n", result ? [result UTF8String] : [@"nil" UTF8String]); if (result) { NSRange versionLoc = [result rangeOfString:@"version "]; if (NSNotFound != versionLoc.location) { NSRange near = {versionLoc.location - 10, versionLoc.length + 50}; printf("found version near '%s'\n", [[result substringWithRange: near] UTF8String]); NSRange spaceSearch = {versionLoc.location + versionLoc.length, 100}; printf("looking for space at %d+%d\n", spaceSearch.location, spaceSearch.length); if (spaceSearch.location >= [result length]) { printf("end of string\n"); return; } NSRange nextSpace = [result rangeOfString:@"\n" options:0 range:spaceSearch]; if (NSNotFound != nextSpace.location) { NSRange numberLoc = {spaceSearch.location, nextSpace.location - spaceSearch.location}; [fuseVersion release]; fuseVersion = [result substringWithRange:numberLoc]; [fuseVersion retain]; printf("number version = %s\n", [fuseVersion UTF8String]); [fuseStatus setObjectValue:[@"present, v" stringByAppendingString:fuseVersion]]; return; } else {printf("missing space\n");} } else {printf("missing versionloc\n");} } else {printf("nil result\n");} } -(void)getFuseVersion { Callback *callback = [Callback create:self method:@selector(parseVersion:)]; NSArray *cmd = [NSArray arrayWithObjects:@"/System/Library/Filesystems/fusefs.fs/Support/mount_fusefs", @"-v", nil]; [BundledTask run:cmd callback:callback]; } -(void)parseArch:(NSString*)arch { NSRange r = [arch rangeOfString:@"\n"]; if (NSNotFound != r.location) { NSRange begin = {0, r.location}; arch = [arch substringWithRange:begin]; } printf("arch: %s\n", [arch UTF8String]); archext = [[@"." stringByAppendingString:arch] retain]; } -(void)getPerlArch { Callback *callback = [Callback create:self method:@selector(parseArch:)]; //NSArray *cmd = [NSArray arrayWithObjects:@"/usr/bin/perl", @"-e", @"use Config; print @Config{myarchname}", nil]; NSArray *cmd = [NSArray arrayWithObject:@"/usr/bin/arch"]; [BundledTask run:cmd callback:callback]; } -(void)setup { [self getPerlArch]; [unmountButton setEnabled:NO]; //NSString *urlStr = [fuseLink stringValue]; NSString *urlStr = @"http://code.google.com/p/macfuse"; // both are needed, otherwise hyperlink won't accept mousedown [fuseLink setAllowsEditingTextAttributes: YES]; [fuseLink setSelectable: YES]; NSURL* url = [NSURL URLWithString:urlStr]; NSMutableAttributedString* string = [[NSMutableAttributedString alloc] init]; [string appendAttributedString: [NSAttributedString hyperlinkFromString:urlStr withURL:url]]; // set the attributed string to the NSTextField [fuseLink setAttributedStringValue: string]; [dropWell registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; [dropWell setCallback:[Callback create:self method:@selector(doMount:)]]; pdfListSource = [[PDFList alloc] init]; [pdfList setDataSource:pdfListSource]; [self getFuseVersion]; } -(NSString *)createMountPathForFile:(NSString *)path { NSString *filename = [path lastPathComponent]; NSString *root = [@"/Volumes/" stringByAppendingString:filename]; NSFileManager *mgr = [NSFileManager defaultManager]; NSString *mountPath = root; root = [root stringByAppendingString:@"-"]; int i = 0; while ([mgr fileExistsAtPath:mountPath]) { mountPath = [root stringByAppendingString:[NSString stringWithFormat:@"%d", ++i]]; } [mgr createDirectoryAtPath:mountPath attributes:nil]; return mountPath; } -(void)mountCallback:(NSString *)output fromTask:(BundledTask *)task { if (output) printf("%s\n", [output UTF8String]); printf("unmount\n"); [task release]; } -(void)doMount:(NSString*)path { printf("mount %s\n", [path UTF8String]); NSMutableArray *array = [pdfListSource array]; NSString *mountPath = [self createMountPathForFile:path]; @try { NSArray *cmd = [NSArray arrayWithObjects:[@"mount_pdf" stringByAppendingString:archext], path, mountPath, nil]; BundledTask *t = [[BundledTask alloc] initWithCmd:cmd]; [t setVerbose:YES]; Callback *callback = [Callback create:self method:@selector(mountCallback:fromTask:) data:t]; [t start:callback]; [array addObject:mountPath]; [array addObject:path]; [unmountButton setEnabled:YES]; [pdfList reloadData]; } @catch (NSException *e) { [[NSAlert alertWithMessageText:@"PDF mount failed" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"Failed to mount PDF file %@ at %@: %@", path, mountPath, e] runModal]; [[NSFileManager defaultManager] removeFileAtPath:mountPath handler:nil]; } } -(IBAction)mountPDF:(id)sender { printf("mountPDF\n"); NSOpenPanel *open = [NSOpenPanel openPanel]; [open setCanChooseFiles:YES]; [open setCanChooseDirectories:NO]; [open setAllowsMultipleSelection:NO]; [open setResolvesAliases:YES]; if (NSOKButton == [open runModalForTypes:[NSArray arrayWithObject:@"pdf"]]) { NSString *path = [open filename]; [self doMount:path]; } } -(IBAction)unmountPDF:(id)sender { printf("unmountPDF\n"); NSIndexSet *indexSet = [pdfList selectedRowIndexes]; NSMutableArray *array = [pdfListSource array]; int i; for (i=[array count] - 2; i>=0; i -= 2) { if ([indexSet containsIndex:i/2]) { NSString *mountPath = [array objectAtIndex:i]; NSString *path = [array objectAtIndex:i+1]; @try { NSArray *cmd = [NSArray arrayWithObjects: @"/sbin/umount", mountPath, nil]; BundledTask *t = [[BundledTask alloc] initWithCmd:cmd]; [t setVerbose:YES]; [[t autorelease] startAndWait]; } @catch (NSException *e) { [[NSAlert alertWithMessageText:@"PDF unmount failed" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"Failed to unmount PDF file %@ at %@: %@", path, mountPath, e] runModal]; } [[NSFileManager defaultManager] removeFileAtPath:mountPath handler:nil]; [array removeObjectAtIndex:i+1]; [array removeObjectAtIndex:i]; } } [pdfList reloadData]; if (0 == [array count]) [unmountButton setEnabled:NO]; } -(IBAction)clickLink:(id)sender { printf("clickLink\n"); } @end