1 /*
2 * Prefs_Be.i - Global preferences, Be specific stuff
3 *
4 * Frodo (C) 1994-1997,2002 Christian Bauer
5 */
6
7 #include <InterfaceKit.h>
8 #include <StorageKit.h>
9 #include <Path.h>
10
11
12 // Special colors
13 const rgb_color light_color = {255, 255, 255, 0};
14 const rgb_color fill_color = {216, 216, 216, 0};
15 const rgb_color dark_color = {184, 184, 184, 0};
16
17
18 // Window thread messages
19 const uint32 MSG_OK = 'okok';
20 const uint32 MSG_CANCEL = 'cncl';
21 const uint32 MSG_SPRITES_ON = 'spon';
22 const uint32 MSG_SPRITE_COLLISIONS = 'scol';
23 const uint32 MSG_JOYSTICK_1_ON = 'joy1';
24 const uint32 MSG_JOYSTICK_2_ON = 'joy2';
25 const uint32 MSG_JOYSTICK_SWAP = 'jswp';
26 const uint32 MSG_LIMIT_SPEED = 'lmit';
27 const uint32 MSG_FAST_RESET = 'frst';
28 const uint32 MSG_CIA_IRQ_HACK = 'cirq';
29 const uint32 MSG_SID_FILTERS = 'filt';
30 const uint32 MSG_DOUBLE_SCAN = 'dbls';
31 const uint32 MSG_MAP_SLASH = 'mpsl';
32 const uint32 MSG_EMUL_1541_PROC = '15pr';
33 const uint32 MSG_DRVTYPE_8 = 'drt8';
34 const uint32 MSG_DRVTYPE_9 = 'drt9';
35 const uint32 MSG_DRVTYPE_10 = 'drt:';
36 const uint32 MSG_DRVTYPE_11 = 'drt;';
37 const uint32 MSG_GETDRIVE_8 = 'gtd8';
38 const uint32 MSG_GETDRIVE_9 = 'gtd9';
39 const uint32 MSG_GETDRIVE_10 = 'gtd:';
40 const uint32 MSG_GETDRIVE_11 = 'gtd;';
41 const uint32 MSG_DRIVE_PANEL_RETURNED = 'gdr8';
42 const uint32 MSG_SID_TYPE = 'sidt';
43 const uint32 MSG_REU_SIZE = 'reus';
44 const uint32 MSG_DISPLAY_TYPE = 'dspt';
45
46 const uint32 MSG_OPEN = 'open';
47 const uint32 MSG_SAVE = 'save';
48 const uint32 MSG_SAVE_AS = 'svas';
49 const uint32 MSG_REVERT = 'rvrt';
50 const uint32 MSG_OPEN_PANEL_RETURNED = 'oprt';
51 const uint32 MSG_SAVE_PANEL_RETURNED = 'svrt';
52
53
54 /*
55 * Preferences window class
56 */
57
58 class NumberControl;
59 class PathControl;
60
61 class PrefsWindow : public BWindow {
62 public:
63 PrefsWindow(Prefs *p, bool start, char *path);
64 virtual void MessageReceived(BMessage *msg);
65 virtual bool QuitRequested(void);
66 virtual bool FilterKeyDown(uint32 *aChar, BView **target);
67
68 private:
69 BCheckBox *make_checkbox(BRect frame, char *label, uint32 what, BView *parent);
70 NumberControl *make_number_entry(BRect frame, char *label_text, BView *parent);
71 BPopUpMenu *make_drvtype_popup(BRect frame, uint32 what, BView *parent);
72 PathControl *make_path_entry(BRect frame, char *label, BView *parent);
73 BPopUpMenu *make_sidtype_popup(BRect frame, char *label_text, uint32 what, BView *parent);
74 BPopUpMenu *make_reusize_popup(BRect frame, char *label_text, uint32 what, BView *parent);
75 BPopUpMenu *make_disptype_popup(BRect frame, char *label_text, uint32 what, BView *parent);
76 void set_values(void);
77 void get_values(void);
78 void ghost_controls(void);
79
80 Prefs *prefs;
81
82 BMessenger this_messenger;
83 BFilePanel *open_panel; // For opening prefs
84 BFilePanel *save_panel; // For saving prefs
85 BFilePanel *file_panel; // For D64/T64 drives
86 BFilePanel *dir_panel; // For directory drives
87 int panel_drive_num; // Drive number (0..3) of the file panel
88
89 BButton *g_ok;
90 BButton *g_cancel;
91 NumberControl *g_normal_cycles;
92 NumberControl *g_bad_line_cycles;
93 NumberControl *g_cia_cycles;
94 NumberControl *g_floppy_cycles;
95 NumberControl *g_skip_frames;
96 BPopUpMenu *g_drive_type[4];
97 PathControl *g_drive_path[4];
98 BPopUpMenu *g_sid_type;
99 BPopUpMenu *g_reu_size;
100 BPopUpMenu *g_display_type;
101 BCheckBox *g_sprites_on;
102 BCheckBox *g_sprite_collisions;
103 BCheckBox *g_joystick_1_on;
104 BCheckBox *g_joystick_2_on;
105 BCheckBox *g_joystick_swap;
106 BCheckBox *g_limit_speed;
107 BCheckBox *g_fast_reset;
108 BCheckBox *g_cia_irq_hack;
109 BCheckBox *g_sid_filters;
110 BCheckBox *g_double_scan;
111 BCheckBox *g_map_slash;
112 BCheckBox *g_emul_1541_proc;
113
114 char *prefs_path;
115 bool startup;
116 };
117
118
119 /*
120 * Start preferences editor (asynchronously)
121 * startup = false: Send MSG_PREFS_DONE to application on close
122 * startup = true : Send MSG_STARTUP to application on close if not canceled,
123 * B_QUIT_REQUESTED otherwise
124 * prefs_name points to the file name of the preferences (which may be changed)
125 */
126
ShowEditor(bool startup,char * prefs_name)127 bool Prefs::ShowEditor(bool startup, char *prefs_name)
128 {
129 PrefsWindow *win = new PrefsWindow(this, startup, prefs_name);
130 win->Show();
131 return true;
132 }
133
134
135 /*
136 * Number-only BTextControl
137 */
138
139 // Class definition
140 class NumberControl : public BTextControl {
141 public:
142 NumberControl(BRect frame, float divider, const char *name, const char *label, const char *text, BMessage *message);
143 void SetValue(long value);
144 long Value(void);
145 };
146
147 // Constructor: Allow only digits
NumberControl(BRect frame,float divider,const char * name,const char * label,const char * text,BMessage * message)148 NumberControl::NumberControl(BRect frame, float divider, const char *name, const char *label, const char *text, BMessage *message)
149 : BTextControl(frame, name, label, text, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
150 {
151 SetDivider(divider);
152 for (int c=0; c<256; c++)
153 if (!isdigit(c) && c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
154 ((BTextView *)ChildAt(0))->DisallowChar(c);
155 }
156
157 // Set integer value
SetValue(long value)158 void NumberControl::SetValue(long value)
159 {
160 char str[32];
161 sprintf(str, "%ld", value);
162 SetText(str);
163 }
164
165 // Get integer value
Value(void)166 long NumberControl::Value(void)
167 {
168 return atol(Text());
169 }
170
171
172 /*
173 * Path-entry BTextControl
174 */
175
176 // Class definition
177 class PathControl : public BTextControl {
178 public:
179 PathControl(BRect frame, float divider, const char *name, const char *label, const char *text, BMessage *message);
180 virtual void MessageReceived(BMessage *msg);
181 };
182
183 // Constructor: Disable some keys
PathControl(BRect frame,float divider,const char * name,const char * label,const char * text,BMessage * message)184 PathControl::PathControl(BRect frame, float divider, const char *name, const char *label, const char *text, BMessage *message)
185 : BTextControl(frame, name, label, text, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
186 {
187 SetDivider(divider);
188 for (int c=0; c<' '; c++)
189 if (c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
190 ((BTextView *)ChildAt(0))->DisallowChar(c);
191 }
192
193 // Message received: Look out for dropped refs
MessageReceived(BMessage * msg)194 void PathControl::MessageReceived(BMessage *msg)
195 {
196 if (msg->what == B_SIMPLE_DATA) {
197 entry_ref the_ref;
198 BEntry the_entry;
199
200 // First look for refs
201 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) {
202 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
203 BPath the_path;
204 the_entry.GetPath(&the_path);
205 SetText(the_path.Path());
206 }
207 } else
208 BTextControl::MessageReceived(msg);
209
210 MakeFocus();
211 } else
212 BTextControl::MessageReceived(msg);
213 }
214
215
216 /*
217 * Open preferences window
218 */
219
PrefsWindow(Prefs * p,bool start,char * path)220 PrefsWindow::PrefsWindow(Prefs *p, bool start, char *path) : BWindow(BRect(0, 0, 400, 349), "Frodo Preferences", B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE), this_messenger(this)
221 {
222 int i;
223 prefs = p;
224 startup = start;
225 prefs_path = path;
226
227 // Move window to right position
228 Lock();
229 MoveTo(80, 80);
230
231 // Set up menus
232 BMenuBar *bar = new BMenuBar(Bounds(), "");
233 BMenu *menu = new BMenu("Preferences");
234 BMenuItem *item;
235 menu->AddItem(item = new BMenuItem("About Frodo" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
236 item->SetTarget(be_app);
237 menu->AddItem(new BSeparatorItem);
238 menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS, new BMessage(MSG_OPEN), 'O'));
239 menu->AddItem(new BMenuItem("Save", new BMessage(MSG_SAVE), 'S'));
240 menu->AddItem(new BMenuItem("Save As" B_UTF8_ELLIPSIS, new BMessage(MSG_SAVE_AS), 'A'));
241 menu->AddItem(new BMenuItem("Revert", new BMessage(MSG_REVERT)));
242 menu->AddItem(new BSeparatorItem);
243 menu->AddItem(item = new BMenuItem("Quit Frodo", new BMessage(B_QUIT_REQUESTED), 'Q'));
244 item->SetTarget(be_app);
245 bar->AddItem(menu);
246 AddChild(bar);
247 SetKeyMenuBar(bar);
248 int mbar_height = bar->Frame().bottom + 1;
249
250 // Resize window to fit menu bar
251 ResizeBy(0, mbar_height);
252
253 // Light gray background
254 BRect b = Bounds();
255 BView *top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, B_WILL_DRAW);
256 AddChild(top);
257 top->SetViewColor(fill_color);
258
259 // Checkboxes
260 g_sprites_on = make_checkbox(BRect(10, 10, 160, 21), "Sprite display", MSG_SPRITES_ON, top);
261 g_sprite_collisions = make_checkbox(BRect(10, 25, 160, 36), "Sprite collisions", MSG_SPRITE_COLLISIONS, top);
262 g_joystick_1_on = make_checkbox(BRect(10, 40, 160, 51), "Joystick on port 1", MSG_JOYSTICK_1_ON, top);
263 g_joystick_2_on = make_checkbox(BRect(10, 55, 160, 66), "Joystick on port 2", MSG_JOYSTICK_2_ON, top);
264 g_joystick_swap = make_checkbox(BRect(10, 70, 160, 81), "Swap joysticks", MSG_JOYSTICK_SWAP, top);
265 g_limit_speed = make_checkbox(BRect(10, 85, 160, 96), "Limit speed", MSG_LIMIT_SPEED, top);
266 g_fast_reset = make_checkbox(BRect(10, 100, 160, 111), "Fast reset", MSG_FAST_RESET, top);
267 g_cia_irq_hack = make_checkbox(BRect(10, 115, 160, 126), "Clear CIA ICR on write", MSG_CIA_IRQ_HACK, top);
268 g_sid_filters = make_checkbox(BRect(10, 130, 160, 141), "SID filters", MSG_SID_FILTERS, top);
269 g_double_scan = make_checkbox(BRect(10, 145, 160, 156), "Doublescan lines", MSG_DOUBLE_SCAN, top);
270
271 // Number entry fields
272 g_normal_cycles = make_number_entry(BRect(160, 10, 390, 26), "Cycles per line (CPU)", top);
273 g_bad_line_cycles = make_number_entry(BRect(160, 30, 390, 46), "Cycles per Bad Line (CPU)", top);
274 g_cia_cycles = make_number_entry(BRect(160, 50, 390, 66), "Cycles per line (CIA)", top);
275 g_floppy_cycles = make_number_entry(BRect(160, 70, 390, 86), "Cycles per line (1541)", top);
276 g_skip_frames = make_number_entry(BRect(160, 90, 390, 106), "Draw every n-th frame", top);
277
278 // Popup fields
279 g_display_type = make_disptype_popup(BRect(160, 110, 390, 126), "Display type", MSG_DISPLAY_TYPE, top);
280 g_sid_type = make_sidtype_popup(BRect(160, 130, 390, 146), "SID emulation type", MSG_SID_TYPE, top);
281 g_reu_size = make_reusize_popup(BRect(160, 150, 390, 166), "REU size", MSG_REU_SIZE, top);
282
283 // Prepare on/off pictures for file panel buttons
284 BView *view = new BView(BRect(0, 0, 19, 15), "", B_FOLLOW_NONE, 0);
285 AddChild(view);
286 view->SetViewColor(fill_color);
287
288 view->BeginPicture(new BPicture);
289 view->SetHighColor(fill_color);
290 view->FillRect(BRect(0, 0, 19, 15));
291 view->SetHighColor(light_color);
292 view->StrokeRect(BRect(0, 0, 18, 0));
293 view->StrokeRect(BRect(0, 0, 0, 14));
294 view->SetHighColor(dark_color);
295 view->StrokeRect(BRect(0, 15, 19, 15));
296 view->StrokeRect(BRect(19, 0, 19, 15));
297 view->SetFont(be_plain_font);
298 view->SetHighColor(0, 0, 0);
299 view->SetLowColor(fill_color);
300 view->MovePenTo(7, 11);
301 view->DrawString("B");
302 BPicture *on = view->EndPicture();
303
304 view->BeginPicture(new BPicture);
305 view->SetHighColor(dark_color);
306 view->FillRect(BRect(0, 0, 19, 15));
307 view->SetHighColor(128, 128, 128);
308 view->StrokeRect(BRect(0, 0, 18, 0));
309 view->StrokeRect(BRect(0, 0, 0, 14));
310 view->SetHighColor(light_color);
311 view->StrokeRect(BRect(0, 15, 19, 15));
312 view->StrokeRect(BRect(19, 0, 19, 15));
313 view->SetFont(be_plain_font);
314 view->SetHighColor(0, 0, 0);
315 view->SetLowColor(dark_color);
316 view->MovePenTo(7, 11);
317 view->DrawString("B");
318 BPicture *off = view->EndPicture();
319
320 RemoveChild(view);
321 delete view;
322
323 // Drive settings
324 BBox *drvbox = new BBox(BRect(10, 173, 390, 304));
325 top->AddChild(drvbox);
326 drvbox->SetViewColor(fill_color);
327 drvbox->SetLowColor(fill_color);
328 drvbox->SetLabel("Drives");
329
330 for (i=0; i<4; i++) {
331 char str[4];
332 sprintf(str, "%d", i+8);
333 g_drive_path[i] = make_path_entry(BRect(10, 14+i*20, 299, 30+i*20), str, drvbox);
334 drvbox->AddChild(new BPictureButton(BRect(304, 16+i*20, 323, 31+i*20), "", new BPicture(*on), new BPicture(*off), new BMessage(MSG_GETDRIVE_8 + i)));
335 g_drive_type[i] = make_drvtype_popup(BRect(329, 14+i*20, 373, 30+i*20), MSG_DRVTYPE_8 + i, drvbox);
336 }
337
338 g_map_slash = make_checkbox(BRect(10, 94, 300, 110), "Map '/'<->'\\' in filenames", MSG_MAP_SLASH, drvbox);
339 g_emul_1541_proc = make_checkbox(BRect(10, 109, 300, 125), "Enable 1541 processor emulation", MSG_EMUL_1541_PROC, drvbox);
340
341 // "OK" button
342 top->AddChild(g_ok = new BButton(BRect(20, 315, 90, 340), "", startup ? "Start" : "OK", new BMessage(MSG_OK)));
343 SetDefaultButton(g_ok);
344
345 // "Cancel" button
346 top->AddChild(g_cancel = new BButton(BRect(b.right-90, 315, b.right-20, 340), "", startup ? "Quit" : "Cancel", new BMessage(MSG_CANCEL)));
347
348 // Set the values of all controls to reflect the preferences
349 set_values();
350 g_normal_cycles->MakeFocus();
351
352 // Create file panels
353 open_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, 0, false, new BMessage(MSG_OPEN_PANEL_RETURNED));
354 open_panel->Window()->SetTitle("Frodo: Open preferences");
355 save_panel = new BFilePanel(B_SAVE_PANEL, &this_messenger, NULL, 0, false, new BMessage(MSG_SAVE_PANEL_RETURNED));
356 save_panel->Window()->SetTitle("Frodo: Save preferences");
357 file_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, 0, false, new BMessage(MSG_DRIVE_PANEL_RETURNED));
358 file_panel->SetPanelDirectory(&AppDirectory);
359 dir_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, B_DIRECTORY_NODE, false, new BMessage(MSG_DRIVE_PANEL_RETURNED));
360 dir_panel->SetPanelDirectory(&AppDirectory);
361 dir_panel->Window()->SetTitle("Frodo: Select directory");
362 dir_panel->SetButtonLabel(B_DEFAULT_BUTTON, "Select");
363
364 Unlock();
365 }
366
367
368 /*
369 * Create checkbox
370 */
371
make_checkbox(BRect frame,char * label,uint32 what,BView * parent)372 BCheckBox *PrefsWindow::make_checkbox(BRect frame, char *label, uint32 what, BView *parent)
373 {
374 BCheckBox *checkbox = new BCheckBox(frame, "", label, new BMessage(what));
375 parent->AddChild(checkbox);
376 return checkbox;
377 }
378
379
380 /*
381 * Create number entry field
382 */
383
make_number_entry(BRect frame,char * label_text,BView * parent)384 NumberControl *PrefsWindow::make_number_entry(BRect frame, char *label_text, BView *parent)
385 {
386 NumberControl *num = new NumberControl(frame, frame.right-frame.left-55, "", label_text, NULL, NULL);
387 parent->AddChild(num);
388
389 num->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_RIGHT);
390 num->SetFont(be_plain_font);
391 num->ChildAt(0)->SetFont(be_plain_font);
392
393 return num;
394 }
395
396
397 /*
398 * Create drive type popup menu
399 */
400
make_drvtype_popup(BRect frame,uint32 what,BView * parent)401 BPopUpMenu *PrefsWindow::make_drvtype_popup(BRect frame, uint32 what, BView *parent)
402 {
403 BPopUpMenu *popup = new BPopUpMenu("drive_type popup", true, true);
404 popup->AddItem(new BMenuItem("Dir", new BMessage(what)));
405 popup->AddItem(new BMenuItem("D64", new BMessage(what)));
406 popup->AddItem(new BMenuItem("T64", new BMessage(what)));
407 popup->SetTargetForItems(this);
408 BMenuField *menu_field = new BMenuField(frame, "drive_type", NULL, popup);
409 menu_field->SetDivider(0);
410 parent->AddChild(menu_field);
411 return popup;
412 }
413
414
415 /*
416 * Create path entry field
417 */
418
make_path_entry(BRect frame,char * label,BView * parent)419 PathControl *PrefsWindow::make_path_entry(BRect frame, char *label, BView *parent)
420 {
421 PathControl *path = new PathControl(frame, 16, "", label, NULL, NULL);
422 parent->AddChild(path);
423
424 path->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
425 path->SetFont(be_plain_font);
426 path->ChildAt(0)->SetFont(be_plain_font);
427 ((BTextView *)(path->ChildAt(0)))->SetMaxBytes(255);
428
429 return path;
430 }
431
432
433 /*
434 * Create display type popup
435 */
436
make_disptype_popup(BRect frame,char * label_text,uint32 what,BView * parent)437 BPopUpMenu *PrefsWindow::make_disptype_popup(BRect frame, char *label_text, uint32 what, BView *parent)
438 {
439 BPopUpMenu *popup = new BPopUpMenu("display_type popup", true, true);
440 popup->AddItem(new BMenuItem("Window", new BMessage(what)));
441 popup->AddItem(new BMenuItem("Screen", new BMessage(what)));
442 popup->SetTargetForItems(this);
443 BMenuField *menu_field = new BMenuField(frame, "display_type", label_text, popup);
444 menu_field->SetDivider(frame.Width()-55);
445 menu_field->SetAlignment(B_ALIGN_RIGHT);
446 parent->AddChild(menu_field);
447 return popup;
448 }
449
450
451 /*
452 * Create SID type popup
453 */
454
make_sidtype_popup(BRect frame,char * label_text,uint32 what,BView * parent)455 BPopUpMenu *PrefsWindow::make_sidtype_popup(BRect frame, char *label_text, uint32 what, BView *parent)
456 {
457 BPopUpMenu *popup = new BPopUpMenu("sid_type popup", true, true);
458 popup->AddItem(new BMenuItem("None", new BMessage(what)));
459 popup->AddItem(new BMenuItem("Digital", new BMessage(what)));
460 popup->SetTargetForItems(this);
461 BMenuField *menu_field = new BMenuField(frame, "sid_type", label_text, popup);
462 menu_field->SetDivider(frame.Width()-55);
463 menu_field->SetAlignment(B_ALIGN_RIGHT);
464 parent->AddChild(menu_field);
465 return popup;
466 }
467
468
469 /*
470 * Create REU size popup
471 */
472
make_reusize_popup(BRect frame,char * label_text,uint32 what,BView * parent)473 BPopUpMenu *PrefsWindow::make_reusize_popup(BRect frame, char *label_text, uint32 what, BView *parent)
474 {
475 BPopUpMenu *popup = new BPopUpMenu("reu_size popup", true, true);
476 popup->AddItem(new BMenuItem("None", new BMessage(what)));
477 popup->AddItem(new BMenuItem("128K", new BMessage(what)));
478 popup->AddItem(new BMenuItem("256K", new BMessage(what)));
479 popup->AddItem(new BMenuItem("512K", new BMessage(what)));
480 popup->SetTargetForItems(this);
481 BMenuField *menu_field = new BMenuField(frame, "reu_size", label_text, popup);
482 menu_field->SetDivider(frame.Width()-55);
483 menu_field->SetAlignment(B_ALIGN_RIGHT);
484 parent->AddChild(menu_field);
485 return popup;
486 }
487
488
489 /*
490 * Set the values of the controls
491 */
492
set_values(void)493 void PrefsWindow::set_values(void)
494 {
495 prefs->Check();
496
497 g_normal_cycles->SetValue(prefs->NormalCycles);
498 g_bad_line_cycles->SetValue(prefs->BadLineCycles);
499 g_cia_cycles->SetValue(prefs->CIACycles);
500 g_floppy_cycles->SetValue(prefs->FloppyCycles);
501 g_skip_frames->SetValue(prefs->SkipFrames);
502
503 for (int i=0; i<4; i++) {
504 g_drive_type[i]->ItemAt(prefs->DriveType[i])->SetMarked(true);
505 g_drive_path[i]->SetText(prefs->DrivePath[i]);
506 }
507
508 g_sid_type->ItemAt(prefs->SIDType)->SetMarked(true);
509 g_reu_size->ItemAt(prefs->REUSize)->SetMarked(true);
510 g_display_type->ItemAt(prefs->DisplayType)->SetMarked(true);
511
512 g_sprites_on->SetValue(prefs->SpritesOn ? B_CONTROL_ON : B_CONTROL_OFF);
513 g_sprite_collisions->SetValue(prefs->SpriteCollisions ? B_CONTROL_ON : B_CONTROL_OFF);
514 g_joystick_1_on->SetValue(prefs->Joystick1On ? B_CONTROL_ON : B_CONTROL_OFF);
515 g_joystick_2_on->SetValue(prefs->Joystick2On ? B_CONTROL_ON : B_CONTROL_OFF);
516 g_joystick_swap->SetValue(prefs->JoystickSwap ? B_CONTROL_ON : B_CONTROL_OFF);
517 g_limit_speed->SetValue(prefs->LimitSpeed ? B_CONTROL_ON : B_CONTROL_OFF);
518 g_fast_reset->SetValue(prefs->FastReset ? B_CONTROL_ON : B_CONTROL_OFF);
519 g_cia_irq_hack->SetValue(prefs->CIAIRQHack ? B_CONTROL_ON : B_CONTROL_OFF);
520 g_sid_filters->SetValue(prefs->SIDFilters ? B_CONTROL_ON : B_CONTROL_OFF);
521 g_double_scan->SetValue(prefs->DoubleScan ? B_CONTROL_ON : B_CONTROL_OFF);
522
523 g_map_slash->SetValue(prefs->MapSlash ? B_CONTROL_ON : B_CONTROL_OFF);
524 g_emul_1541_proc->SetValue(prefs->Emul1541Proc ? B_CONTROL_ON : B_CONTROL_OFF);
525
526 ghost_controls();
527 }
528
529
530 /*
531 * Get the values of the controls
532 */
533
get_values(void)534 void PrefsWindow::get_values(void)
535 {
536 prefs->NormalCycles = g_normal_cycles->Value();
537 prefs->BadLineCycles = g_bad_line_cycles->Value();
538 prefs->CIACycles = g_cia_cycles->Value();
539 prefs->FloppyCycles = g_floppy_cycles->Value();
540 prefs->SkipFrames = g_skip_frames->Value();
541
542 for (int i=0; i<4; i++)
543 strcpy(prefs->DrivePath[i], g_drive_path[i]->Text());
544
545 prefs->Check();
546 }
547
548
549 /*
550 * Enable/disable certain controls
551 */
552
ghost_controls(void)553 void PrefsWindow::ghost_controls(void)
554 {
555 g_normal_cycles->SetEnabled(!IsFrodoSC);
556 g_bad_line_cycles->SetEnabled(!IsFrodoSC);
557 g_cia_cycles->SetEnabled(!IsFrodoSC);
558 g_floppy_cycles->SetEnabled(!IsFrodoSC);
559 g_cia_irq_hack->SetEnabled(!IsFrodoSC);
560 g_double_scan->SetEnabled(prefs->DisplayType == DISPTYPE_SCREEN);
561 }
562
563
564 /*
565 * Message from controls/menus received
566 */
567
MessageReceived(BMessage * msg)568 void PrefsWindow::MessageReceived(BMessage *msg)
569 {
570 switch (msg->what) {
571 case MSG_OK:
572 get_values();
573 if (startup)
574 be_app->PostMessage(MSG_STARTUP);
575 else {
576 BMessage msg(MSG_PREFS_DONE);
577 msg.AddBool("canceled", false);
578 msg.AddPointer("prefs", prefs);
579 be_app->PostMessage(&msg);
580 }
581 PostMessage(B_QUIT_REQUESTED);
582 break;
583
584 case MSG_CANCEL:
585 if (startup)
586 be_app->PostMessage(B_QUIT_REQUESTED);
587 else {
588 BMessage msg(MSG_PREFS_DONE);
589 msg.AddBool("canceled", true);
590 msg.AddPointer("prefs", prefs);
591 be_app->PostMessage(&msg);
592 }
593 PostMessage(B_QUIT_REQUESTED);
594 break;
595
596 case MSG_SPRITES_ON:
597 prefs->SpritesOn = !prefs->SpritesOn;
598 break;
599
600 case MSG_SPRITE_COLLISIONS:
601 prefs->SpriteCollisions = !prefs->SpriteCollisions;
602 break;
603
604 case MSG_JOYSTICK_1_ON:
605 prefs->Joystick1On = !prefs->Joystick1On;
606 break;
607
608 case MSG_JOYSTICK_2_ON:
609 prefs->Joystick2On = !prefs->Joystick2On;
610 break;
611
612 case MSG_JOYSTICK_SWAP:
613 prefs->JoystickSwap = !prefs->JoystickSwap;
614 break;
615
616 case MSG_LIMIT_SPEED:
617 prefs->LimitSpeed = !prefs->LimitSpeed;
618 break;
619
620 case MSG_FAST_RESET:
621 prefs->FastReset = !prefs->FastReset;
622 break;
623
624 case MSG_CIA_IRQ_HACK:
625 prefs->CIAIRQHack = !prefs->CIAIRQHack;
626 break;
627
628 case MSG_SID_FILTERS:
629 prefs->SIDFilters = !prefs->SIDFilters;
630 break;
631
632 case MSG_DOUBLE_SCAN:
633 prefs->DoubleScan = !prefs->DoubleScan;
634 break;
635
636 case MSG_SID_TYPE:
637 prefs->SIDType = msg->FindInt32("index");
638 break;
639
640 case MSG_REU_SIZE:
641 prefs->REUSize = msg->FindInt32("index");
642 break;
643
644 case MSG_DISPLAY_TYPE:
645 prefs->DisplayType = msg->FindInt32("index");
646 g_double_scan->SetEnabled(prefs->DisplayType == DISPTYPE_SCREEN);
647 break;
648
649 case MSG_MAP_SLASH:
650 prefs->MapSlash = !prefs->MapSlash;
651 break;
652
653 case MSG_EMUL_1541_PROC:
654 prefs->Emul1541Proc = !prefs->Emul1541Proc;
655 break;
656
657 case MSG_DRVTYPE_8:
658 case MSG_DRVTYPE_9:
659 case MSG_DRVTYPE_10:
660 case MSG_DRVTYPE_11:
661 prefs->DriveType[msg->what & 3] = msg->FindInt32("index");
662 break;
663
664 case MSG_GETDRIVE_8:
665 case MSG_GETDRIVE_9:
666 case MSG_GETDRIVE_10:
667 case MSG_GETDRIVE_11:
668 panel_drive_num = msg->what & 3;
669 file_panel->Hide();
670 dir_panel->Hide();
671 if (prefs->DriveType[panel_drive_num] == DRVTYPE_D64) {
672 file_panel->Window()->SetTitle("Frodo: Select disk image file");
673 file_panel->Show();
674 } else if (prefs->DriveType[panel_drive_num] == DRVTYPE_T64) {
675 file_panel->Window()->SetTitle("Frodo: Select archive file");
676 file_panel->Show();
677 } else
678 dir_panel->Show();
679 break;
680
681 case MSG_DRIVE_PANEL_RETURNED: { // Drive path file panel returned
682 entry_ref the_ref;
683 BEntry the_entry;
684 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR)
685 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
686 BPath the_path;
687 the_entry.GetPath(&the_path);
688 strncpy(prefs->DrivePath[panel_drive_num], the_path.Path(), 255);
689 prefs->DrivePath[panel_drive_num][255] = 0;
690 set_values();
691 }
692 break;
693 }
694
695 case MSG_OPEN:
696 open_panel->Show();
697 break;
698
699 case MSG_OPEN_PANEL_RETURNED: { // Open file panel returned
700 get_values(); // Useful if Load() is unsuccessful
701
702 entry_ref the_ref;
703 BEntry the_entry;
704 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR)
705 if (the_entry.SetTo(&the_ref) == B_NO_ERROR)
706 if (the_entry.IsFile()) {
707 BPath the_path;
708 the_entry.GetPath(&the_path);
709 strncpy(prefs_path, the_path.Path(), 1023);
710 prefs_path[1023] = 0;
711 prefs->Load(prefs_path);
712 set_values();
713 }
714 }
715
716 case MSG_SAVE:
717 get_values();
718 prefs->Save(prefs_path);
719 break;
720
721 case MSG_SAVE_AS:
722 save_panel->Show();
723 break;
724
725 case MSG_SAVE_PANEL_RETURNED: { // Save file panel returned
726 entry_ref the_ref;
727 BEntry the_entry;
728 if (msg->FindRef("directory", &the_ref) == B_NO_ERROR)
729 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
730 BPath the_path;
731 the_entry.GetPath(&the_path);
732 strncpy(prefs_path, the_path.Path(), 1023);
733 strncat(prefs_path, "/", 1023);
734 strncat(prefs_path, msg->FindString("name"), 1023);
735 prefs_path[1023] = 0;
736 get_values();
737 if (!prefs->Save(prefs_path))
738 ShowRequester("Couldn't save preferences.", "Too bad");
739 }
740 break;
741 }
742
743 case MSG_REVERT:
744 get_values(); // Useful if Load() is unsuccessful
745 prefs->Load(prefs_path);
746 set_values();
747 break;
748
749 default:
750 BWindow::MessageReceived(msg);
751 }
752 }
753
754
755 /*
756 * Intercept ESC key (works as clicking the Cancel button)
757 */
758
FilterKeyDown(uint32 * aChar,BView ** target)759 bool PrefsWindow::FilterKeyDown(uint32 *aChar, BView **target)
760 {
761 if (*aChar == B_ESCAPE) {
762 // Flash Cancel button
763 g_cancel->SetValue(B_CONTROL_ON);
764 snooze(100000.0);
765 PostMessage(MSG_CANCEL);
766 }
767 return true;
768 }
769
770
771 /*
772 * Quit requested
773 */
774
QuitRequested(void)775 bool PrefsWindow::QuitRequested(void)
776 {
777 delete open_panel;
778 delete save_panel;
779 delete file_panel;
780 delete dir_panel;
781 return true;
782 }
783