1 | //␊ |
2 | // BootSetupController.mm␊ |
3 | // ChameleonPrefPane␊ |
4 | //␊ |
5 | // Created by Rekursor on 1/22/10.␊ |
6 | //␊ |
7 | ␊ |
8 | #import "BootSetupController.h"␊ |
9 | #import "ChameleonPrefPane.h"␊ |
10 | #import "TableViewsController.h"␊ |
11 | #import "ShellProcess.h"␊ |
12 | #import "PartitionInfoManager.h"␊ |
13 | #include "ChameleonPropertyList.h"␊ |
14 | ␊ |
15 | static const char cPartDescSep = ';'; // partition descriptor separator␊ |
16 | ␊ |
17 | static BootSetupController *gInstance = NULL;␊ |
18 | ␊ |
19 | @implementation BootSetupController␊ |
20 | ␊ |
21 | //--------------------------------------------------------------------------␊ |
22 | - (id) init␊ |
23 | {␊ |
24 | ␉self = [super init];␊ |
25 | ␉return (gInstance = self);␊ |
26 | }␉␊ |
27 | ␊ |
28 | //--------------------------------------------------------------------------␊ |
29 | - (void) addOptionsDesc␊ |
30 | {␊ |
31 | BootProp::instance().addOptionDesc(mDefaultPartition, mDefaultPartitionText, OptionString, "Default Partition", "");␊ |
32 | BootProp::instance().addOptionDesc(mHidePartition , mHidePartitionText, OptionString, "Hide Partition", "");␊ |
33 | BootProp::instance().addOptionDesc(mRenamePartition , mRenamePartitionText, OptionString, "Rename Partition", "");␊ |
34 | }␊ |
35 | ␊ |
36 | //--------------------------------------------------------------------------␊ |
37 | - (void) refreshLockStates␊ |
38 | {␊ |
39 | ␉// non boot config options (not automatized)␊ |
40 | [PreferencesControllerBase refreshLockState: mSwapHD01 ];␊ |
41 | [PreferencesControllerBase refreshLockState: mSwapHD02 ];␊ |
42 | [PreferencesControllerBase refreshLockState: mFreezeParts ];␊ |
43 | [PreferencesControllerBase refreshLockState: mInjectFrozenParts ];␊ |
44 | [PreferencesControllerBase refreshLockState: mBootConfigPath ];␊ |
45 | [PreferencesControllerBase refreshLockState: mBootConfigPathText ];␊ |
46 | }␊ |
47 | ␊ |
48 | //--------------------------------------------------------------------------␊ |
49 | - (void) setDefaultsValues: (NSMutableDictionary*) dict␊ |
50 | {␊ |
51 | ␉[dict setObject:[[[NSNumber alloc] initWithBool: false] autorelease] forKey: keySwapHD01];␊ |
52 | ␉[dict setObject:[[[NSNumber alloc] initWithBool: false] autorelease] forKey: keySwapHD02];␊ |
53 | ␉[dict setObject:[[[NSNumber alloc] initWithBool: false] autorelease] forKey: keyUseFrozenParts];␊ |
54 | ␉[dict setObject:[[[NSNumber alloc] initWithBool: false] autorelease] forKey: keyUseFrozenParts];␊ |
55 | ␉[dict setObject:[[[NSString alloc] initWithString: @""] autorelease] forKey: keyForceBootConfigPath];␊ |
56 | }␊ |
57 | //--------------------------------------------------------------------------␊ |
58 | -(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict␊ |
59 | {␊ |
60 | ␉[mSwapHD01 setIntValue: [[dict objectForKey:␉keySwapHD01] intValue]];␊ |
61 | ␉[mSwapHD02 setIntValue: [[dict objectForKey:␉keySwapHD02] intValue]];␊ |
62 | ␉[mFreezeParts setIntValue: [[dict objectForKey: keyUseFrozenParts] intValue] ];␊ |
63 | ␉id obj = [dict objectForKey: keyForceBootConfigPath];␊ |
64 | ␉[mBootConfigPathText setStringValue: obj ? obj : @"" ];␊ |
65 | ␉int val = (obj && [[mBootConfigPathText stringValue] length] >0 ? 1 : 0);␊ |
66 | ␉[mBootConfigPath setIntValue: val];␊ |
67 | ␉[dict setObject:[NSString stringWithString: [mBootConfigPathText stringValue]] ␊ |
68 | ␉␉␉ forKey: keyForceBootConfigPath];␊ |
69 | ␉[mBootConfigPathText setEnabled: val ? true : false]; ␊ |
70 | ␉[mBootConfigPathText setEditable: val ? true : false];␊ |
71 | ␉[mBootExtraPathText setStringValue: [[mBootConfigPathText stringValue] stringByDeletingLastPathComponent]];␊ |
72 | ␉[mBootCdbootPathText setStringValue: [[mBootConfigPathText stringValue] stringByDeletingLastPathComponent]];␊ |
73 | }␊ |
74 | ␊ |
75 | //--------------------------------------------------------------------------␊ |
76 | - (void) loadFrozenParts␊ |
77 | {␊ |
78 | ␉// iterate for all entries to add␊ |
79 | ␉char keyPartN[32] = ""; ␊ |
80 | ␉int k=0;␊ |
81 | ␉␊ |
82 | ␉NSMutableArray* partList = (NSMutableArray*) [PartsInfoMgr parts];␊ |
83 | ␉[partList removeAllObjects];␊ |
84 | ␉␊ |
85 | ␉for (int i=0; i< [[self preferencesParts] count]; i++)␊ |
86 | ␉{␊ |
87 | ␉␉// get the key␊ |
88 | ␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
89 | ␉␉NSString* obj = [[self preferencesParts] objectForKey: [NSString stringWithUTF8String: keyPartN] ];␊ |
90 | ␉␉// assign this key if valid␊ |
91 | ␉␉if (obj!=nil && [obj length]>0)␊ |
92 | ␉␉{␊ |
93 | ␉␉␉PartitionInfoElement* p = [[[PartitionInfoElement alloc] init] autorelease];␊ |
94 | ␉␉␉// parse string␊ |
95 | ␉␉␉NSArray* words = [obj componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString: @";"]];␊ |
96 | ␉␉␉k=0;␊ |
97 | ␉␉␉int diskNum=0, partNum=0;␊ |
98 | ␉␉␉for (NSString * word in words)␊ |
99 | ␉␉␉{␊ |
100 | ␉␉␉␉switch (k) {␊ |
101 | ␉␉␉␉␉case 0: // disk number␊ |
102 | ␉␉␉␉␉␉diskNum = [word intValue] ;␊ |
103 | ␉␉␉␉␉␉[ p setDiskNumber:diskNum];␊ |
104 | ␉␉␉␉␉␉break;␊ |
105 | ␉␉␉␉␉case 1: // partition number␊ |
106 | ␉␉␉␉␉␉partNum = [word intValue] ;␊ |
107 | ␉␉␉␉␉␉[ p setPartitionNumber: partNum];␉␉␉␉␉␉␉␊ |
108 | ␉␉␉␉␉␉break;␊ |
109 | ␉␉␉␉␉case 2: // volume label␊ |
110 | ␉␉␉␉␉␉[p setVName: word];␊ |
111 | ␉␉␉␉␉␉[p setVAliasName: word];␊ |
112 | ␉␉␉␉␉␉break;␊ |
113 | ␉␉␉␉␉case 3: // fstype␊ |
114 | ␉␉␉␉␉␉[p setVKind: word];␊ |
115 | ␉␉␉␉␉␉break;␊ |
116 | ␉␉␉␉␉case 4: // vUUID␊ |
117 | ␉␉␉␉␉␉[p setVUUID: word];␊ |
118 | ␉␉␉␉␉␉break;␊ |
119 | ␉␉␉␉␉default:␊ |
120 | ␉␉␉␉␉␉break;␊ |
121 | ␉␉␉␉}␊ |
122 | ␉␉␉␉k++;␊ |
123 | ␉␉␉}␊ |
124 | ␉␉␉␊ |
125 | ␉␉␉[partList addObject:p];␊ |
126 | ␉␉}␊ |
127 | ␉}␊ |
128 | ␉// for mgr to refresh hide and rename attributes␊ |
129 | ␉[PartsInfoMgr hideParts:nil];␊ |
130 | ␉[PartsInfoMgr renameParts:nil];␊ |
131 | ␉␊ |
132 | }␊ |
133 | ␊ |
134 | //--------------------------------------------------------------------------␊ |
135 | - (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst;␊ |
136 | {␊ |
137 | ␉//if(!BootProp::instance().isValid()) return;␊ |
138 | ␉if ([mFreezeParts intValue]==0) ␊ |
139 | ␉␉[PartsInfoMgr reload];␊ |
140 | ␉else ␊ |
141 | ␉␉[self loadFrozenParts ];␊ |
142 | ␉␊ |
143 | ␉if (bSwap)␊ |
144 | ␉{␊ |
145 | ␉␉[PartsInfoMgr swapHD:iSrc with: iDst ];␉␊ |
146 | ␉}␊ |
147 | ␉␊ |
148 | ␉[ [self chameleon] selectDefaultPartition];␊ |
149 | ␉␊ |
150 | }␊ |
151 | ␊ |
152 | //--------------------------------------------------------------------------␊ |
153 | - (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst␊ |
154 | {␊ |
155 | ␉␊ |
156 | ␉if( val>0 && ![[BootSetupController instance]->mFreezeParts intValue]) //on␊ |
157 | ␉{␊ |
158 | ␉␉[self swapDisks: true src:isrc dst:idst ];␊ |
159 | ␉}␊ |
160 | ␉else␊ |
161 | ␉{␊ |
162 | ␉␉[self swapDisks: false src:isrc dst:idst ];␊ |
163 | ␉}␊ |
164 | ␉␊ |
165 | ␉if(doSave)␊ |
166 | ␉{␊ |
167 | ␉␉if (isrc==0 && idst==1)␊ |
168 | ␉␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD01];␊ |
169 | ␉␉if (isrc==0 && idst==2)␊ |
170 | ␉␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD02];␊ |
171 | ␉␉[ [self chameleon] savePreferences:[self preferencesFile] ];␊ |
172 | ␉}␊ |
173 | ␉␊ |
174 | ␉[[[TableViewsController instance] partitionsTable] reloadData];␊ |
175 | ␉[[[TableViewsController instance] partitionsTable] scrollRowToVisible: 0];␊ |
176 | }␊ |
177 | ␊ |
178 | ␊ |
179 | //--------------------------------------------------------------------------␊ |
180 | - (IBAction)onInjectPartsToFreeze: (id)sender␊ |
181 | {␊ |
182 | ␉int size = [[PartsInfoMgr parts] count ];␊ |
183 | ␉NSString * title = GetLocStrDef(@"Freeze_Dialog", @"msgbox", @"Inject Partitions to Freeze Configuration");␊ |
184 | ␉if (!size) ␊ |
185 | ␉{ // nothing to inject␊ |
186 | ␉␉NSRunAlertPanel(title, ␊ |
187 | ␉␉␉␉␉␉GetLocStrDef(@"Freeze_NoPart", @"msgbox", @"No current partitions to inject, did you check boot config file ?"),␊ |
188 | ␉␉␉␉␉␉@"OK", nil,nil);␊ |
189 | ␉␉return;␊ |
190 | ␉}␊ |
191 | ␉// generate the parts list in preferences proplist␊ |
192 | ␉NSInteger n = NSRunAlertPanel(title, ␊ |
193 | ␉␉␉␉␉␉␉␉ GetLocStrDef(@"Freeze_Overwrite", @"msgbox",␊ |
194 | ␉␉␉␉␉␉␉␉␉␉␉ @"Are you sure you want to overwrite your Freeze settings with current partition list ?"),␊ |
195 | ␉␉␉␉␉␉␉␉ @"OK", @"Cancel",nil);␊ |
196 | ␉if (n==1)␊ |
197 | ␉{␊ |
198 | ␉␉// populate the dictionary with the current partitions␊ |
199 | ␉␉␊ |
200 | ␉␉// empty dictionary and update key in parent:␊ |
201 | ␉␉[[self preferencesFile] removeObjectForKey: keyPartitionsList];␊ |
202 | ␉␉[[self preferencesParts] removeAllObjects ];␊ |
203 | ␉␉␊ |
204 | ␉␉// iterate for all entries to add␊ |
205 | ␉␉char partDesc[256]="";␊ |
206 | ␉␉char keyPartN[32] = "";␊ |
207 | ␉␉for (int i=0; i< size; i++)␊ |
208 | ␉␉{␊ |
209 | ␉␉␉␊ |
210 | ␉␉␉PartitionInfoElement* p = [PartsInfoMgr objectAtIndex:i];␊ |
211 | ␉␉␉␊ |
212 | ␉␉␉// format the partition key and descriptor string␊ |
213 | ␉␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
214 | ␉␉␉␊ |
215 | ␉␉␉snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s%c%s",␊ |
216 | ␉␉␉␉␉ [p diskNumber], cPartDescSep,␊ |
217 | ␉␉␉␉␉ [p partitionNumber], cPartDescSep,␊ |
218 | ␉␉␉␉␉ [[p vAliasName] UTF8String], cPartDescSep,␊ |
219 | ␉␉␉␉␉ [[p vKind] UTF8String], cPartDescSep, ␊ |
220 | ␉␉␉␉␉ [[p vUUID] UTF8String]);␊ |
221 | ␉␉␉␊ |
222 | ␉␉␉// write it to the dictionary␊ |
223 | ␉␉␉NSString * key = [NSString stringWithUTF8String: keyPartN];␊ |
224 | ␉␉␉NSString * desc = [NSString stringWithUTF8String: partDesc]; ␊ |
225 | ␉␉␉[[self preferencesParts] setObject: desc forKey: key];␊ |
226 | ␉␉}␊ |
227 | ␉␉[[self preferencesFile] setObject: [self preferencesParts] forKey: keyPartitionsList];␊ |
228 | ␉␉[self savePreferences ];␊ |
229 | ␉}␊ |
230 | }␊ |
231 | ␊ |
232 | //--------------------------------------------------------------------------␊ |
233 | - (IBAction) onForceBootConfigPath: (id) sender␊ |
234 | {␊ |
235 | NSString * f;␊ |
236 | ␊ |
237 | ␉if (sender == mBootConfigPath)␊ |
238 | ␉{␊ |
239 | ␉␉int val = [mBootConfigPath intValue];␊ |
240 | ␉␉[mBootConfigPathText setEnabled: val ? true : false]; ␊ |
241 | ␉␉[mBootConfigPathText setEditable: val ? true : false];␊ |
242 | ␉␉␊ |
243 | ␉␉if (val) ␊ |
244 | ␉␉{␊ |
245 | ␉␉␉f = [self selectPlistFile: @"org.chameleon.Boot.plist"];␊ |
246 | ␉␉␉if(f)␊ |
247 | ␉␉␉{␊ |
248 | ␉␉␉␉[mBootConfigPathText setStringValue:f];␊ |
249 | ␉␉␉␉[mBootExtraPathText setStringValue: [f stringByDeletingLastPathComponent] ];␊ |
250 | ␉␉␉␉[mBootCdbootPathText setStringValue: [f stringByDeletingLastPathComponent]];␊ |
251 | ␉␉␉}␊ |
252 | ␉␉}␊ |
253 | ␉␉␉␊ |
254 | ␊ |
255 | ␉␉[[self preferencesFile] setObject: ␊ |
256 | ␉␉ val ? [mBootConfigPathText stringValue] : [NSString stringWithUTF8String: ""] ␊ |
257 | ␉␉␉␉␉␉␉␉ forKey: keyForceBootConfigPath];␊ |
258 | ␉␉␊ |
259 | ␉}␊ |
260 | ␉else{␊ |
261 | ␉␉f = [mBootConfigPathText stringValue];␊ |
262 | ␉␉[[self preferencesFile] setObject:f forKey: keyForceBootConfigPath];␊ |
263 | ␉␉[mBootExtraPathText setStringValue: [f stringByDeletingLastPathComponent] ];␊ |
264 | ␉␉[mBootCdbootPathText setStringValue: [f stringByDeletingLastPathComponent]];␊ |
265 | ␉}␊ |
266 | ␉[self savePreferences ];␊ |
267 | ␉BootProp::instance().cleanup();␊ |
268 | ␉[[ChameleonPrefPane instance ] initBootConfig];␊ |
269 | }␊ |
270 | ␊ |
271 | //--------------------------------------------------------------------------␊ |
272 | -(void) updateHideRen: (bool) loadOptions␊ |
273 | {␊ |
274 | NSString* partsToHide = [mHidePartition intValue] ? [mHidePartitionText stringValue] : @"";␊ |
275 | NSString* partsToRename = [mRenamePartition intValue] ? [mRenamePartitionText stringValue] : @"";␊ |
276 | ␊ |
277 | if (loadOptions)␊ |
278 | [PreferencesControllerBase loadOptionsFromBootFile ];␊ |
279 | NSLog(@"parts to hide=%@ to ren=%@", partsToHide, partsToRename);␊ |
280 | [PartsInfoMgr reloadWithHideSpec: partsToHide andRenameSpec: partsToRename ];␊ |
281 | ␊ |
282 | }␊ |
283 | ␊ |
284 | //--------------------------------------------------------------------------␊ |
285 | -(IBAction) onCheckButtonChange: (NSButton*) sender␊ |
286 | {␊ |
287 | ␉// IMPROVE ME: Should automatize the callback/load/save mechanism ␊ |
288 | ␉// for the preferences file like the bootConfig file␊ |
289 | ␉if (sender == mSwapHD01 || sender == mSwapHD02)␊ |
290 | ␉{␊ |
291 | ␉␉[PartsInfoMgr resetSwapping];␊ |
292 | ␉␉[self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1];␊ |
293 | ␉␉[self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2];␊ |
294 | ␉}␊ |
295 | ␉else if (sender == mFreezeParts)␊ |
296 | ␉{␊ |
297 | ␉␉bool val = !![sender intValue];␊ |
298 | ␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts];␊ |
299 | ␉␉[[self chameleon] savePreferences: [self preferencesFile]];␊ |
300 | ␉␉[ self onCheckButtonChange: mSwapHD01];␊ |
301 | ␉}␊ |
302 | ␉else if (sender == mInjectFrozenParts)␊ |
303 | ␉{␊ |
304 | ␉␉[self onInjectPartsToFreeze: mInjectFrozenParts];␊ |
305 | ␉}␉␊ |
306 | ␉else if (sender == mDefaultPartition )␊ |
307 | ␉{ // sync with other panels␊ |
308 | ␉␉[self handleSender:sender];␊ |
309 | [ [self chameleon] selectDefaultPartition];␊ |
310 | ␊ |
311 | ␉}␉␊ |
312 | ␉else if (sender == mHidePartition || sender == mRenamePartition )␊ |
313 | ␉{ // sync with other panels␊ |
314 | [self updateHideRen: false ];␊ |
315 | ␉␉[self handleSender:sender];␊ |
316 | ␉}␉␊ |
317 | ␉else if (sender == mBootConfigPath || (NSTextField*)sender == mBootConfigPathText)␊ |
318 | ␉{ // sync with other panels␊ |
319 | ␉␉[self onForceBootConfigPath: sender];␊ |
320 | ␉}␉␊ |
321 | ␉else if (sender == mBootExtraPath || (NSTextField*)sender == mBootExtraPathText)␊ |
322 | ␉{ // sync with other panels␊ |
323 | ␉␉[self onForceBootConfigPath: sender];␊ |
324 | ␉}␉␊ |
325 | ␉else if (sender == mBootCdbootPath || (NSTextField*)sender == mBootCdbootPathText)␊ |
326 | ␉{ // sync with other panels␊ |
327 | ␉␉[self onForceBootConfigPath: sender];␊ |
328 | ␉}␉␊ |
329 | ␉// Handle BootOptions generically:␊ |
330 | ␉else ␊ |
331 | ␉␉[self handleSender:sender];␊ |
332 | }␊ |
333 | //--------------------------------------------------------------------------␊ |
334 | -(IBAction) onTextFiedChange: (NSTextField*) sender␊ |
335 | {␊ |
336 | ␉if ( sender == mDefaultPartitionText || sender == mHidePartitionText ||␊ |
337 | ␉␉␉ sender == mRenamePartitionText )␊ |
338 | ␉{␊ |
339 | ␊ |
340 | ␉␉[self handleSender:sender];␊ |
341 | [self updateHideRen: true ];␊ |
342 | ␊ |
343 | ␉␉[self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1];␊ |
344 | ␉␉[self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2];␊ |
345 | ␊ |
346 | if (sender == mDefaultPartitionText)␊ |
347 | [ [self chameleon] selectDefaultPartition];␊ |
348 | ␉}␊ |
349 | ␉else if (sender == mBootConfigPathText)␊ |
350 | ␉{␊ |
351 | ␉␉[self onForceBootConfigPath: sender];␊ |
352 | ␉}␊ |
353 | }␊ |
354 | //--------------------------------------------------------------------------␊ |
355 | - (IBAction) onCdBootConfigPath: (id) sender␊ |
356 | {␊ |
357 | ␉if ( sender == mBootCdbootPath)␊ |
358 | ␉{␊ |
359 | ␉␉NSString * dir = [self selectDirectory:@"/"];␊ |
360 | ␉␉if (dir!=nil)␊ |
361 | ␉␉␉[mBootCdbootPathText setStringValue: dir];␊ |
362 | ␉}␊ |
363 | ␉␉␉␊ |
364 | }␊ |
365 | //--------------------------------------------------------------------------␊ |
366 | - (IBAction) onExtraConfigPath: (id) sender␊ |
367 | {␊ |
368 | ␉if ( sender == mBootExtraPath)␊ |
369 | ␉{␊ |
370 | ␉␉NSString * dir = [self selectDirectory:@"/"];␊ |
371 | ␉␉if (dir!=nil)␊ |
372 | ␉␉␉[mBootExtraPathText setStringValue: dir];␊ |
373 | ␉}␊ |
374 | }␊ |
375 | ␊ |
376 | //--------------------------------------------------------------------------␊ |
377 | - (IBAction) onCreateBootCD: (id) sender␊ |
378 | {␊ |
379 | ␉// using rek modified rohan script from Lizard boot cd creator:␊ |
380 | ␉NSString* destination = @"~/Desktop/Chameleon";␊ |
381 | ␉NSString* pathTask = [self getResourcePath:@"cdBootCreator" ofType:@"sh"];␊ |
382 | ␉NSString* pathExtra = [mBootExtraPathText stringValue];␊ |
383 | ␉NSString* pathCdboot = [mBootCdbootPathText stringValue];␊ |
384 | ␉NSMutableArray* arr = [[NSMutableArray alloc] init];␊ |
385 | ␉bool result;␊ |
386 | ␉␊ |
387 | ␉if ( ␊ |
388 | ␉␉pathTask!=nil && [pathTask length] > 0 ␊ |
389 | ␉␉&& pathExtra !=nil && [pathExtra length] > 0 ␊ |
390 | ␉␉&& pathCdboot !=nil && [pathCdboot length] > 0 ␊ |
391 | ␉ )␊ |
392 | ␉{␊ |
393 | ␉␉[arr addObject: pathExtra];␊ |
394 | ␉␉[arr addObject: pathCdboot];␉␊ |
395 | ␉␉result = [self executeTaskAndWaitForTermination: pathTask withArgs: arr];␊ |
396 | ␉␉if (result)␊ |
397 | ␉␉{␊ |
398 | ␉␉␉[self msgBoxInfo:␊ |
399 | ␉␉␉ [NSString stringWithFormat: ␊ |
400 | ␉␉␉ GetLocStrDef(@"CD_Success", @"msgbox", @"Boot cd creator script successfully executed. BootCD.iso created in %@."), ␊ |
401 | ␉␉␉ destination]];␊ |
402 | ␉␉}␊ |
403 | ␉␉else␊ |
404 | ␉␉␉[self msgBoxError:␊ |
405 | ␉␉␉␉GetLocStrDef(@"CD_Failure", @"msgbox", @"ERROR: Couldn't execute boot cd creator script successfully!")];␊ |
406 | ␉}␊ |
407 | ␉␊ |
408 | ␉[arr release];␊ |
409 | }␊ |
410 | //--------------------------------------------------------------------------␊ |
411 | + (BootSetupController *)instance { return(gInstance);}␊ |
412 | ␊ |
413 | @end␊ |
414 | |