| // | 
 | //  FileSettings.m | 
 | //  PythonLauncher | 
 | // | 
 | //  Created by Jack Jansen on Sun Jul 21 2002. | 
 | //  Copyright (c) 2002 __MyCompanyName__. All rights reserved. | 
 | // | 
 |  | 
 | #import "FileSettings.h" | 
 |  | 
 | @implementation FileSettings | 
 |  | 
 | + (id)getFactorySettingsForFileType: (NSString *)filetype | 
 | { | 
 |     static FileSettings *fsdefault_py, *fsdefault_pyw, *fsdefault_pyc; | 
 |     FileSettings **curdefault; | 
 |      | 
 |     if ([filetype isEqualToString: @"Python Script"]) { | 
 |         curdefault = &fsdefault_py; | 
 |     } else if ([filetype isEqualToString: @"Python GUI Script"]) { | 
 |         curdefault = &fsdefault_pyw; | 
 |     } else if ([filetype isEqualToString: @"Python Bytecode Document"]) { | 
 |         curdefault = &fsdefault_pyc; | 
 |     } else { | 
 |         NSLog(@"Funny File Type: %@\n", filetype); | 
 |         curdefault = &fsdefault_py; | 
 |         filetype = @"Python Script"; | 
 |     } | 
 |     if (!*curdefault) { | 
 |         *curdefault = [[FileSettings new] initForFSDefaultFileType: filetype]; | 
 |     } | 
 |     return *curdefault; | 
 | } | 
 |  | 
 | + (id)getDefaultsForFileType: (NSString *)filetype | 
 | { | 
 |     static FileSettings *default_py, *default_pyw, *default_pyc; | 
 |     FileSettings **curdefault; | 
 |      | 
 |     if ([filetype isEqualToString: @"Python Script"]) { | 
 |         curdefault = &default_py; | 
 |     } else if ([filetype isEqualToString: @"Python GUI Script"]) { | 
 |         curdefault = &default_pyw; | 
 |     } else if ([filetype isEqualToString: @"Python Bytecode Document"]) { | 
 |         curdefault = &default_pyc; | 
 |     } else { | 
 |         NSLog(@"Funny File Type: %@\n", filetype); | 
 |         curdefault = &default_py; | 
 |         filetype = @"Python Script"; | 
 |     } | 
 |     if (!*curdefault) { | 
 |         *curdefault = [[FileSettings new] initForDefaultFileType: filetype]; | 
 |     } | 
 |     return *curdefault; | 
 | } | 
 |  | 
 | + (id)newSettingsForFileType: (NSString *)filetype | 
 | { | 
 |     FileSettings *cur; | 
 |      | 
 |     cur = [FileSettings new]; | 
 |     [cur initForFileType: filetype]; | 
 |     return [cur retain]; | 
 | } | 
 |  | 
 | - (id)initWithFileSettings: (FileSettings *)source | 
 | { | 
 |     self = [super init]; | 
 |     if (!self) return self; | 
 |      | 
 |     interpreter = [source->interpreter retain]; | 
 |     honourhashbang = source->honourhashbang; | 
 |     debug = source->debug; | 
 |     verbose = source->verbose; | 
 |     inspect = source->inspect; | 
 |     optimize = source->optimize; | 
 |     nosite = source->nosite; | 
 |     tabs = source->tabs; | 
 |     others = [source->others retain]; | 
 |     scriptargs = [source->scriptargs retain]; | 
 |     with_terminal = source->with_terminal; | 
 |     prefskey = source->prefskey; | 
 |     if (prefskey) [prefskey retain]; | 
 |      | 
 |     return self; | 
 | } | 
 |  | 
 | - (id)initForFileType: (NSString *)filetype | 
 | { | 
 |     FileSettings *defaults; | 
 |      | 
 |     defaults = [FileSettings getDefaultsForFileType: filetype]; | 
 |     self = [self initWithFileSettings: defaults]; | 
 |     origsource = [defaults retain]; | 
 |     return self; | 
 | } | 
 |  | 
 | //- (id)init | 
 | //{ | 
 | //    self = [self initForFileType: @"Python Script"]; | 
 | //    return self; | 
 | //} | 
 |  | 
 | - (id)initForFSDefaultFileType: (NSString *)filetype | 
 | { | 
 |     int i; | 
 |     NSString *filename; | 
 |     NSDictionary *dict; | 
 |     static NSDictionary *factorySettings; | 
 |      | 
 |     self = [super init]; | 
 |     if (!self) return self; | 
 |      | 
 |     if (factorySettings == NULL) { | 
 |         NSBundle *bdl = [NSBundle mainBundle]; | 
 |         NSString *path = [ bdl pathForResource: @"factorySettings" | 
 |                 ofType: @"plist"]; | 
 |         factorySettings = [[NSDictionary dictionaryWithContentsOfFile: | 
 |             path] retain]; | 
 |         if (factorySettings == NULL) { | 
 |             NSLog(@"Missing %@", path); | 
 |             return NULL; | 
 |         } | 
 |     } | 
 |     dict = [factorySettings objectForKey: filetype]; | 
 |     if (dict == NULL) { | 
 |         NSLog(@"factorySettings.plist misses file type \"%@\"", filetype); | 
 |         interpreter = [@"no default found" retain]; | 
 |         return NULL; | 
 |     } | 
 |     [self applyValuesFromDict: dict]; | 
 |     interpreters = [dict objectForKey: @"interpreter_list"]; | 
 |     interpreter = NULL; | 
 |     for (i=0; i < [interpreters count]; i++) { | 
 |         filename = [interpreters objectAtIndex: i]; | 
 |         filename = [filename stringByExpandingTildeInPath]; | 
 |         if ([[NSFileManager defaultManager] fileExistsAtPath: filename]) { | 
 |             interpreter = [filename retain]; | 
 |             break; | 
 |         } | 
 |     } | 
 |     if (interpreter == NULL) | 
 |         interpreter = [@"no default found" retain]; | 
 |     origsource = NULL; | 
 |     return self; | 
 | } | 
 |  | 
 | - (void)applyUserDefaults: (NSString *)filetype | 
 | { | 
 |     NSUserDefaults *defaults; | 
 |     NSDictionary *dict; | 
 |      | 
 |     defaults = [NSUserDefaults standardUserDefaults]; | 
 |     dict = [defaults dictionaryForKey: filetype]; | 
 |     if (!dict) | 
 |         return; | 
 |     [self applyValuesFromDict: dict]; | 
 | } | 
 |      | 
 | - (id)initForDefaultFileType: (NSString *)filetype | 
 | { | 
 |     FileSettings *fsdefaults; | 
 |      | 
 |     fsdefaults = [FileSettings getFactorySettingsForFileType: filetype]; | 
 |     self = [self initWithFileSettings: fsdefaults]; | 
 |     if (!self) return self; | 
 |     interpreters = [fsdefaults->interpreters retain]; | 
 |     scriptargs = [@"" retain]; | 
 |     [self applyUserDefaults: filetype]; | 
 |     prefskey = [filetype retain]; | 
 |     return self; | 
 | } | 
 |  | 
 | - (void)reset | 
 | { | 
 |     if (origsource) { | 
 |         [self updateFromSource: origsource]; | 
 |     } else { | 
 |         FileSettings *fsdefaults; | 
 |         fsdefaults = [FileSettings getFactorySettingsForFileType: prefskey]; | 
 |         [self updateFromSource: fsdefaults]; | 
 |     } | 
 | } | 
 |  | 
 | - (void)updateFromSource: (id <FileSettingsSource>)source | 
 | { | 
 |     interpreter = [[source interpreter] retain]; | 
 |     honourhashbang = [source honourhashbang]; | 
 |     debug = [source debug]; | 
 |     verbose = [source verbose]; | 
 |     inspect = [source inspect]; | 
 |     optimize = [source optimize]; | 
 |     nosite = [source nosite]; | 
 |     tabs = [source tabs]; | 
 |     others = [[source others] retain]; | 
 |     scriptargs = [[source scriptargs] retain]; | 
 |     with_terminal = [source with_terminal]; | 
 |     // And if this is a user defaults object we also save the | 
 |     // values | 
 |     if (!origsource) { | 
 |         NSUserDefaults *defaults; | 
 |         NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: | 
 |             interpreter, @"interpreter", | 
 |             [NSNumber numberWithBool: honourhashbang], @"honourhashbang", | 
 |             [NSNumber numberWithBool: debug], @"debug", | 
 |             [NSNumber numberWithBool: verbose], @"verbose", | 
 |             [NSNumber numberWithBool: inspect], @"inspect", | 
 |             [NSNumber numberWithBool: optimize], @"optimize", | 
 |             [NSNumber numberWithBool: nosite], @"nosite", | 
 |             [NSNumber numberWithBool: tabs], @"tabs", | 
 |             others, @"others", | 
 |             scriptargs, @"scriptargs", | 
 |             [NSNumber numberWithBool: with_terminal], @"with_terminal", | 
 |             nil]; | 
 |         defaults = [NSUserDefaults standardUserDefaults]; | 
 |         [defaults setObject: dict forKey: prefskey]; | 
 |     } | 
 | } | 
 |  | 
 | - (void)applyValuesFromDict: (NSDictionary *)dict | 
 | { | 
 |     id value; | 
 |      | 
 |     value = [dict objectForKey: @"interpreter"]; | 
 |     if (value) interpreter = [value retain]; | 
 |     value = [dict objectForKey: @"honourhashbang"]; | 
 |     if (value) honourhashbang = [value boolValue]; | 
 |     value = [dict objectForKey: @"debug"]; | 
 |     if (value) debug = [value boolValue]; | 
 |     value = [dict objectForKey: @"verbose"]; | 
 |     if (value) verbose = [value boolValue]; | 
 |     value = [dict objectForKey: @"inspect"]; | 
 |     if (value) inspect = [value boolValue]; | 
 |     value = [dict objectForKey: @"optimize"]; | 
 |     if (value) optimize = [value boolValue]; | 
 |     value = [dict objectForKey: @"nosite"]; | 
 |     if (value) nosite = [value boolValue]; | 
 |     value = [dict objectForKey: @"tabs"]; | 
 |     if (value) tabs = [value boolValue]; | 
 |     value = [dict objectForKey: @"others"]; | 
 |     if (value) others = [value retain]; | 
 |     value = [dict objectForKey: @"scriptargs"]; | 
 |     if (value) scriptargs = [value retain]; | 
 |     value = [dict objectForKey: @"with_terminal"]; | 
 |     if (value) with_terminal = [value boolValue]; | 
 | } | 
 |  | 
 | - (NSString*)_replaceSingleQuotes: (NSString*)string | 
 | { | 
 | 	/* Replace all single-quotes by '"'"', that way shellquoting will | 
 | 	 * be correct when the result value is delimited  using single quotes. | 
 | 	 */ | 
 | 	NSArray* components = [string componentsSeparatedByString:@"'"]; | 
 |  | 
 | 	return [components componentsJoinedByString:@"'\"'\"'"]; | 
 | } | 
 |  | 
 | - (NSString *)commandLineForScript: (NSString *)script | 
 | { | 
 |     NSString *cur_interp = NULL; | 
 |     NSString* script_dir = NULL; | 
 |     char hashbangbuf[1024]; | 
 |     FILE *fp; | 
 |     char *p; | 
 |  | 
 |     script_dir = [script substringToIndex: | 
 | 	    [script length]-[[script lastPathComponent] length]]; | 
 |      | 
 |     if (honourhashbang && | 
 |        (fp=fopen([script fileSystemRepresentation], "r")) && | 
 |        fgets(hashbangbuf, sizeof(hashbangbuf), fp) && | 
 |        strncmp(hashbangbuf, "#!", 2) == 0 && | 
 |        (p=strchr(hashbangbuf, '\n'))) { | 
 |             *p = '\0'; | 
 |             p = hashbangbuf + 2; | 
 |             while (*p == ' ') p++; | 
 |             cur_interp = [NSString stringWithUTF8String: p]; | 
 |     } | 
 |     if (!cur_interp) | 
 |         cur_interp = interpreter; | 
 |          | 
 |     return [NSString stringWithFormat: | 
 |         @"cd '%@' && '%@'%s%s%s%s%s%s %@ '%@' %@ %s", | 
 |     	[self _replaceSingleQuotes:script_dir], | 
 |         [self _replaceSingleQuotes:cur_interp], | 
 |         debug?" -d":"", | 
 |         verbose?" -v":"", | 
 |         inspect?" -i":"", | 
 |         optimize?" -O":"", | 
 |         nosite?" -S":"", | 
 |         tabs?" -t":"", | 
 |         others, | 
 |         [self _replaceSingleQuotes:script], | 
 |         scriptargs ? scriptargs : @"", | 
 |         with_terminal? "&& echo Exit status: $? && exit 1" : " &"]; | 
 | } | 
 |  | 
 | - (NSArray *) interpreters { return interpreters;}; | 
 |  | 
 | // FileSettingsSource protocol  | 
 | - (NSString *) interpreter { return interpreter;}; | 
 | - (BOOL) honourhashbang { return honourhashbang; }; | 
 | - (BOOL) debug { return debug;}; | 
 | - (BOOL) verbose { return verbose;}; | 
 | - (BOOL) inspect { return inspect;}; | 
 | - (BOOL) optimize { return optimize;}; | 
 | - (BOOL) nosite { return nosite;}; | 
 | - (BOOL) tabs { return tabs;}; | 
 | - (NSString *) others { return others;}; | 
 | - (NSString *) scriptargs { return scriptargs;}; | 
 | - (BOOL) with_terminal { return with_terminal;}; | 
 |  | 
 | @end |