home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / BeOS / prefs_editor_beos.cpp < prev    next >
C/C++ Source or Header  |  1999-10-29  |  30KB  |  996 lines

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