ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp
Revision: 1.5
Committed: 1999-11-01T16:24:10Z (25 years ago) by cebix
Branch: MAIN
CVS Tags: snapshot-22121999, release-0_8-1, snapshot-02111999
Changes since 1.4: +21 -5 lines
Log Message:
- AmigaOS: removed support for SAS/C
- AmigaOS: sys_amiga.cpp: supports 64-bit device access and respects
  device block size on writes
- AmigaOS: added support for resource forks and Finder info for ExtFS
- AmigaOS: added "ExtFS" gadget to prefs editor
- protection mask for all open()/creat()/mkdir() calls is now 0666 or
  0777

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