ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/prefs_editor_beos.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:25Z (24 years, 9 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs_editor_beos.cpp - Preferences editor, BeOS implementation
3     *
4     * Basilisk II (C) 1997-1999 Christian Bauer
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include <AppKit.h>
22     #include <InterfaceKit.h>
23     #include <StorageKit.h>
24     #include <SerialPort.h>
25     #include <stdio.h>
26     #include <stdlib.h>
27     #include <string.h>
28     #include <ctype.h>
29     #include <fs_info.h>
30    
31     #include "sysdeps.h"
32     #include "main.h"
33     #include "cdrom.h"
34     #include "xpram.h"
35     #include "prefs.h"
36     #include "version.h"
37     #include "user_strings.h"
38     #include "prefs_editor.h"
39    
40    
41     // Special colors
42     const rgb_color fill_color = {216, 216, 216, 0};
43     const rgb_color slider_fill_color = {102, 152, 255, 0};
44    
45     // Display types
46     enum {
47     DISPLAY_WINDOW,
48     DISPLAY_SCREEN
49     };
50    
51     // Window messages
52     const uint32 MSG_OK = 'okok'; // "Start" clicked
53     const uint32 MSG_CANCEL = 'cncl'; // "Quit" clicked
54     const uint32 MSG_ZAP_PRAM = 'zprm';
55    
56     const int NUM_PANES = 4;
57    
58     const uint32 MSG_VOLUME_SELECTED = 'volu'; // "Volumes" pane
59     const uint32 MSG_VOLUME_INVOKED = 'voli';
60     const uint32 MSG_ADD_VOLUME = 'addv';
61     const uint32 MSG_CREATE_VOLUME = 'crev';
62     const uint32 MSG_REMOVE_VOLUME = 'remv';
63     const uint32 MSG_ADD_VOLUME_PANEL = 'advp';
64     const uint32 MSG_CREATE_VOLUME_PANEL = 'crvp';
65     const uint32 MSG_DEVICE_NAME = 'devn';
66     const uint32 MSG_BOOT_ANY = 'bany';
67     const uint32 MSG_BOOT_CDROM = 'bcdr';
68     const uint32 MSG_NOCDROM = 'nocd';
69    
70     const uint32 MSG_REF_5HZ = ' 5Hz'; // "Graphics/Sound" pane
71     const uint32 MSG_REF_7_5HZ = ' 7Hz';
72     const uint32 MSG_REF_10HZ = '10Hz';
73     const uint32 MSG_REF_15HZ = '15Hz';
74     const uint32 MSG_REF_30HZ = '30Hz';
75     const uint32 MSG_VIDEO_WINDOW = 'vtyw';
76     const uint32 MSG_VIDEO_SCREEN = 'vtys';
77     const uint32 MSG_SCREEN_MODE = 'sm\0\0';
78     const uint32 MSG_NOSOUND = 'nosn';
79    
80     const uint32 MSG_SER_A = 'sera'; // "Serial/Network" pane
81     const uint32 MSG_SER_B = 'serb';
82     const uint32 MSG_ETHER = 'ethr';
83    
84     const uint32 MSG_RAMSIZE = 'rmsz'; // "Memory/Misc" pane
85     const uint32 MSG_MODELID_5 = 'mi05';
86     const uint32 MSG_MODELID_14 = 'mi14';
87    
88    
89     // RAM size slider class
90     class RAMSlider : public BSlider {
91     public:
92     RAMSlider(BRect frame, const char *name, const char *label, BMessage *message,
93     int32 minValue, int32 maxValue, thumb_style thumbType = B_BLOCK_THUMB,
94     uint32 resizingMode = B_FOLLOW_LEFT |
95     B_FOLLOW_TOP,
96     uint32 flags = B_NAVIGABLE | B_WILL_DRAW |
97     B_FRAME_EVENTS) : BSlider(frame, name, label, message, minValue, maxValue, thumbType, resizingMode, flags)
98     {
99     update_text = (char *)malloc(256);
100     }
101    
102     virtual ~RAMSlider()
103     {
104     if (update_text)
105     free(update_text);
106     }
107    
108     virtual char *UpdateText(void) const
109     {
110     if (update_text) {
111     sprintf(update_text, GetString(STR_RAMSIZE_FMT), Value());
112     }
113     return update_text;
114     }
115    
116     private:
117     char *update_text;
118     };
119    
120    
121     // Volumes list view class
122     class VolumeListView : public BListView {
123     public:
124     VolumeListView(BRect frame, const char *name, list_view_type type = B_SINGLE_SELECTION_LIST, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE)
125     : BListView(frame, name, type, resizeMask, flags)
126     {}
127    
128     // Handle dropped files and volumes
129     virtual void MessageReceived(BMessage *msg)
130     {
131     if (msg->what == B_SIMPLE_DATA) {
132     BMessage msg2(MSG_ADD_VOLUME_PANEL);
133     entry_ref ref;
134     for (int i=0; msg->FindRef("refs", i, &ref) == B_NO_ERROR; i++)
135     msg2.AddRef("refs", &ref);
136     Window()->PostMessage(&msg2);
137     } else
138     BListView::MessageReceived(msg);
139     }
140     };
141    
142    
143     // Number-entry BTextControl
144     class NumberControl : public BTextControl {
145     public:
146     NumberControl(BRect frame, float divider, const char *name, const char *label, long value, BMessage *message)
147     : BTextControl(frame, name, label, NULL, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
148     {
149     SetDivider(divider);
150     for (int c=0; c<256; c++)
151     if (!isdigit(c) && c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
152     ((BTextView *)ChildAt(0))->DisallowChar(c);
153     SetValue(value);
154     }
155    
156     // Set integer value
157     void SetValue(long value)
158     {
159     char str[32];
160     sprintf(str, "%ld", value);
161     SetText(str);
162     }
163    
164     // Get integer value
165     long Value(void)
166     {
167     return atol(Text());
168     }
169     };
170    
171    
172     // Path-entry BTextControl
173     class PathControl : public BTextControl {
174     public:
175     PathControl(BRect frame, const char *name, const char *label, const char *text, BMessage *message) : BTextControl(frame, name, label, text, message)
176     {
177     for (int c=0; c<' '; c++)
178     if (c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
179     ((BTextView *)ChildAt(0))->DisallowChar(c);
180     }
181    
182     virtual void MessageReceived(BMessage *msg)
183     {
184     if (msg->what == B_SIMPLE_DATA) {
185     entry_ref the_ref;
186     BEntry the_entry;
187    
188     // Look for dropped refs
189     if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) {
190     if (the_entry.SetTo(&the_ref) == B_NO_ERROR && the_entry.IsFile()) {
191     BPath the_path;
192     the_entry.GetPath(&the_path);
193     SetText(the_path.Path());
194     }
195     } else
196     BTextControl::MessageReceived(msg);
197    
198     MakeFocus();
199     } else
200     BTextControl::MessageReceived(msg);
201     }
202     };
203    
204    
205     // Preferences window class
206     class PrefsWindow : public BWindow {
207     public:
208     PrefsWindow(uint32 msg);
209     virtual ~PrefsWindow();
210     virtual void MessageReceived(BMessage *msg);
211    
212     private:
213     void hide_show_graphics_ctrls(void);
214     void read_graphics_prefs(void);
215     void add_serial_names(BPopUpMenu *menu, uint32 msg);
216     void read_memory_prefs(void);
217    
218     BView *create_volumes_pane(void);
219     BView *create_graphics_pane(void);
220     BView *create_serial_pane(void);
221     BView *create_memory_pane(void);
222    
223     uint32 ok_message;
224     bool send_quit_on_close;
225    
226     system_info sys_info;
227     BMessenger this_messenger;
228     BView *top;
229     BRect top_frame;
230     BTabView *pane_tabs;
231     BView *panes[NUM_PANES];
232     int current_pane;
233    
234     VolumeListView *volume_list;
235     BCheckBox *nocdrom_checkbox;
236     BMenuField *frameskip_menu;
237     NumberControl *display_x_ctrl;
238     NumberControl *display_y_ctrl;
239     BMenuField *scr_mode_menu;
240     BCheckBox *nosound_checkbox;
241     BCheckBox *ether_checkbox;
242     RAMSlider *ramsize_slider;
243     PathControl *rom_control;
244    
245     BFilePanel *add_volume_panel;
246     BFilePanel *create_volume_panel;
247    
248     uint32 max_ramsize; // In MB
249     int display_type;
250     int scr_mode_bit;
251     };
252    
253    
254     /*
255     * Show preferences editor (asynchronously)
256     * Under BeOS, the return value is ignored. Instead, a message is sent to the
257     * application when the user clicks on "Start" or "Quit"
258     */
259    
260     bool PrefsEditor(void)
261     {
262     new PrefsWindow('strt');
263     return true;
264     }
265    
266    
267     /*
268     * Preferences window constructor
269     */
270    
271     PrefsWindow::PrefsWindow(uint32 msg) : BWindow(BRect(0, 0, 400, 269), GetString(STR_PREFS_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), this_messenger(this)
272     {
273     int i;
274     ok_message = msg;
275     send_quit_on_close = true;
276     get_system_info(&sys_info);
277    
278     // Move window to right position
279     Lock();
280     MoveTo(80, 80);
281    
282     // Set up menus
283     BMenuBar *bar = new BMenuBar(Bounds(), "menu");
284     BMenu *menu = new BMenu(GetString(STR_PREFS_MENU));
285     menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ABOUT), new BMessage(B_ABOUT_REQUESTED)));
286     menu->AddItem(new BSeparatorItem);
287     menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_START), new BMessage(MSG_OK)));
288     menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ZAP_PRAM), new BMessage(MSG_ZAP_PRAM)));
289     menu->AddItem(new BSeparatorItem);
290     menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_QUIT), new BMessage(MSG_CANCEL), 'Q'));
291     bar->AddItem(menu);
292     AddChild(bar);
293     SetKeyMenuBar(bar);
294     int mbar_height = bar->Bounds().bottom + 1;
295    
296     // Resize window to fit menu bar
297     ResizeBy(0, mbar_height);
298    
299     // Light gray background
300     BRect b = Bounds();
301     top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, B_WILL_DRAW);
302     AddChild(top);
303     top->SetViewColor(fill_color);
304     top_frame = top->Bounds();
305    
306     // Create panes
307     panes[0] = create_volumes_pane();
308     panes[1] = create_graphics_pane();
309     panes[2] = create_serial_pane();
310     panes[3] = create_memory_pane();
311    
312     // Prefs item tab view
313     pane_tabs = new BTabView(BRect(10, 10, top_frame.right-10, top_frame.bottom-50), "items", B_WIDTH_FROM_LABEL);
314     for (i=0; i<NUM_PANES; i++)
315     pane_tabs->AddTab(panes[i]);
316     top->AddChild(pane_tabs);
317    
318     volume_list->Select(0);
319    
320     // Create volume file panels
321     add_volume_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_ADD_VOLUME_PANEL));
322     add_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_ADD_VOLUME_PANEL_BUTTON));
323     add_volume_panel->Window()->SetTitle(GetString(STR_ADD_VOLUME_TITLE));
324     create_volume_panel = new BFilePanel(B_SAVE_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_CREATE_VOLUME_PANEL));
325     create_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_CREATE_VOLUME_PANEL_BUTTON));
326     create_volume_panel->Window()->SetTitle(GetString(STR_CREATE_VOLUME_TITLE));
327    
328     create_volume_panel->Window()->Lock();
329     BView *background = create_volume_panel->Window()->ChildAt(0);
330     background->FindView("PoseView")->ResizeBy(0, -30);
331     background->FindView("VScrollBar")->ResizeBy(0, -30);
332     background->FindView("CountVw")->MoveBy(0, -30);
333     BView *v = background->FindView("HScrollBar");
334     if (v)
335     v->MoveBy(0, -30);
336     else {
337     i = 0;
338     while ((v = background->ChildAt(i++)) != NULL) {
339     if (v->Name() == NULL || v->Name()[0] == 0) {
340     v->MoveBy(0, -30); // unnamed horizontal scroll bar
341     break;
342     }
343     }
344     }
345     BView *filename = background->FindView("text view");
346     BRect fnr(filename->Frame());
347     fnr.OffsetBy(0, -30);
348     NumberControl *nc = new NumberControl(fnr, 80, "hardfile_size", GetString(STR_HARDFILE_SIZE_CTRL), 40, NULL);
349     background->AddChild(nc);
350     create_volume_panel->Window()->Unlock();
351    
352     // "Start" button
353     BButton *button = new BButton(BRect(20, top_frame.bottom-35, 90, top_frame.bottom-10), "start", GetString(STR_START_BUTTON), new BMessage(MSG_OK));
354     top->AddChild(button);
355     SetDefaultButton(button);
356    
357     // "Quit" button
358     top->AddChild(new BButton(BRect(top_frame.right-90, top_frame.bottom-35, top_frame.right-20, top_frame.bottom-10), "cancel", GetString(STR_QUIT_BUTTON), new BMessage(MSG_CANCEL)));
359    
360     Unlock();
361     Show();
362     }
363    
364    
365     /*
366     * Preferences window destructor
367     */
368    
369     PrefsWindow::~PrefsWindow()
370     {
371     delete add_volume_panel;
372     delete create_volume_panel;
373     if (send_quit_on_close)
374     be_app->PostMessage(B_QUIT_REQUESTED);
375     }
376    
377    
378     /*
379     * Create "Volumes" pane
380     */
381    
382     BView *PrefsWindow::create_volumes_pane(void)
383     {
384     BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_VOLUMES_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
385     pane->SetViewColor(fill_color);
386     float right = pane->Bounds().right-10;
387    
388     const char *str;
389     int32 index = 0;
390     volume_list = new VolumeListView(BRect(15, 10, pane->Bounds().right-30, 113), "volumes");
391     while ((str = PrefsFindString("disk", index++)) != NULL)
392     volume_list->AddItem(new BStringItem(str));
393     volume_list->SetSelectionMessage(new BMessage(MSG_VOLUME_SELECTED));
394     volume_list->SetInvocationMessage(new BMessage(MSG_VOLUME_INVOKED));
395     pane->AddChild(new BScrollView("volumes_border", volume_list, B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
396    
397     pane->AddChild(new BButton(BRect(10, 118, pane->Bounds().right/3, 138), "add_volume", GetString(STR_ADD_VOLUME_BUTTON), new BMessage(MSG_ADD_VOLUME)));
398     pane->AddChild(new BButton(BRect(pane->Bounds().right/3, 118, pane->Bounds().right*2/3, 138), "create_volume", GetString(STR_CREATE_VOLUME_BUTTON), new BMessage(MSG_CREATE_VOLUME)));
399     pane->AddChild(new BButton(BRect(pane->Bounds().right*2/3, 118, pane->Bounds().right-11, 138), "remove_volume", GetString(STR_REMOVE_VOLUME_BUTTON), new BMessage(MSG_REMOVE_VOLUME)));
400    
401     BMenuField *menu_field;
402     BPopUpMenu *menu = new BPopUpMenu("");
403     menu_field = new BMenuField(BRect(10, 145, right, 160), "bootdriver", GetString(STR_BOOTDRIVER_CTRL), menu);
404     menu_field->SetDivider(90);
405     menu->AddItem(new BMenuItem(GetString(STR_BOOT_ANY_LAB), new BMessage(MSG_BOOT_ANY)));
406     menu->AddItem(new BMenuItem(GetString(STR_BOOT_CDROM_LAB), new BMessage(MSG_BOOT_CDROM)));
407     pane->AddChild(menu_field);
408     int16 i16 = PrefsFindInt16("bootdriver");
409     BMenuItem *item;
410     if (i16 == 0) {
411     if ((item = menu->FindItem(GetString(STR_BOOT_ANY_LAB))) != NULL)
412     item->SetMarked(true);
413     } else if (i16 == CDROMRefNum) {
414     if ((item = menu->FindItem(GetString(STR_BOOT_CDROM_LAB))) != NULL)
415     item->SetMarked(true);
416     }
417    
418     nocdrom_checkbox = new BCheckBox(BRect(10, 165, right, 180), "nocdrom", GetString(STR_NOCDROM_CTRL), new BMessage(MSG_NOCDROM));
419     pane->AddChild(nocdrom_checkbox);
420     nocdrom_checkbox->SetValue(PrefsFindBool("nocdrom") ? B_CONTROL_ON : B_CONTROL_OFF);
421    
422     return pane;
423     }
424    
425    
426     /*
427     * Create "Graphics/Sound" pane
428     */
429    
430     // Screen mode list
431     struct scr_mode_desc {
432     int mode_mask;
433     int str;
434     };
435    
436     static const scr_mode_desc scr_mode[] = {
437     {B_8_BIT_640x480, STR_8_BIT_640x480_LAB},
438     {B_8_BIT_800x600, STR_8_BIT_800x600_LAB},
439     {B_8_BIT_1024x768, STR_8_BIT_1024x768_LAB},
440     {B_8_BIT_1152x900, STR_8_BIT_1152x900_LAB},
441     {B_8_BIT_1280x1024, STR_8_BIT_1280x1024_LAB},
442     {B_8_BIT_1600x1200, STR_8_BIT_1600x1200_LAB},
443     {B_15_BIT_640x480, STR_15_BIT_640x480_LAB},
444     {B_15_BIT_800x600, STR_15_BIT_800x600_LAB},
445     {B_15_BIT_1024x768, STR_15_BIT_1024x768_LAB},
446     {B_15_BIT_1152x900, STR_15_BIT_1152x900_LAB},
447     {B_15_BIT_1280x1024, STR_15_BIT_1280x1024_LAB},
448     {B_15_BIT_1600x1200, STR_15_BIT_1600x1200_LAB},
449     {B_32_BIT_640x480, STR_24_BIT_640x480_LAB},
450     {B_32_BIT_800x600, STR_24_BIT_800x600_LAB},
451     {B_32_BIT_1024x768, STR_24_BIT_1024x768_LAB},
452     {B_32_BIT_1152x900, STR_24_BIT_1152x900_LAB},
453     {B_32_BIT_1280x1024, STR_24_BIT_1280x1024_LAB},
454     {B_32_BIT_1600x1200, STR_24_BIT_1600x1200_LAB},
455     {0, 0} // End marker
456     };
457    
458     void PrefsWindow::hide_show_graphics_ctrls(void)
459     {
460     if (display_type == DISPLAY_WINDOW) {
461     if (!scr_mode_menu->IsHidden())
462     scr_mode_menu->Hide();
463     if (frameskip_menu->IsHidden())
464     frameskip_menu->Show();
465     if (display_x_ctrl->IsHidden())
466     display_x_ctrl->Show();
467     if (display_y_ctrl->IsHidden())
468     display_y_ctrl->Show();
469     } else {
470     if (!frameskip_menu->IsHidden())
471     frameskip_menu->Hide();
472     if (!display_x_ctrl->IsHidden())
473     display_x_ctrl->Hide();
474     if (!display_y_ctrl->IsHidden())
475     display_y_ctrl->Hide();
476     if (scr_mode_menu->IsHidden())
477     scr_mode_menu->Show();
478     }
479     }
480    
481     void PrefsWindow::read_graphics_prefs(void)
482     {
483     char str[64];
484     if (display_type == DISPLAY_WINDOW) {
485     sprintf(str, "win/%d/%d", display_x_ctrl->Value(), display_y_ctrl->Value());
486     } else {
487     sprintf(str, "scr/%d", scr_mode_bit);
488     }
489     PrefsReplaceString("screen", str);
490     }
491    
492     BView *PrefsWindow::create_graphics_pane(void)
493     {
494     BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_GRAPHICS_SOUND_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
495     pane->SetViewColor(fill_color);
496     float right = pane->Bounds().right-10;
497    
498     const char *mode_str = PrefsFindString("screen");
499     int width = 512, height = 384;
500     scr_mode_bit = 0;
501     display_type = DISPLAY_WINDOW;
502     if (mode_str) {
503     if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
504     display_type = DISPLAY_WINDOW;
505     else if (sscanf(mode_str, "scr/%d", &scr_mode_bit) == 1)
506     display_type = DISPLAY_SCREEN;
507     }
508    
509     BMenuField *menu_field;
510     BMenuItem *item;
511     BPopUpMenu *menu;
512    
513     menu = new BPopUpMenu("");
514     menu_field = new BMenuField(BRect(10, 5, right, 20), "videotype", GetString(STR_VIDEO_TYPE_CTRL), menu);
515     menu_field->SetDivider(120);
516     menu->AddItem(item = new BMenuItem(GetString(STR_WINDOW_LAB), new BMessage(MSG_VIDEO_WINDOW)));
517     if (display_type == DISPLAY_WINDOW)
518     item->SetMarked(true);
519     menu->AddItem(item = new BMenuItem(GetString(STR_FULLSCREEN_LAB), new BMessage(MSG_VIDEO_SCREEN)));
520     if (display_type == DISPLAY_SCREEN)
521     item->SetMarked(true);
522     pane->AddChild(menu_field);
523    
524     menu = new BPopUpMenu("");
525     frameskip_menu = new BMenuField(BRect(10, 26, right, 41), "frameskip", GetString(STR_FRAMESKIP_CTRL), menu);
526     frameskip_menu->SetDivider(120);
527     menu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ)));
528     menu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ)));
529     menu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ)));
530     menu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ)));
531     menu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ)));
532     pane->AddChild(frameskip_menu);
533     int32 i32 = PrefsFindInt32("frameskip");
534     if (i32 == 12) {
535     if ((item = menu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL)
536     item->SetMarked(true);
537     } else if (i32 == 8) {
538     if ((item = menu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL)
539     item->SetMarked(true);
540     } else if (i32 == 6) {
541     if ((item = menu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL)
542     item->SetMarked(true);
543     } else if (i32 == 4) {
544     if ((item = menu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL)
545     item->SetMarked(true);
546     } else if (i32 == 2) {
547     if ((item = menu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL)
548     item->SetMarked(true);
549     }
550    
551     display_x_ctrl = new NumberControl(BRect(10, 48, right / 2, 66), 118, "width", GetString(STR_DISPLAY_X_CTRL), width, NULL);
552     pane->AddChild(display_x_ctrl);
553     display_y_ctrl = new NumberControl(BRect(10, 69, right / 2, 87), 118, "height", GetString(STR_DISPLAY_Y_CTRL), height, NULL);
554     pane->AddChild(display_y_ctrl);
555    
556     menu = new BPopUpMenu("");
557     scr_mode_menu = new BMenuField(BRect(10, 26, right, 41), "screenmode", GetString(STR_SCREEN_MODE_CTRL), menu);
558     scr_mode_menu->SetDivider(120);
559     for (int i=0; scr_mode[i].mode_mask; i++) {
560     menu->AddItem(item = new BMenuItem(GetString(scr_mode[i].str), new BMessage(MSG_SCREEN_MODE + i)));
561     if (scr_mode[i].mode_mask & (1 << scr_mode_bit))
562     item->SetMarked(true);
563     }
564     pane->AddChild(scr_mode_menu);
565    
566     nosound_checkbox = new BCheckBox(BRect(10, 90, right, 105), "nosound", GetString(STR_NOSOUND_CTRL), new BMessage(MSG_NOSOUND));
567     pane->AddChild(nosound_checkbox);
568     nosound_checkbox->SetValue(PrefsFindBool("nosound") ? B_CONTROL_ON : B_CONTROL_OFF);
569    
570     hide_show_graphics_ctrls();
571     return pane;
572     }
573    
574    
575     /*
576     * Create "Serial Ports" pane
577     */
578    
579     void PrefsWindow::add_serial_names(BPopUpMenu *menu, uint32 msg)
580     {
581     BSerialPort *port = new BSerialPort;
582     char name[B_PATH_NAME_LENGTH];
583     for (int i=0; i<port->CountDevices(); i++) {
584     port->GetDeviceName(i, name);
585     menu->AddItem(new BMenuItem(name, new BMessage(msg)));
586     }
587     if (sys_info.platform_type == B_BEBOX_PLATFORM) {
588     BDirectory dir;
589     BEntry entry;
590     dir.SetTo("/dev/parallel");
591     if (dir.InitCheck() == B_NO_ERROR) {
592     dir.Rewind();
593     while (dir.GetNextEntry(&entry) >= 0) {
594     if (!entry.IsDirectory()) {
595     entry.GetName(name);
596     menu->AddItem(new BMenuItem(name, new BMessage(msg)));
597     }
598     }
599     }
600     }
601     delete port;
602     }
603    
604     static void set_serial_label(BPopUpMenu *menu, const char *prefs_name)
605     {
606     const char *str;
607     BMenuItem *item;
608     if ((str = PrefsFindString(prefs_name)) != NULL)
609     if ((item = menu->FindItem(str)) != NULL)
610     item->SetMarked(true);
611     }
612    
613     BView *PrefsWindow::create_serial_pane(void)
614     {
615     BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_SERIAL_NETWORK_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
616     pane->SetViewColor(fill_color);
617     float right = pane->Bounds().right-10;
618    
619     BMenuField *menu_field;
620     BPopUpMenu *menu_a = new BPopUpMenu("");
621     add_serial_names(menu_a, MSG_SER_A);
622     menu_field = new BMenuField(BRect(10, 5, right, 20), "seriala", GetString(STR_SERIALA_CTRL), menu_a);
623     menu_field->SetDivider(90);
624     pane->AddChild(menu_field);
625     set_serial_label(menu_a, "seriala");
626    
627     BPopUpMenu *menu_b = new BPopUpMenu("");
628     add_serial_names(menu_b, MSG_SER_B);
629     menu_field = new BMenuField(BRect(10, 26, right, 41), "serialb", GetString(STR_SERIALB_CTRL), menu_b);
630     menu_field->SetDivider(90);
631     pane->AddChild(menu_field);
632     set_serial_label(menu_b, "serialb");
633    
634     ether_checkbox = new BCheckBox(BRect(10, 47, right, 62), "ether", GetString(STR_ETHER_ENABLE_CTRL), new BMessage(MSG_ETHER));
635     pane->AddChild(ether_checkbox);
636     ether_checkbox->SetValue(PrefsFindString("ether") ? B_CONTROL_ON : B_CONTROL_OFF);
637    
638     return pane;
639     }
640    
641    
642     /*
643     * Create "Memory" pane
644     */
645    
646     void PrefsWindow::read_memory_prefs(void)
647     {
648     const char *str = rom_control->Text();
649     if (strlen(str))
650     PrefsReplaceString("rom", str);
651     else
652     PrefsRemoveItem("rom");
653     }
654    
655     BView *PrefsWindow::create_memory_pane(void)
656     {
657     char str[256], str2[256];
658     BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_MEMORY_MISC_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
659     pane->SetViewColor(fill_color);
660     float right = pane->Bounds().right-10;
661    
662     BEntry entry("/boot/var/swap");
663     off_t swap_space;
664     if (entry.GetSize(&swap_space) == B_NO_ERROR)
665     max_ramsize = swap_space / (1024 * 1024) - 8;
666     else
667     max_ramsize = sys_info.max_pages * B_PAGE_SIZE / (1024 * 1024) - 8;
668    
669     int32 value = PrefsFindInt32("ramsize") / (1024 * 1024);
670    
671     ramsize_slider = new RAMSlider(BRect(10, 5, right, 55), "ramsize", GetString(STR_RAMSIZE_SLIDER), new BMessage(MSG_RAMSIZE), 1, max_ramsize, B_TRIANGLE_THUMB);
672     ramsize_slider->SetValue(value);
673     ramsize_slider->UseFillColor(true, &slider_fill_color);
674     sprintf(str, GetString(STR_RAMSIZE_FMT), 1);
675     sprintf(str2, GetString(STR_RAMSIZE_FMT), max_ramsize);
676     ramsize_slider->SetLimitLabels(str, str2);
677     pane->AddChild(ramsize_slider);
678    
679     BMenuField *menu_field;
680     BMenuItem *item;
681     BPopUpMenu *menu;
682    
683     int id = PrefsFindInt32("modelid");
684     menu = new BPopUpMenu("");
685     menu_field = new BMenuField(BRect(10, 60, right, 75), "modelid", GetString(STR_MODELID_CTRL), menu);
686     menu_field->SetDivider(120);
687     menu->AddItem(item = new BMenuItem(GetString(STR_MODELID_5_LAB), new BMessage(MSG_MODELID_5)));
688     if (id == 5)
689     item->SetMarked(true);
690     menu->AddItem(item = new BMenuItem(GetString(STR_MODELID_14_LAB), new BMessage(MSG_MODELID_14)));
691     if (id == 14)
692     item->SetMarked(true);
693     pane->AddChild(menu_field);
694    
695     rom_control = new PathControl(BRect(10, 82, right, 97), "rom", GetString(STR_ROM_FILE_CTRL), PrefsFindString("rom"), NULL);
696     rom_control->SetDivider(117);
697     pane->AddChild(rom_control);
698    
699     return pane;
700     }
701    
702    
703     /*
704     * Message from controls/menus received
705     */
706    
707     void PrefsWindow::MessageReceived(BMessage *msg)
708     {
709     switch (msg->what) {
710     case MSG_OK: { // "Start" button clicked
711     read_memory_prefs();
712     read_graphics_prefs();
713     SavePrefs();
714     send_quit_on_close = false;
715     PostMessage(B_QUIT_REQUESTED);
716     be_app->PostMessage(ok_message);
717     break;
718     }
719    
720     case MSG_CANCEL: // "Quit" button clicked
721     send_quit_on_close = false;
722     PostMessage(B_QUIT_REQUESTED);
723     be_app->PostMessage(B_QUIT_REQUESTED);
724     break;
725    
726     case B_ABOUT_REQUESTED: { // "About" menu item selected
727     char str[256];
728     sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
729     strcat(str, " ");
730     strcat(str, GetString(STR_ABOUT_TEXT2));
731     BAlert *about = new BAlert(GetString(STR_WINDOW_TITLE), str, GetString(STR_OK_BUTTON));
732     about->Go();
733     break;
734     }
735    
736     case MSG_ZAP_PRAM: // "Zap PRAM File" menu item selected
737     ZapPRAM();
738     break;
739    
740     case MSG_VOLUME_INVOKED: { // Double-clicked on volume name, toggle read-only flag
741     int selected = volume_list->CurrentSelection();
742     if (selected >= 0) {
743     const char *str = PrefsFindString("disk", selected);
744     BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected);
745     delete item;
746     char newstr[256];
747     if (str[0] == '*')
748     strcpy(newstr, str+1);
749     else {
750     strcpy(newstr, "*");
751     strcat(newstr, str);
752     }
753     PrefsReplaceString("disk", newstr, selected);
754     volume_list->AddItem(new BStringItem(newstr), selected);
755     volume_list->Select(selected);
756     }
757     break;
758     }
759    
760     case MSG_ADD_VOLUME:
761     add_volume_panel->Show();
762     break;
763    
764     case MSG_CREATE_VOLUME:
765     create_volume_panel->Show();
766     break;
767    
768     case MSG_ADD_VOLUME_PANEL: {
769     entry_ref ref;
770     if (msg->FindRef("refs", &ref) == B_NO_ERROR) {
771     BEntry entry(&ref, true);
772     BPath path;
773     entry.GetPath(&path);
774     if (entry.IsFile()) {
775     PrefsAddString("disk", path.Path());
776     volume_list->AddItem(new BStringItem(path.Path()));
777     } else if (entry.IsDirectory()) {
778     BVolume volume;
779     if (path.Path()[0] == '/' && strchr(path.Path()+1, '/') == NULL && entry.GetVolume(&volume) == B_NO_ERROR) {
780     int32 i = 0;
781     dev_t d;
782     fs_info info;
783     while ((d = next_dev(&i)) >= 0) {
784     fs_stat_dev(d, &info);
785     if (volume.Device() == info.dev) {
786     PrefsAddString("disk", info.device_name);
787     volume_list->AddItem(new BStringItem(info.device_name));
788     }
789     }
790     }
791     }
792     }
793     break;
794     }
795    
796     case MSG_CREATE_VOLUME_PANEL: {
797     entry_ref dir;
798     if (msg->FindRef("directory", &dir) == B_NO_ERROR) {
799     BEntry entry(&dir, true);
800     BPath path;
801     entry.GetPath(&path);
802     path.Append(msg->FindString("name"));
803    
804     create_volume_panel->Window()->Lock();
805     BView *background = create_volume_panel->Window()->ChildAt(0);
806     NumberControl *v = (NumberControl *)background->FindView("hardfile_size");
807     int size = v->Value();
808    
809     char cmd[1024];
810     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", path.Path(), size);
811     int ret = system(cmd);
812     if (ret == 0) {
813     PrefsAddString("disk", path.Path());
814     volume_list->AddItem(new BStringItem(path.Path()));
815     } else {
816     sprintf(cmd, GetString(STR_CREATE_VOLUME_WARN), strerror(ret));
817     WarningAlert(cmd);
818     }
819     }
820     break;
821     }
822    
823     case MSG_REMOVE_VOLUME: {
824     int selected = volume_list->CurrentSelection();
825     if (selected >= 0) {
826     PrefsRemoveItem("disk", selected);
827     BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected);
828     delete item;
829     volume_list->Select(selected);
830     }
831     break;
832     }
833    
834     case MSG_BOOT_ANY:
835     PrefsReplaceInt16("bootdriver", 0);
836     break;
837    
838     case MSG_BOOT_CDROM:
839     PrefsReplaceInt16("bootdriver", CDROMRefNum);
840     break;
841    
842     case MSG_NOCDROM:
843     PrefsReplaceBool("nocdrom", nocdrom_checkbox->Value() == B_CONTROL_ON);
844     break;
845    
846     case MSG_VIDEO_WINDOW:
847     display_type = DISPLAY_WINDOW;
848     hide_show_graphics_ctrls();
849     break;
850    
851     case MSG_VIDEO_SCREEN:
852     display_type = DISPLAY_SCREEN;
853     hide_show_graphics_ctrls();
854     break;
855    
856     case MSG_REF_5HZ:
857     PrefsReplaceInt32("frameskip", 12);
858     break;
859    
860     case MSG_REF_7_5HZ:
861     PrefsReplaceInt32("frameskip", 8);
862     break;
863    
864     case MSG_REF_10HZ:
865     PrefsReplaceInt32("frameskip", 6);
866     break;
867    
868     case MSG_REF_15HZ:
869     PrefsReplaceInt32("frameskip", 4);
870     break;
871    
872     case MSG_REF_30HZ:
873     PrefsReplaceInt32("frameskip", 2);
874     break;
875    
876     case MSG_NOSOUND:
877     PrefsReplaceBool("nosound", nosound_checkbox->Value() == B_CONTROL_ON);
878     break;
879    
880     case MSG_SER_A: {
881     BMenuItem *source = NULL;
882     msg->FindPointer("source", (void **)&source);
883     if (source)
884     PrefsReplaceString("seriala", source->Label());
885     break;
886     }
887    
888     case MSG_SER_B: {
889     BMenuItem *source = NULL;
890     msg->FindPointer("source", (void **)&source);
891     if (source)
892     PrefsReplaceString("serialb", source->Label());
893     break;
894     }
895    
896     case MSG_ETHER:
897     if (ether_checkbox->Value() == B_CONTROL_ON)
898     PrefsReplaceString("ether", "yes");
899     else
900     PrefsRemoveItem("ether");
901     break;
902    
903     case MSG_RAMSIZE:
904     PrefsReplaceInt32("ramsize", ramsize_slider->Value() * 1024 * 1024);
905     break;
906    
907     case MSG_MODELID_5:
908     PrefsReplaceInt32("modelid", 5);
909     break;
910    
911     case MSG_MODELID_14:
912     PrefsReplaceInt32("modelid", 14);
913     break;
914    
915     default: {
916     // Screen mode messages
917     if ((msg->what & 0xffff0000) == MSG_SCREEN_MODE) {
918     int m = msg->what & 0xffff;
919     uint32 mask = scr_mode[m].mode_mask;
920     for (int i=0; i<32; i++)
921     if (mask & (1 << i))
922     scr_mode_bit = i;
923     } else
924     BWindow::MessageReceived(msg);
925     }
926     }
927     }