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 | ␊ |
11 | static const char* sPartDescSep = ";"; // cstring version␊ |
12 | static const char cPartDescSep = ';'; // partition descriptor separator␊ |
13 | ␊ |
14 | static BootSetupController *gInstance = NULL;␊ |
15 | ␊ |
16 | @implementation BootSetupController␊ |
17 | ␊ |
18 | //--------------------------------------------------------------------------␊ |
19 | - (id) init␊ |
20 | {␊ |
21 | ␉self = [super init];␊ |
22 | ␉return (gInstance = self);␊ |
23 | }␉␊ |
24 | ␊ |
25 | //--------------------------------------------------------------------------␊ |
26 | - (void) addOptionsDesc␊ |
27 | {␊ |
28 | BootProp::instance().addOptionDesc(mDefaultPartition, mDefaultPartitionText, OptionString, "Default Partition", "");␊ |
29 | BootProp::instance().addOptionDesc(mHidePartition , mHidePartitionText, OptionString, "Hide Partition", "");␊ |
30 | BootProp::instance().addOptionDesc(mRenamePartition , mRenamePartitionText, OptionString, "Rename Partition", "");␊ |
31 | }␊ |
32 | ␊ |
33 | //--------------------------------------------------------------------------␊ |
34 | - (void) refreshLockStates␊ |
35 | {␊ |
36 | ␉// non boot config options (not automatized)␊ |
37 | [PreferencesControllerBase refreshLockState: mSwapHD01 ];␊ |
38 | [PreferencesControllerBase refreshLockState: mSwapHD02 ];␊ |
39 | [PreferencesControllerBase refreshLockState: mFreezeParts ];␊ |
40 | [PreferencesControllerBase refreshLockState: mInjectFrozenParts ];␊ |
41 | [PreferencesControllerBase refreshLockState: mBootConfigPath ];␊ |
42 | [PreferencesControllerBase refreshLockState: mBootConfigPathText ];␊ |
43 | }␊ |
44 | ␊ |
45 | //--------------------------------------------------------------------------␊ |
46 | - (void) setDefaultsValues: (NSMutableDictionary*) dict␊ |
47 | {␊ |
48 | ␉[dict setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD01];␊ |
49 | ␉[dict setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD02];␊ |
50 | ␉[dict setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts];␊ |
51 | ␉[dict setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts];␊ |
52 | ␉[dict setObject:[[NSString alloc] initWithString: @""] forKey: keyForceBootConfigPath];␊ |
53 | }␊ |
54 | //--------------------------------------------------------------------------␊ |
55 | -(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict␊ |
56 | {␊ |
57 | ␉[mSwapHD01 setIntValue: [[dict objectForKey:␉keySwapHD01] intValue]];␊ |
58 | ␉[mSwapHD02 setIntValue: [[dict objectForKey:␉keySwapHD02] intValue]];␊ |
59 | ␉[mFreezeParts setIntValue: [[dict objectForKey: keyUseFrozenParts] intValue] ];␊ |
60 | ␉id obj = [dict objectForKey: keyForceBootConfigPath];␊ |
61 | ␉[mBootConfigPathText setStringValue: obj ? obj : @"" ];␊ |
62 | ␉int val = (obj && [[mBootConfigPathText stringValue] length] >0 ? 1 : 0);␊ |
63 | ␉[mBootConfigPath setIntValue: val];␊ |
64 | ␉[dict setObject:[[NSString alloc] initWithString: [mBootConfigPathText stringValue]] ␊ |
65 | ␉␉␉ forKey: keyForceBootConfigPath];␊ |
66 | ␉[mBootConfigPathText setEnabled: val ? true : false]; ␊ |
67 | ␉[mBootConfigPathText setEditable: val ? true : false];␊ |
68 | ␊ |
69 | }␊ |
70 | ␊ |
71 | //--------------------------------------------------------------------------␊ |
72 | - (void) loadFrozenParts␊ |
73 | {␊ |
74 | ␉std::vector<PartitionInfo>& partList = partExtractor->editPartList(); //rw␊ |
75 | ␉// iterate for all entries to add␊ |
76 | ␉char keyPartN[32] = ""; ␊ |
77 | ␉char buffer[256]="";␊ |
78 | ␉int k=0;␊ |
79 | ␉␊ |
80 | ␉partList.clear();␊ |
81 | ␉for (int i=0; i< [[self preferencesParts] count]; i++)␊ |
82 | ␉{␊ |
83 | ␉␉// get the key␊ |
84 | ␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
85 | ␉␉NSString* obj = [[self preferencesParts] objectForKey: [[NSString alloc] initWithUTF8String: keyPartN] ];␊ |
86 | ␉␉// assign this key if valid␊ |
87 | ␉␉if (obj!=nil && [obj length]>0)␊ |
88 | ␉␉{␊ |
89 | ␉␉␉PartitionInfo p;␊ |
90 | ␉␉␉// parse string␊ |
91 | ␉␉␉strncpy(buffer, [obj UTF8String], sizeof(buffer)-1);␊ |
92 | ␉␉␉k=0;␊ |
93 | ␉␉␉for(const char* word = strtok(buffer,";"); word; word=strtok(NULL,sPartDescSep),k++)␊ |
94 | ␉␉␉{␊ |
95 | ␉␉␉␉switch (k) {␊ |
96 | ␉␉␉␉␉case 0: // parse disk number␊ |
97 | ␉␉␉␉␉␉if (isdigit(*word)) p.disk(*word-'0');␊ |
98 | ␉␉␉␉␉␉break;␊ |
99 | ␉␉␉␉␉case 1: // parse partition number␊ |
100 | ␉␉␉␉␉␉if (isdigit(*word)) p.partition(*word-'0');␊ |
101 | ␉␉␉␉␉␉break;␊ |
102 | ␉␉␉␉␉case 2: // parse volume label␊ |
103 | ␉␉␉␉␉␉p.label(word);␊ |
104 | ␉␉␉␉␉case 3:␊ |
105 | ␉␉␉␉␉␉p.fsType(word);␊ |
106 | ␉␉␉␉␉␉break;␊ |
107 | ␉␉␉␉␉default:␊ |
108 | ␉␉␉␉␉␉break;␊ |
109 | ␉␉␉␉}␊ |
110 | ␉␉␉}␊ |
111 | ␉␉␉partList.push_back(p);␊ |
112 | ␉␉}␊ |
113 | ␉}␊ |
114 | ␉partExtractor->sortPartList();␊ |
115 | ␉␊ |
116 | }␊ |
117 | ␊ |
118 | //--------------------------------------------------------------------------␊ |
119 | - (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst;␊ |
120 | {␊ |
121 | ␉if(!partExtractor || !BootProp::instance().isValid()) return;␊ |
122 | ␉if (bSwap)␊ |
123 | ␉{␊ |
124 | ␉␉partExtractor->swapHD(iSrc, iDst);␉␊ |
125 | ␉}␊ |
126 | ␉␊ |
127 | ␉if ([mFreezeParts intValue]==0) ␊ |
128 | ␉␉partExtractor->extractPartitions();␊ |
129 | ␉else ␊ |
130 | ␉␉[self loadFrozenParts ];␊ |
131 | ␉␊ |
132 | ␉[ [self chameleon] selectDefaultPartition];␊ |
133 | ␉␊ |
134 | }␊ |
135 | ␊ |
136 | //--------------------------------------------------------------------------␊ |
137 | - (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst␊ |
138 | {␊ |
139 | ␉␊ |
140 | ␉if( val>0 && ![[BootSetupController instance]->mFreezeParts intValue]) //on␊ |
141 | ␉{␊ |
142 | ␉␉[self swapDisks: true src:isrc dst:idst ];␊ |
143 | ␉}␊ |
144 | ␉else␊ |
145 | ␉{␊ |
146 | ␉␉[self swapDisks: false src:isrc dst:idst ];␊ |
147 | ␉}␊ |
148 | ␉␊ |
149 | ␉if(doSave)␊ |
150 | ␉{␊ |
151 | ␉␉if (isrc==0 && idst==1)␊ |
152 | ␉␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD01];␊ |
153 | ␉␉if (isrc==0 && idst==2)␊ |
154 | ␉␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD02];␊ |
155 | ␉␉[ [self chameleon] savePreferences:[self preferencesFile] ];␊ |
156 | ␉}␊ |
157 | ␉␊ |
158 | ␉[[[ChameleonPrefPane instance] partitionsTable] reloadData];␊ |
159 | ␉[[[ChameleonPrefPane instance] partitionsTable] scrollRowToVisible: 0];␊ |
160 | ␉//[self tableViewSelectionDidChange: nil];␊ |
161 | ␉␊ |
162 | }␊ |
163 | ␊ |
164 | ␊ |
165 | //--------------------------------------------------------------------------␊ |
166 | - (IBAction)onInjectPartsToFreeze: (id)sender␊ |
167 | {␊ |
168 | ␉int size = partExtractor ? partExtractor->partList().size() : 0;␊ |
169 | ␉if (!size) ␊ |
170 | ␉{ // nothing to inject␊ |
171 | ␉␉NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", ␊ |
172 | ␉␉␉␉␉␉@"No current partitions to inject, did you check boot config file ?",@"OK", nil,nil);␊ |
173 | ␉␉return;␊ |
174 | ␉}␊ |
175 | ␉// generate the parts list in preferences proplist␊ |
176 | ␉NSInteger n = NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", ␊ |
177 | ␉␉␉␉␉␉␉␉ @"Are you sure you want to overwrite your Freeze settings with current partition list ?",␊ |
178 | ␉␉␉␉␉␉␉␉ @"OK", @"Cancel",nil);␊ |
179 | ␉if (n==1)␊ |
180 | ␉{␊ |
181 | ␉␉// populate the dictionary with the current partitions␊ |
182 | ␉␉␊ |
183 | ␉␉// empty dictionary and update key in parent:␊ |
184 | ␉␉[[self preferencesFile] removeObjectForKey: keyPartitionsList];␊ |
185 | ␉␉[[self preferencesParts] removeAllObjects ];␊ |
186 | ␉␉␊ |
187 | ␉␉// iterate for all entries to add␊ |
188 | ␉␉char partDesc[256]="";␊ |
189 | ␉␉char keyPartN[32] = "";␊ |
190 | ␉␉for (int i=0; i< size; i++)␊ |
191 | ␉␉{␊ |
192 | ␉␉␉␊ |
193 | ␉␉␉const PartitionInfo& p =partExtractor->partList()[i];␊ |
194 | ␉␉␉␊ |
195 | ␉␉␉// format the partition key and descriptor string␊ |
196 | ␉␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
197 | ␉␉␉␊ |
198 | ␉␉␉snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s",␊ |
199 | ␉␉␉␉␉ p.disk(), cPartDescSep,␊ |
200 | ␉␉␉␉␉ p.partition(), cPartDescSep,␊ |
201 | ␉␉␉␉␉ p.clabel(), cPartDescSep,␊ |
202 | ␉␉␉␉␉ p.cfsType());␊ |
203 | ␉␉␉␊ |
204 | ␉␉␉// write it to the dictionary␊ |
205 | ␉␉␉NSString * key = [[NSString alloc] initWithUTF8String: keyPartN];␊ |
206 | ␉␉␉NSString * desc = [[NSString alloc] initWithUTF8String: partDesc]; ␊ |
207 | ␉␉␉[[self preferencesParts] setObject: desc forKey: key];␊ |
208 | ␉␉}␊ |
209 | ␉␉[[self preferencesFile] setObject: [self preferencesParts] forKey: keyPartitionsList];␊ |
210 | ␉␉[self savePreferences ];␊ |
211 | ␉}␊ |
212 | }␊ |
213 | ␊ |
214 | //--------------------------------------------------------------------------␊ |
215 | - (IBAction) onForceBootConfigPath: (id) sender␊ |
216 | {␊ |
217 | ␉if (sender == mBootConfigPath)␊ |
218 | ␉{␊ |
219 | ␉␉int val = [mBootConfigPath intValue];␊ |
220 | ␉␉[mBootConfigPathText setEnabled: val ? true : false]; ␊ |
221 | ␉␉[mBootConfigPathText setEditable: val ? true : false];␊ |
222 | ␉␉␊ |
223 | ␉␉if (val) ␊ |
224 | ␉␉{␊ |
225 | ␉␉␉NSString * f = [self selectPlistFile: @"com.Apple.boot.plist"];␊ |
226 | ␉␉␉if(f)␊ |
227 | ␉␉␉{␊ |
228 | ␉␉␉␉[mBootConfigPathText setStringValue:f];␊ |
229 | ␉␉␉␉[f release];␊ |
230 | ␉␉␉}␊ |
231 | ␉␉}␊ |
232 | ␉␉␉␊ |
233 | ␊ |
234 | ␉␉[[self preferencesFile] setObject: ␊ |
235 | ␉␉ val ? [mBootConfigPathText stringValue] : [[NSString alloc] initWithUTF8String: ""] ␊ |
236 | ␉␉␉␉␉␉␉␉ forKey: keyForceBootConfigPath];␊ |
237 | ␉␉␊ |
238 | ␉}␊ |
239 | ␉else␊ |
240 | ␉␉[[self preferencesFile] setObject: [mBootConfigPathText stringValue] forKey: keyForceBootConfigPath];␊ |
241 | ␉[self savePreferences ];␊ |
242 | ␊ |
243 | ␉␉␊ |
244 | ␉[PreferencesControllerBase loadOptionsFromBootFile ];␊ |
245 | ␊ |
246 | }␊ |
247 | //--------------------------------------------------------------------------␊ |
248 | -(IBAction) onCheckButtonChange: (NSButton*) sender␊ |
249 | {␊ |
250 | ␉// IMPROVE ME: Should automatize the callback/load/save mechanism ␊ |
251 | ␉// for the preferences file like the bootConfig file␊ |
252 | ␉if (sender == mSwapHD01 || sender == mSwapHD02)␊ |
253 | ␉{␊ |
254 | ␉␉partExtractor->resetSwapping();␊ |
255 | ␉␉[self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1];␊ |
256 | ␉␉[self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2];␊ |
257 | ␉}␊ |
258 | ␉else if (sender == mFreezeParts)␊ |
259 | ␉{␊ |
260 | ␉␉bool val = !![sender intValue];␊ |
261 | ␉␉[[self preferencesFile] setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts];␊ |
262 | ␉␉[[self chameleon] savePreferences: [self preferencesFile]];␊ |
263 | ␉␉[ self onCheckButtonChange: mSwapHD01];␊ |
264 | ␉}␊ |
265 | ␉else if (sender == mInjectFrozenParts)␊ |
266 | ␉{␊ |
267 | ␉␉[self onInjectPartsToFreeze: mInjectFrozenParts];␊ |
268 | ␉}␉␊ |
269 | ␉else if (sender == mDefaultPartition || sender == mHidePartition␊ |
270 | ␉␉␉ || sender == mRenamePartition )␊ |
271 | ␉{ // sync with other panels␊ |
272 | ␉␉[self handleSender:sender];␊ |
273 | ␉}␉␊ |
274 | ␉else if (sender == mBootConfigPath || (NSTextField*)sender == mBootConfigPathText)␊ |
275 | ␉{ // sync with other panels␊ |
276 | ␉␉[self onForceBootConfigPath: sender];␊ |
277 | ␉}␉␊ |
278 | ␉// Handle BootOptions generically:␊ |
279 | ␉else ␊ |
280 | ␉␉[self handleSender:sender];␊ |
281 | }␊ |
282 | //--------------------------------------------------------------------------␊ |
283 | -(IBAction) onTextFiedChange: (NSTextField*) sender␊ |
284 | {␊ |
285 | ␉if ( sender == mDefaultPartitionText || sender == mHidePartitionText ||␊ |
286 | ␉␉␉ sender == mRenamePartitionText )␊ |
287 | ␉{␊ |
288 | ␉␉[self handleSender:sender];␊ |
289 | ␊ |
290 | ␉␉[PreferencesControllerBase loadOptionsFromBootFile ];␊ |
291 | ␉␉partExtractor->extractPartitions(␊ |
292 | ␉␉␉␉␉␉␉␉␉␉ [[mHidePartitionText stringValue] UTF8String],␊ |
293 | ␉␉␉␉␉␉␉␉␉␉ [[mRenamePartitionText stringValue] UTF8String]␊ |
294 | ␉␉␉␉␉␉␉␉␉␉ );␊ |
295 | ␉␉[self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1];␊ |
296 | ␉␉[self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2];␊ |
297 | ␉}␉␊ |
298 | }␊ |
299 | ␊ |
300 | //--------------------------------------------------------------------------␊ |
301 | + (BootSetupController *)instance { return(gInstance);}␊ |
302 | ␊ |
303 | @end␊ |
304 | |