macemu/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp
2008-01-01 09:40:36 +00:00

1736 lines
42 KiB
C++

/*
* prefs_editor_amiga.cpp - Preferences editor, AmigaOS implementation (using gtlayout.library)
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <intuition/intuition.h>
#include <libraries/asl.h>
#include <libraries/gtlayout.h>
#include <libraries/Picasso96.h>
#include <cybergraphics/cybergraphics.h>
#include <graphics/displayinfo.h>
#include <devices/ahi.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/gtlayout.h>
#include <proto/graphics.h>
#include <proto/asl.h>
#include <proto/Picasso96.h>
#include <proto/cybergraphics.h>
#include <proto/ahi.h>
#include <inline/exec.h>
#include <inline/dos.h>
#include <inline/intuition.h>
#include <inline/gadtools.h>
#include <inline/gtlayout.h>
#include <inline/graphics.h>
#include <inline/asl.h>
#include <inline/Picasso96.h>
#include <inline/cybergraphics.h>
#include <inline/cybergraphics.h>
#include <inline/ahi.h>
#include <clib/alib_protos.h>
#include "sysdeps.h"
#include "main.h"
#include "xpram.h"
#include "cdrom.h"
#include "user_strings.h"
#include "version.h"
#include "prefs.h"
#include "prefs_editor.h"
// Gadget/menu IDs
const int MSG_OK = 0x0100; // "Start" button
const int MSG_CANCEL = 0x0101; // "Quit" button
const int MSG_ABOUT = 0x0102; // "About..." menu item
const int MSG_ZAP_PRAM = 0x0103; // "Zap PRAM" menu item
const int GAD_PAGEGROUP = 0x0200;
const int GAD_DISK_LIST = 0x0300; // "Volumes" pane
const int GAD_ADD_VOLUME = 0x0301;
const int GAD_EDIT_VOLUME = 0x0302;
const int GAD_REMOVE_VOLUME = 0x0303;
const int GAD_CDROM_DEVICE = 0x0304;
const int GAD_CDROM_UNIT = 0x0305;
const int GAD_BOOTDRIVER = 0x0306;
const int GAD_NOCDROM = 0x0307;
const int GAD_EXTFS = 0x0308;
const int GAD_VOLUME_READONLY = 0x0310; // "Add/Edit Volume" window
const int GAD_VOLUME_TYPE = 0x0311;
const int GAD_VOLUME_FILE = 0x0312;
const int GAD_VOLUME_DEVICE = 0x0313;
const int GAD_VOLUME_UNIT = 0x0314;
const int GAD_VOLUME_OPENFLAGS = 0x0315;
const int GAD_VOLUME_STARTBLOCK = 0x0316;
const int GAD_VOLUME_SIZE = 0x0317;
const int GAD_VOLUME_BLOCKSIZE = 0x0318;
const int GAD_VOLUME_PAGEGROUP = 0x0319;
const int GAD_SCSI0_DEVICE = 0x0400; // "SCSI" pane
const int GAD_SCSI1_DEVICE = 0x0401;
const int GAD_SCSI2_DEVICE = 0x0402;
const int GAD_SCSI3_DEVICE = 0x0403;
const int GAD_SCSI4_DEVICE = 0x0404;
const int GAD_SCSI5_DEVICE = 0x0405;
const int GAD_SCSI6_DEVICE = 0x0406;
const int GAD_SCSI0_UNIT = 0x0410;
const int GAD_SCSI1_UNIT = 0x0411;
const int GAD_SCSI2_UNIT = 0x0412;
const int GAD_SCSI3_UNIT = 0x0413;
const int GAD_SCSI4_UNIT = 0x0414;
const int GAD_SCSI5_UNIT = 0x0415;
const int GAD_SCSI6_UNIT = 0x0416;
const int GAD_SCSI_MEMTYPE = 0x0420;
const int GAD_VIDEO_TYPE = 0x0500; // "Graphics/Sound" pane
const int GAD_DISPLAY_X = 0x0501;
const int GAD_DISPLAY_Y = 0x0502;
const int GAD_FRAMESKIP = 0x0503;
const int GAD_SCREEN_MODE = 0x0504;
const int GAD_AHI_MODE = 0x0505;
const int GAD_NOSOUND = 0x0506;
const int GAD_SERIALA_DEVICE = 0x0600; // "Serial/Network" pane
const int GAD_SERIALA_UNIT = 0x0601;
const int GAD_SERIALA_ISPAR = 0x0602;
const int GAD_SERIALB_DEVICE = 0x0603;
const int GAD_SERIALB_UNIT = 0x0604;
const int GAD_SERIALB_ISPAR = 0x0605;
const int GAD_ETHER_DEVICE = 0x0606;
const int GAD_ETHER_UNIT = 0x00607;
const int GAD_RAMSIZE = 0x0700; // "Memory/Misc" pane
const int GAD_MODELID = 0x0701;
const int GAD_ROM_FILE = 0x0702;
// Global variables
struct Library *GTLayoutBase = NULL;
static struct FileRequester *dev_request = NULL, *file_request = NULL;
// gtlayout.library macros
#define VGROUP LT_New(h, LA_Type, VERTICAL_KIND, TAG_END)
#define HGROUP LT_New(h, LA_Type, HORIZONTAL_KIND, TAG_END)
#define ENDGROUP LT_EndGroup(h)
// Prototypes
static void create_volumes_pane(struct LayoutHandle *h);
static void create_scsi_pane(struct LayoutHandle *h);
static void create_graphics_pane(struct LayoutHandle *h);
static void create_serial_pane(struct LayoutHandle *h);
static void create_memory_pane(struct LayoutHandle *h);
static void add_edit_volume(struct LayoutHandle *h, bool adding);
static void remove_volume(struct LayoutHandle *h);
static void ghost_volumes_gadgets(struct LayoutHandle *h);
static void ghost_graphics_gadgets(struct LayoutHandle *h);
static void screen_mode_req(struct Window *win, struct LayoutHandle *h);
static void ahi_mode_req(struct Window *win, struct LayoutHandle *h);
static void read_settings(struct LayoutHandle *h);
/*
* Locale hook - returns string for given ID
*/
static __saveds __attribute__((regparm(3))) const char *locale_hook_func(struct Hook *hook /*a0*/, void *id /*a1*/, struct LayoutHandle *h /*a2*/)
{
return GetString((uint32)id);
}
struct Hook locale_hook = {{NULL, NULL}, (HOOKFUNC)locale_hook_func, NULL, NULL};
/*
* Show preferences editor
* Returns true when user clicked on "Start", false otherwise
*/
bool PrefsEditor(void)
{
bool retval = true, done = false;
struct LayoutHandle *h = NULL;
struct Window *win = NULL;
struct Menu *menu = NULL;
// Pane tabs
static const LONG labels[] = {
STR_VOLUMES_PANE_TITLE,
STR_SCSI_PANE_TITLE,
STR_GRAPHICS_SOUND_PANE_TITLE,
STR_SERIAL_NETWORK_PANE_TITLE,
STR_MEMORY_MISC_PANE_TITLE,
-1
};
// Open gtlayout.library
GTLayoutBase = (struct Library *)OpenLibrary("gtlayout.library", 39);
if (GTLayoutBase == NULL) {
WarningAlert(GetString(STR_NO_GTLAYOUT_LIB_WARN));
return true;
}
// Create layout handle
h = LT_CreateHandleTags(NULL,
LAHN_AutoActivate, FALSE,
LAHN_LocaleHook, (ULONG)&locale_hook,
TAG_END
);
if (h == NULL)
goto quit;
// Create menus
menu = LT_NewMenuTags(
LAMN_LayoutHandle, (ULONG)h,
LAMN_TitleID, STR_PREFS_MENU,
LAMN_ItemID, STR_PREFS_ITEM_ABOUT,
LAMN_UserData, MSG_ABOUT,
LAMN_ItemText, (ULONG)NM_BARLABEL,
LAMN_ItemID, STR_PREFS_ITEM_START,
LAMN_UserData, MSG_OK,
LAMN_ItemID, STR_PREFS_ITEM_ZAP_PRAM,
LAMN_UserData, MSG_ZAP_PRAM,
LAMN_ItemText, (ULONG)NM_BARLABEL,
LAMN_ItemID, STR_PREFS_ITEM_QUIT,
LAMN_UserData, MSG_CANCEL,
LAMN_KeyText, (ULONG)"Q",
TAG_END
);
// Create window contents
VGROUP;
VGROUP;
LT_New(h, LA_Type, TAB_KIND,
LATB_LabelTable, (ULONG)labels,
LATB_AutoPageID, GAD_PAGEGROUP,
LATB_FullWidth, TRUE,
TAG_END
);
ENDGROUP;
// Panes
LT_New(h, LA_Type, VERTICAL_KIND,
LA_ID, GAD_PAGEGROUP,
LAGR_ActivePage, 0,
TAG_END
);
create_volumes_pane(h);
create_scsi_pane(h);
create_graphics_pane(h);
create_serial_pane(h);
create_memory_pane(h);
ENDGROUP;
// Separator between tabs and buttons
VGROUP;
LT_New(h, LA_Type, XBAR_KIND,
LAXB_FullSize, TRUE,
TAG_END
);
ENDGROUP;
// "Start" and "Quit" buttons
LT_New(h, LA_Type, HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_START_BUTTON,
LA_ID, MSG_OK,
LABT_ReturnKey, TRUE,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_QUIT_BUTTON,
LA_ID, MSG_CANCEL,
LABT_EscKey, TRUE,
TAG_END
);
ENDGROUP;
ENDGROUP;
// Open window
win = LT_Build(h,
LAWN_TitleID, STR_PREFS_TITLE,
LAWN_Menu, (ULONG)menu,
LAWN_IDCMP, IDCMP_CLOSEWINDOW,
LAWN_BelowMouse, TRUE,
LAWN_SmartZoom, TRUE,
WA_SimpleRefresh, TRUE,
WA_Activate, TRUE,
WA_CloseGadget, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
TAG_END
);
if (win == NULL)
goto quit;
// Create file requesters
dev_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASLFR_DoPatterns, TRUE,
ASLFR_RejectIcons, TRUE,
ASLFR_InitialDrawer, (ULONG)"DEVS:",
ASLFR_InitialPattern, (ULONG)"#?.device",
TAG_END
);
file_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASLFR_DoPatterns, TRUE,
ASLFR_RejectIcons, TRUE,
ASLFR_InitialPattern, (ULONG)"#?",
TAG_END
);
// Event loop
do {
struct IntuiMessage *msg;
// Wait for message
WaitPort(win->UserPort);
// Get pending messages
while (msg = LT_GetIMsg(h)) {
// Get data from message and reply
ULONG cl = msg->Class;
UWORD code = msg->Code;
struct Gadget *gad = (struct Gadget *)msg->IAddress;
LT_ReplyIMsg(msg);
// Handle message according to class
switch (cl) {
case IDCMP_CLOSEWINDOW:
retval = false;
done = true;
break;
case IDCMP_GADGETUP:
switch (gad->GadgetID) {
case MSG_OK:
read_settings(h);
SavePrefs();
retval = true;
done = true;
break;
case MSG_CANCEL:
retval = false;
done = true;
break;
case GAD_DISK_LIST:
ghost_volumes_gadgets(h);
break;
case GAD_ADD_VOLUME:
LT_LockWindow(win);
add_edit_volume(h, true);
LT_UnlockWindow(win);
break;
case GAD_EDIT_VOLUME:
LT_LockWindow(win);
add_edit_volume(h, false);
LT_UnlockWindow(win);
break;
case GAD_REMOVE_VOLUME:
remove_volume(h);
break;
case GAD_BOOTDRIVER:
switch (code) {
case 0:
PrefsReplaceInt32("bootdriver", 0);
break;
case 1:
PrefsReplaceInt32("bootdriver", CDROMRefNum);
break;
}
break;
case GAD_SCSI_MEMTYPE:
PrefsReplaceInt32("scsimemtype", code);
break;
case GAD_VIDEO_TYPE:
ghost_graphics_gadgets(h);
break;
case GAD_FRAMESKIP:
switch (code) {
case 0:
PrefsReplaceInt32("frameskip", 12);
break;
case 1:
PrefsReplaceInt32("frameskip", 8);
break;
case 2:
PrefsReplaceInt32("frameskip", 6);
break;
case 3:
PrefsReplaceInt32("frameskip", 4);
break;
case 4:
PrefsReplaceInt32("frameskip", 2);
break;
case 5:
PrefsReplaceInt32("frameskip", 1);
break;
}
break;
case GAD_MODELID:
switch (code) {
case 0:
PrefsReplaceInt32("modelid", 5);
break;
case 1:
PrefsReplaceInt32("modelid", 14);
break;
}
break;
}
break;
case IDCMP_IDCMPUPDATE:
switch (gad->GadgetID) {
case GAD_DISK_LIST: // Double-click on volumes list = edit volume
LT_LockWindow(win);
add_edit_volume(h, false);
LT_UnlockWindow(win);
break;
case GAD_SCREEN_MODE:
screen_mode_req(win, h);
break;
case GAD_AHI_MODE:
ahi_mode_req(win, h);
break;
case GAD_CDROM_DEVICE:
case GAD_SCSI0_DEVICE:
case GAD_SCSI1_DEVICE:
case GAD_SCSI2_DEVICE:
case GAD_SCSI3_DEVICE:
case GAD_SCSI4_DEVICE:
case GAD_SCSI5_DEVICE:
case GAD_SCSI6_DEVICE:
case GAD_SERIALA_DEVICE:
case GAD_SERIALB_DEVICE:
if (dev_request) {
LT_LockWindow(win);
BOOL result = AslRequestTags(dev_request,
ASLFR_Window, (ULONG)win,
ASLFR_InitialDrawer, (ULONG) "Devs:",
TAG_END);
LT_UnlockWindow(win);
if (result) {
char *str;
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
strncpy(str, dev_request->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
str[255] = 0;
LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
}
}
break;
case GAD_ETHER_DEVICE:
if (dev_request) {
LT_LockWindow(win);
BOOL result = AslRequestTags(dev_request,
ASLFR_Window, (ULONG)win,
ASLFR_InitialDrawer, (ULONG) "Devs:Networks",
TAG_END);
LT_UnlockWindow(win);
if (result) {
char *str;
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
strncpy(str, dev_request->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
str[255] = 0;
LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
}
}
break;
case GAD_ROM_FILE:
if (file_request) {
LT_LockWindow(win);
BOOL result = AslRequestTags(file_request, ASLFR_Window, (ULONG)win, TAG_END);
LT_UnlockWindow(win);
if (result) {
char *str;
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
strncpy(str, file_request->rf_Dir, 255);
str[255] = 0;
AddPart(str, file_request->rf_File, 255);
LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
}
}
break;
}
break;
case IDCMP_MENUPICK:
while (code != MENUNULL) {
struct MenuItem *item = ItemAddress(menu, code);
if (item == NULL)
break;
switch ((ULONG)GTMENUITEM_USERDATA(item)) {
case MSG_OK:
read_settings(h);
SavePrefs();
retval = true;
done = true;
break;
case MSG_CANCEL:
retval = false;
done = true;
break;
case MSG_ABOUT: {
char str[256];
sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
strncat(str, "\n", 255);
strncat(str, GetString(STR_ABOUT_TEXT2), 255);
EasyStruct req;
req.es_StructSize = sizeof(EasyStruct);
req.es_Flags = 0;
req.es_Title = (UBYTE *)GetString(STR_ABOUT_TITLE);
req.es_TextFormat = (UBYTE *)str;
req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON);
LT_LockWindow(win);
EasyRequest(win, &req, NULL);
LT_UnlockWindow(win);
break;
}
case MSG_ZAP_PRAM:
ZapPRAM();
break;
}
code = item->NextSelect;
}
break;
}
}
} while (!done);
quit:
// Free requesters
FreeAslRequest(dev_request);
FreeAslRequest(file_request);
// Delete Menus
LT_DisposeMenu(menu);
// Delete handle
LT_DeleteHandle(h);
// Close gtlayout.library
CloseLibrary(GTLayoutBase);
return retval;
}
/*
* "Volumes" pane
*/
static struct List disk_list;
static char cdrom_name[256], extfs_name[256];
static ULONG cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize;
static BYTE bootdriver_num, nocdrom;
// Read volumes preferences
static void parse_volumes_prefs(void)
{
NewList(&disk_list);
const char *str;
for (int i=0; (str = PrefsFindString("disk", i)) != NULL; i++) {
struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR);
item->ln_Name = (char *)str;
AddTail(&disk_list, item);
}
cdrom_name[0] = 0;
cdrom_unit = 0; cdrom_flags = 0; cdrom_start = 0; cdrom_size = 0; cdrom_bsize = 2048;
str = PrefsFindString("cdrom");
if (str)
sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", cdrom_name, &cdrom_unit, &cdrom_flags, &cdrom_start, &cdrom_size, &cdrom_bsize);
bootdriver_num = 0;
int bootdriver = PrefsFindInt32("bootdriver");
switch (bootdriver) {
case 0:
bootdriver_num = 0;
break;
case CDROMRefNum:
bootdriver_num = 1;
break;
}
nocdrom = PrefsFindBool("nocdrom");
extfs_name[0] = 0;
str = PrefsFindString("extfs");
if (str)
strncpy(extfs_name, str, sizeof(extfs_name) - 1);
}
// Ghost/unghost "Edit" and "Remove" buttons
static void ghost_volumes_gadgets(struct LayoutHandle *h)
{
UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END);
if (sel == 0xffff) {
LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, TRUE, TAG_END);
LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, TRUE, TAG_END);
} else {
LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, FALSE, TAG_END);
LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, FALSE, TAG_END);
}
}
// Get device data from partition name
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)
{
// Remove everything after and including the ':'
char str[256];
strncpy(str, part, sizeof(str) - 1);
str[sizeof(str) - 1] = 0;
char *colon = strchr(str, ':');
if (colon)
*colon = 0;
// Look for partition
struct DosList *dl = LockDosList(LDF_DEVICES | LDF_READ);
dl = FindDosEntry(dl, str, LDF_DEVICES);
if (dl) {
// Get File System Startup Message
struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)(dl->dol_misc.dol_handler.dol_Startup << 2);
if (fssm) {
// Get DOS environment vector
struct DosEnvec *de = (struct DosEnvec *)(fssm->fssm_Environ << 2);
if (de && de->de_TableSize >= DE_UPPERCYL) {
// Read settings from FSSM and Envec
strncpy(dev_name, (char *)(fssm->fssm_Device << 2) + 1, 255);
dev_name[255] = 0;
dev_unit = fssm->fssm_Unit;
dev_flags = fssm->fssm_Flags;
dev_start = de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl;
dev_size = de->de_BlocksPerTrack * de->de_Surfaces * (de->de_HighCyl - de->de_LowCyl + 1);
dev_bsize = de->de_SizeBlock << 2;
}
}
}
UnLockDosList(LDF_DEVICES | LDF_READ);
}
// Display and handle "Add/Edit Volume" window
static void add_edit_volume(struct LayoutHandle *h2, bool adding)
{
bool ok_clicked = false;
UWORD sel = LT_GetAttributes(h2, GAD_DISK_LIST, TAG_END);
if ((sel == 0xffff) && !adding)
return;
char dev_name[256] = "";
char file_name[256] = "";
ULONG dev_unit = 0, dev_flags = 0, dev_start = 0, dev_size = 0, dev_bsize = 512;
BYTE read_only = false, is_device = false;
if (!adding) {
const char *str = PrefsFindString("disk", sel);
if (str == NULL)
return;
if (str[0] == '*') {
read_only = true;
str++;
}
if (strstr(str, "/dev/") == str) {
is_device = true;
sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", dev_name, &dev_unit, &dev_flags, &dev_start, &dev_size, &dev_bsize);
} else {
strncpy(file_name, str, sizeof(file_name) - 1);
file_name[sizeof(file_name) - 1] = 0;
}
}
// Create layout handle
struct LayoutHandle *h = NULL;
struct Window *win = NULL;
h = LT_CreateHandleTags(NULL,
LAHN_AutoActivate, FALSE,
LAHN_LocaleHook, (ULONG)&locale_hook,
TAG_END
);
if (h == NULL)
return;
// Create window contents
VGROUP;
// Volume gadgets
VGROUP;
LT_New(h, LA_Type, CHECKBOX_KIND,
LA_LabelID, STR_VOL_READONLY_CTRL,
LA_ID, GAD_VOLUME_READONLY,
LA_BYTE, (ULONG)&read_only,
TAG_END
);
LT_New(h, LA_Type, CYCLE_KIND,
LA_LabelID, STR_VOL_TYPE_CTRL,
LA_ID, GAD_VOLUME_TYPE,
LACY_AutoPageID, GAD_VOLUME_PAGEGROUP,
LACY_FirstLabel, STR_VOL_FILE_LAB,
LACY_LastLabel, STR_VOL_DEVICE_LAB,
LA_BYTE, (ULONG)&is_device,
TAG_END
);
ENDGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_ID, GAD_VOLUME_PAGEGROUP,
LAGR_ActivePage, is_device,
TAG_END
);
VGROUP;
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_VOL_FILE_CTRL,
LA_ID, GAD_VOLUME_FILE,
LA_Chars, 20,
LA_STRPTR, (ULONG)file_name,
GTST_MaxChars, sizeof(file_name) - 1,
LAST_Picker, TRUE,
TAG_END
);
ENDGROUP;
VGROUP;
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_VOLUME_DEVICE,
LA_Chars, 20,
LA_STRPTR, (ULONG)dev_name,
GTST_MaxChars, sizeof(dev_name) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_VOLUME_UNIT,
LA_LONG, (ULONG)&dev_unit,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_VOL_OPENFLAGS_CTRL,
LA_ID, GAD_VOLUME_OPENFLAGS,
LA_LONG, (ULONG)&dev_flags,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_VOL_STARTBLOCK_CTRL,
LA_ID, GAD_VOLUME_STARTBLOCK,
LA_LONG, (ULONG)&dev_start,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_VOL_SIZE_CTRL,
LA_ID, GAD_VOLUME_SIZE,
LA_LONG, (ULONG)&dev_size,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_VOL_BLOCKSIZE_CTRL,
LA_ID, GAD_VOLUME_BLOCKSIZE,
LA_LONG, (ULONG)&dev_bsize,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
ENDGROUP;
ENDGROUP;
// Separator between gadgets and buttons
VGROUP;
LT_New(h, LA_Type, XBAR_KIND,
LAXB_FullSize, TRUE,
TAG_END
);
ENDGROUP;
// "OK" and "Cancel" buttons
LT_New(h, LA_Type, HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_OK_BUTTON,
LA_ID, MSG_OK,
LABT_ReturnKey, TRUE,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_CANCEL_BUTTON,
LA_ID, MSG_CANCEL,
LABT_EscKey, TRUE,
TAG_END
);
ENDGROUP;
ENDGROUP;
// Open window
win = LT_Build(h,
LAWN_TitleID, adding ? STR_ADD_VOLUME_TITLE : STR_EDIT_VOLUME_TITLE,
LAWN_IDCMP, IDCMP_CLOSEWINDOW,
LAWN_BelowMouse, TRUE,
LAWN_SmartZoom, TRUE,
WA_SimpleRefresh, TRUE,
WA_Activate, TRUE,
WA_CloseGadget, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
TAG_END
);
if (win == NULL) {
LT_DeleteHandle(h);
return;
}
// Event loop
bool done = false;
do {
struct IntuiMessage *msg;
// Wait for message
WaitPort(win->UserPort);
// Get pending messages
while (msg = LT_GetIMsg(h)) {
// Get data from message and reply
ULONG cl = msg->Class;
UWORD code = msg->Code;
struct Gadget *gad = (struct Gadget *)msg->IAddress;
LT_ReplyIMsg(msg);
// Handle message according to class
switch (cl) {
case IDCMP_CLOSEWINDOW:
done = true;
break;
case IDCMP_GADGETUP:
switch (gad->GadgetID) {
case MSG_OK:
ok_clicked = true;
done = true;
break;
case MSG_CANCEL:
done = true;
break;
}
break;
case IDCMP_IDCMPUPDATE: {
struct FileRequester *req = NULL;
switch (gad->GadgetID) {
case GAD_VOLUME_FILE:
req = file_request;
goto do_req;
case GAD_VOLUME_DEVICE:
req = dev_request;
do_req: if (req) {
LT_LockWindow(win);
BOOL result = AslRequestTags(req, ASLFR_Window, (ULONG)win, TAG_END);
LT_UnlockWindow(win);
if (result) {
char *str;
GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END);
if (gad->GadgetID == GAD_VOLUME_FILE) {
strncpy(str, req->rf_Dir, 255);
str[255] = 0;
AddPart(str, req->rf_File, 255);
} else {
if (strlen(req->rf_File)) {
strncpy(str, req->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that.
str[255] = 0;
} else if (strlen(req->rf_Dir) && req->rf_Dir[strlen(req->rf_Dir) - 1] == ':') {
analyze_partition(req->rf_Dir, str, dev_unit, dev_flags, dev_start, dev_size, dev_bsize);
LT_SetAttributes(h, GAD_VOLUME_UNIT, GTIN_Number, dev_unit, TAG_END);
LT_SetAttributes(h, GAD_VOLUME_OPENFLAGS, GTIN_Number, dev_flags, TAG_END);
LT_SetAttributes(h, GAD_VOLUME_STARTBLOCK, GTIN_Number, dev_start, TAG_END);
LT_SetAttributes(h, GAD_VOLUME_SIZE, GTIN_Number, dev_size, TAG_END);
LT_SetAttributes(h, GAD_VOLUME_BLOCKSIZE, GTIN_Number, dev_bsize, TAG_END);
}
}
LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END);
}
}
break;
}
break;
}
}
}
} while (!done);
// Update preferences and list view
if (ok_clicked) {
char str[256];
LT_UpdateStrings(h);
if (is_device)
sprintf(str, "%s/dev/%s/%ld/%ld/%ld/%ld/%ld", read_only ? "*" : "", dev_name, dev_unit, dev_flags, dev_start, dev_size, dev_bsize);
else
sprintf(str, "%s%s", read_only ? "*" : "", file_name);
LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END);
if (adding) {
// Add new item
int i;
PrefsAddString("disk", str);
struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR);
for (i=0; PrefsFindString("disk", i); i++) ;
item->ln_Name = (char *)PrefsFindString("disk", i - 1);
AddTail(&disk_list, item);
} else {
// Replace existing item
PrefsReplaceString("disk", str, sel);
struct Node *item = disk_list.lh_Head;
for (int i=0; item->ln_Succ; i++) {
if (i == sel) {
item->ln_Name = (char *)PrefsFindString("disk", sel);
break;
}
item = item->ln_Succ;
}
}
LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, TAG_END);
ghost_volumes_gadgets(h2);
}
// Delete handle
LT_DeleteHandle(h);
}
// Remove volume from list
static void remove_volume(struct LayoutHandle *h)
{
UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END);
if (sel != 0xffff) {
// Remove item from preferences and list view
LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END);
PrefsRemoveItem("disk", sel);
struct Node *item = disk_list.lh_Head;
for (int i=0; item->ln_Succ; i++) {
struct Node *next = item->ln_Succ;
if (i == sel) {
Remove(item);
FreeMem(item, sizeof(struct Node));
break;
}
item = next;
}
LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, GTLV_Selected, 0xffff, TAG_END);
ghost_volumes_gadgets(h);
}
}
// Read settings from gadgets and set preferences
static void read_volumes_settings(void)
{
struct Node *item = disk_list.lh_Head;
while (item->ln_Succ) {
struct Node *next = item->ln_Succ;
Remove(item);
FreeMem(item, sizeof(struct Node));
item = next;
}
if (strlen(cdrom_name)) {
char str[256];
sprintf(str, "/dev/%s/%ld/%ld/%ld/%ld/%ld", cdrom_name, cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize);
PrefsReplaceString("cdrom", str);
} else
PrefsRemoveItem("cdrom");
PrefsReplaceBool("nocdrom", nocdrom);
if (strlen(extfs_name))
PrefsReplaceString("extfs", extfs_name);
}
// Create "Volumes" pane
static void create_volumes_pane(struct LayoutHandle *h)
{
parse_volumes_prefs();
VGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_VOLUMES_CTRL,
TAG_END
);
VGROUP;
LT_New(h, LA_Type, LISTVIEW_KIND,
LA_ID, GAD_DISK_LIST,
LA_Chars, 20,
GTLV_Labels, (ULONG)&disk_list,
LALV_Lines, 6,
LALV_Link, (ULONG)NIL_LINK,
LALV_ResizeX, TRUE,
LALV_ResizeY, TRUE,
LALV_Selected, 0,
TAG_END
);
ENDGROUP;
LT_New(h, LA_Type, HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_ADD_VOLUME_BUTTON,
LA_ID, GAD_ADD_VOLUME,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_EDIT_VOLUME_BUTTON,
LA_ID, GAD_EDIT_VOLUME,
TAG_END
);
LT_New(h, LA_Type, BUTTON_KIND,
LA_LabelID, STR_REMOVE_VOLUME_BUTTON,
LA_ID, GAD_REMOVE_VOLUME,
TAG_END
);
ENDGROUP;
ENDGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_CDROM_DRIVE_CTRL,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_CDROM_DEVICE,
LA_Chars, 20,
LA_STRPTR, (ULONG)cdrom_name,
GTST_MaxChars, sizeof(cdrom_name) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_CDROM_UNIT,
LA_LONG, (ULONG)&cdrom_unit,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, CYCLE_KIND,
LA_LabelID, STR_BOOTDRIVER_CTRL,
LA_ID, GAD_BOOTDRIVER,
LACY_FirstLabel, STR_BOOT_ANY_LAB,
LACY_LastLabel, STR_BOOT_CDROM_LAB,
LA_BYTE, (ULONG)&bootdriver_num,
TAG_END
);
LT_New(h, LA_Type, CHECKBOX_KIND,
LA_LabelID, STR_NOCDROM_CTRL,
LA_ID, GAD_NOCDROM,
LA_BYTE, (ULONG)&nocdrom,
TAG_END
);
ENDGROUP;
VGROUP;
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_EXTFS_CTRL,
LA_ID, GAD_EXTFS,
LA_Chars, 20,
LA_STRPTR, (ULONG)extfs_name,
GTST_MaxChars, sizeof(extfs_name) - 1,
TAG_END
);
ENDGROUP;
ENDGROUP;
}
/*
* "SCSI" pane
*/
static char scsi_dev[6][256];
static LONG scsi_unit[6];
static LONG scsi_memtype;
// Read SCSI preferences
static void parse_scsi_prefs(void)
{
for (int i=0; i<7; i++) {
scsi_dev[i][0] = 0;
scsi_unit[i] = 0;
char prefs_name[16];
sprintf(prefs_name, "scsi%d", i);
const char *str = PrefsFindString(prefs_name);
if (str)
sscanf(str, "%[^/]/%ld", scsi_dev[i], &scsi_unit[i]);
}
scsi_memtype = PrefsFindInt32("scsimemtype");
}
// Read settings from gadgets and set preferences
static void read_scsi_settings(void)
{
for (int i=0; i<7; i++) {
char prefs_name[16];
sprintf(prefs_name, "scsi%d", i);
if (strlen(scsi_dev[i])) {
char str[256];
sprintf(str, "%s/%ld", scsi_dev[i], scsi_unit[i]);
PrefsReplaceString(prefs_name, str);
} else
PrefsRemoveItem(prefs_name);
}
}
// Create "SCSI" pane
static void create_scsi_pane(struct LayoutHandle *h)
{
parse_scsi_prefs();
VGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_SCSI_DEVICES_CTRL,
TAG_END
);
for (int i=0; i<7; i++) {
HGROUP;
LT_New(h, LA_Type, TEXT_KIND,
LA_LabelID, STR_SCSI_ID_0 + i,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_SCSI0_DEVICE + i,
LA_Chars, 20,
LA_STRPTR, (ULONG)scsi_dev[i],
GTST_MaxChars, sizeof(scsi_dev[i]) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_SCSI0_UNIT + i,
LA_Chars, 4,
LA_LONG, (ULONG)&scsi_unit[i],
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
ENDGROUP;
}
ENDGROUP;
VGROUP;
LT_New(h, LA_Type, CYCLE_KIND,
LA_LabelID, STR_SCSI_MEMTYPE_CTRL,
LA_ID, GAD_SCSI_MEMTYPE,
LACY_FirstLabel, STR_MEMTYPE_CHIP_LAB,
LACY_LastLabel, STR_MEMTYPE_ANY_LAB,
LA_LONG, (ULONG)&scsi_memtype,
TAG_END
);
ENDGROUP;
ENDGROUP;
}
/*
* "Graphics/Sound" pane
*/
// Display types
enum {
DISPLAY_WINDOW,
DISPLAY_PIP,
DISPLAY_SCREEN
};
static LONG display_type;
static LONG dis_width, dis_height;
static ULONG mode_id;
static BYTE frameskip_num;
static struct NameInfo mode_name;
static ULONG ahi_id;
static char ahi_mode_name[256];
static BYTE nosound;
// Read graphics preferences
static void parse_graphics_prefs(void)
{
display_type = DISPLAY_WINDOW;
dis_width = 512;
dis_height = 384;
mode_id = 0;
ahi_id = AHI_DEFAULT_ID;
ahi_mode_name[0] = 0;
frameskip_num = 0;
int frameskip = PrefsFindInt32("frameskip");
switch (frameskip) {
case 12:
frameskip_num = 0;
break;
case 8:
frameskip_num = 1;
break;
case 6:
frameskip_num = 2;
break;
case 4:
frameskip_num = 3;
break;
case 2:
frameskip_num = 4;
break;
case 1:
frameskip_num = 5;
break;
}
const char *str = PrefsFindString("screen");
if (str) {
if (sscanf(str, "win/%ld/%ld", &dis_width, &dis_height) == 2)
display_type = DISPLAY_WINDOW;
else if (sscanf(str, "pip/%ld/%ld", &dis_width, &dis_height) == 2)
display_type = DISPLAY_PIP;
else if (sscanf(str, "scr/%08lx", &mode_id) == 1)
display_type = DISPLAY_SCREEN;
}
GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id);
str = PrefsFindString("sound");
if (str) {
if (sscanf(str, "ahi/%08lx", &ahi_id) == 1 && AHIBase) {
AHI_GetAudioAttrs(ahi_id, NULL,
AHIDB_Name, (ULONG)ahi_mode_name,
AHIDB_BufferLen, sizeof(ahi_mode_name) - 1,
TAG_END
);
}
}
nosound = PrefsFindBool("nosound");
}
// Ghost/unghost graphics gadgets, depending on display type
static void ghost_graphics_gadgets(struct LayoutHandle *h)
{
bool dis_xy, dis_skip, dis_mode;
switch (display_type) {
case DISPLAY_WINDOW:
dis_xy = false;
dis_skip = false;
dis_mode = true;
break;
case DISPLAY_PIP:
dis_xy = false;
dis_skip = true;
dis_mode = true;
break;
case DISPLAY_SCREEN:
dis_xy = true;
dis_skip = true;
dis_mode = false;
break;
}
LT_SetAttributes(h, GAD_DISPLAY_X, GA_Disabled, dis_xy, TAG_END);
LT_SetAttributes(h, GAD_DISPLAY_Y, GA_Disabled, dis_xy, TAG_END);
LT_SetAttributes(h, GAD_FRAMESKIP, GA_Disabled, dis_skip, TAG_END);
LT_SetAttributes(h, GAD_SCREEN_MODE, GA_Disabled, dis_mode, TAG_END);
LT_SetAttributes(h, GAD_AHI_MODE, GA_Disabled, AHIBase == NULL, TAG_END);
}
// Show screen mode requester
static void screen_mode_req(struct Window *win, struct LayoutHandle *h)
{
if (P96Base == NULL && CyberGfxBase == NULL)
return;
LT_LockWindow(win);
ULONG id;
// Try P96 first, because it also provides a (fake) cybergraphics.library
if (P96Base) {
id = p96RequestModeIDTags(
P96MA_MinDepth, 8,
P96MA_FormatsAllowed, RGBFF_CLUT | RGBFF_R5G5B5 | RGBFF_A8R8G8B8,
TAG_END
);
} else {
UWORD ModelArray[] = { PIXFMT_LUT8, PIXFMT_RGB15, PIXFMT_ARGB32, 0, ~0 };
id = (ULONG) CModeRequestTags(NULL,
CYBRMREQ_MinDepth, 8,
CYBRMREQ_CModelArray, (ULONG) ModelArray,
TAG_END
);
}
LT_UnlockWindow(win);
if (id != INVALID_ID) {
mode_id = id;
GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id);
LT_SetAttributes(h, GAD_SCREEN_MODE, GTTX_Text, (ULONG)mode_name.Name, TAG_END);
}
}
// Show AHI mode requester
static void ahi_mode_req(struct Window *win, struct LayoutHandle *h)
{
if (AHIBase == NULL)
return;
struct AHIAudioModeRequester *req = AHI_AllocAudioRequest(
AHIR_Window, (ULONG)win,
TAG_END
);
if (req == NULL)
return;
LT_LockWindow(win);
BOOL ok = AHI_AudioRequest(req,
AHIR_InitialAudioID, ahi_id,
TAG_END
);
LT_UnlockWindow(win);
if (ok) {
ahi_id = req->ahiam_AudioID;
AHI_GetAudioAttrs(ahi_id, NULL,
AHIDB_Name, (ULONG)ahi_mode_name,
AHIDB_BufferLen, sizeof(ahi_mode_name) - 1,
TAG_END
);
LT_SetAttributes(h, GAD_AHI_MODE, GTTX_Text, (ULONG)ahi_mode_name, TAG_END);
}
AHI_FreeAudioRequest(req);
}
// Read settings from gadgets and set preferences
static void read_graphics_settings(void)
{
char str[256];
switch (display_type) {
case DISPLAY_WINDOW:
sprintf(str, "win/%ld/%ld", dis_width, dis_height);
break;
case DISPLAY_PIP:
sprintf(str, "pip/%ld/%ld", dis_width, dis_height);
break;
case DISPLAY_SCREEN:
sprintf(str, "scr/%08lx", mode_id);
break;
default:
PrefsRemoveItem("screen");
return;
}
PrefsReplaceString("screen", str);
sprintf(str, "ahi/%08lx", ahi_id);
PrefsReplaceString("sound", str);
PrefsReplaceBool("nosound", nosound);
}
// Create "Graphics/Sound" pane
static void create_graphics_pane(struct LayoutHandle *h)
{
parse_graphics_prefs();
VGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_GRAPHICS_CTRL,
TAG_END
);
static const LONG labels[] = {STR_WINDOW_LAB, STR_PIP_LAB, STR_FULLSCREEN_LAB, -1};
LT_New(h, LA_Type, CYCLE_KIND,
LA_LabelID, STR_VIDEO_TYPE_CTRL,
LA_ID, GAD_VIDEO_TYPE,
LACY_LabelTable, (ULONG)labels,
LA_LONG, (ULONG)&display_type,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_DISPLAY_X_CTRL,
LA_ID, GAD_DISPLAY_X,
LA_LONG, (ULONG)&dis_width,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_DISPLAY_Y_CTRL,
LA_ID, GAD_DISPLAY_Y,
LA_LONG, (ULONG)&dis_height,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, POPUP_KIND,
LA_LabelID, STR_FRAMESKIP_CTRL,
LA_ID, GAD_FRAMESKIP,
LAPU_FirstLabel, STR_REF_5HZ_LAB,
LAPU_LastLabel, STR_REF_60HZ_LAB,
LA_BYTE, (ULONG)&frameskip_num,
TAG_END
);
LT_New(h, LA_Type, TEXT_KIND,
LA_LabelID, STR_SCREEN_MODE_CTRL,
LA_ID, GAD_SCREEN_MODE,
LA_Chars, DISPLAYNAMELEN,
LATX_Picker, TRUE,
GTTX_Text, (ULONG)mode_name.Name,
GTTX_Border, TRUE,
TAG_END
);
ENDGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_SOUND_CTRL,
TAG_END
);
LT_New(h, LA_Type, TEXT_KIND,
LA_LabelID, STR_AHI_MODE_CTRL,
LA_ID, GAD_AHI_MODE,
LA_Chars, DISPLAYNAMELEN,
LATX_Picker, TRUE,
GTTX_Text, (ULONG)ahi_mode_name,
GTTX_Border, TRUE,
TAG_END
);
LT_New(h, LA_Type, CHECKBOX_KIND,
LA_LabelID, STR_NOSOUND_CTRL,
LA_ID, GAD_NOSOUND,
LA_BYTE, (ULONG)&nosound,
TAG_END
);
ENDGROUP;
ENDGROUP;
ghost_graphics_gadgets(h);
}
/*
* "Serial/Network" pane
*/
static char seriala_dev[256], serialb_dev[256];
static LONG seriala_unit, serialb_unit;
static BYTE seriala_ispar, serialb_ispar;
static char ether_dev[256];
static ULONG ether_unit;
// Read serial/network preferences
static void parse_ser_prefs(const char *prefs, char *dev, LONG &unit, BYTE &ispar)
{
dev[0] = 0;
unit = 0;
ispar = false;
const char *str = PrefsFindString(prefs);
if (str) {
if (str[0] == '*') {
ispar = true;
str++;
}
sscanf(str, "%[^/]/%ld", dev, &unit);
}
}
static void parse_serial_prefs(void)
{
parse_ser_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar);
parse_ser_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar);
ether_dev[0] = 0;
ether_unit = 0;
const char *str = PrefsFindString("ether");
if (str) {
const char *FirstSlash = strchr(str, '/');
const char *LastSlash = strrchr(str, '/');
if (FirstSlash && FirstSlash && FirstSlash != LastSlash) {
// Device name contains path, i.e. "Networks/xyzzy.device"
const char *lp = str;
char *dp = ether_dev;
while (lp != LastSlash)
*dp++ = *lp++;
*dp = '\0';
sscanf(LastSlash, "/%ld", &ether_unit);
// printf("dev=<%s> unit=%d\n", ether_dev, ether_unit);
} else {
sscanf(str, "%[^/]/%ld", ether_dev, &ether_unit);
}
}
}
// Set serial preference item
static void make_serial_prefs(const char *prefs, const char *dev, LONG unit, BYTE ispar)
{
if (strlen(dev)) {
char str[256];
sprintf(str, "%s%s/%ld", ispar ? "*" : "", dev, unit);
PrefsReplaceString(prefs, str);
} else
PrefsRemoveItem(prefs);
}
// Read settings from gadgets and set preferences
static void read_serial_settings(void)
{
make_serial_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar);
make_serial_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar);
if (strlen(ether_dev)) {
char str[256];
sprintf(str, "%s/%ld", ether_dev, ether_unit);
PrefsReplaceString("ether", str);
} else
PrefsRemoveItem("ether");
}
// Create "Serial/Network" pane
static void create_serial_pane(struct LayoutHandle *h)
{
parse_serial_prefs();
VGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_SERIALA_CTRL,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_SERIALA_DEVICE,
LA_Chars, 20,
LA_STRPTR, (ULONG)seriala_dev,
GTST_MaxChars, sizeof(seriala_dev) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_SERIALA_UNIT,
LA_LONG, (ULONG)&seriala_unit,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, CHECKBOX_KIND,
LA_LabelID, STR_ISPAR_CTRL,
LA_ID, GAD_SERIALA_ISPAR,
LA_BYTE, (ULONG)&seriala_ispar,
TAG_END
);
ENDGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_SERIALB_CTRL,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_SERIALB_DEVICE,
LA_Chars, 20,
LA_STRPTR, (ULONG)serialb_dev,
GTST_MaxChars, sizeof(serialb_dev) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_SERIALB_UNIT,
LA_LONG, (ULONG)&serialb_unit,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
LT_New(h, LA_Type, CHECKBOX_KIND,
LA_LabelID, STR_ISPAR_CTRL,
LA_ID, GAD_SERIALB_ISPAR,
LA_BYTE, (ULONG)&serialb_ispar,
TAG_END
);
ENDGROUP;
LT_New(h, LA_Type, VERTICAL_KIND,
LA_LabelID, STR_ETHERNET_IF_CTRL,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_DEVICE_CTRL,
LA_ID, GAD_ETHER_DEVICE,
LA_Chars, 20,
LA_STRPTR, (ULONG)ether_dev,
GTST_MaxChars, sizeof(ether_dev) - 1,
LAST_Picker, TRUE,
TAG_END
);
LT_New(h, LA_Type, INTEGER_KIND,
LA_LabelID, STR_UNIT_CTRL,
LA_ID, GAD_ETHER_UNIT,
LA_LONG, (ULONG)&ether_unit,
LAIN_UseIncrementers, TRUE,
GTIN_MaxChars, 8,
TAG_END
);
ENDGROUP;
ENDGROUP;
}
/*
* "Memory/Misc" pane
*/
static ULONG ramsize_mb;
static BYTE model_num;
static char rom_file[256];
// Read memory/misc preferences
static void parse_memory_prefs(void)
{
ramsize_mb = PrefsFindInt32("ramsize") >> 20;
model_num = 0;
int id = PrefsFindInt32("modelid");
switch (id) {
case 5:
model_num = 0;
break;
case 14:
model_num = 1;
break;
}
rom_file[0] = 0;
const char *str = PrefsFindString("rom");
if (str) {
strncpy(rom_file, str, sizeof(rom_file) - 1);
rom_file[sizeof(rom_file) - 1] = 0;
}
}
// Read settings from gadgets and set preferences
static void read_memory_settings(void)
{
PrefsReplaceInt32("ramsize", ramsize_mb << 20);
if (strlen(rom_file))
PrefsReplaceString("rom", rom_file);
else
PrefsRemoveItem("rom");
}
// Create "Memory/Misc" pane
static void create_memory_pane(struct LayoutHandle *h)
{
parse_memory_prefs();
VGROUP;
LT_New(h, LA_Type, LEVEL_KIND,
LA_LabelID, STR_RAMSIZE_SLIDER,
LA_ID, GAD_RAMSIZE,
LA_Chars, 20,
LA_LONG, (ULONG)&ramsize_mb,
GTSL_LevelFormat, (ULONG)GetString(STR_RAMSIZE_FMT),
GTSL_Min, 1,
GTSL_Max, AvailMem(MEMF_LARGEST) >> 20,
TAG_END
);
LT_New(h, LA_Type, CYCLE_KIND,
LA_LabelID, STR_MODELID_CTRL,
LA_ID, GAD_MODELID,
LACY_FirstLabel, STR_MODELID_5_LAB,
LACY_LastLabel, STR_MODELID_14_LAB,
LA_BYTE, (ULONG)&model_num,
TAG_END
);
LT_New(h, LA_Type, STRING_KIND,
LA_LabelID, STR_ROM_FILE_CTRL,
LA_ID, GAD_ROM_FILE,
LA_Chars, 20,
LA_STRPTR, (ULONG)rom_file,
GTST_MaxChars, sizeof(rom_file) - 1,
LAST_Picker, TRUE,
TAG_END
);
ENDGROUP;
}
/*
* Read settings from gadgets and set preferences
*/
static void read_settings(struct LayoutHandle *h)
{
LT_UpdateStrings(h);
read_volumes_settings();
read_scsi_settings();
read_graphics_settings();
read_serial_settings();
read_memory_settings();
}