ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp
Revision: 1.2
Committed: 1999-10-19T19:28:16Z (25 years, 1 month ago) by cebix
Branch: MAIN
CVS Tags: snapshot-21101999
Changes since 1.1: +89 -82 lines
Log Message:
- now compiles with GCC under AmigaOS

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