1 /*
2   Hatari - dlgFloppy.c
3 
4   This file is distributed under the GNU General Public License, version 2
5   or at your option any later version. Read the file gpl.txt for details.
6 */
7 const char DlgFloppy_fileid[] = "Hatari dlgFloppy.c : " __DATE__ " " __TIME__;
8 
9 #include <assert.h>
10 #include "main.h"
11 #include "configuration.h"
12 #include "dialog.h"
13 #include "sdlgui.h"
14 #include "file.h"
15 #include "floppy.h"
16 
17 #include "gui-retro.h"
18 
19 #define FLOPPYDLG_ENABLE_A    3
20 #define FLOPPYDLG_HEADS_DS_A  4
21 #define FLOPPYDLG_EJECTA      5
22 #define FLOPPYDLG_BROWSEA     6
23 #define FLOPPYDLG_DISKA       7
24 
25 #define FLOPPYDLG_ENABLE_B    9
26 #define FLOPPYDLG_HEADS_DS_B  10
27 #define FLOPPYDLG_EJECTB      11
28 #define FLOPPYDLG_BROWSEB     12
29 #define FLOPPYDLG_DISKB       13
30 
31 #define FLOPPYDLG_IMGDIR      15
32 #define FLOPPYDLG_BROWSEIMG   16
33 #define FLOPPYDLG_AUTOB       17
34 #define FLOPPYDLG_FASTFLOPPY  18
35 #define FLOPPYDLG_CREATEIMG   19
36 #define FLOPPYDLG_PROTOFF     21
37 #define FLOPPYDLG_PROTON      22
38 #define FLOPPYDLG_PROTAUTO    23
39 #define FLOPPYDLG_EXIT        24
40 
41 /* The floppy disks dialog: */
42 static SGOBJ floppydlg[] =
43 {
44 	{ SGBOX, 0, 0, 0,0, 64,20, NULL },
45 	{ SGTEXT, 0, 0, 25,1, 12,1, "Floppy disks" },
46 
47 	{ SGTEXT, 0, 0, 2,3, 8,1, "Drive A:" },
48 	{ SGCHECKBOX, 0, 0, 12,3,  9,1, "Enabled" },
49 	{ SGCHECKBOX, 0, 0, 23,3, 14,1, "Double Sided" },
50 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 46,3,  7,1, "Eject" },
51 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 54,3,  8,1, "Browse" },
52 	{ SGTEXT, 0, 0, 3,4, 58,1, NULL },
53 
54 	{ SGTEXT, 0, 0, 2,6, 8,1, "Drive B:" },
55 	{ SGCHECKBOX, 0, 0, 12,6,  9,1, "Enabled" },
56 	{ SGCHECKBOX, 0, 0, 23,6, 14,1, "Double Sided" },
57 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 46,6,  7,1, "Eject" },
58 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 54,6,  8,1, "Browse" },
59 	{ SGTEXT, 0, 0, 3,7, 58,1, NULL },
60 
61 	{ SGTEXT, 0, 0, 2,9, 32,1, "Default floppy images directory:" },
62 	{ SGTEXT, 0, 0, 3,10, 58,1, NULL },
63 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 54, 9,  8,1, "Browse" },
64 	{ SGCHECKBOX, 0, 0,  2,12, 15,1, "Auto insert B" },
65 	{ SGCHECKBOX, 0, 0,  2,14, 20,1, "Fast floppy access" },
66 	{ SGBUTTON,   SG_EXIT/*0*/, 0, 42,14, 20,1, "Create blank image" },
67 	{ SGTEXT, 0, 0, 2,16, 17,1, "Write protection:" },
68 	{ SGRADIOBUT, 0, 0, 21,16,  5,1, "Off" },
69 	{ SGRADIOBUT, 0, 0, 28,16,  4,1, "On" },
70 	{ SGRADIOBUT, 0, 0, 34,16,  6,1, "Auto" },
71 	{ SGBUTTON, SG_EXIT/*SG_DEFAULT*/, 0, 22,18, 20,1, "Back to main menu" },
72 	{ -1, 0, 0, 0,0, 0,0, NULL }
73 };
74 
75 
76 #define DLGMOUNT_A       2
77 #define DLGMOUNT_B       3
78 #define DLGMOUNT_CANCEL  4
79 
80 /* The "Alert"-dialog: */
81 static SGOBJ alertdlg[] =
82 {
83 	{ SGBOX, 0, 0, 0,0, 40,6, NULL },
84 	{ SGTEXT, 0, 0, 3,1, 30,1, "Insert last created disk to?" },
85 	{ SGBUTTON, SG_EXIT/*0*/, 0, 3,4, 10,1, "Drive A:" },
86 	{ SGBUTTON, SG_EXIT/*0*/, 0, 15,4, 10,1, "Drive B:" },
87 	{ SGBUTTON, SG_EXIT/*SG_CANCEL*/, 0, 27,4, 10,1, "Cancel" },
88 	{ -1, 0, 0, 0,0, 0,0, NULL }
89 };
90 
91 
92 /**
93  * Let user browse given disk, insert disk if one selected.
94  */
DlgDisk_BrowseDisk(char * dlgname,int drive,int diskid)95 static void DlgDisk_BrowseDisk(char *dlgname, int drive, int diskid)
96 {
97 	char *selname, *zip_path;
98 	const char *tmpname, *realname;
99 
100 	assert(drive >= 0 && drive < MAX_FLOPPYDRIVES);
101 	if (ConfigureParams.DiskImage.szDiskFileName[drive][0])
102 		tmpname = ConfigureParams.DiskImage.szDiskFileName[drive];
103 	else
104 		tmpname = ConfigureParams.DiskImage.szDiskImageDirectory;
105 
106 	selname = SDLGui_FileSelect("NULL",tmpname, &zip_path, false);
107 	if (!selname)
108 		return;
109 
110 	if (File_Exists(selname))
111 	{
112 		realname = Floppy_SetDiskFileName(drive, selname, zip_path);
113 		if (realname)
114 			File_ShrinkName(dlgname, realname, floppydlg[diskid].w);
115 	}
116 	else
117 	{
118 		Floppy_SetDiskFileNameNone(drive);
119 		dlgname[0] = '\0';
120 	}
121 	if (zip_path)
122 		free(zip_path);
123 	free(selname);
124 }
125 
126 
127 /**
128  * Let user browse given directory, set directory if one selected.
129  */
DlgDisk_BrowseDir(char * dlgname,char * confname,int maxlen)130 static void DlgDisk_BrowseDir(char *dlgname, char *confname, int maxlen)
131 {
132 	char *str, *selname;
133 
134 	selname = SDLGui_FileSelect("NULL",confname, NULL, false);
135 	if (!selname)
136 		return;
137 
138 	strcpy(confname, selname);
139 	free(selname);
140 
141 	str = strrchr(confname, PATHSEP);
142 	if (str != NULL)
143 		str[1] = 0;
144 	File_CleanFileName(confname);
145 	File_ShrinkName(dlgname, confname, maxlen);
146 }
147 
148 
149 /**
150  * Ask whether new disk should be inserted to A: or B: and if yes, insert.
151  */
DlgFloppy_QueryInsert(char * namea,int ida,char * nameb,int idb,const char * path)152 static void DlgFloppy_QueryInsert(char *namea, int ida, char *nameb, int idb, const char *path)
153 {
154 	const char *realname;
155 	int diskid, dlgid;
156 	char *dlgname;
157 
158 	SDLGui_CenterDlg(alertdlg);
159 	switch (SDLGui_DoDialog(alertdlg, NULL))
160 	{
161 		case DLGMOUNT_A:
162 			dlgname = namea;
163 			dlgid = ida;
164 			diskid = 0;
165 			break;
166 		case DLGMOUNT_B:
167 			dlgname = nameb;
168 			dlgid = idb;
169 			diskid = 1;
170 			break;
171 		default:
172 			return;
173 	}
174 
175 	realname = Floppy_SetDiskFileName(diskid, path, NULL);
176 	if (realname)
177 		File_ShrinkName(dlgname, realname, floppydlg[dlgid].w);
178 }
179 
180 
181 /**
182  * Show and process the floppy disk image dialog.
183  */
DlgFloppy_Main(void)184 void DlgFloppy_Main(void)
185 {
186 	int but, i;
187 	char *newdisk;
188 	char dlgname[MAX_FLOPPYDRIVES][64], dlgdiskdir[64];
189 
190 	SDLGui_CenterDlg(floppydlg);
191 
192 	/* Set up dialog to actual values: */
193 
194 	/* Disk name A: */
195 	if (EmulationDrives[0].bDiskInserted)
196 		File_ShrinkName(dlgname[0], ConfigureParams.DiskImage.szDiskFileName[0],
197 		                floppydlg[FLOPPYDLG_DISKA].w);
198 	else
199 		dlgname[0][0] = '\0';
200 	floppydlg[FLOPPYDLG_DISKA].txt = dlgname[0];
201 
202 	/* Disk name B: */
203 	if (EmulationDrives[1].bDiskInserted)
204 		File_ShrinkName(dlgname[1], ConfigureParams.DiskImage.szDiskFileName[1],
205 		                floppydlg[FLOPPYDLG_DISKB].w);
206 	else
207 		dlgname[1][0] = '\0';
208 	floppydlg[FLOPPYDLG_DISKB].txt = dlgname[1];
209 
210 	/* Default image directory: */
211 	File_ShrinkName(dlgdiskdir, ConfigureParams.DiskImage.szDiskImageDirectory,
212 	                floppydlg[FLOPPYDLG_IMGDIR].w);
213 	floppydlg[FLOPPYDLG_IMGDIR].txt = dlgdiskdir;
214 
215 	/* Auto insert disk B: */
216 	if (ConfigureParams.DiskImage.bAutoInsertDiskB)
217 		floppydlg[FLOPPYDLG_AUTOB].state |= SG_SELECTED;
218 	else
219 		floppydlg[FLOPPYDLG_AUTOB].state &= ~SG_SELECTED;
220 
221 	/* Write protection */
222 	for (i = FLOPPYDLG_PROTOFF; i <= FLOPPYDLG_PROTAUTO; i++)
223 	{
224 		floppydlg[i].state &= ~SG_SELECTED;
225 	}
226 	floppydlg[FLOPPYDLG_PROTOFF+ConfigureParams.DiskImage.nWriteProtection].state |= SG_SELECTED;
227 
228 	/* Fast floppy access */
229 	if (ConfigureParams.DiskImage.FastFloppy)
230 		floppydlg[FLOPPYDLG_FASTFLOPPY].state |= SG_SELECTED;
231 	else
232 		floppydlg[FLOPPYDLG_FASTFLOPPY].state &= ~SG_SELECTED;
233 
234 	/* Enable/disable drives A: and B: */
235 	if (ConfigureParams.DiskImage.EnableDriveA)
236 		floppydlg[FLOPPYDLG_ENABLE_A].state |= SG_SELECTED;
237 	else
238 		floppydlg[FLOPPYDLG_ENABLE_A].state &= ~SG_SELECTED;
239 
240 	if (ConfigureParams.DiskImage.EnableDriveB)
241 		floppydlg[FLOPPYDLG_ENABLE_B].state |= SG_SELECTED;
242 	else
243 		floppydlg[FLOPPYDLG_ENABLE_B].state &= ~SG_SELECTED;
244 
245 	/* Set drives to single sided or double sided */
246 	if (ConfigureParams.DiskImage.DriveA_NumberOfHeads == 2)
247 		floppydlg[FLOPPYDLG_HEADS_DS_A].state |= SG_SELECTED;
248 	else
249 		floppydlg[FLOPPYDLG_HEADS_DS_A].state &= ~SG_SELECTED;
250 
251 	if (ConfigureParams.DiskImage.DriveB_NumberOfHeads == 2)
252 		floppydlg[FLOPPYDLG_HEADS_DS_B].state |= SG_SELECTED;
253 	else
254 		floppydlg[FLOPPYDLG_HEADS_DS_B].state &= ~SG_SELECTED;
255 
256 	/* Draw and process the dialog */
257 	do
258 	{
259 		but = SDLGui_DoDialog(floppydlg, NULL);
260 		switch (but)
261 		{
262 		 case FLOPPYDLG_EJECTA:                         /* Eject disk in drive A: */
263 			Floppy_SetDiskFileNameNone(0);
264 			dlgname[0][0] = '\0';
265 			break;
266 		 case FLOPPYDLG_BROWSEA:                        /* Choose a new disk A: */
267 			DlgDisk_BrowseDisk(dlgname[0], 0, FLOPPYDLG_DISKA);
268 			break;
269 		 case FLOPPYDLG_EJECTB:                         /* Eject disk in drive B: */
270 			Floppy_SetDiskFileNameNone(1);
271 			dlgname[1][0] = '\0';
272 			break;
273 		case FLOPPYDLG_BROWSEB:                         /* Choose a new disk B: */
274 			DlgDisk_BrowseDisk(dlgname[1], 1, FLOPPYDLG_DISKB);
275 			break;
276 		 case FLOPPYDLG_BROWSEIMG:
277 			DlgDisk_BrowseDir(dlgdiskdir,
278 			                 ConfigureParams.DiskImage.szDiskImageDirectory,
279 			                 floppydlg[FLOPPYDLG_IMGDIR].w);
280 			break;
281 		 case FLOPPYDLG_CREATEIMG:
282 			newdisk = DlgNewDisk_Main();
283 			if (newdisk)
284 			{
285 				DlgFloppy_QueryInsert(dlgname[0], FLOPPYDLG_DISKA,
286 						      dlgname[1], FLOPPYDLG_DISKB,
287 						      newdisk);
288 				free(newdisk);
289 			}
290 			break;
291 		}
292 		if (gui_poll_events()) break;
293 	}
294 	while (but != FLOPPYDLG_EXIT && but != SDLGUI_QUIT
295 	        && but != SDLGUI_ERROR && !bQuitProgram);
296 
297 	/* Read values from dialog: */
298 
299 	for (i = FLOPPYDLG_PROTOFF; i <= FLOPPYDLG_PROTAUTO; i++)
300 	{
301 		if (floppydlg[i].state & SG_SELECTED)
302 		{
303 			ConfigureParams.DiskImage.nWriteProtection = i-FLOPPYDLG_PROTOFF;
304 			break;
305 		}
306 	}
307 
308 	ConfigureParams.DiskImage.bAutoInsertDiskB = (floppydlg[FLOPPYDLG_AUTOB].state & SG_SELECTED);
309 	ConfigureParams.DiskImage.FastFloppy = (floppydlg[FLOPPYDLG_FASTFLOPPY].state & SG_SELECTED);
310 	ConfigureParams.DiskImage.EnableDriveA = (floppydlg[FLOPPYDLG_ENABLE_A].state & SG_SELECTED);
311 	ConfigureParams.DiskImage.EnableDriveB = (floppydlg[FLOPPYDLG_ENABLE_B].state & SG_SELECTED);
312 	ConfigureParams.DiskImage.DriveA_NumberOfHeads = ( (floppydlg[FLOPPYDLG_HEADS_DS_A].state & SG_SELECTED) ? 2 : 1 );
313 	ConfigureParams.DiskImage.DriveB_NumberOfHeads = ( (floppydlg[FLOPPYDLG_HEADS_DS_B].state & SG_SELECTED) ? 2 : 1 );
314 }
315