1/*
2  Hatari - PrefsController.m
3
4  This file is distributed under the GNU General Public License, version 2
5  or at your option any later version. Read the file gpl.txt for details.
6
7  Preferences window controller implementation file
8
9  Feb-Mar 2006, Sébastien Molines - Created
10  Jan 2006, Sébastien Molines - Updated for recent emulator updates
11  Miguel SARO, J. VERNET
12*/
13// bOKDialog = Dialog_MainDlg(&bForceReset, &bLoadedSnapshot);   // prise des préférences
14// TODO: Set the default paths to MacOS-friendly values
15// TODO: Move hardcoded string to localizable resources (e.g. string "Reset the emulator?")
16
17
18#import "PrefsController.h"
19#import "Shared.h"
20
21#include "main.h"
22#include "configuration.h"
23#include "change.h"
24#include "dialog.h"
25#include "file.h"
26#include "floppy.h"
27#include "screen.h"
28#include "sdlgui.h"
29#include "paths.h"
30#include "keymap.h"
31
32// Macros to transfer data between Cocoa controls and Hatari data structures
33
34// de l'affichage vers la structure  (saveAllControls)
35#define EXPORT_TEXTFIELD(mutablStrng, target) [mutablStrng getCString:target maxLength:sizeof((target))-1 encoding:NSASCIIStringEncoding]
36#define EXPORT_NTEXTFIELD(nstextfield, target) target = [nstextfield intValue]
37#define EXPORT_SWITCH(nsbutton, target) target = ([(nsbutton) state] == NSOnState)
38#define EXPORT_RADIO(nsmatrix, target) target = [[(nsmatrix) selectedCell] tag]
39#define EXPORT_DROPDOWN(nspopupbutton, target) target = [[(nspopupbutton) selectedItem] tag]
40#define EXPORT_SLIDER(nsslider, target) target = [(nsslider) intValue]
41
42// la structure vers l'affichage (setAllControls)
43#define IMPORT_TEXTFIELD(nstextfield, mutablStrng, source) [mutablStrng setString:[NSString stringWithCString:(source) encoding:NSASCIIStringEncoding]] ; [nstextfield setStringValue:[NSApp pathUser:mutablStrng]]
44#define IMPORT_NTEXTFIELD(nstextfield, source) [(nstextfield) setIntValue:(source)]
45#define IMPORT_SWITCH(nsbutton, source) [(nsbutton) setState:((source))? NSOnState : NSOffState]
46#define IMPORT_RADIO(nsmatrix, source) [(nsmatrix) selectCellWithTag:(source)]
47#define IMPORT_DROPDOWN(nspopupbutton, source) [(nspopupbutton) selectItemAtIndex:[(nspopupbutton) indexOfItemWithTag:(source)]]
48#define IMPORT_SLIDER(nsslider,source) [(nsslider) setIntValue:source]
49
50#define INITIAL_DIR(dossier) [dossier length] < 2 ? @"~" : dossier
51
52// Back up of the current configuration parameters
53//
54CNF_PARAMS CurrentParams;
55
56
57// Keys to be listed in the Joysticks dropdowns
58SDLKey Preferences_KeysForJoysticks[] =
59{
60	SDLK_BACKSPACE,
61	SDLK_TAB,
62	SDLK_CLEAR,
63	SDLK_RETURN,
64	SDLK_PAUSE,
65	SDLK_ESCAPE,
66	SDLK_SPACE,
67	SDLK_EXCLAIM,
68	SDLK_QUOTEDBL,
69	SDLK_HASH,
70	SDLK_DOLLAR,
71	SDLK_AMPERSAND,
72	SDLK_QUOTE,
73	SDLK_LEFTPAREN,
74	SDLK_RIGHTPAREN,
75	SDLK_ASTERISK,
76	SDLK_PLUS,
77	SDLK_COMMA,
78	SDLK_MINUS,
79	SDLK_PERIOD,
80	SDLK_SLASH,
81	SDLK_0,
82	SDLK_1,
83	SDLK_2,
84	SDLK_3,
85	SDLK_4,
86	SDLK_5,
87	SDLK_6,
88	SDLK_7,
89	SDLK_8,
90	SDLK_9,
91	SDLK_COLON,
92	SDLK_SEMICOLON,
93	SDLK_LESS,
94	SDLK_EQUALS,
95	SDLK_GREATER,
96	SDLK_QUESTION,
97	SDLK_AT,
98	SDLK_LEFTBRACKET,
99	SDLK_BACKSLASH,
100	SDLK_RIGHTBRACKET,
101	SDLK_CARET,
102	SDLK_UNDERSCORE,
103	SDLK_BACKQUOTE,
104	SDLK_a,
105	SDLK_b,
106	SDLK_c,
107	SDLK_d,
108	SDLK_e,
109	SDLK_f,
110	SDLK_g,
111	SDLK_h,
112	SDLK_i,
113	SDLK_j,
114	SDLK_k,
115	SDLK_l,
116	SDLK_m,
117	SDLK_n,
118	SDLK_o,
119	SDLK_p,
120	SDLK_q,
121	SDLK_r,
122	SDLK_s,
123	SDLK_t,
124	SDLK_u,
125	SDLK_v,
126	SDLK_w,
127	SDLK_x,
128	SDLK_y,
129	SDLK_z,
130	SDLK_DELETE,
131	SDLK_KP0,
132	SDLK_KP1,
133	SDLK_KP2,
134	SDLK_KP3,
135	SDLK_KP4,
136	SDLK_KP5,
137	SDLK_KP6,
138	SDLK_KP7,
139	SDLK_KP8,
140	SDLK_KP9,
141	SDLK_KP_PERIOD,
142	SDLK_KP_DIVIDE,
143	SDLK_KP_MULTIPLY,
144	SDLK_KP_MINUS,
145	SDLK_KP_PLUS,
146	SDLK_KP_ENTER,
147	SDLK_KP_EQUALS,
148	SDLK_UP,
149	SDLK_DOWN,
150	SDLK_RIGHT,
151	SDLK_LEFT,
152	SDLK_INSERT,
153	SDLK_HOME,
154	SDLK_END,
155	SDLK_PAGEUP,
156	SDLK_PAGEDOWN,
157	SDLK_F1,
158	SDLK_F2,
159	SDLK_F3,
160	SDLK_F4,
161	SDLK_F5,
162	SDLK_F6,
163	SDLK_F7,
164	SDLK_F8,
165	SDLK_F9,
166	SDLK_F10,
167	SDLK_F11,
168	SDLK_F12,
169	SDLK_F13,
170	SDLK_F14,
171	SDLK_F15,
172	SDLK_NUMLOCK,
173	SDLK_CAPSLOCK,
174	SDLK_SCROLLOCK,
175	SDLK_RSHIFT,
176	SDLK_LSHIFT,
177	SDLK_RCTRL,
178	SDLK_LCTRL,
179	SDLK_RALT,
180	SDLK_LALT,
181	SDLK_RMETA,
182	SDLK_LMETA,
183#if !WITH_SDL2
184	SDLK_LSUPER,
185	SDLK_RSUPER,
186	SDLK_COMPOSE,
187	SDLK_BREAK,
188	SDLK_EURO,
189#endif
190	SDLK_MODE,
191	SDLK_HELP,
192	SDLK_PRINT,
193	SDLK_SYSREQ,
194	SDLK_MENU,
195	SDLK_POWER,
196	SDLK_UNDO
197};
198
199size_t Preferences_cKeysForJoysticks = sizeof(Preferences_KeysForJoysticks) / sizeof(Preferences_KeysForJoysticks[0]);
200
201#define DLGSOUND_11KHZ      0
202#define DLGSOUND_12KHZ      1
203#define DLGSOUND_16KHZ      2
204#define DLGSOUND_22KHZ      3
205#define DLGSOUND_25KHZ      4
206#define DLGSOUND_32KHZ      5
207#define DLGSOUND_44KHZ      6
208#define DLGSOUND_48KHZ      7
209#define DLGSOUND_50KHZ      8
210
211static const int nSoundFreqs[] =
212{
213	11025,
214	12517,
215	16000,
216	22050,
217	25033,
218	32000,
219	44100,
220	48000,
221	50066
222};
223
224
225@implementation PrefsController
226
227char szPath[FILENAME_MAX];
228
229
230- (IBAction)finished:(id)sender
231{
232	Main_RequestQuit(0) ;
233}
234
235/*-----------------------------------------------------------------------*/
236/*                                                                       */
237/*  Helper method for Choose buttons                                     */
238/*  Returns: TRUE is the user selected a path, FALSE if he/she aborted   */
239/*-----------------------------------------------------------------------*/
240- (BOOL)choosePathForControl:(NSTextField*)textField chooseDirectories:(BOOL)chooseDirectories defaultInitialDir:(NSString*)defaultInitialDir
241																					mutString:(NSMutableString *)mutString what:(NSArray *)what
242{
243	NSString *directoryToOpen ;
244	NSString *fileToPreselect ;
245	NSString *newPath ;
246
247	if ((mutString != nil) && ([mutString length] > 2))
248	 {	directoryToOpen = [mutString stringByDeletingLastPathComponent];			// There is existing path: we use it.
249		fileToPreselect = [mutString lastPathComponent]; }
250	else
251	 {	directoryToOpen = [defaultInitialDir stringByExpandingTildeInPath];			// no path: use user's directory
252		fileToPreselect = nil; } ;
253
254	newPath = [NSApp hopenfile:chooseDirectories defoDir:directoryToOpen defoFile:fileToPreselect types:what];
255	if ([newPath length] != 0)														// user canceled if empty
256	{
257		[mutString setString:[NSString stringWithString:newPath]] ;					// save this path
258		[textField setStringValue:[NSApp pathUser:newPath]];						// show localized path
259		return YES;
260	} ;
261
262	return NO;																		// Selection aborted
263}
264
265
266//-----------------------------------------------------------------------*/
267//
268//  Helper method to insert a floppy image
269//  TODO: Add code to restrict to known file types
270//
271/*-----------------------------------------------------------------------*/
272
273- (void)insertFloppyImageIntoDrive:(int)drive forTextField:(NSTextField*)floppyTextField  realPath:(NSMutableString *)realPath
274{
275	if ([self choosePathForControl:floppyTextField  chooseDirectories:NO defaultInitialDir:imgeDir
276											mutString:realPath  what:[NSArray arrayWithObjects:allF,nil]])
277
278		Floppy_SetDiskFileName(drive, [realPath cStringUsingEncoding:NSASCIIStringEncoding], NULL);
279		// Insert the floppy image at this path  ????
280}
281
282
283//-----------------------------------------------------------------------------
284- (NSString *)initial:(NSString *)route
285{
286BOOL flag1, flag2;
287
288	if ((route==nil) || ([route length]==0))  return @"~" ;
289	flag1 = [[NSFileManager defaultManager] fileExistsAtPath:route isDirectory:&flag2] ;
290	if (flag1 && !flag2)
291		return route ;
292	return [route stringByDeletingLastPathComponent] ;
293}
294
295//
296//  Methods for all the "Choose" buttons
297//
298- (IBAction)chooseCartridgeImage:(id)sender;
299{
300	[self choosePathForControl: cartridgeImage chooseDirectories:NO defaultInitialDir:[self initial:cartridge]			// cartridge
301												mutString:cartridge  what:[NSArray arrayWithObjects:allC,nil]];
302}
303
304
305- (IBAction)chooseDefaultImagesLocation:(id)sender
306{
307	[self choosePathForControl: defaultImagesLocation chooseDirectories:YES defaultInitialDir:[self initial:imgeDir]	// images location
308												mutString:imgeDir  what:nil];
309}
310
311- (IBAction)chooseFloppyImageA:(id)sender
312{
313	[self insertFloppyImageIntoDrive:0 forTextField:floppyImageA realPath:floppyA];										// floppy A
314}
315
316- (IBAction)chooseFloppyImageB:(id)sender
317{
318	[self insertFloppyImageIntoDrive:1 forTextField:floppyImageB realPath:floppyB];										// floppy B
319}
320
321- (IBAction)chooseGemdosImage:(id)sender																				// directory for Gemdos
322{
323	[self choosePathForControl: gemdosImage chooseDirectories:YES defaultInitialDir:INITIAL_DIR(gemdos)					// gemdos
324												mutString:gemdos  what:nil] ;
325	if ([gemdos length] >2 ) [gemdosImage setStringValue:[NSApp pathUser:gemdos]] ;
326}
327
328- (IBAction)chooseHdImage:(id)sender
329{
330	[self choosePathForControl: hdImage chooseDirectories:NO defaultInitialDir:[self initial:hrdDisk]					// HD image ?
331												mutString:hrdDisk  what:[NSArray arrayWithObjects:@"img",@"hdv",nil]] ;
332}
333
334- (IBAction)chooseIdeMasterHdImage:(id)sender
335{
336	[self choosePathForControl: ideMasterHdImage chooseDirectories:NO defaultInitialDir:[self initial:masterIDE]		// IDE master
337												mutString:masterIDE  what:[NSArray arrayWithObject:@"hdv"]];
338}
339
340- (IBAction)chooseIdeSlaveHdImage:(id)sender
341{
342	[self choosePathForControl: ideSlaveHdImage chooseDirectories:NO defaultInitialDir:[self initial:slaveIDE]			// IDE slave
343												mutString:slaveIDE  what:[NSArray arrayWithObject:@"hdv"]];
344}
345
346- (IBAction)chooseKeyboardMappingFile:(id)sender
347{
348	[self choosePathForControl: keyboardMappingFile chooseDirectories:NO defaultInitialDir:[self initial:keyboard]		// keyboard mapping
349												mutString:keyboard  what:[NSArray arrayWithObjects:@"txt",@"map",nil]];
350}
351
352- (IBAction)chooseMidiOutputFile:(id)sender
353{
354	[self choosePathForControl: writeMidiToFile chooseDirectories:NO defaultInitialDir:[self initial:midiOut]			// midi output
355												mutString:midiOut  what:[NSArray arrayWithObject:@"mid"]];
356}
357
358- (IBAction)choosePrintToFile:(id)sender
359{
360	[self choosePathForControl: printToFile chooseDirectories:NO defaultInitialDir:[self initial:printit]				// print to file
361												mutString:printit  what:[NSArray arrayWithObject:@"prn"]];
362}
363
364- (IBAction)chooseRS232InputFile:(id)sender
365{
366	[self choosePathForControl: readRS232FromFile chooseDirectories:NO defaultInitialDir:[self initial:rs232In]			// RS232 input
367												mutString:rs232In  what:nil];
368}
369
370- (IBAction)chooseRS232OutputFile:(id)sender
371{
372	[self choosePathForControl: writeRS232ToFile chooseDirectories:NO defaultInitialDir:[self initial:rs232Out]			// RS232 output
373												mutString:rs232Out  what:nil];
374}
375
376- (IBAction)chooseTosImage:(id)sender;
377{
378	[self choosePathForControl: tosImage chooseDirectories:NO defaultInitialDir:[self initial:TOS]						// TOS image
379												mutString:TOS  what:[NSArray arrayWithObjects:allT,nil]];
380}
381
382
383/*-----------------------------------------------------------------------*/
384/*                                                                       */
385/*  Methods for the "Eject" buttons                                      */
386/*-----------------------------------------------------------------------*/
387- (IBAction)ejectFloppyA:(id)sender
388{
389	Floppy_SetDiskFileNameNone(0);
390
391	// Refresh  control & mutablestring
392	[floppyImageA setStringValue:@""];
393	[floppyA setString:@""] ;
394}
395
396- (IBAction)ejectFloppyB:(id)sender
397{
398	Floppy_SetDiskFileNameNone(1);
399
400	// Refresh  control & mutablestring
401	[floppyImageB setStringValue:@""];
402	[floppyB setString:@""] ;
403}
404
405- (IBAction)ejectGemdosImage:(id)sender
406{
407	// Clear the control. Later. saveAllControls will set the ConfigureParams accordingly to signal this is ejected
408	[gemdosImage setStringValue:@""];
409	[gemdos setString:@""] ;
410}
411
412- (IBAction)ejectHdImage:(id)sender
413{
414	// Clear the control. Later. saveAllControls will set the ConfigureParams accordingly to signal this is ejected
415	[hdImage setStringValue:@""];
416	[hrdDisk setString:@""] ;
417}
418
419- (IBAction)ejectIdeMasterHdImage:(id)sender
420{
421	// Clear the control. Later. saveAllControls will set the ConfigureParams accordingly to signal this is ejected
422	[ideMasterHdImage setStringValue:@""];
423	[masterIDE setString:@""] ;
424}
425
426- (IBAction)ejectIdeSlaveHdImage:(id)sender
427{
428	// Clear the control. Later. saveAllControls will set the ConfigureParams accordingly to signal this is ejected
429	[ideSlaveHdImage setStringValue:@""];
430	[slaveIDE setString:@""] ;
431}
432
433/*-----------------------------------------------------------------------*/
434/**
435 * Methods for the "Load Config" button
436 */
437
438- (IBAction)loadConfigFrom:(id)sender
439{
440	NSArray		*lesURLs  ;
441	NSString	*ru ;
442	BOOL		btOk ;
443
444	ru = [NSString stringWithCString:(Paths_GetHatariHome()) encoding:NSASCIIStringEncoding] ;
445	[opnPanel setAllowedFileTypes:[NSArray arrayWithObject:@"cfg"]] ;
446	[opnPanel setCanChooseDirectories: NO];
447	[opnPanel setCanChooseFiles: YES];
448	[opnPanel setAccessoryView:partage] ;
449
450	if ([opnPanel respondsToSelector:@selector(setDirectoryURL:)])
451	 {	[opnPanel setDirectoryURL:[NSURL fileURLWithPath:ru isDirectory:YES]] ;
452		[opnPanel setNameFieldStringValue:@"hatari"] ;
453		btOk = [opnPanel runModal] == NSOKButton ;										// Ok ?
454	 }
455	else
456		btOk = [opnPanel runModalForDirectory:ru file:@"hatari"] == NSOKButton	;
457
458	if (!btOk)  return ;																// Cancel
459
460	lesURLs = [opnPanel URLs] ;
461	if ((lesURLs == nil) || ([lesURLs count] == 0))
462		return ;
463
464	[configNm setString:[[lesURLs objectAtIndex:0] path]] ;
465
466		// Make a non-const C string out of it
467	[configNm getCString:sConfigFileName maxLength:FILENAME_MAX encoding:NSASCIIStringEncoding];
468
469		// Load the config into ConfigureParams
470	Configuration_Load(sConfigFileName);
471
472		// Refresh all the controls to match ConfigureParams
473	[self setAllControls];
474}
475
476/**
477 * Methods for the "Save Config" button  (bottom preference window)
478 */
479- (IBAction)saveConfigAs:(id)sender
480{
481NSString	*ru ;
482BOOL		btOk ;
483
484	ru = [NSString stringWithCString:(Paths_GetHatariHome()) encoding:NSASCIIStringEncoding] ;
485	[savPanel setAllowedFileTypes:[NSArray arrayWithObject:@"cfg"]] ;
486	[savPanel setAccessoryView:hartage] ;
487
488	if ([savPanel respondsToSelector:@selector(setDirectoryURL:)])
489	 {	[savPanel setDirectoryURL:[NSURL fileURLWithPath:ru isDirectory:YES]] ;			// Since OS X 10.6
490		[savPanel setNameFieldStringValue:@"hatari"] ;
491		btOk = [savPanel runModal] == NSOKButton ;											// Ok ?
492	 }
493	else
494		btOk = [savPanel runModalForDirectory:ru file:@"hatari"] == NSOKButton ;		// avant 10.6
495
496	if (!btOk)
497		return ;                                                                        // Cancel
498
499	[configNm setString:[[savPanel URL] path]];
500
501																	// Make a non-const C string out of it
502	[configNm getCString:sConfigFileName maxLength:FILENAME_MAX encoding:NSASCIIStringEncoding];
503	[self saveAllControls] ;										// Save the config from ConfigureParams
504	Configuration_Save();											// [self configSave:configNm] ;
505}
506
507- (IBAction)aller:(id)sender
508{
509NSString  *defaultDirectory ;
510
511	defaultDirectory = [NSString stringWithCString:(Paths_GetHatariHome()) encoding:NSASCIIStringEncoding] ;
512	if ([opnPanel respondsToSelector:@selector(setDirectoryURL:)])
513		[opnPanel setDirectoryURL:[NSURL fileURLWithPath:defaultDirectory isDirectory:YES]] ;
514	else
515		[opnPanel setDirectory:defaultDirectory] ;
516}
517
518- (IBAction)halle:(id)sender
519{
520NSString  *defaultDirectory ;
521
522	defaultDirectory = [NSString stringWithCString:(Paths_GetHatariHome()) encoding:NSASCIIStringEncoding] ;
523	if ([savPanel respondsToSelector:@selector(setDirectoryURL:)])
524		[savPanel setDirectoryURL:[NSURL fileURLWithPath:defaultDirectory isDirectory:YES]] ;
525	else
526		[savPanel setDirectory:defaultDirectory] ;
527}
528
529
530/*-----------------------------------------------------------------------*/
531/*
532  Commits and closes         Ok button in preferences window
533*/
534- (IBAction)commitAndClose:(id)sender
535{
536
537	// The user clicked OK
538	[self saveAllControls];
539
540	[window close] ;
541
542
543}
544
545// Populate Joystick key dropdown
546
547- (void)initKeysDropDown:(NSPopUpButton*)dropDown
548{
549	[dropDown removeAllItems];
550	unsigned int i;
551	for (i = 0; i < Preferences_cKeysForJoysticks; i++)
552	{
553		SDLKey key = Preferences_KeysForJoysticks[i];
554		const char* szKeyName = SDL_GetKeyName(key);
555		[dropDown addItemWithTitle:[[NSString stringWithCString:szKeyName encoding:NSASCIIStringEncoding] capitalizedString]];
556		[[dropDown lastItem] setTag:key];
557	}
558}
559
560
561/*-----------------------------------------------------------------------*/
562/*
563  Displays the Preferences dialog   Ouverture de la fenêtre des préférences
564*/
565- (IBAction)loadPrefs:(id)sender
566{
567	[configNm setString:[NSString stringWithCString:sConfigFileName encoding:NSASCIIStringEncoding]] ;
568
569	if (!bInitialized)
570	{
571		// Note: These inits cannot be done in awakeFromNib as by this time SDL is not yet initialized.
572
573		// Fill the keyboard dropdowns
574		[self initKeysDropDown:joystickUp];
575		[self initKeysDropDown:joystickRight];
576		[self initKeysDropDown:joystickDown];
577		[self initKeysDropDown:joystickLeft];
578		[self initKeysDropDown:joystickFire];
579
580		// Get and store the number of real joysticks
581		cRealJoysticks = SDL_NumJoysticks();
582
583		// Fill the real joysticks dropdown, if any are available
584		if (cRealJoysticks > 0)
585		{
586			[realJoystick removeAllItems];
587			int i;
588			for (i = 0; i < cRealJoysticks; i++)
589			{
590				const char* szJoystickName = SDL_JoystickName(i);
591				[realJoystick addItemWithTitle:[[NSString stringWithCString:szJoystickName encoding:NSASCIIStringEncoding] capitalizedString]];
592				[[realJoystick lastItem] setTag:i];
593			}
594		}
595		else	// No real joysticks: Disable the controls
596		{
597			[[joystickMode cellWithTag:1] setEnabled:FALSE];
598			[realJoystick setEnabled:FALSE];
599		}
600
601		bInitialized = true;
602	}
603
604
605	// Backup of configuration settings to CurrentParams (which we will only
606	// commit back to the configuration settings if choosing OK)
607	CurrentParams = ConfigureParams;
608	applyChanges=false;
609
610	[self setAllControls];
611
612	// Display the window
613	ModalWrapper *mw=[[ModalWrapper alloc] init];
614
615	[mw runModal:window];
616
617	[mw release];								// */
618
619	// solve bug screen-reset: close and kill preference windows before
620	// M. Saro, 2013
621
622    //if(Ok button in preferences Windows)
623    {
624        // Check if change need reset
625        if (Change_DoNeedReset(&CurrentParams, &ConfigureParams))
626        {
627            applyChanges = [NSApp myAlerte:NSInformationalAlertStyle Txt:nil firstB:localize(@"Don't reset") alternateB:localize(@"Reset")
628											otherB:nil informativeTxt:localize(@"Must be reset") ] == NSAlertAlternateReturn ;
629			if (applyChanges)
630				Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, true) ;
631            else
632                ConfigureParams = CurrentParams;    //Restore backup params
633        }
634        else
635            Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, false); //Apply config without reset
636    }
637    // else // not OK button
638    // {
639    //      ConfigureParams = CurrentParams; //Restore backup params
640    // }
641
642}
643
644/*-----------------------------------------------------------------------*/
645/*
646  Updates the controls following a change in the joystick selection
647*/
648- (IBAction)changeViewedJoystick:(id)sender
649{
650	// Save the pre-joystick controls, as we are about to change them
651	[self saveJoystickControls];
652
653	// Refresh the per-joystick controls
654	[self setJoystickControls];
655
656	// Update the controls' enabled states
657	[self updateEnabledStates:self];
658}
659
660
661/*-----------------------------------------------------------------------*/
662/*
663  Initializes all controls, transfert des préférences dans la fenêtre
664*/
665- (void)setAllControls
666{
667
668	// Import the floppy paths into their controls.
669	IMPORT_TEXTFIELD(floppyImageA, floppyA, ConfigureParams.DiskImage.szDiskFileName[0]);				// le A
670	IMPORT_TEXTFIELD(floppyImageB, floppyB, ConfigureParams.DiskImage.szDiskFileName[1]);				// le B
671
672	// Import all the preferences into their controls
673	IMPORT_TEXTFIELD(cartridgeImage, cartridge, ConfigureParams.Rom.szCartridgeImageFileName);
674	IMPORT_TEXTFIELD(defaultImagesLocation, imgeDir, ConfigureParams.DiskImage.szDiskImageDirectory);
675	IMPORT_TEXTFIELD(keyboardMappingFile, keyboard, ConfigureParams.Keyboard.szMappingFileName);
676	IMPORT_TEXTFIELD(printToFile, printit, ConfigureParams.Printer.szPrintToFileName);
677	IMPORT_TEXTFIELD(tosImage, TOS, ConfigureParams.Rom.szTosImageFileName);
678	IMPORT_TEXTFIELD(configFile, configNm, sConfigFileName);
679	IMPORT_TEXTFIELD(readRS232FromFile, rs232In, ConfigureParams.RS232.szInFileName);
680	IMPORT_TEXTFIELD(writeRS232ToFile, rs232Out, ConfigureParams.RS232.szOutFileName);
681
682	IMPORT_SWITCH(autoInsertB, ConfigureParams.DiskImage.bAutoInsertDiskB);
683	IMPORT_SWITCH(blitter, ConfigureParams.System.bBlitter);
684	IMPORT_SWITCH(bootFromHD, ConfigureParams.HardDisk.bBootFromHardDisk);
685	IMPORT_SWITCH(captureOnChange, ConfigureParams.Screen.bCrop);
686	IMPORT_RADIO(colorDepth, ConfigureParams.Screen.nVdiColors);
687	IMPORT_SWITCH(compatibleCpu, ConfigureParams.System.bCompatibleCpu);
688	IMPORT_RADIO(cpuClock, ConfigureParams.System.nCpuFreq);
689	IMPORT_RADIO(cpuType, ConfigureParams.System.nCpuLevel);
690	IMPORT_SWITCH(enableMidi, ConfigureParams.Midi.bEnableMidi);
691	IMPORT_SWITCH(enablePrinter, ConfigureParams.Printer.bEnablePrinting);
692	IMPORT_SWITCH(enableRS232, ConfigureParams.RS232.bEnableRS232);
693	IMPORT_SWITCH(enableSound, ConfigureParams.Sound.bEnableSound);
694	IMPORT_DROPDOWN(frameSkip, ConfigureParams.Screen.nFrameSkips);
695	IMPORT_RADIO(keyboardMapping, ConfigureParams.Keyboard.nKeymapType);
696	IMPORT_RADIO(machineType, ConfigureParams.System.nMachineType);
697	IMPORT_RADIO(monitor, ConfigureParams.Screen.nMonitorType);
698	IMPORT_SWITCH(patchTimerD, ConfigureParams.System.bPatchTimerD);
699	IMPORT_RADIO(ramSize, ConfigureParams.Memory.nMemorySize);
700	IMPORT_SWITCH(realTime, ConfigureParams.System.bRealTimeClock);
701	IMPORT_SWITCH(fastFDC, ConfigureParams.DiskImage.FastFloppy);
702	IMPORT_SWITCH(useBorders, ConfigureParams.Screen.bAllowOverscan);
703	IMPORT_SWITCH(useVDIResolution, ConfigureParams.Screen.bUseExtVdiResolutions);
704	IMPORT_RADIO(floppyWriteProtection, ConfigureParams.DiskImage.nWriteProtection);
705	IMPORT_RADIO(HDWriteProtection, ConfigureParams.HardDisk.nWriteProtection);
706	// IMPORT_SWITCH(zoomSTLowRes, ConfigureParams.Screen.bZoomLowRes);
707	IMPORT_SWITCH(showStatusBar, ConfigureParams.Screen.bShowStatusbar);
708	IMPORT_DROPDOWN(enableDSP,ConfigureParams.System.nDSPType);
709
710	// 12/04/2010
711	IMPORT_SWITCH(falconTTRatio, ConfigureParams.Screen.bAspectCorrect);
712	IMPORT_SWITCH(fullScreen, ConfigureParams.Screen.bFullScreen);
713	IMPORT_SWITCH(ledDisks, ConfigureParams.Screen.bShowDriveLed);
714	IMPORT_SWITCH(keepDesktopResolution, ConfigureParams.Screen.bKeepResolution);
715
716	//v1.6.1
717	IMPORT_SWITCH(FastBootPatch,ConfigureParams.System.bFastBoot);
718	IMPORT_RADIO(YMVoicesMixing,ConfigureParams.Sound.YmVolumeMixing);
719
720	//deal with the Max Zoomed Stepper
721	IMPORT_NTEXTFIELD(maxZoomedWidth, ConfigureParams.Screen.nMaxWidth);
722	IMPORT_NTEXTFIELD(maxZoomedHeight, ConfigureParams.Screen.nMaxHeight);
723
724	[widthStepper setDoubleValue:[maxZoomedWidth intValue]];
725	[heightStepper setDoubleValue:[maxZoomedHeight intValue]];
726
727
728	[(force8bpp) setState:((ConfigureParams.Screen.nForceBpp==8))? NSOnState : NSOffState];
729
730
731	int i;
732
733	for (i = 0; i <= DLGSOUND_50KHZ-DLGSOUND_11KHZ; i++)
734	{
735		if (ConfigureParams.Sound.nPlaybackFreq > nSoundFreqs[i]-500
736		    && ConfigureParams.Sound.nPlaybackFreq < nSoundFreqs[i]+500)
737		{
738			[playbackQuality selectCellWithTag:(i)];
739			break;
740		}
741	}
742
743
744	if (ConfigureParams.Screen.nVdiWidth >= 1024)
745		[resolution selectCellWithTag:(2)];
746	else if (ConfigureParams.Screen.nVdiWidth >= 768)
747		[resolution selectCellWithTag:(1)];
748	else
749		[resolution selectCellWithTag:(0)];
750
751	// If the HD flag is set, load the HD path, otherwise make it blank
752	if (ConfigureParams.Acsi[0].bUseDevice)
753	{
754		IMPORT_TEXTFIELD(hdImage, hrdDisk, ConfigureParams.Acsi[0].sDeviceFile);
755	}
756	else
757	{
758		[hdImage setStringValue:@""]; [hrdDisk setString:@""] ;
759	}
760
761	// If the IDE HD flag is set, load the IDE HD path, otherwise make it blank
762	//Master
763	if (ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage)
764	{
765		IMPORT_TEXTFIELD(ideMasterHdImage, masterIDE, ConfigureParams.HardDisk.szIdeMasterHardDiskImage);
766	}
767	else
768	{
769		[ideMasterHdImage setStringValue:@""]; [masterIDE setString:@""] ;
770	}
771	//Slave
772	if (ConfigureParams.HardDisk.bUseIdeSlaveHardDiskImage)
773	{
774		IMPORT_TEXTFIELD(ideSlaveHdImage, slaveIDE, ConfigureParams.HardDisk.szIdeSlaveHardDiskImage);
775	}
776	else
777	{
778		[ideSlaveHdImage setStringValue:@""]; [slaveIDE setString:@""] ;
779	}
780
781	// If the Gemdos flag is set, load the Gemdos path, otherwise make it blank
782	if (ConfigureParams.HardDisk.bUseHardDiskDirectories)
783	{
784		[gemdos setString:[NSString stringWithCString:(ConfigureParams.HardDisk.szHardDiskDirectories[0]) encoding:NSASCIIStringEncoding]] ;
785//		[gemdosImage setStringValue:[NSApp pathUser:[gemdos stringByDeletingLastPathComponent]]] ;
786		[gemdosImage setStringValue:[NSApp pathUser:gemdos]] ;
787	}
788	else
789	{
790		[gemdosImage setStringValue:@""]; [gemdos setString:@""];
791	}
792
793	// Set the per-joystick controls
794	[self setJoystickControls];
795
796	// Update the controls' enabled states
797	[self updateEnabledStates:self];
798}
799
800
801/*------------------------------------------------------------------------*/
802/* Updates the enabled states of controls who depend on other controls    */
803/**************************************************************************/
804
805- (IBAction)updateEnabledStates:(id)sender
806{
807	// Joystick key controls are only enabled if "Use keyboard" is selected
808	int nJoystickMode;
809	EXPORT_RADIO(joystickMode, nJoystickMode);
810	BOOL bUsingKeyboard = (nJoystickMode == JOYSTICK_KEYBOARD);
811	[joystickUp setEnabled:bUsingKeyboard];
812	[joystickRight setEnabled:bUsingKeyboard];
813	[joystickDown setEnabled:bUsingKeyboard];
814	[joystickLeft setEnabled:bUsingKeyboard];
815	[joystickFire setEnabled:bUsingKeyboard];
816
817	// Resolution and colour depth depend on Extended GEM VDI resolution
818	BOOL bUsingVDI;
819	EXPORT_SWITCH(useVDIResolution, bUsingVDI);
820	[resolution setEnabled:bUsingVDI];
821	[colorDepth setEnabled:bUsingVDI];
822
823	// Playback quality depends on enable sound
824	BOOL bSoundEnabled;
825	EXPORT_SWITCH(enableSound, bSoundEnabled);
826	[playbackQuality setEnabled:bSoundEnabled];
827}
828
829
830/*-----------------------------------------------------------------------*/
831/* Updates the joystick controls to match the new joystick selection     */
832/*************************************************************************/
833
834- (void)setJoystickControls
835{
836	// Get and persist the ID of the newly selected joystick
837	EXPORT_DROPDOWN(currentJoystick, nCurrentJoystick);
838
839	// Data validation: If the JoyID is out of bounds, correct it and, if set to use real joystick, change to disabled
840	if ( (ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoyId < 0)
841	|| (ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoyId >= cRealJoysticks) )
842	{
843		ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoyId = 0;
844		if (ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode == JOYSTICK_REALSTICK)
845		{
846			ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode = JOYSTICK_DISABLED;
847		}
848	}
849
850	// Don't change the realJoystick dropdown if none is available (to keep "(None available)" selected)
851	if (cRealJoysticks > 0)
852	{
853		IMPORT_DROPDOWN(realJoystick, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoyId);
854	}
855
856	IMPORT_RADIO(joystickMode, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode);
857	IMPORT_DROPDOWN(joystickUp, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeUp);
858	IMPORT_DROPDOWN(joystickRight, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeRight);
859	IMPORT_DROPDOWN(joystickDown, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeDown);
860	IMPORT_DROPDOWN(joystickLeft, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeLeft);
861	IMPORT_DROPDOWN(joystickFire, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeFire);
862	IMPORT_SWITCH(enableAutoFire, ConfigureParams.Joysticks.Joy[nCurrentJoystick].bEnableAutoFire);
863}
864
865
866/*-----------------------------------------------------------------------*/
867/*   Saves the setting for the joystick currently being viewed           */
868- (void)saveJoystickControls
869{
870	EXPORT_RADIO(joystickMode, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode);
871	EXPORT_DROPDOWN(realJoystick, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nJoyId);
872	EXPORT_DROPDOWN(joystickUp, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeUp);
873	EXPORT_DROPDOWN(joystickRight, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeRight);
874	EXPORT_DROPDOWN(joystickDown, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeDown);
875	EXPORT_DROPDOWN(joystickLeft, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeLeft);
876	EXPORT_DROPDOWN(joystickFire, ConfigureParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeFire);
877	EXPORT_SWITCH(enableAutoFire, ConfigureParams.Joysticks.Joy[nCurrentJoystick].bEnableAutoFire);
878}
879
880
881/*-----------------------------------------------------------------------*/
882/* Saves the settings for all controls                                   */
883- (void)saveAllControls
884{
885	// Export the preference controls into their vars
886
887	EXPORT_TEXTFIELD(cartridge, ConfigureParams.Rom.szCartridgeImageFileName);
888	EXPORT_TEXTFIELD(imgeDir, ConfigureParams.DiskImage.szDiskImageDirectory);
889	EXPORT_TEXTFIELD(keyboard, ConfigureParams.Keyboard.szMappingFileName);
890	EXPORT_TEXTFIELD(printit, ConfigureParams.Printer.szPrintToFileName);
891	EXPORT_TEXTFIELD(rs232In, ConfigureParams.RS232.szInFileName);
892	EXPORT_TEXTFIELD(TOS, ConfigureParams.Rom.szTosImageFileName);
893	EXPORT_TEXTFIELD(midiOut, ConfigureParams.Midi.sMidiOutFileName);
894	EXPORT_TEXTFIELD(rs232Out, ConfigureParams.RS232.szOutFileName);
895
896	//EXPORT_TEXTFIELD(cartridgeImage, ConfigureParams.Rom.szCartridgeImageFileName);
897
898	EXPORT_SWITCH(autoInsertB, ConfigureParams.DiskImage.bAutoInsertDiskB);
899	EXPORT_SWITCH(blitter, ConfigureParams.System.bBlitter);
900	EXPORT_SWITCH(bootFromHD, ConfigureParams.HardDisk.bBootFromHardDisk);
901	EXPORT_SWITCH(captureOnChange, ConfigureParams.Screen.bCrop);
902	EXPORT_RADIO(colorDepth, ConfigureParams.Screen.nVdiColors);
903	EXPORT_SWITCH(compatibleCpu, ConfigureParams.System.bCompatibleCpu);
904	EXPORT_RADIO(cpuClock, ConfigureParams.System.nCpuFreq);
905	EXPORT_RADIO(cpuType, ConfigureParams.System.nCpuLevel);
906	EXPORT_SWITCH(enableMidi, ConfigureParams.Midi.bEnableMidi);
907	EXPORT_SWITCH(enablePrinter, ConfigureParams.Printer.bEnablePrinting);
908	EXPORT_SWITCH(enableRS232, ConfigureParams.RS232.bEnableRS232);
909	EXPORT_SWITCH(enableSound, ConfigureParams.Sound.bEnableSound);
910	EXPORT_DROPDOWN(frameSkip, ConfigureParams.Screen.nFrameSkips);
911	EXPORT_RADIO(keyboardMapping, ConfigureParams.Keyboard.nKeymapType);
912	EXPORT_RADIO(machineType, ConfigureParams.System.nMachineType);
913	EXPORT_RADIO(monitor, ConfigureParams.Screen.nMonitorType);
914	EXPORT_SWITCH(patchTimerD, ConfigureParams.System.bPatchTimerD);
915	EXPORT_RADIO(ramSize, ConfigureParams.Memory.nMemorySize);
916	EXPORT_SWITCH(realTime, ConfigureParams.System.bRealTimeClock);
917	EXPORT_SWITCH(fastFDC, ConfigureParams.DiskImage.FastFloppy);
918	EXPORT_SWITCH(useBorders, ConfigureParams.Screen.bAllowOverscan);
919	EXPORT_SWITCH(useVDIResolution, ConfigureParams.Screen.bUseExtVdiResolutions);
920	EXPORT_RADIO(floppyWriteProtection, ConfigureParams.DiskImage.nWriteProtection);
921	EXPORT_RADIO(HDWriteProtection, ConfigureParams.HardDisk.nWriteProtection);
922	// EXPORT_SWITCH(zoomSTLowRes, ConfigureParams.Screen.bZoomLowRes);
923	EXPORT_SWITCH(showStatusBar,ConfigureParams.Screen.bShowStatusbar);
924	EXPORT_DROPDOWN(enableDSP,ConfigureParams.System.nDSPType);
925
926	EXPORT_SWITCH(falconTTRatio, ConfigureParams.Screen.bAspectCorrect);
927	EXPORT_SWITCH(fullScreen, ConfigureParams.Screen.bFullScreen);
928	EXPORT_SWITCH(ledDisks, ConfigureParams.Screen.bShowDriveLed);
929	EXPORT_SWITCH(keepDesktopResolution, ConfigureParams.Screen.bKeepResolution);
930
931	//v1.6.1
932	EXPORT_SWITCH(FastBootPatch,ConfigureParams.System.bFastBoot);
933	EXPORT_RADIO(YMVoicesMixing,ConfigureParams.Sound.YmVolumeMixing);
934
935	EXPORT_NTEXTFIELD(maxZoomedWidth, ConfigureParams.Screen.nMaxWidth);
936	EXPORT_NTEXTFIELD(maxZoomedHeight, ConfigureParams.Screen.nMaxHeight);
937
938	ConfigureParams.Screen.nForceBpp = ([force8bpp state] == NSOnState) ? 8 : 0;
939
940	ConfigureParams.Sound.nPlaybackFreq = nSoundFreqs[[[playbackQuality selectedCell] tag]];
941
942	switch ([[resolution selectedCell] tag])
943	{
944	 case 0:
945		ConfigureParams.Screen.nVdiWidth = 640;
946		ConfigureParams.Screen.nVdiHeight = 480;
947		break;
948	 case 1:
949		ConfigureParams.Screen.nVdiWidth = 800;
950		ConfigureParams.Screen.nVdiHeight = 600;
951		break;
952	 case 2:
953		ConfigureParams.Screen.nVdiWidth = 1024;
954		ConfigureParams.Screen.nVdiHeight = 768;
955		break;
956	}
957
958	// Define the HD flag, and export the HD path if one is selected
959	if ([hrdDisk length] > 0)
960	{
961		EXPORT_TEXTFIELD(hrdDisk, ConfigureParams.Acsi[0].sDeviceFile);
962		ConfigureParams.Acsi[0].bUseDevice = true;
963	}
964	else
965	{
966		ConfigureParams.Acsi[0].bUseDevice = false;
967	}
968
969	// Define the IDE HD flag, and export the IDE HD path if one is selected
970	if ([masterIDE length] > 0)
971	{
972		EXPORT_TEXTFIELD(masterIDE, ConfigureParams.HardDisk.szIdeMasterHardDiskImage);
973		ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage = YES;
974	}
975	else
976	{
977		ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage = NO;
978	}
979
980	// IDE Slave
981	if ([slaveIDE length] > 0)
982	{
983		EXPORT_TEXTFIELD(slaveIDE, ConfigureParams.HardDisk.szIdeSlaveHardDiskImage);
984		ConfigureParams.HardDisk.bUseIdeSlaveHardDiskImage = YES;
985	}
986	else
987	{
988		ConfigureParams.HardDisk.bUseIdeSlaveHardDiskImage = NO;
989	}
990
991	// Define the Gemdos flag, and export the Gemdos path if one is selected
992	if ([gemdos length] > 0)
993	{
994		EXPORT_TEXTFIELD(gemdos, ConfigureParams.HardDisk.szHardDiskDirectories[0]);
995		ConfigureParams.HardDisk.bUseHardDiskDirectories = YES;
996	}
997	else
998	{
999		ConfigureParams.HardDisk.bUseHardDiskDirectories = NO;
1000	}
1001
1002	// Save the per-joystick controls
1003	[self saveJoystickControls];
1004}
1005
1006// Max Zoomed Adjust
1007
1008- (IBAction) setWidth:(id)sender;
1009{
1010	NSLog(@"Change Max Zoom width: %d", [sender intValue]);
1011    [maxZoomedWidth setIntValue: [sender intValue]];
1012}
1013
1014- (IBAction) setHeight:(id)sender;
1015{
1016	NSLog(@"Change Max Zoom height: %d", [sender intValue]);
1017    [maxZoomedHeight setIntValue: [sender intValue]];
1018}
1019
1020+(PrefsController *)prefs
1021{
1022	static PrefsController *prefs = nil;
1023	if (!prefs)
1024		prefs = [[PrefsController alloc] init];
1025
1026	return prefs;
1027}																	// */
1028
1029- (void)awakeFromNib
1030{
1031	cartridge = [NSMutableString stringWithCapacity:50] ; [cartridge setString:@""] ; [cartridge retain] ;
1032	imgeDir = [NSMutableString stringWithCapacity:50] ; [imgeDir setString:@""] ; [imgeDir retain] ;
1033	floppyA = [NSMutableString stringWithCapacity:50] ; [floppyA setString:@""] ; [floppyA retain] ;
1034	floppyB = [NSMutableString stringWithCapacity:50] ; [floppyB setString:@""] ; [floppyB retain] ;
1035	gemdos = [NSMutableString stringWithCapacity:50] ; [gemdos setString:@""] ; [gemdos retain] ;
1036	hrdDisk = [NSMutableString stringWithCapacity:50] ; [hrdDisk setString:@""] ; [hrdDisk retain] ;
1037	masterIDE = [NSMutableString stringWithCapacity:50] ; [masterIDE setString:@""] ; [masterIDE retain] ;
1038	slaveIDE = [NSMutableString stringWithCapacity:50] ; [slaveIDE setString:@""] ; [slaveIDE retain] ;
1039	keyboard = [NSMutableString stringWithCapacity:50] ; [keyboard setString:@""] ; [keyboard retain] ;
1040	midiOut = [NSMutableString stringWithCapacity:50] ; [midiOut setString:@""] ; [midiOut retain] ;
1041	printit = [NSMutableString stringWithCapacity:50] ; [printit setString:@""] ; [printit retain] ;
1042	rs232In = [NSMutableString stringWithCapacity:50] ; [rs232In setString:@""] ; [rs232In retain] ;
1043	rs232Out = [NSMutableString stringWithCapacity:50] ; [rs232Out setString:@""] ; [rs232Out retain] ;
1044	TOS = [NSMutableString stringWithCapacity:50] ; [TOS setString:@""] ; [TOS retain] ;
1045	configNm = [NSMutableString stringWithCapacity:50] ; [configNm setString:@""] ; [configNm retain] ;
1046	opnPanel = [NSOpenPanel openPanel]; [opnPanel retain] ;
1047	savPanel = [NSSavePanel savePanel]; [savPanel retain] ;
1048}
1049
1050@end
1051