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

File Contents

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