home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / AmigaOS / prefs_editor_amiga.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-24  |  42.0 KB  |  1,723 lines

  1. /*
  2.  *  prefs_editor_amiga.cpp - Preferences editor, AmigaOS implementation (using gtlayout.library)
  3.  *
  4.  *  Basilisk II (C) 1997-2001 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 <exec/types.h>
  22. #include <exec/memory.h>
  23. #include <dos/dos.h>
  24. #include <dos/dosextens.h>
  25. #include <dos/filehandler.h>
  26. #include <intuition/intuition.h>
  27. #include <libraries/asl.h>
  28. #include <libraries/gtlayout.h>
  29. #include <libraries/Picasso96.h>
  30. #include <cybergraphics/cybergraphics.h>
  31. #include <graphics/displayinfo.h>
  32. #include <devices/ahi.h>
  33. #include <proto/exec.h>
  34. #include <proto/dos.h>
  35. #include <proto/intuition.h>
  36. #include <proto/gadtools.h>
  37. #include <proto/gtlayout.h>
  38. #include <proto/graphics.h>
  39. #include <proto/asl.h>
  40. #include <proto/Picasso96.h>
  41. #include <proto/cybergraphics.h>
  42. #include <proto/ahi.h>
  43.  
  44. #include "sysdeps.h"
  45. #include "main.h"
  46. #include "xpram.h"
  47. #include "cdrom.h"
  48. #include "user_strings.h"
  49. #include "version.h"
  50. #include "prefs.h"
  51. #include "prefs_editor.h"
  52.  
  53.  
  54. // Gadget/menu IDs
  55. const int MSG_OK = 0x0100;                    // "Start" button
  56. const int MSG_CANCEL = 0x0101;                // "Quit" button
  57. const int MSG_ABOUT = 0x0102;                // "About..." menu item
  58. const int MSG_ZAP_PRAM = 0x0103;            // "Zap PRAM" menu item
  59.  
  60. const int GAD_PAGEGROUP = 0x0200;
  61.  
  62. const int GAD_DISK_LIST = 0x0300;            // "Volumes" pane
  63. const int GAD_ADD_VOLUME = 0x0301;
  64. const int GAD_EDIT_VOLUME = 0x0302;
  65. const int GAD_REMOVE_VOLUME = 0x0303;
  66. const int GAD_CDROM_DEVICE = 0x0304;
  67. const int GAD_CDROM_UNIT = 0x0305;
  68. const int GAD_BOOTDRIVER = 0x0306;
  69. const int GAD_NOCDROM = 0x0307;
  70. const int GAD_EXTFS = 0x0308;
  71.  
  72. const int GAD_VOLUME_READONLY = 0x0310;        // "Add/Edit Volume" window
  73. const int GAD_VOLUME_TYPE = 0x0311;
  74. const int GAD_VOLUME_FILE = 0x0312;
  75. const int GAD_VOLUME_DEVICE = 0x0313;
  76. const int GAD_VOLUME_UNIT = 0x0314;
  77. const int GAD_VOLUME_OPENFLAGS = 0x0315;
  78. const int GAD_VOLUME_STARTBLOCK = 0x0316;
  79. const int GAD_VOLUME_SIZE = 0x0317;
  80. const int GAD_VOLUME_BLOCKSIZE = 0x0318;
  81. const int GAD_VOLUME_PAGEGROUP = 0x0319;
  82.  
  83. const int GAD_SCSI0_DEVICE = 0x0400;        // "SCSI" pane
  84. const int GAD_SCSI1_DEVICE = 0x0401;
  85. const int GAD_SCSI2_DEVICE = 0x0402;
  86. const int GAD_SCSI3_DEVICE = 0x0403;
  87. const int GAD_SCSI4_DEVICE = 0x0404;
  88. const int GAD_SCSI5_DEVICE = 0x0405;
  89. const int GAD_SCSI6_DEVICE = 0x0406;
  90. const int GAD_SCSI0_UNIT = 0x0410;
  91. const int GAD_SCSI1_UNIT = 0x0411;
  92. const int GAD_SCSI2_UNIT = 0x0412;
  93. const int GAD_SCSI3_UNIT = 0x0413;
  94. const int GAD_SCSI4_UNIT = 0x0414;
  95. const int GAD_SCSI5_UNIT = 0x0415;
  96. const int GAD_SCSI6_UNIT = 0x0416;
  97. const int GAD_SCSI_MEMTYPE = 0x0420;
  98.  
  99. const int GAD_VIDEO_TYPE = 0x0500;            // "Graphics/Sound" pane
  100. const int GAD_DISPLAY_X = 0x0501;
  101. const int GAD_DISPLAY_Y = 0x0502;
  102. const int GAD_FRAMESKIP = 0x0503;
  103. const int GAD_SCREEN_MODE = 0x0504;
  104. const int GAD_AHI_MODE = 0x0505;
  105. const int GAD_NOSOUND = 0x0506;
  106.  
  107. const int GAD_SERIALA_DEVICE = 0x0600;        // "Serial/Network" pane
  108. const int GAD_SERIALA_UNIT = 0x0601;
  109. const int GAD_SERIALA_ISPAR = 0x0602;
  110. const int GAD_SERIALB_DEVICE = 0x0603;
  111. const int GAD_SERIALB_UNIT = 0x0604;
  112. const int GAD_SERIALB_ISPAR = 0x0605;
  113. const int GAD_ETHER_DEVICE = 0x0606;
  114. const int GAD_ETHER_UNIT = 0x00607;
  115.  
  116. const int GAD_RAMSIZE = 0x0700;                // "Memory/Misc" pane
  117. const int GAD_MODELID = 0x0701;
  118. const int GAD_ROM_FILE = 0x0702;
  119.  
  120.  
  121. // Global variables
  122. struct Library *GTLayoutBase = NULL;
  123. static struct FileRequester *dev_request = NULL, *file_request = NULL;
  124.  
  125. // gtlayout.library macros
  126. #define VGROUP LT_New(h, LA_Type, VERTICAL_KIND, TAG_END)
  127. #define HGROUP LT_New(h, LA_Type, HORIZONTAL_KIND, TAG_END)
  128. #define ENDGROUP LT_EndGroup(h)
  129.  
  130. // Prototypes
  131. static void create_volumes_pane(struct LayoutHandle *h);
  132. static void create_scsi_pane(struct LayoutHandle *h);
  133. static void create_graphics_pane(struct LayoutHandle *h);
  134. static void create_serial_pane(struct LayoutHandle *h);
  135. static void create_memory_pane(struct LayoutHandle *h);
  136. static void add_edit_volume(struct LayoutHandle *h, bool adding);
  137. static void remove_volume(struct LayoutHandle *h);
  138. static void ghost_volumes_gadgets(struct LayoutHandle *h);
  139. static void ghost_graphics_gadgets(struct LayoutHandle *h);
  140. static void screen_mode_req(struct Window *win, struct LayoutHandle *h);
  141. static void ahi_mode_req(struct Window *win, struct LayoutHandle *h);
  142. static void read_settings(struct LayoutHandle *h);
  143.  
  144.  
  145. /*
  146.  *  Locale hook - returns string for given ID
  147.  */
  148.  
  149. static __saveds __attribute__((regparm(3))) const char *locale_hook_func(struct Hook *hook /*a0*/, void *id /*a1*/, struct LayoutHandle *h /*a2*/)
  150. {
  151.     return GetString((uint32)id);
  152. }
  153.  
  154. struct Hook locale_hook = {{NULL, NULL}, (HOOKFUNC)locale_hook_func, NULL, NULL};
  155.  
  156.  
  157. /*
  158.  *  Show preferences editor
  159.  *  Returns true when user clicked on "Start", false otherwise
  160.  */
  161.  
  162. bool PrefsEditor(void)
  163. {
  164.     bool retval = true, done = false;
  165.     struct LayoutHandle *h = NULL;
  166.     struct Window *win = NULL;
  167.     struct Menu *menu = NULL;
  168.  
  169.     // Pane tabs
  170.     static const LONG labels[] = {
  171.         STR_VOLUMES_PANE_TITLE,
  172.         STR_SCSI_PANE_TITLE,
  173.         STR_GRAPHICS_SOUND_PANE_TITLE,
  174.         STR_SERIAL_NETWORK_PANE_TITLE,
  175.         STR_MEMORY_MISC_PANE_TITLE,
  176.         -1
  177.     };
  178.  
  179.     // Open gtlayout.library
  180.     GTLayoutBase = (struct Library *)OpenLibrary((UBYTE *)"gtlayout.library", 39);
  181.     if (GTLayoutBase == NULL) {
  182.         WarningAlert(GetString(STR_NO_GTLAYOUT_LIB_WARN));
  183.         return true;
  184.     }
  185.  
  186.     // Create layout handle
  187.     h = LT_CreateHandleTags(NULL,
  188.         LAHN_AutoActivate, FALSE,
  189.         LAHN_LocaleHook, (ULONG)&locale_hook,
  190.         TAG_END
  191.     );
  192.     if (h == NULL)
  193.         goto quit;
  194.  
  195.     // Create menus
  196.     menu = LT_NewMenuTags(
  197.         LAMN_LayoutHandle, (ULONG)h,
  198.         LAMN_TitleID, STR_PREFS_MENU,
  199.         LAMN_ItemID, STR_PREFS_ITEM_ABOUT,
  200.         LAMN_UserData, MSG_ABOUT,
  201.         LAMN_ItemText, (ULONG)NM_BARLABEL,
  202.         LAMN_ItemID, STR_PREFS_ITEM_START,
  203.         LAMN_UserData, MSG_OK,
  204.         LAMN_ItemID, STR_PREFS_ITEM_ZAP_PRAM,
  205.         LAMN_UserData, MSG_ZAP_PRAM,
  206.         LAMN_ItemText, (ULONG)NM_BARLABEL,
  207.         LAMN_ItemID, STR_PREFS_ITEM_QUIT,
  208.         LAMN_UserData, MSG_CANCEL,
  209.         LAMN_KeyText, (ULONG)"Q",
  210.         TAG_END
  211.     );
  212.  
  213.     // Create window contents
  214.     VGROUP;
  215.         VGROUP;
  216.             LT_New(h, LA_Type, TAB_KIND,
  217.                 LATB_LabelTable, (ULONG)labels,
  218.                 LATB_AutoPageID, GAD_PAGEGROUP,
  219.                 LATB_FullWidth, TRUE,
  220.                 TAG_END
  221.             );
  222.         ENDGROUP;
  223.  
  224.         // Panes
  225.         LT_New(h, LA_Type, VERTICAL_KIND,
  226.             LA_ID, GAD_PAGEGROUP,
  227.             LAGR_ActivePage, 0,
  228.             TAG_END
  229.         );
  230.             create_volumes_pane(h);
  231.             create_scsi_pane(h);
  232.             create_graphics_pane(h);
  233.             create_serial_pane(h);
  234.             create_memory_pane(h);
  235.         ENDGROUP;
  236.  
  237.         // Separator between tabs and buttons
  238.         VGROUP;
  239.             LT_New(h, LA_Type, XBAR_KIND,
  240.                 LAXB_FullSize, TRUE,
  241.                 TAG_END
  242.             );
  243.         ENDGROUP;
  244.  
  245.         // "Start" and "Quit" buttons
  246.         LT_New(h, LA_Type, HORIZONTAL_KIND,
  247.             LAGR_SameSize, TRUE,
  248.             LAGR_Spread, TRUE,
  249.             TAG_END
  250.         );
  251.             LT_New(h, LA_Type, BUTTON_KIND,
  252.                 LA_LabelID, STR_START_BUTTON,
  253.                 LA_ID, MSG_OK,
  254.                 LABT_ReturnKey, TRUE,
  255.                 TAG_END
  256.             );
  257.             LT_New(h, LA_Type, BUTTON_KIND,
  258.                 LA_LabelID, STR_QUIT_BUTTON,
  259.                 LA_ID, MSG_CANCEL,
  260.                 LABT_EscKey, TRUE,
  261.                 TAG_END
  262.             );
  263.         ENDGROUP;
  264.     ENDGROUP;
  265.  
  266.     // Open window
  267.     win = LT_Build(h,
  268.         LAWN_TitleID, STR_PREFS_TITLE,
  269.         LAWN_Menu, (ULONG)menu,
  270.         LAWN_IDCMP, IDCMP_CLOSEWINDOW,
  271.         LAWN_BelowMouse, TRUE,
  272.         LAWN_SmartZoom, TRUE,
  273.         WA_SimpleRefresh, TRUE,
  274.         WA_Activate, TRUE,
  275.         WA_CloseGadget, TRUE,
  276.         WA_DepthGadget, TRUE,
  277.         WA_DragBar, TRUE,
  278.         TAG_END
  279.     );
  280.     if (win == NULL)
  281.         goto quit;
  282.  
  283.     // Create file requesters
  284.     dev_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  285.         ASLFR_DoPatterns, TRUE,
  286.         ASLFR_RejectIcons, TRUE,
  287.         ASLFR_InitialDrawer, (ULONG)"DEVS:",
  288.         ASLFR_InitialPattern, (ULONG)"#?.device",
  289.         TAG_END
  290.     );
  291.     file_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  292.         ASLFR_DoPatterns, TRUE,
  293.         ASLFR_RejectIcons, TRUE,
  294.         ASLFR_InitialPattern, (ULONG)"#?",
  295.         TAG_END
  296.     );
  297.  
  298.     // Event loop
  299.     do {
  300.         struct IntuiMessage *msg;
  301.  
  302.         // Wait for message
  303.         WaitPort(win->UserPort);
  304.  
  305.         // Get pending messages
  306.         while (msg = LT_GetIMsg(h)) {
  307.  
  308.             // Get data from message and reply
  309.             ULONG cl = msg->Class;
  310.             UWORD code = msg->Code;
  311.             struct Gadget *gad = (struct Gadget *)msg->IAddress;
  312.             LT_ReplyIMsg(msg);
  313.  
  314.             // Handle message according to class
  315.             switch (cl) {
  316.                 case IDCMP_CLOSEWINDOW:
  317.                     retval = false;
  318.                     done = true;
  319.                     break;
  320.  
  321.                 case IDCMP_GADGETUP:
  322.                     switch (gad->GadgetID) {
  323.                         case MSG_OK:
  324.                             read_settings(h);
  325.                             SavePrefs();
  326.                             retval = true;
  327.                             done = true;
  328.                             break;
  329.  
  330.                         case MSG_CANCEL:
  331.                             retval = false;
  332.                             done = true;
  333.                             break;
  334.  
  335.                         case GAD_DISK_LIST:
  336.                             ghost_volumes_gadgets(h);
  337.                             break;
  338.  
  339.                         case GAD_ADD_VOLUME:
  340.                             LT_LockWindow(win);
  341.                             add_edit_volume(h, true);
  342.                             LT_UnlockWindow(win);
  343.                             break;
  344.  
  345.                         case GAD_EDIT_VOLUME:
  346.                             LT_LockWindow(win);
  347.                             add_edit_volume(h, false);
  348.                             LT_UnlockWindow(win);
  349.                             break;
  350.  
  351.                         case GAD_REMOVE_VOLUME:
  352.                             remove_volume(h);
  353.                             break;
  354.  
  355.                         case GAD_BOOTDRIVER:
  356.                             switch (code) {
  357.                                 case 0:
  358.                                     PrefsReplaceInt32("bootdriver", 0);
  359.                                     break;
  360.                                 case 1:
  361.                                     PrefsReplaceInt32("bootdriver", CDROMRefNum);
  362.                                     break;
  363.                             }
  364.                             break;
  365.  
  366.                         case GAD_SCSI_MEMTYPE:
  367.                             PrefsReplaceInt32("scsimemtype", code);
  368.                             break;
  369.  
  370.                         case GAD_VIDEO_TYPE:
  371.                             ghost_graphics_gadgets(h);
  372.                             break;
  373.  
  374.                         case GAD_FRAMESKIP:
  375.                             switch (code) {
  376.                                 case 0:
  377.                                     PrefsReplaceInt32("frameskip", 12);
  378.                                     break;
  379.                                 case 1:
  380.                                     PrefsReplaceInt32("frameskip", 8);
  381.                                     break;
  382.                                 case 2:
  383.                                     PrefsReplaceInt32("frameskip", 6);
  384.                                     break;
  385.                                 case 3:
  386.                                     PrefsReplaceInt32("frameskip", 4);
  387.                                     break;
  388.                                 case 4:
  389.                                     PrefsReplaceInt32("frameskip", 2);
  390.                                     break;
  391.                                 case 5:
  392.                                     PrefsReplaceInt32("frameskip", 1);
  393.                                     break;
  394.                             }
  395.                             break;
  396.  
  397.                         case GAD_MODELID:
  398.                             switch (code) {
  399.                                 case 0:
  400.                                     PrefsReplaceInt32("modelid", 5);
  401.                                     break;
  402.                                 case 1:
  403.                                     PrefsReplaceInt32("modelid", 14);
  404.                                     break;
  405.                             }
  406.                             break;
  407.                     }
  408.                     break;
  409.  
  410.                 case IDCMP_IDCMPUPDATE:
  411.                     switch (gad->GadgetID) {
  412.                         case GAD_DISK_LIST:    // Double-click on volumes list = edit volume
  413.                             LT_LockWindow(win);
  414.                             add_edit_volume(h, false);
  415.                             LT_UnlockWindow(win);
  416.                             break;
  417.  
  418.                         case GAD_SCREEN_MODE:
  419.                             screen_mode_req(win, h);
  420.                             break;
  421.  
  422.                         case GAD_AHI_MODE:
  423.                             ahi_mode_req(win, h);
  424.                             break;
  425.  
  426.                         case GAD_CDROM_DEVICE:
  427.                         case GAD_SCSI0_DEVICE:
  428.                         case GAD_SCSI1_DEVICE:
  429.                         case GAD_SCSI2_DEVICE:
  430.                         case GAD_SCSI3_DEVICE:
  431.                         case GAD_SCSI4_DEVICE:
  432.                         case GAD_SCSI5_DEVICE:
  433.                         case GAD_SCSI6_DEVICE:
  434.                         case GAD_SERIALA_DEVICE:
  435.                         case GAD_SERIALB_DEVICE:
  436.                             if (dev_request) {
  437.                                 LT_LockWindow(win);
  438.                                 BOOL result = AslRequestTags(dev_request,
  439.                                     ASLFR_Window, (ULONG)win, 
  440.                                     ASLFR_InitialDrawer, (ULONG) "Devs:",
  441.                                     TAG_END);
  442.                                 LT_UnlockWindow(win);
  443.                                 if (result) {
  444.                                     char *str;
  445.                                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
  446.                                     strncpy(str, dev_request->rf_File, 255);    // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
  447.                                     str[255] = 0;
  448.                                     LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
  449.                                 }
  450.                             }
  451.                             break;
  452.  
  453.                         case GAD_ETHER_DEVICE:
  454.                             if (dev_request) {
  455.                                 LT_LockWindow(win);
  456.                                 BOOL result = AslRequestTags(dev_request,
  457.                                     ASLFR_Window, (ULONG)win, 
  458.                                     ASLFR_InitialDrawer, (ULONG) "Devs:Networks",
  459.                                     TAG_END);
  460.                                 LT_UnlockWindow(win);
  461.                                 if (result) {
  462.                                     char *str;
  463.                                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
  464.                                     strncpy(str, dev_request->rf_File, 255);    // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
  465.                                     str[255] = 0;
  466.                                     LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
  467.                                 }
  468.                             }
  469.                             break;
  470.  
  471.                         case GAD_ROM_FILE:
  472.                             if (file_request) {
  473.                                 LT_LockWindow(win);
  474.                                 BOOL result = AslRequestTags(file_request, ASLFR_Window, (ULONG)win, TAG_END);
  475.                                 LT_UnlockWindow(win);
  476.                                 if (result) {
  477.                                     char *str;
  478.                                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
  479.                                     strncpy(str, file_request->rf_Dir, 255);
  480.                                     str[255] = 0;
  481.                                     AddPart(str, file_request->rf_File, 255);
  482.                                     LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
  483.                                 }
  484.                             }
  485.                             break;
  486.                     }
  487.                     break;
  488.  
  489.                 case IDCMP_MENUPICK:
  490.                     while (code != MENUNULL) {
  491.                         struct MenuItem *item = ItemAddress(menu, code);
  492.                         if (item == NULL)
  493.                             break;
  494.                         switch ((ULONG)GTMENUITEM_USERDATA(item)) {
  495.                             case MSG_OK:
  496.                                 read_settings(h);
  497.                                 SavePrefs();
  498.                                 retval = true;
  499.                                 done = true;
  500.                                 break;
  501.  
  502.                             case MSG_CANCEL:
  503.                                 retval = false;
  504.                                 done = true;
  505.                                 break;
  506.  
  507.                             case MSG_ABOUT: {
  508.                                 char str[256];
  509.                                 sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
  510.                                 strncat(str, "\n", 255);
  511.                                 strncat(str, GetString(STR_ABOUT_TEXT2), 255);
  512.  
  513.                                 EasyStruct req;
  514.                                 req.es_StructSize = sizeof(EasyStruct);
  515.                                 req.es_Flags = 0;
  516.                                 req.es_Title = (UBYTE *)GetString(STR_ABOUT_TITLE);
  517.                                 req.es_TextFormat = (UBYTE *)str;
  518.                                 req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON);
  519.                                 LT_LockWindow(win);
  520.                                 EasyRequest(win, &req, NULL);
  521.                                 LT_UnlockWindow(win);
  522.                                 break;
  523.                             }
  524.  
  525.                             case MSG_ZAP_PRAM:
  526.                                 ZapPRAM();
  527.                                 break;
  528.                         }
  529.                         code = item->NextSelect;
  530.                     }
  531.                     break;
  532.             }
  533.         }
  534.     } while (!done);
  535.  
  536. quit:
  537.     // Free requesters
  538.     FreeAslRequest(dev_request);
  539.     FreeAslRequest(file_request);
  540.  
  541.     // Delete Menus
  542.     LT_DisposeMenu(menu);
  543.  
  544.     // Delete handle
  545.     LT_DeleteHandle(h);
  546.  
  547.     // Close gtlayout.library
  548.     CloseLibrary(GTLayoutBase);
  549.     return retval;
  550. }
  551.  
  552.  
  553. /*
  554.  *  "Volumes" pane
  555.  */
  556.  
  557. static struct List disk_list;
  558. static char cdrom_name[256], extfs_name[256];
  559. static ULONG cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize;
  560. static BYTE bootdriver_num, nocdrom;
  561.  
  562. // Read volumes preferences
  563. static void parse_volumes_prefs(void)
  564. {
  565.     NewList(&disk_list);
  566.     const char *str;
  567.     for (int i=0; (str = PrefsFindString("disk", i)) != NULL; i++) {
  568.         struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR);
  569.         item->ln_Name = (char *)str;
  570.         AddTail(&disk_list, item);
  571.     }
  572.  
  573.     cdrom_name[0] = 0;
  574.     cdrom_unit = 0; cdrom_flags = 0; cdrom_start = 0; cdrom_size = 0; cdrom_bsize = 2048;
  575.  
  576.     str = PrefsFindString("cdrom");
  577.     if (str)
  578.         sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", cdrom_name, &cdrom_unit, &cdrom_flags, &cdrom_start, &cdrom_size, &cdrom_bsize);
  579.  
  580.     bootdriver_num = 0;
  581.  
  582.     int bootdriver = PrefsFindInt32("bootdriver");
  583.     switch (bootdriver) {
  584.         case 0:
  585.             bootdriver_num = 0;
  586.             break;
  587.         case CDROMRefNum:
  588.             bootdriver_num = 1;
  589.             break;
  590.     }
  591.  
  592.     nocdrom = PrefsFindBool("nocdrom");
  593.  
  594.     extfs_name[0] = 0;
  595.     str = PrefsFindString("extfs");
  596.     if (str)
  597.         strncpy(extfs_name, str, sizeof(extfs_name) - 1);
  598. }
  599.  
  600. // Ghost/unghost "Edit" and "Remove" buttons
  601. static void ghost_volumes_gadgets(struct LayoutHandle *h)
  602. {
  603.     UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END);
  604.     if (sel == 0xffff) {
  605.         LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, TRUE, TAG_END);
  606.         LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, TRUE, TAG_END);
  607.     } else {
  608.         LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, FALSE, TAG_END);
  609.         LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, FALSE, TAG_END);
  610.     }
  611. }
  612.  
  613. // Get device data from partition name
  614. static void analyze_partition(const char *part, char *dev_name, ULONG &dev_unit, ULONG &dev_flags, ULONG &dev_start, ULONG &dev_size, ULONG &dev_bsize)
  615. {
  616.     // Remove everything after and including the ':'
  617.     char str[256];
  618.     strncpy(str, part, sizeof(str) - 1);
  619.     str[sizeof(str) - 1] = 0;
  620.     char *colon = strchr(str, ':');
  621.     if (colon)
  622.         *colon = 0;
  623.  
  624.     // Look for partition
  625.     struct DosList *dl = LockDosList(LDF_DEVICES | LDF_READ);
  626.     dl = FindDosEntry(dl, str, LDF_DEVICES);
  627.     if (dl) {
  628.         // Get File System Startup Message
  629.         struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)(dl->dol_misc.dol_handler.dol_Startup << 2);
  630.         if (fssm) {
  631.             // Get DOS environment vector
  632.             struct DosEnvec *de = (struct DosEnvec *)(fssm->fssm_Environ << 2);
  633.             if (de && de->de_TableSize >= DE_UPPERCYL) {
  634.                 // Read settings from FSSM and Envec
  635.                 strncpy(dev_name, (char *)(fssm->fssm_Device << 2) + 1, 255);
  636.                 dev_name[255] = 0;
  637.                 dev_unit = fssm->fssm_Unit;
  638.                 dev_flags = fssm->fssm_Flags;
  639.                 dev_start = de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl;
  640.                 dev_size = de->de_BlocksPerTrack * de->de_Surfaces * (de->de_HighCyl - de->de_LowCyl + 1);
  641.                 dev_bsize = de->de_SizeBlock << 2;
  642.             }
  643.         }
  644.     }
  645.     UnLockDosList(LDF_DEVICES | LDF_READ);
  646. }
  647.  
  648. // Display and handle "Add/Edit Volume" window
  649. static void add_edit_volume(struct LayoutHandle *h2, bool adding)
  650. {
  651.     bool ok_clicked = false;
  652.  
  653.     UWORD sel = LT_GetAttributes(h2, GAD_DISK_LIST, TAG_END);
  654.     if ((sel == 0xffff) && !adding)
  655.         return;
  656.  
  657.     char dev_name[256] = "";
  658.     char file_name[256] = "";
  659.     ULONG dev_unit = 0, dev_flags = 0, dev_start = 0, dev_size = 0, dev_bsize = 512;
  660.     BYTE read_only = false, is_device = false;
  661.  
  662.     if (!adding) {
  663.         const char *str = PrefsFindString("disk", sel);
  664.         if (str == NULL)
  665.             return;
  666.         if (str[0] == '*') {
  667.             read_only = true;
  668.             str++;
  669.         }
  670.         if (strstr(str, "/dev/") == str) {
  671.             is_device = true;
  672.             sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", dev_name, &dev_unit, &dev_flags, &dev_start, &dev_size, &dev_bsize);
  673.         } else {
  674.             strncpy(file_name, str, sizeof(file_name) - 1);
  675.             file_name[sizeof(file_name) - 1] = 0;
  676.         }
  677.     }
  678.  
  679.     // Create layout handle
  680.     struct LayoutHandle *h = NULL;
  681.     struct Window *win = NULL;
  682.     h = LT_CreateHandleTags(NULL,
  683.         LAHN_AutoActivate, FALSE,
  684.         LAHN_LocaleHook, (ULONG)&locale_hook,
  685.         TAG_END
  686.     );
  687.     if (h == NULL)
  688.         return;
  689.  
  690.     // Create window contents
  691.     VGROUP;
  692.         // Volume gadgets
  693.         VGROUP;
  694.             LT_New(h, LA_Type, CHECKBOX_KIND,
  695.                 LA_LabelID, STR_VOL_READONLY_CTRL,
  696.                 LA_ID, GAD_VOLUME_READONLY,
  697.                 LA_BYTE, (ULONG)&read_only,
  698.                 TAG_END
  699.             );
  700.             LT_New(h, LA_Type, CYCLE_KIND,
  701.                 LA_LabelID, STR_VOL_TYPE_CTRL,
  702.                 LA_ID, GAD_VOLUME_TYPE,
  703.                 LACY_AutoPageID, GAD_VOLUME_PAGEGROUP,
  704.                 LACY_FirstLabel, STR_VOL_FILE_LAB,
  705.                 LACY_LastLabel, STR_VOL_DEVICE_LAB,
  706.                 LA_BYTE, (ULONG)&is_device,
  707.                 TAG_END
  708.             );
  709.         ENDGROUP;
  710.         LT_New(h, LA_Type, VERTICAL_KIND,
  711.             LA_ID, GAD_VOLUME_PAGEGROUP,
  712.             LAGR_ActivePage, is_device,
  713.             TAG_END
  714.         );
  715.             VGROUP;
  716.                 LT_New(h, LA_Type, STRING_KIND,
  717.                     LA_LabelID, STR_VOL_FILE_CTRL,
  718.                     LA_ID, GAD_VOLUME_FILE,
  719.                     LA_Chars, 20,
  720.                     LA_STRPTR, (ULONG)file_name,
  721.                     GTST_MaxChars, sizeof(file_name) - 1,
  722.                     LAST_Picker, TRUE,
  723.                     TAG_END
  724.                 );
  725.             ENDGROUP;
  726.             VGROUP;
  727.                 LT_New(h, LA_Type, STRING_KIND,
  728.                     LA_LabelID, STR_DEVICE_CTRL,
  729.                     LA_ID, GAD_VOLUME_DEVICE,
  730.                     LA_Chars, 20,
  731.                     LA_STRPTR, (ULONG)dev_name,
  732.                     GTST_MaxChars, sizeof(dev_name) - 1,
  733.                     LAST_Picker, TRUE,
  734.                     TAG_END
  735.                 );
  736.                 LT_New(h, LA_Type, INTEGER_KIND,
  737.                     LA_LabelID, STR_UNIT_CTRL,
  738.                     LA_ID, GAD_VOLUME_UNIT,
  739.                     LA_LONG, (ULONG)&dev_unit,
  740.                     LAIN_UseIncrementers, TRUE,
  741.                     GTIN_MaxChars, 8,
  742.                     TAG_END
  743.                 );
  744.                 LT_New(h, LA_Type, INTEGER_KIND,
  745.                     LA_LabelID, STR_VOL_OPENFLAGS_CTRL,
  746.                     LA_ID, GAD_VOLUME_OPENFLAGS,
  747.                     LA_LONG, (ULONG)&dev_flags,
  748.                     LAIN_UseIncrementers, TRUE,
  749.                     GTIN_MaxChars, 8,
  750.                     TAG_END
  751.                 );
  752.                 LT_New(h, LA_Type, INTEGER_KIND,
  753.                     LA_LabelID, STR_VOL_STARTBLOCK_CTRL,
  754.                     LA_ID, GAD_VOLUME_STARTBLOCK,
  755.                     LA_LONG, (ULONG)&dev_start,
  756.                     LAIN_UseIncrementers, TRUE,
  757.                     GTIN_MaxChars, 8,
  758.                     TAG_END
  759.                 );
  760.                 LT_New(h, LA_Type, INTEGER_KIND,
  761.                     LA_LabelID, STR_VOL_SIZE_CTRL,
  762.                     LA_ID, GAD_VOLUME_SIZE,
  763.                     LA_LONG, (ULONG)&dev_size,
  764.                     LAIN_UseIncrementers, TRUE,
  765.                     GTIN_MaxChars, 8,
  766.                     TAG_END
  767.                 );
  768.                 LT_New(h, LA_Type, INTEGER_KIND,
  769.                     LA_LabelID, STR_VOL_BLOCKSIZE_CTRL,
  770.                     LA_ID, GAD_VOLUME_BLOCKSIZE,
  771.                     LA_LONG, (ULONG)&dev_bsize,
  772.                     LAIN_UseIncrementers, TRUE,
  773.                     GTIN_MaxChars, 8,
  774.                     TAG_END
  775.                 );
  776.             ENDGROUP;
  777.         ENDGROUP;
  778.  
  779.         // Separator between gadgets and buttons
  780.         VGROUP;
  781.             LT_New(h, LA_Type, XBAR_KIND,
  782.                 LAXB_FullSize, TRUE,
  783.                 TAG_END
  784.             );
  785.         ENDGROUP;
  786.  
  787.         // "OK" and "Cancel" buttons
  788.         LT_New(h, LA_Type, HORIZONTAL_KIND,
  789.             LAGR_SameSize, TRUE,
  790.             LAGR_Spread, TRUE,
  791.             TAG_END
  792.         );
  793.             LT_New(h, LA_Type, BUTTON_KIND,
  794.                 LA_LabelID, STR_OK_BUTTON,
  795.                 LA_ID, MSG_OK,
  796.                 LABT_ReturnKey, TRUE,
  797.                 TAG_END
  798.             );
  799.             LT_New(h, LA_Type, BUTTON_KIND,
  800.                 LA_LabelID, STR_CANCEL_BUTTON,
  801.                 LA_ID, MSG_CANCEL,
  802.                 LABT_EscKey, TRUE,
  803.                 TAG_END
  804.             );
  805.         ENDGROUP;
  806.     ENDGROUP;
  807.  
  808.     // Open window
  809.     win = LT_Build(h,
  810.         LAWN_TitleID, adding ? STR_ADD_VOLUME_TITLE : STR_EDIT_VOLUME_TITLE,
  811.         LAWN_IDCMP, IDCMP_CLOSEWINDOW,
  812.         LAWN_BelowMouse, TRUE,
  813.         LAWN_SmartZoom, TRUE,
  814.         WA_SimpleRefresh, TRUE,
  815.         WA_Activate, TRUE,
  816.         WA_CloseGadget, TRUE,
  817.         WA_DepthGadget, TRUE,
  818.         WA_DragBar, TRUE,
  819.         TAG_END
  820.     );
  821.     if (win == NULL) {
  822.         LT_DeleteHandle(h);
  823.         return;
  824.     }
  825.  
  826.     // Event loop
  827.     bool done = false;
  828.     do {
  829.         struct IntuiMessage *msg;
  830.  
  831.         // Wait for message
  832.         WaitPort(win->UserPort);
  833.  
  834.         // Get pending messages
  835.         while (msg = LT_GetIMsg(h)) {
  836.  
  837.             // Get data from message and reply
  838.             ULONG cl = msg->Class;
  839.             UWORD code = msg->Code;
  840.             struct Gadget *gad = (struct Gadget *)msg->IAddress;
  841.             LT_ReplyIMsg(msg);
  842.  
  843.             // Handle message according to class
  844.             switch (cl) {
  845.                 case IDCMP_CLOSEWINDOW:
  846.                     done = true;
  847.                     break;
  848.  
  849.                 case IDCMP_GADGETUP:
  850.                     switch (gad->GadgetID) {
  851.                         case MSG_OK:
  852.                             ok_clicked = true;
  853.                             done = true;
  854.                             break;
  855.                         case MSG_CANCEL:
  856.                             done = true;
  857.                             break;
  858.                     }
  859.                     break;
  860.  
  861.                 case IDCMP_IDCMPUPDATE: {
  862.                     struct FileRequester *req = NULL;
  863.                     switch (gad->GadgetID) {
  864.                         case GAD_VOLUME_FILE:
  865.                             req = file_request;
  866.                             goto do_req;
  867.                         case GAD_VOLUME_DEVICE:
  868.                             req = dev_request;
  869. do_req:                        if (req) {
  870.                                 LT_LockWindow(win);
  871.                                 BOOL result = AslRequestTags(req, ASLFR_Window, (ULONG)win, TAG_END);
  872.                                 LT_UnlockWindow(win);
  873.                                 if (result) {
  874.                                     char *str;
  875.                                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
  876.                                     if (gad->GadgetID == GAD_VOLUME_FILE) {
  877.                                         strncpy(str, req->rf_Dir, 255);
  878.                                         str[255] = 0;
  879.                                         AddPart(str, req->rf_File, 255);
  880.                                     } else {
  881.                                         if (strlen(req->rf_File)) {
  882.                                             strncpy(str, req->rf_File, 255);    // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
  883.                                             str[255] = 0;
  884.                                         } else if (strlen(req->rf_Dir) && req->rf_Dir[strlen(req->rf_Dir) - 1] == ':') {
  885.                                             analyze_partition(req->rf_Dir, str, dev_unit, dev_flags, dev_start, dev_size, dev_bsize);
  886.                                             LT_SetAttributes(h, GAD_VOLUME_UNIT, GTIN_Number, dev_unit, TAG_END);
  887.                                             LT_SetAttributes(h, GAD_VOLUME_OPENFLAGS, GTIN_Number, dev_flags, TAG_END);
  888.                                             LT_SetAttributes(h, GAD_VOLUME_STARTBLOCK, GTIN_Number, dev_start, TAG_END);
  889.                                             LT_SetAttributes(h, GAD_VOLUME_SIZE, GTIN_Number, dev_size, TAG_END);
  890.                                             LT_SetAttributes(h, GAD_VOLUME_BLOCKSIZE, GTIN_Number, dev_bsize, TAG_END);
  891.                                         }
  892.                                     }
  893.                                     LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
  894.                                 }
  895.                             }
  896.                             break;
  897.                     }
  898.                     break;
  899.                 }
  900.             }
  901.         }
  902.     } while (!done);
  903.  
  904.     // Update preferences and list view
  905.     if (ok_clicked) {
  906.         char str[256];
  907.         LT_UpdateStrings(h);
  908.  
  909.         if (is_device)
  910.             sprintf(str, "%s/dev/%s/%ld/%ld/%ld/%ld/%ld", read_only ? "*" : "", dev_name, dev_unit, dev_flags, dev_start, dev_size, dev_bsize);
  911.         else
  912.             sprintf(str, "%s%s", read_only ? "*" : "", file_name);
  913.         LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END);
  914.  
  915.         if (adding) {
  916.  
  917.             // Add new item
  918.             int i;
  919.             PrefsAddString("disk", str);
  920.             struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR);
  921.             for (i=0; PrefsFindString("disk", i); i++) ;
  922.             item->ln_Name = (char *)PrefsFindString("disk", i - 1);
  923.             AddTail(&disk_list, item);
  924.  
  925.         } else {
  926.  
  927.             // Replace existing item
  928.             PrefsReplaceString("disk", str, sel);
  929.             struct Node *item = disk_list.lh_Head;
  930.             for (int i=0; item->ln_Succ; i++) {
  931.                 if (i == sel) {
  932.                     item->ln_Name = (char *)PrefsFindString("disk", sel);
  933.                     break;
  934.                 }
  935.                 item = item->ln_Succ;
  936.             }
  937.         }
  938.         LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, TAG_END);
  939.         ghost_volumes_gadgets(h2);
  940.     }
  941.  
  942.     // Delete handle
  943.     LT_DeleteHandle(h);
  944. }
  945.  
  946. // Remove volume from list
  947. static void remove_volume(struct LayoutHandle *h)
  948. {
  949.     UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END);
  950.     if (sel != 0xffff) {
  951.  
  952.         // Remove item from preferences and list view
  953.         LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END);
  954.         PrefsRemoveItem("disk", sel);
  955.         struct Node *item = disk_list.lh_Head;
  956.         for (int i=0; item->ln_Succ; i++) {
  957.             struct Node *next = item->ln_Succ;
  958.             if (i == sel) {
  959.                 Remove(item);
  960.                 FreeMem(item, sizeof(struct Node));
  961.                 break;
  962.             }
  963.             item = next;
  964.         }
  965.         LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, GTLV_Selected, 0xffff, TAG_END);
  966.         ghost_volumes_gadgets(h);
  967.     }
  968. }
  969.  
  970. // Read settings from gadgets and set preferences
  971. static void read_volumes_settings(void)
  972. {
  973.     struct Node *item = disk_list.lh_Head;
  974.     while (item->ln_Succ) {
  975.         struct Node *next = item->ln_Succ;
  976.         Remove(item);
  977.         FreeMem(item, sizeof(struct Node));
  978.         item = next;
  979.     }
  980.  
  981.     if (strlen(cdrom_name)) {
  982.         char str[256];
  983.         sprintf(str, "/dev/%s/%ld/%ld/%ld/%ld/%ld", cdrom_name, cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize);
  984.         PrefsReplaceString("cdrom", str);
  985.     } else
  986.         PrefsRemoveItem("cdrom");
  987.  
  988.     PrefsReplaceBool("nocdrom", nocdrom);
  989.  
  990.     if (strlen(extfs_name))
  991.         PrefsReplaceString("extfs", extfs_name);
  992. }
  993.  
  994. // Create "Volumes" pane
  995. static void create_volumes_pane(struct LayoutHandle *h)
  996. {
  997.     parse_volumes_prefs();
  998.  
  999.     VGROUP;
  1000.         LT_New(h, LA_Type, VERTICAL_KIND,
  1001.             LA_LabelID, STR_VOLUMES_CTRL,
  1002.             TAG_END
  1003.         );
  1004.             VGROUP;
  1005.                 LT_New(h, LA_Type, LISTVIEW_KIND,
  1006.                     LA_ID, GAD_DISK_LIST,
  1007.                     LA_Chars, 20,
  1008.                     GTLV_Labels, (ULONG)&disk_list,
  1009.                     LALV_Lines, 6,
  1010.                     LALV_Link, (ULONG)NIL_LINK,
  1011.                     LALV_ResizeX, TRUE,
  1012.                     LALV_ResizeY, TRUE,
  1013.                     LALV_Selected, 0,
  1014.                     TAG_END
  1015.                 );
  1016.             ENDGROUP;
  1017.             LT_New(h, LA_Type, HORIZONTAL_KIND,
  1018.                 LAGR_SameSize, TRUE,
  1019.                 LAGR_Spread, TRUE,
  1020.                 TAG_END
  1021.             );
  1022.                 LT_New(h, LA_Type, BUTTON_KIND,
  1023.                     LA_LabelID, STR_ADD_VOLUME_BUTTON,
  1024.                     LA_ID, GAD_ADD_VOLUME,
  1025.                     TAG_END
  1026.                 );
  1027.                 LT_New(h, LA_Type, BUTTON_KIND,
  1028.                     LA_LabelID, STR_EDIT_VOLUME_BUTTON,
  1029.                     LA_ID, GAD_EDIT_VOLUME,
  1030.                     TAG_END
  1031.                 );
  1032.                 LT_New(h, LA_Type, BUTTON_KIND,
  1033.                     LA_LabelID, STR_REMOVE_VOLUME_BUTTON,
  1034.                     LA_ID, GAD_REMOVE_VOLUME,
  1035.                     TAG_END
  1036.                 );
  1037.             ENDGROUP;
  1038.         ENDGROUP;
  1039.         LT_New(h, LA_Type, VERTICAL_KIND,
  1040.             LA_LabelID, STR_CDROM_DRIVE_CTRL,
  1041.             TAG_END
  1042.         );
  1043.             LT_New(h, LA_Type, STRING_KIND,
  1044.                 LA_LabelID, STR_DEVICE_CTRL,
  1045.                 LA_ID, GAD_CDROM_DEVICE,
  1046.                 LA_Chars, 20,
  1047.                 LA_STRPTR, (ULONG)cdrom_name,
  1048.                 GTST_MaxChars, sizeof(cdrom_name) - 1,
  1049.                 LAST_Picker, TRUE,
  1050.                 TAG_END
  1051.             );
  1052.             LT_New(h, LA_Type, INTEGER_KIND,
  1053.                 LA_LabelID, STR_UNIT_CTRL,
  1054.                 LA_ID, GAD_CDROM_UNIT,
  1055.                 LA_LONG, (ULONG)&cdrom_unit,
  1056.                 LAIN_UseIncrementers, TRUE,
  1057.                 GTIN_MaxChars, 8,
  1058.                 TAG_END
  1059.             );
  1060.             LT_New(h, LA_Type, CYCLE_KIND,
  1061.                 LA_LabelID, STR_BOOTDRIVER_CTRL,
  1062.                 LA_ID, GAD_BOOTDRIVER,
  1063.                 LACY_FirstLabel, STR_BOOT_ANY_LAB,
  1064.                 LACY_LastLabel, STR_BOOT_CDROM_LAB,
  1065.                 LA_BYTE, (ULONG)&bootdriver_num,
  1066.                 TAG_END
  1067.             );
  1068.             LT_New(h, LA_Type, CHECKBOX_KIND,
  1069.                 LA_LabelID, STR_NOCDROM_CTRL,
  1070.                 LA_ID, GAD_NOCDROM,
  1071.                 LA_BYTE, (ULONG)&nocdrom,
  1072.                 TAG_END
  1073.             );
  1074.         ENDGROUP;
  1075.         VGROUP;
  1076.             LT_New(h, LA_Type, STRING_KIND,
  1077.                 LA_LabelID, STR_EXTFS_CTRL,
  1078.                 LA_ID, GAD_EXTFS,
  1079.                 LA_Chars, 20,
  1080.                 LA_STRPTR, (ULONG)extfs_name,
  1081.                 GTST_MaxChars, sizeof(extfs_name) - 1,
  1082.                 TAG_END
  1083.             );
  1084.         ENDGROUP;
  1085.     ENDGROUP;
  1086. }
  1087.  
  1088.  
  1089. /*
  1090.  *  "SCSI" pane
  1091.  */
  1092.  
  1093. static char scsi_dev[6][256];
  1094. static LONG scsi_unit[6];
  1095. static LONG scsi_memtype;
  1096.  
  1097. // Read SCSI preferences
  1098. static void parse_scsi_prefs(void)
  1099. {
  1100.     for (int i=0; i<7; i++) {
  1101.         scsi_dev[i][0] = 0;
  1102.         scsi_unit[i] = 0;
  1103.  
  1104.         char prefs_name[16];
  1105.         sprintf(prefs_name, "scsi%d", i);
  1106.         const char *str = PrefsFindString(prefs_name);
  1107.         if (str)
  1108.             sscanf(str, "%[^/]/%ld", scsi_dev[i], &scsi_unit[i]);
  1109.     }
  1110.  
  1111.     scsi_memtype = PrefsFindInt32("scsimemtype");
  1112. }
  1113.  
  1114. // Read settings from gadgets and set preferences
  1115. static void read_scsi_settings(void)
  1116. {
  1117.     for (int i=0; i<7; i++) {
  1118.         char prefs_name[16];
  1119.         sprintf(prefs_name, "scsi%d", i);
  1120.  
  1121.         if (strlen(scsi_dev[i])) {
  1122.             char str[256];
  1123.             sprintf(str, "%s/%ld", scsi_dev[i], scsi_unit[i]);
  1124.             PrefsReplaceString(prefs_name, str);
  1125.         } else
  1126.             PrefsRemoveItem(prefs_name);
  1127.     }
  1128. }
  1129.  
  1130. // Create "SCSI" pane
  1131. static void create_scsi_pane(struct LayoutHandle *h)
  1132. {
  1133.     parse_scsi_prefs();
  1134.  
  1135.     VGROUP;
  1136.         LT_New(h, LA_Type, VERTICAL_KIND,
  1137.             LA_LabelID, STR_SCSI_DEVICES_CTRL,
  1138.             TAG_END
  1139.         );
  1140.             for (int i=0; i<7; i++) {
  1141.                 HGROUP;
  1142.                     LT_New(h, LA_Type, TEXT_KIND,
  1143.                         LA_LabelID, STR_SCSI_ID_0 + i,
  1144.                         TAG_END
  1145.                     );
  1146.                     LT_New(h, LA_Type, STRING_KIND,
  1147.                         LA_LabelID, STR_DEVICE_CTRL,
  1148.                         LA_ID, GAD_SCSI0_DEVICE + i,
  1149.                         LA_Chars, 20,
  1150.                         LA_STRPTR, (ULONG)scsi_dev[i],
  1151.                         GTST_MaxChars, sizeof(scsi_dev[i]) - 1,
  1152.                         LAST_Picker, TRUE,
  1153.                         TAG_END
  1154.                     );
  1155.                     LT_New(h, LA_Type, INTEGER_KIND,
  1156.                         LA_LabelID, STR_UNIT_CTRL,
  1157.                         LA_ID, GAD_SCSI0_UNIT + i,
  1158.                         LA_Chars, 4,
  1159.                         LA_LONG, (ULONG)&scsi_unit[i],
  1160.                         LAIN_UseIncrementers, TRUE,
  1161.                         GTIN_MaxChars, 8,
  1162.                         TAG_END
  1163.                     );
  1164.                 ENDGROUP;
  1165.             }
  1166.         ENDGROUP;
  1167.         VGROUP;
  1168.             LT_New(h, LA_Type, CYCLE_KIND,
  1169.                 LA_LabelID, STR_SCSI_MEMTYPE_CTRL,
  1170.                 LA_ID, GAD_SCSI_MEMTYPE,
  1171.                 LACY_FirstLabel, STR_MEMTYPE_CHIP_LAB,
  1172.                 LACY_LastLabel, STR_MEMTYPE_ANY_LAB,
  1173.                 LA_LONG, (ULONG)&scsi_memtype,
  1174.                 TAG_END
  1175.             );
  1176.         ENDGROUP;
  1177.     ENDGROUP;
  1178. }
  1179.  
  1180.  
  1181. /*
  1182.  *  "Graphics/Sound" pane
  1183.  */
  1184.  
  1185. // Display types
  1186. enum {
  1187.     DISPLAY_WINDOW,
  1188.     DISPLAY_PIP,
  1189.     DISPLAY_SCREEN
  1190. };
  1191.  
  1192. static LONG display_type;
  1193. static LONG dis_width, dis_height;
  1194. static ULONG mode_id;
  1195. static BYTE frameskip_num;
  1196. static struct NameInfo mode_name;
  1197. static ULONG ahi_id;
  1198. static char ahi_mode_name[256];
  1199. static BYTE nosound;
  1200.  
  1201. // Read graphics preferences
  1202. static void parse_graphics_prefs(void)
  1203. {
  1204.     display_type = DISPLAY_WINDOW;
  1205.     dis_width = 512;
  1206.     dis_height = 384;
  1207.     mode_id = 0;
  1208.     ahi_id = AHI_DEFAULT_ID;
  1209.     ahi_mode_name[0] = 0;
  1210.  
  1211.     frameskip_num = 0;
  1212.     int frameskip = PrefsFindInt32("frameskip");
  1213.     switch (frameskip) {
  1214.         case 12:
  1215.             frameskip_num = 0;
  1216.             break;
  1217.         case 8:
  1218.             frameskip_num = 1;
  1219.             break;
  1220.         case 6:
  1221.             frameskip_num = 2;
  1222.             break;
  1223.         case 4:
  1224.             frameskip_num = 3;
  1225.             break;
  1226.         case 2:
  1227.             frameskip_num = 4;
  1228.             break;
  1229.         case 1:
  1230.             frameskip_num = 5;
  1231.             break;
  1232.     }
  1233.  
  1234.     const char *str = PrefsFindString("screen");
  1235.     if (str) {
  1236.         if (sscanf(str, "win/%ld/%ld", &dis_width, &dis_height) == 2)
  1237.             display_type = DISPLAY_WINDOW;
  1238.         else if (sscanf(str, "pip/%ld/%ld", &dis_width, &dis_height) == 2)
  1239.             display_type = DISPLAY_PIP;
  1240.         else if (sscanf(str, "scr/%08lx", &mode_id) == 1)
  1241.             display_type = DISPLAY_SCREEN;
  1242.     }
  1243.  
  1244.     GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id);
  1245.  
  1246.     str = PrefsFindString("sound");
  1247.     if (str) {
  1248.         if (sscanf(str, "ahi/%08lx", &ahi_id) == 1 && AHIBase) {
  1249.             AHI_GetAudioAttrs(ahi_id, NULL,
  1250.                 AHIDB_Name, (ULONG)ahi_mode_name,
  1251.                 AHIDB_BufferLen, sizeof(ahi_mode_name) - 1,
  1252.                 TAG_END
  1253.             );
  1254.         }
  1255.     }
  1256.     nosound = PrefsFindBool("nosound");
  1257. }
  1258.  
  1259. // Ghost/unghost graphics gadgets, depending on display type
  1260. static void ghost_graphics_gadgets(struct LayoutHandle *h)
  1261. {
  1262.     bool dis_xy, dis_skip, dis_mode;
  1263.     switch (display_type) {
  1264.         case DISPLAY_WINDOW:
  1265.             dis_xy = false;
  1266.             dis_skip = false;
  1267.             dis_mode = true;
  1268.             break;
  1269.         case DISPLAY_PIP:
  1270.             dis_xy = false;
  1271.             dis_skip = true;
  1272.             dis_mode = true;
  1273.             break;
  1274.         case DISPLAY_SCREEN:
  1275.             dis_xy = true;
  1276.             dis_skip = true;
  1277.             dis_mode = false;
  1278.             break;
  1279.     }
  1280.     LT_SetAttributes(h, GAD_DISPLAY_X, GA_Disabled, dis_xy, TAG_END);
  1281.     LT_SetAttributes(h, GAD_DISPLAY_Y, GA_Disabled, dis_xy, TAG_END);
  1282.     LT_SetAttributes(h, GAD_FRAMESKIP, GA_Disabled, dis_skip, TAG_END);
  1283.     LT_SetAttributes(h, GAD_SCREEN_MODE, GA_Disabled, dis_mode, TAG_END);
  1284.     LT_SetAttributes(h, GAD_AHI_MODE, GA_Disabled, AHIBase == NULL, TAG_END);
  1285. }
  1286.  
  1287. // Show screen mode requester
  1288. static void screen_mode_req(struct Window *win, struct LayoutHandle *h)
  1289. {
  1290.     if (P96Base == NULL && CyberGfxBase == NULL)
  1291.         return;
  1292.  
  1293.     LT_LockWindow(win);
  1294.  
  1295.     ULONG id;
  1296.  
  1297.     // Try P96 first, because it also provides a (fake) cybergraphics.library
  1298.     if (P96Base) {
  1299.         id = p96RequestModeIDTags(
  1300.             P96MA_MinDepth, 8,
  1301.             P96MA_FormatsAllowed, RGBFF_CLUT | RGBFF_R5G5B5 | RGBFF_A8R8G8B8,
  1302.             TAG_END
  1303.         );
  1304.     } else {
  1305.         UWORD ModelArray[] = { PIXFMT_LUT8, PIXFMT_RGB15, PIXFMT_ARGB32, 0, ~0 };
  1306.         id = (ULONG) CModeRequestTags(NULL,
  1307.             CYBRMREQ_MinDepth, 8,
  1308.             CYBRMREQ_CModelArray, (ULONG) ModelArray,
  1309.             TAG_END
  1310.         );
  1311.     }
  1312.     LT_UnlockWindow(win);
  1313.  
  1314.     if (id != INVALID_ID) {
  1315.         mode_id = id;
  1316.         GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id);
  1317.         LT_SetAttributes(h, GAD_SCREEN_MODE, GTTX_Text, (ULONG)mode_name.Name, TAG_END);
  1318.     }
  1319. }
  1320.  
  1321. // Show AHI mode requester
  1322. static void ahi_mode_req(struct Window *win, struct LayoutHandle *h)
  1323. {
  1324.     if (AHIBase == NULL)
  1325.         return;
  1326.  
  1327.     struct AHIAudioModeRequester *req = AHI_AllocAudioRequest(
  1328.         AHIR_Window, (ULONG)win,
  1329.         TAG_END
  1330.     );
  1331.     if (req == NULL)
  1332.         return;
  1333.  
  1334.     LT_LockWindow(win);
  1335.     BOOL ok = AHI_AudioRequest(req,
  1336.         AHIR_InitialAudioID, ahi_id,
  1337.         TAG_END
  1338.     );
  1339.     LT_UnlockWindow(win);
  1340.  
  1341.     if (ok) {
  1342.         ahi_id = req->ahiam_AudioID;
  1343.         AHI_GetAudioAttrs(ahi_id, NULL,
  1344.             AHIDB_Name, (ULONG)ahi_mode_name,
  1345.             AHIDB_BufferLen, sizeof(ahi_mode_name) - 1,
  1346.             TAG_END
  1347.         );
  1348.         LT_SetAttributes(h, GAD_AHI_MODE, GTTX_Text, (ULONG)ahi_mode_name, TAG_END);
  1349.     }
  1350.     AHI_FreeAudioRequest(req);
  1351. }
  1352.  
  1353. // Read settings from gadgets and set preferences
  1354. static void read_graphics_settings(void)
  1355. {
  1356.     char str[256];
  1357.     switch (display_type) {
  1358.         case DISPLAY_WINDOW:
  1359.             sprintf(str, "win/%ld/%ld", dis_width, dis_height);
  1360.             break;
  1361.         case DISPLAY_PIP:
  1362.             sprintf(str, "pip/%ld/%ld", dis_width, dis_height);
  1363.             break;
  1364.         case DISPLAY_SCREEN:
  1365.             sprintf(str, "scr/%08lx", mode_id);
  1366.             break;
  1367.         default:
  1368.             PrefsRemoveItem("screen");
  1369.             return;
  1370.     }
  1371.     PrefsReplaceString("screen", str);
  1372.  
  1373.     sprintf(str, "ahi/%08lx", ahi_id);
  1374.     PrefsReplaceString("sound", str);
  1375.  
  1376.     PrefsReplaceBool("nosound", nosound);
  1377. }
  1378.  
  1379. // Create "Graphics/Sound" pane
  1380. static void create_graphics_pane(struct LayoutHandle *h)
  1381. {
  1382.     parse_graphics_prefs();
  1383.  
  1384.     VGROUP;
  1385.         LT_New(h, LA_Type, VERTICAL_KIND,
  1386.             LA_LabelID, STR_GRAPHICS_CTRL,
  1387.             TAG_END
  1388.         );
  1389.             static const LONG labels[] = {STR_WINDOW_LAB, STR_PIP_LAB, STR_FULLSCREEN_LAB, -1};
  1390.             LT_New(h, LA_Type, CYCLE_KIND,
  1391.                 LA_LabelID, STR_VIDEO_TYPE_CTRL,
  1392.                 LA_ID, GAD_VIDEO_TYPE,
  1393.                 LACY_LabelTable, (ULONG)labels,
  1394.                 LA_LONG, (ULONG)&display_type,
  1395.                 TAG_END
  1396.             );
  1397.             LT_New(h, LA_Type, INTEGER_KIND,
  1398.                 LA_LabelID, STR_DISPLAY_X_CTRL,
  1399.                 LA_ID, GAD_DISPLAY_X,
  1400.                 LA_LONG, (ULONG)&dis_width,
  1401.                 GTIN_MaxChars, 8,
  1402.                 TAG_END
  1403.             );
  1404.             LT_New(h, LA_Type, INTEGER_KIND,
  1405.                 LA_LabelID, STR_DISPLAY_Y_CTRL,
  1406.                 LA_ID, GAD_DISPLAY_Y,
  1407.                 LA_LONG, (ULONG)&dis_height,
  1408.                 GTIN_MaxChars, 8,
  1409.                 TAG_END
  1410.             );
  1411.             LT_New(h, LA_Type, POPUP_KIND,
  1412.                 LA_LabelID, STR_FRAMESKIP_CTRL,
  1413.                 LA_ID, GAD_FRAMESKIP,
  1414.                 LAPU_FirstLabel, STR_REF_5HZ_LAB,
  1415.                 LAPU_LastLabel, STR_REF_60HZ_LAB,
  1416.                 LA_BYTE, (ULONG)&frameskip_num,
  1417.                 TAG_END
  1418.             );
  1419.             LT_New(h, LA_Type, TEXT_KIND,
  1420.                 LA_LabelID, STR_SCREEN_MODE_CTRL,
  1421.                 LA_ID, GAD_SCREEN_MODE,
  1422.                 LA_Chars, DISPLAYNAMELEN,
  1423.                 LATX_Picker, TRUE,
  1424.                 GTTX_Text, (ULONG)mode_name.Name,
  1425.                 GTTX_Border, TRUE,
  1426.                 TAG_END
  1427.             );
  1428.         ENDGROUP;
  1429.         LT_New(h, LA_Type, VERTICAL_KIND,
  1430.             LA_LabelID, STR_SOUND_CTRL,
  1431.             TAG_END
  1432.         );
  1433.             LT_New(h, LA_Type, TEXT_KIND,
  1434.                 LA_LabelID, STR_AHI_MODE_CTRL,
  1435.                 LA_ID, GAD_AHI_MODE,
  1436.                 LA_Chars, DISPLAYNAMELEN,
  1437.                 LATX_Picker, TRUE,
  1438.                 GTTX_Text, (ULONG)ahi_mode_name,
  1439.                 GTTX_Border, TRUE,
  1440.                 TAG_END
  1441.             );
  1442.             LT_New(h, LA_Type, CHECKBOX_KIND,
  1443.                 LA_LabelID, STR_NOSOUND_CTRL,
  1444.                 LA_ID, GAD_NOSOUND,
  1445.                 LA_BYTE, (ULONG)&nosound,
  1446.                 TAG_END
  1447.             );
  1448.         ENDGROUP;
  1449.     ENDGROUP;
  1450.  
  1451.     ghost_graphics_gadgets(h);
  1452. }
  1453.  
  1454.  
  1455. /*
  1456.  *  "Serial/Network" pane
  1457.  */
  1458.  
  1459. static char seriala_dev[256], serialb_dev[256];
  1460. static LONG seriala_unit, serialb_unit;
  1461. static BYTE seriala_ispar, serialb_ispar;
  1462.  
  1463. static char ether_dev[256];
  1464. static ULONG ether_unit;
  1465.  
  1466. // Read serial/network preferences
  1467. static void parse_ser_prefs(const char *prefs, char *dev, LONG &unit, BYTE &ispar)
  1468. {
  1469.     dev[0] = 0;
  1470.     unit = 0;
  1471.     ispar = false;
  1472.  
  1473.     const char *str = PrefsFindString(prefs);
  1474.     if (str) {
  1475.         if (str[0] == '*') {
  1476.             ispar = true;
  1477.             str++;
  1478.         }
  1479.         sscanf(str, "%[^/]/%ld", dev, &unit);
  1480.     }
  1481. }
  1482.  
  1483. static void parse_serial_prefs(void)
  1484. {
  1485.     parse_ser_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar);
  1486.     parse_ser_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar);
  1487.  
  1488.     ether_dev[0] = 0;
  1489.     ether_unit = 0;
  1490.  
  1491.     const char *str = PrefsFindString("ether");
  1492.     if (str) {
  1493.         const char *FirstSlash = strchr(str, '/');
  1494.         const char *LastSlash = strrchr(str, '/');
  1495.  
  1496.         if (FirstSlash && FirstSlash && FirstSlash != LastSlash) {
  1497.             // Device name contains path, i.e. "Networks/xyzzy.device"
  1498.             const char *lp = str;
  1499.             char *dp = ether_dev;
  1500.  
  1501.             while (lp != LastSlash)
  1502.                 *dp++ = *lp++;
  1503.             *dp = '\0';
  1504.  
  1505.             sscanf(LastSlash, "/%ld", ðer_unit);
  1506.  
  1507. //            printf("dev=<%s> unit=%d\n", ether_dev, ether_unit);
  1508.         } else {
  1509.             sscanf(str, "%[^/]/%ld", ether_dev, ðer_unit);
  1510.         }
  1511.     }
  1512. }
  1513.  
  1514. // Set serial preference item
  1515. static void make_serial_prefs(const char *prefs, const char *dev, LONG unit, BYTE ispar)
  1516. {
  1517.     if (strlen(dev)) {
  1518.         char str[256];
  1519.         sprintf(str, "%s%s/%ld", ispar ? "*" : "", dev, unit);
  1520.         PrefsReplaceString(prefs, str);
  1521.     } else
  1522.         PrefsRemoveItem(prefs);
  1523. }
  1524.  
  1525. // Read settings from gadgets and set preferences
  1526. static void read_serial_settings(void)
  1527. {
  1528.     make_serial_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar);
  1529.     make_serial_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar);
  1530.  
  1531.     if (strlen(ether_dev)) {
  1532.         char str[256];
  1533.  
  1534.         sprintf(str, "%s/%ld", ether_dev, ether_unit);
  1535.         PrefsReplaceString("ether", str);
  1536.     } else
  1537.         PrefsRemoveItem("ether");
  1538. }
  1539.  
  1540. // Create "Serial/Network" pane
  1541. static void create_serial_pane(struct LayoutHandle *h)
  1542. {
  1543.     parse_serial_prefs();
  1544.  
  1545.     VGROUP;
  1546.         LT_New(h, LA_Type, VERTICAL_KIND,
  1547.             LA_LabelID, STR_SERIALA_CTRL,
  1548.             TAG_END
  1549.         );
  1550.             LT_New(h, LA_Type, STRING_KIND,
  1551.                 LA_LabelID, STR_DEVICE_CTRL,
  1552.                 LA_ID, GAD_SERIALA_DEVICE,
  1553.                 LA_Chars, 20,
  1554.                 LA_STRPTR, (ULONG)seriala_dev,
  1555.                 GTST_MaxChars, sizeof(seriala_dev) - 1,
  1556.                 LAST_Picker, TRUE,
  1557.                 TAG_END
  1558.             );
  1559.             LT_New(h, LA_Type, INTEGER_KIND,
  1560.                 LA_LabelID, STR_UNIT_CTRL,
  1561.                 LA_ID, GAD_SERIALA_UNIT,
  1562.                 LA_LONG, (ULONG)&seriala_unit,
  1563.                 LAIN_UseIncrementers, TRUE,
  1564.                 GTIN_MaxChars, 8,
  1565.                 TAG_END
  1566.             );
  1567.             LT_New(h, LA_Type, CHECKBOX_KIND,
  1568.                 LA_LabelID, STR_ISPAR_CTRL,
  1569.                 LA_ID, GAD_SERIALA_ISPAR,
  1570.                 LA_BYTE, (ULONG)&seriala_ispar,
  1571.                 TAG_END
  1572.             );
  1573.         ENDGROUP;
  1574.  
  1575.         LT_New(h, LA_Type, VERTICAL_KIND,
  1576.             LA_LabelID, STR_SERIALB_CTRL,
  1577.             TAG_END
  1578.         );
  1579.             LT_New(h, LA_Type, STRING_KIND,
  1580.                 LA_LabelID, STR_DEVICE_CTRL,
  1581.                 LA_ID, GAD_SERIALB_DEVICE,
  1582.                 LA_Chars, 20,
  1583.                 LA_STRPTR, (ULONG)serialb_dev,
  1584.                 GTST_MaxChars, sizeof(serialb_dev) - 1,
  1585.                 LAST_Picker, TRUE,
  1586.                 TAG_END
  1587.             );
  1588.             LT_New(h, LA_Type, INTEGER_KIND,
  1589.                 LA_LabelID, STR_UNIT_CTRL,
  1590.                 LA_ID, GAD_SERIALB_UNIT,
  1591.                 LA_LONG, (ULONG)&serialb_unit,
  1592.                 LAIN_UseIncrementers, TRUE,
  1593.                 GTIN_MaxChars, 8,
  1594.                 TAG_END
  1595.             );
  1596.             LT_New(h, LA_Type, CHECKBOX_KIND,
  1597.                 LA_LabelID, STR_ISPAR_CTRL,
  1598.                 LA_ID, GAD_SERIALB_ISPAR,
  1599.                 LA_BYTE, (ULONG)&serialb_ispar,
  1600.                 TAG_END
  1601.             );
  1602.         ENDGROUP;
  1603.  
  1604.         LT_New(h, LA_Type, VERTICAL_KIND,
  1605.             LA_LabelID, STR_ETHERNET_IF_CTRL,
  1606.             TAG_END
  1607.         );
  1608.             LT_New(h, LA_Type, STRING_KIND,
  1609.                 LA_LabelID, STR_DEVICE_CTRL,
  1610.                 LA_ID, GAD_ETHER_DEVICE,
  1611.                 LA_Chars, 20,
  1612.                 LA_STRPTR, (ULONG)ether_dev,
  1613.                 GTST_MaxChars, sizeof(ether_dev) - 1,
  1614.                 LAST_Picker, TRUE,
  1615.                 TAG_END
  1616.             );
  1617.             LT_New(h, LA_Type, INTEGER_KIND,
  1618.                 LA_LabelID, STR_UNIT_CTRL,
  1619.                 LA_ID, GAD_ETHER_UNIT,
  1620.                 LA_LONG, (ULONG)ðer_unit,
  1621.                 LAIN_UseIncrementers, TRUE,
  1622.                 GTIN_MaxChars, 8,
  1623.                 TAG_END
  1624.             );
  1625.         ENDGROUP;
  1626.     ENDGROUP;
  1627. }
  1628.  
  1629.  
  1630. /*
  1631.  *  "Memory/Misc" pane
  1632.  */
  1633.  
  1634. static ULONG ramsize_mb;
  1635. static BYTE model_num;
  1636. static char rom_file[256];
  1637.  
  1638. // Read memory/misc preferences
  1639. static void parse_memory_prefs(void)
  1640. {
  1641.     ramsize_mb = PrefsFindInt32("ramsize") >> 20;
  1642.  
  1643.     model_num = 0;
  1644.     int id = PrefsFindInt32("modelid");
  1645.     switch (id) {
  1646.         case 5:
  1647.             model_num = 0;
  1648.             break;
  1649.         case 14:
  1650.             model_num = 1;
  1651.             break;
  1652.     }
  1653.  
  1654.     rom_file[0] = 0;
  1655.     const char *str = PrefsFindString("rom");
  1656.     if (str) {
  1657.         strncpy(rom_file, str, sizeof(rom_file) - 1);
  1658.         rom_file[sizeof(rom_file) - 1] = 0;
  1659.     }
  1660. }
  1661.  
  1662. // Read settings from gadgets and set preferences
  1663. static void read_memory_settings(void)
  1664. {
  1665.     PrefsReplaceInt32("ramsize", ramsize_mb << 20);
  1666.  
  1667.     if (strlen(rom_file))
  1668.         PrefsReplaceString("rom", rom_file);
  1669.     else
  1670.         PrefsRemoveItem("rom");
  1671. }
  1672.  
  1673. // Create "Memory/Misc" pane
  1674. static void create_memory_pane(struct LayoutHandle *h)
  1675. {
  1676.     parse_memory_prefs();
  1677.  
  1678.     VGROUP;
  1679.         LT_New(h, LA_Type, LEVEL_KIND,
  1680.             LA_LabelID, STR_RAMSIZE_SLIDER,
  1681.             LA_ID, GAD_RAMSIZE,
  1682.             LA_Chars, 20,
  1683.             LA_LONG, (ULONG)&ramsize_mb,
  1684.             GTSL_LevelFormat, (ULONG)GetString(STR_RAMSIZE_FMT),
  1685.             GTSL_Min, 1,
  1686.             GTSL_Max, AvailMem(MEMF_LARGEST) >> 20,
  1687.             TAG_END
  1688.         );
  1689.         LT_New(h, LA_Type, CYCLE_KIND,
  1690.             LA_LabelID, STR_MODELID_CTRL,
  1691.             LA_ID, GAD_MODELID,
  1692.             LACY_FirstLabel, STR_MODELID_5_LAB,
  1693.             LACY_LastLabel, STR_MODELID_14_LAB,
  1694.             LA_BYTE, (ULONG)&model_num,
  1695.             TAG_END
  1696.         );
  1697.         LT_New(h, LA_Type, STRING_KIND,
  1698.             LA_LabelID, STR_ROM_FILE_CTRL,
  1699.             LA_ID, GAD_ROM_FILE,
  1700.             LA_Chars, 20,
  1701.             LA_STRPTR, (ULONG)rom_file,
  1702.             GTST_MaxChars, sizeof(rom_file) - 1,
  1703.             LAST_Picker, TRUE,
  1704.             TAG_END
  1705.         );
  1706.     ENDGROUP;
  1707. }
  1708.  
  1709.  
  1710. /*
  1711.  *  Read settings from gadgets and set preferences
  1712.  */
  1713.  
  1714. static void read_settings(struct LayoutHandle *h)
  1715. {
  1716.     LT_UpdateStrings(h);
  1717.     read_volumes_settings();
  1718.     read_scsi_settings();
  1719.     read_graphics_settings();
  1720.     read_serial_settings();
  1721.     read_memory_settings();
  1722. }
  1723.