1 /*
2  * UAE - the Un*x Amiga Emulator
3  *
4  * Yet Another User Interface for the X11 version
5  *
6  * Copyright 1997, 1998 Bernd Schmidt
7  * Copyright 1998 Michael Krause
8  *
9  * The Tk GUI doesn't work.
10  * The X Forms Library isn't available as source, and there aren't any
11  * binaries compiled against glibc
12  *
13  * So let's try this...
14  */
15 
16 #include "sysconfig.h"
17 #include "sysdeps.h"
18 
19 #include "options.h"
20 #include "uae.h"
21 #include "memory.h"
22 #include "custom.h"
23 #include "audio.h"
24 #include "gui.h"
25 #include "newcpu.h"
26 #include "autoconf.h"
27 #include "filesys.h"
28 #include "threaddep/thread.h"
29 #include "sounddep/sound.h"
30 #include "savestate.h"
31 #include "debug.h"
32 #include "inputdevice.h"
33 #include "romlist.h"
34 #include "zfile.h"
35 
36 #include <gtk/gtk.h>
37 #include <gdk/gdk.h>
38 
39 #include "util.h"
40 
41 static int gui_active, gui_available;
42 
43 static GtkWidget *gui_window;
44 
45 static GtkWidget *pause_uae_widget, *snap_save_widget, *snap_load_widget;
46 
47 static GtkWidget *chipsize_widget[5];
48 static GtkWidget *bogosize_widget[4];
49 static GtkWidget *fastsize_widget[5];
50 static GtkWidget *z3size_widget[10];
51 static GtkWidget *p96size_widget[7];
52 static GtkWidget *rom_text_widget, *rom_path_widget, *key_text_widget;
53 static GtkWidget *romlist_widget, *romsel_button;
54 static int romlist_nr_entries;
55 
56 static GtkWidget *disk_insert_widget[4], *disk_eject_widget[4], *disk_text_widget[4];
57 static GtkWidget *dftype_widget[4];
58 static GtkWidget *disk_type_widget[4];
59 
60 static GtkAdjustment *cpuspeed_adj;
61 static GtkWidget *cpuspeed_widgets[4], *cpuspeed_scale;
62 static GtkWidget *cpu_widget[7], *fpu_widget[5];
63 static GtkWidget *sound_widget[4], *sound_ch_widget[3], *sound_interpol_widget[3];
64 static GtkWidget *sound_filter_widget[5];
65 static GtkAdjustment *stereo_sep_adj, *stereo_delay_adj;
66 static GtkWidget *stereo_sep_scale, *stereo_delay_scale;
67 
68 static GtkWidget *coll_widget[4], *cslevel_widget[4], *ntsc_widget[2];
69 static GtkWidget *mbtype_widget, *mbtype_labelled;
70 static GtkWidget *fcop_widget;
71 
72 static GtkAdjustment *framerate_adj;
73 static GtkWidget *bimm_widget, *b32_widget, *afscr_widget, *pfscr_widget;
74 
75 struct scrmode_widgets
76 {
77     GtkWidget *frame, *modelist;
78     GtkWidget *hcenter, *vcenter, *aspect, *linedbl, *leds;
79     GtkWidget *hc_label, *vc_label, *ld_label;
80 };
81 
82 static struct scrmode_widgets gw_windowed, gw_fullscreen;
83 
84 static GtkWidget *joy_widget[2][6], *legacy_widget, *kbdlang_widget;
85 
86 static GtkWidget *led_widgets[5];
87 static GdkColor led_on[5], led_off[5];
88 static unsigned int prevledstate;
89 
90 static GtkListStore *hd_store;
91 static GtkWidget *hdlist_widget, *bootrom_widget;
92 static GtkWidget *hdchange_button, *hddel_button;
93 static GtkTreeSelection *hd_selection;
94 
95 static GtkWidget *preset_list, *preset_button;
96 static GtkTreeSelection *preset_selection;
97 
98 static GtkWidget *req68020, *req68ec020, *req68030, *reqa4000, *reqa1000;
99 static int rom_req;
100 
101 static GtkWidget *lab_info;
102 static GtkWidget *notebook;
103 
104 GtkWidget *disk_selector;
105 
106 static uae_sem_t gui_sem;
107 
108 /* Copies of certain changed_prefs elements, local to the GUI thread and
109    protected by the gui_sem.  */
110 static struct gfx_params gfx_w, gfx_f;
111 static char *gui_snapname, *gui_romname, *gui_keyname;
112 static char *new_disk_string[4];
113 
114 
115 static smp_comm_pipe to_gui_pipe, from_gui_pipe;
116 
117 /* Set to ignore the widget callbacks while we're in the process of updating
118    them with new data.  */
119 static int ignore_gui_changes;
120 
121 /*
122  * Messages sent to GUI from UAE via to_gui_pipe
123  */
124 enum gui_commands {
125     GUICMD_SHOW,                 // Show yourself
126     GUICMD_UPDATE,               // Refresh your state from changed preferences
127     GUICMD_DISKCHANGE,           // Hey! A disk has been changed. Do something!
128     GUICMD_MSGBOX,               // Display a message box for me, please
129     GUICMD_NEW_ROMLIST,          // The ROM list has been updated.
130     GUICMD_FLOPPYDLG,            // Open a floppy insert dialog
131     GUICMD_FULLSCREEN,           // Fullscreen mode was toggled; update checkboxes
132     GUICMD_PAUSE,                // We're now paused, in case you didn't notice
133     GUICMD_UNPAUSE               // We're now running.
134 };
135 
136 static uae_sem_t gui_sem, gui_init_sem, gui_quit_sem; /* gui_sem protects the DFx fields */
137 
138 static volatile int quit_gui = 0;
139 
140 /* Message box functions.  */
141 
142 
make_labelled_button(guchar * label,GtkAccelGroup * accel_group)143 static GtkWidget *make_labelled_button (guchar *label, GtkAccelGroup *accel_group)
144 {
145     return gtk_button_new_with_mnemonic (label);
146 }
147 
find_current_toggle(GtkWidget ** widgets,int count)148 static int find_current_toggle (GtkWidget **widgets, int count)
149 {
150     int i;
151     for (i = 0; i < count; i++)
152 	if (GTK_TOGGLE_BUTTON (*widgets++)->active)
153 	    return i;
154     write_log ("GTKUI: Can't happen!\n");
155     return -1;
156 }
157 
158 /*
159  * make_message_box()
160  *
161  * This does the actual work of constructing the message dialog.
162  *
163  * title   - displayed in the dialog's titlebar
164  * message - the message itself
165  * modal   - whether the dialog should block input to the rest of the GUI
166  * sem     - semaphore used for signalling that the dialog's finished
167  *
168  * TODO: Make that semaphore go away. We shouldn't need to know about it here.
169  */
170 
make_message_box(const char * title,const char * message,int modal)171 static void make_message_box (const char *title, const char *message, int modal)
172 {
173     GtkWidget *dialog;
174     GtkWidget *vbox, *hbox;
175     GtkWidget *label;
176 
177     if (title == NULL || strlen (title) == 0)
178 	title = PACKAGE_NAME " information";
179     dialog = gtk_dialog_new_with_buttons (title, NULL,
180 					  (modal ? GTK_DIALOG_MODAL : 0),
181 					  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
182 					  NULL);
183 
184     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
185 
186     vbox = GTK_DIALOG (dialog)->vbox;
187 
188     hbox = gtk_hbox_new (FALSE, 0);
189     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 20);
190     gtk_widget_show (hbox);
191 
192     label = gtk_label_new (message);
193     gtk_widget_show (label);
194     gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 20);
195     gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
196 
197     gtk_dialog_run (GTK_DIALOG (dialog));
198 
199     gtk_widget_destroy (dialog);
200 }
201 
mkmsgbox(const char * title,const char * message)202 static void mkmsgbox (const char *title, const char *message)
203 {
204     make_message_box (title, message, 1);
205 }
206 
207 /*
208  * handle_message_box_request()
209  *
210  * This is called from the GUI's context in repsonse to do_message_box()
211  * to actually create the dialog box
212  */
handle_message_box_request(smp_comm_pipe * msg_pipe)213 static void handle_message_box_request (smp_comm_pipe *msg_pipe)
214 {
215     const char *title = (const char *) read_comm_pipe_pvoid_blocking (msg_pipe);
216     const char *msg = (const char *) read_comm_pipe_pvoid_blocking (msg_pipe);
217     int modal = read_comm_pipe_int_blocking (msg_pipe);
218     uae_sem_t *msg_quit_sem = (uae_sem_t *) read_comm_pipe_pvoid_blocking (msg_pipe);
219 
220     make_message_box (title, msg, modal);
221     uae_sem_post (msg_quit_sem);
222 }
223 
224 /*
225  * do_message_box()
226  *
227  * This makes up for GTK's lack of a function for creating simple message dialogs.
228  * It can be called from any context. gui_init() must have been called at some point
229  * previously.
230  *
231  * title   - will be displayed in the dialog's titlebar (or NULL for default)
232  * message - the message itself
233  * modal   - should the dialog block input to the rest of the GUI
234  * wait    - should the dialog wait until the user has acknowledged it
235  */
do_message_box(const guchar * title,const guchar * message,gboolean modal,gboolean wait)236 static void do_message_box (const guchar *title, const guchar *message, gboolean modal, gboolean wait)
237 {
238     uae_sem_t msg_quit_sem;
239 
240     // If we a need reply, then this semaphore which will be used
241     // to signal us when the dialog has been exited.
242     uae_sem_init (&msg_quit_sem, 0, 0);
243 
244     write_comm_pipe_int   (&to_gui_pipe, GUICMD_MSGBOX, 0);
245     write_comm_pipe_pvoid (&to_gui_pipe, (void *) title, 0);
246     write_comm_pipe_pvoid (&to_gui_pipe, (void *) message, 0);
247     write_comm_pipe_int   (&to_gui_pipe, (int) modal, 0);
248     write_comm_pipe_pvoid (&to_gui_pipe, wait?&msg_quit_sem:NULL, 1);
249 
250     if (wait)
251 	uae_sem_wait (&msg_quit_sem);
252 }
253 
gui_message(const char * format,...)254 void gui_message (const char *format, ...)
255 {
256     char msg[2048];
257     va_list parms;
258 
259     va_start (parms,format);
260     vsprintf ( msg, format, parms);
261     va_end (parms);
262 
263     if (gui_available)
264 	do_message_box (NULL, msg, TRUE, TRUE);
265 
266     write_log (msg);
267 }
268 
269 /* Config save/load.  */
270 
save_config(void)271 static void save_config (void)
272 {
273     FILE *f;
274     char tmp[257];
275 
276     /* Backup the options file.  */
277     strcpy (tmp, optionsfile);
278     strcat (tmp, "~");
279     rename (optionsfile, tmp);
280 
281     f = fopen (optionsfile, "w");
282     if (f == NULL) {
283 	write_log ("Error saving options file!\n");
284 	return;
285     }
286     save_options (f, &changed_prefs);
287     fclose (f);
288 }
289 
nr_for_led(GtkWidget * led)290 static int nr_for_led (GtkWidget *led)
291 {
292     int i;
293     i = 0;
294     while (led_widgets[i] != led)
295 	i++;
296     return i;
297 }
298 
enable_disk_buttons(int enable)299 static void enable_disk_buttons (int enable)
300 {
301     int i;
302     for (i = 0; i < 4; i++) {
303 	drive_type t = changed_prefs.dfxtype[i];
304 	gtk_widget_set_sensitive (disk_insert_widget[i], enable && t != DRV_NONE);
305 	gtk_widget_set_sensitive (disk_eject_widget[i], enable && t != DRV_NONE);
306 	gtk_widget_set_sensitive (dftype_widget[i], enable);
307     }
308 }
309 
set_disk_state(void)310 static void set_disk_state (void)
311 {
312     int i;
313     ignore_gui_changes++;
314     for (i = 0; i < 4; i++) {
315 	drive_type t = changed_prefs.dfxtype[i];
316 	int n;
317 	if (i == 0)
318 	    n = t == DRV_35_DD ? 0 : 1;
319 	else
320 	    n = t == DRV_35_DD ? 1 : t == DRV_35_HD ? 2 : 0;
321 	gtk_combo_box_set_active (GTK_COMBO_BOX (dftype_widget[i]), n);
322     }
323     ignore_gui_changes--;
324 }
325 
set_romlist_state(void)326 static void set_romlist_state (void)
327 {
328     int i;
329     int active_entry = 0;
330 
331     for (i = 1; i < romlist_nr_entries; i++)
332 	gtk_combo_box_remove_text (GTK_COMBO_BOX (romlist_widget), 1);
333     romlist_nr_entries = 1;
334 
335     for (i = 0;; i++) {
336 	struct romlist *rl = romlist_from_idx (i, ROMTYPE_KICK, 1);
337 	if (!rl)
338 	    break;
339 	if ((changed_prefs.rom_crc32 != 0 && rl->rd->crc32 == changed_prefs.rom_crc32)
340 	    || (changed_prefs.rom_crc32 == 0 && strcmp (rl->path, changed_prefs.romfile) == 0))
341 	    active_entry = romlist_nr_entries;
342 	gtk_combo_box_append_text (GTK_COMBO_BOX (romlist_widget), rl->rd->name);
343 	romlist_nr_entries++;
344     }
345     gtk_combo_box_set_active (GTK_COMBO_BOX (romlist_widget), active_entry);
346     gtk_widget_set_sensitive (romsel_button, active_entry == 0);
347     gtk_widget_set_sensitive (rom_text_widget, active_entry == 0);
348 }
349 
set_cpu_state(void)350 static void set_cpu_state (void)
351 {
352     gtk_widget_set_sensitive (cpuspeed_scale, changed_prefs.m68k_speed > 0);
353 
354     gtk_widget_set_sensitive (fpu_widget[0], changed_prefs.cpu_model != 68040 && changed_prefs.cpu_model != 68060);
355     gtk_widget_set_sensitive (fpu_widget[1], changed_prefs.cpu_model == 68020 || changed_prefs.cpu_model == 68030);
356     gtk_widget_set_sensitive (fpu_widget[2], changed_prefs.cpu_model == 68020 || changed_prefs.cpu_model == 68030);
357     gtk_widget_set_sensitive (fpu_widget[3], changed_prefs.cpu_model == 68040);
358     gtk_widget_set_sensitive (fpu_widget[4], changed_prefs.cpu_model == 68060);
359 }
360 
set_cpu_widget(void)361 static void set_cpu_widget (void)
362 {
363     int nr = (changed_prefs.cpu_model == 68000 ? 0
364 	      : changed_prefs.cpu_model == 68010 ? 1
365 	      : changed_prefs.cpu_model == 68020 ? 2
366 	      : changed_prefs.cpu_model == 68030 ? 4
367 	      : changed_prefs.cpu_model == 68040 ? 5
368 	      : 6);
369 
370     if (nr == 2 && !changed_prefs.address_space_24)
371 	nr++;
372     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpu_widget[nr]), TRUE);
373 
374     nr = (changed_prefs.fpu_model == 68881 ? 1
375 	  : changed_prefs.fpu_model == 68882 ? 2
376 	  : changed_prefs.cpu_model == 68040 ? 3
377 	  : changed_prefs.cpu_model == 68060 ? 4
378 	  : 0);
379     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[nr]), TRUE);
380     nr = changed_prefs.m68k_speed + 1 < 3 ? changed_prefs.m68k_speed + 1 : 2;
381     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpuspeed_widgets[nr]), TRUE);
382 }
383 
384 /* The idea behind this is to keep entries in aspect/centering boxes even
385    if a screen mode is selected where they are unnecessary, but set the
386    prefs to sane values.  */
adjust_gfx_prefs(struct gfx_params * gp,struct scrmode_widgets * w)387 static void adjust_gfx_prefs (struct gfx_params *gp, struct scrmode_widgets *w)
388 {
389     int need_hcenter, need_vcenter, need_aspect, need_linedbl;
390     need_hcenter = gp->width < 400 || (gp->width > 512 && gp->width < 800);
391     need_vcenter = gp->height <= 256 || (gp->height > 300 && gp->height <= 512);
392     need_linedbl = gp->height >= 400;
393     need_aspect = ((gp->height < 256 || (gp->height > 300 && gp->height < 512))
394 		   && gp->height * 5 / 4 < gp->width);
395 
396     gtk_widget_set_sensitive (w->vc_label, need_vcenter);
397     gtk_widget_set_sensitive (w->hc_label, need_hcenter);
398     gtk_widget_set_sensitive (w->aspect, need_aspect);
399     gtk_widget_set_sensitive (w->ld_label, need_linedbl);
400 
401     if (!need_linedbl)
402 	gp->linedbl = 0;
403     if (!need_aspect)
404 	gp->correct_aspect = FALSE;
405     if (!need_vcenter)
406 	gp->ycenter = 0;
407     if (!need_hcenter)
408 	gp->xcenter = 0;
409 }
410 
set_gfx_mode_state(struct gfx_params * gp,struct scrmode_widgets * w)411 static void set_gfx_mode_state (struct gfx_params *gp, struct scrmode_widgets *w)
412 {
413     ignore_gui_changes++;
414 
415     gtk_combo_box_set_active (GTK_COMBO_BOX (w->linedbl), gp->linedbl ? gp->linedbl - 1 : 1);
416     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w->aspect), gp->correct_aspect);
417     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w->leds), gp->leds_on_screen);
418 
419     gtk_combo_box_set_active (GTK_COMBO_BOX (w->hcenter), gp->xcenter);
420     gtk_combo_box_set_active (GTK_COMBO_BOX (w->vcenter), gp->ycenter);
421     ignore_gui_changes--;
422 }
423 
set_fullscreen_state(void)424 static void set_fullscreen_state (void)
425 {
426     ignore_gui_changes++;
427     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (afscr_widget), changed_prefs.gfx_afullscreen != 0);
428     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pfscr_widget), changed_prefs.gfx_pfullscreen != 0);
429     ignore_gui_changes--;
430 }
431 
set_gfx_state(void)432 static void set_gfx_state (void)
433 {
434     int t;
435 
436     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bimm_widget), changed_prefs.immediate_blits != 0);
437 
438     ignore_gui_changes++;
439     uae_sem_wait (&gui_sem);
440     t = fixup_prefs_dimensions (&gfx_w, gfx_windowed_modes, n_windowed_modes);
441     gtk_combo_box_set_active (GTK_COMBO_BOX (gw_windowed.modelist), t);
442     t = fixup_prefs_dimensions (&gfx_f, gfx_fullscreen_modes, n_fullscreen_modes);
443     gtk_combo_box_set_active (GTK_COMBO_BOX (gw_fullscreen.modelist), t);
444     ignore_gui_changes--;
445 
446     adjust_gfx_prefs (&gfx_w, &gw_windowed);
447     adjust_gfx_prefs (&gfx_f, &gw_fullscreen);
448     uae_sem_post (&gui_sem);
449 
450     set_gfx_mode_state (&gfx_w, &gw_windowed);
451     set_gfx_mode_state (&gfx_f, &gw_fullscreen);
452 
453     set_fullscreen_state ();
454 #if 0
455     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b32_widget), changed_prefs.blits_32bit_enabled != 0);
456 #endif
457 }
458 
459 /* The intended behaviour here is that on startup, and when loading a state
460    file, we examine the prefs to see if they match a given motherboard, and
461    initialize the combo box accordingly.  When the user changes it, default
462    settings are automatically chosen unless the user sets "Generic", in which
463    case he has control over all the options.  */
discover_cstype(void)464 static void discover_cstype (void)
465 {
466     int t0;
467     int cstype = cstype_from_prefs (&changed_prefs);
468 
469     t0 = (cstype == CP_GENERIC ? 0
470 	  : cstype == CP_A1000 ? 1
471 	  : cstype == CP_A500 || cstype == CP_A500P ? 2
472 	  : cstype == CP_A600 ? 3
473 	  : cstype == CP_A1200 ? 4
474 	  : cstype == CP_A3000 ? 5
475 	  : 6);
476 
477     ignore_gui_changes++;
478     gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), t0);
479     ignore_gui_changes--;
480 }
481 
set_chipset_state(void)482 static void set_chipset_state (void)
483 {
484     int t0 = 0;
485 
486     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (coll_widget[changed_prefs.collision_level]), TRUE);
487     if (changed_prefs.chipset_mask & CSMASK_AGA)
488 	t0 = 3;
489     else if (changed_prefs.chipset_mask & CSMASK_ECS_DENISE)
490 	t0 = 2;
491     else if (changed_prefs.chipset_mask & CSMASK_ECS_AGNUS)
492 	t0 = 1;
493     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cslevel_widget[t0]), TRUE);
494 }
495 
set_sound_state(void)496 static void set_sound_state (void)
497 {
498     int n;
499 
500     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_widget[changed_prefs.produce_sound]), 1);
501     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_interpol_widget[changed_prefs.sound_interpol]), 1);
502     n = (changed_prefs.sound_filter == FILTER_SOUND_OFF ? 0
503 	 : ((changed_prefs.sound_filter == FILTER_SOUND_EMUL ? 1 : 2)
504 	    + (changed_prefs.sound_filter_type == FILTER_SOUND_TYPE_A500 ? 0 : 2)));
505     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_filter_widget[n]), 1);
506 }
507 
set_mem_state(void)508 static void set_mem_state (void)
509 {
510     int bogo2m_ok;
511     int t, t2, i;
512 
513     for (i = 0; i < 10; i++)
514 	gtk_widget_set_sensitive (z3size_widget[i], ! changed_prefs.address_space_24);
515     for (i = 0; i < 7; i++)
516 	gtk_widget_set_sensitive (p96size_widget[i],
517 				  changed_prefs.bootrom && ! changed_prefs.address_space_24);
518 
519     bogo2m_ok = !((changed_prefs.chipset_mask & CSMASK_AGA) || changed_prefs.cpu_model >= 68020);
520     gtk_widget_set_sensitive (bogosize_widget[3], bogo2m_ok);
521 
522     t = 0;
523     t2 = changed_prefs.chipmem_size;
524     while (t < 4 && t2 > 0x80000)
525 	t++, t2 >>= 1;
526     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chipsize_widget[t]), 1);
527 
528     t = 0;
529     t2 = changed_prefs.bogomem_size;
530     if (t2 > 0x100000 && !bogo2m_ok)
531 	t2 = 0x100000;
532     changed_prefs.bogomem_size = t2;
533     while (t < 3 && t2 >= 0x80000)
534 	t++, t2 >>= 1;
535     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bogosize_widget[t]), 1);
536 
537     t = 0;
538     t2 = changed_prefs.fastmem_size;
539     while (t < 4 && t2 >= 0x100000)
540 	t++, t2 >>= 1;
541     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fastsize_widget[t]), 1);
542 
543     t = 0;
544     t2 = changed_prefs.z3fastmem_size;
545     while (t < 9 && t2 >= 0x100000)
546 	t++, t2 >>= 1;
547     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (z3size_widget[t]), 1);
548 
549     t = 0;
550     t2 = changed_prefs.gfxmem_size;
551     while (t < 6 && t2 >= 0x100000)
552 	t++, t2 >>= 1;
553     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p96size_widget[t]), 1);
554 
555     gtk_label_set_text (GTK_LABEL (rom_path_widget), changed_prefs.path_rom);
556     gtk_label_set_text (GTK_LABEL (rom_text_widget), changed_prefs.romfile);
557     gtk_label_set_text (GTK_LABEL (key_text_widget), changed_prefs.keyfile);
558 }
559 
set_joy_state(void)560 static void set_joy_state (void)
561 {
562     int joy_count = inputdevice_get_device_total (IDTYPE_JOYSTICK);
563     int j0j = jsem_isjoy (0, &changed_prefs);
564     int j0m = jsem_ismouse (0, &changed_prefs);
565     int j0k = jsem_iskbdjoy (0, &changed_prefs);
566     int j1j = jsem_isjoy (1, &changed_prefs);
567     int j1m = jsem_ismouse (1, &changed_prefs);
568     int j1k = jsem_iskbdjoy (1, &changed_prefs);
569     int j0t = (j0j == 0 || j0j == 1 ? j0j
570 	       : j0m == 0 ? 2
571 	       : j0k + 3);
572     int j1t = (j1j == 0 || j1j == 1 ? j1j
573 	       : j1m == 0 ? 2
574 	       : j1k + 3);
575     int i;
576 
577     if (j0t == j1t) {
578 	/* Can't happen */
579 	j0t++;
580 	j0t %= 6;
581     }
582 
583     for (i = 0; i < 6; i++) {
584 	int available = i >= 2 || joy_count > i;
585 	if (changed_prefs.input_selected_setting != 0)
586 	    available = 0;
587 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[0][i]), j0t == i);
588 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[1][i]), j1t == i);
589 	gtk_widget_set_sensitive (joy_widget[0][i], available && j1t != i);
590 	gtk_widget_set_sensitive (joy_widget[1][i], available && j0t != i);
591     }
592 
593     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (legacy_widget),
594 				  changed_prefs.input_selected_setting == 0);
595 
596     gtk_combo_box_set_active (GTK_COMBO_BOX (kbdlang_widget),
597 			      changed_prefs.keyboard_lang);
598 }
599 
set_hd_state(void)600 static void set_hd_state (void)
601 {
602     char texts[9][256];
603     int nr = nr_units (currprefs.mountinfo);
604     int i;
605 
606     gtk_list_store_clear (hd_store);
607     for (i = 0; i < nr; i++) {
608 	GtkTreeIter iter;
609 	int secspertrack, surfaces, reserved, blocksize, size;
610 	int cylinders, readonly, pri, type;
611 	char *volname, *rootdir, *devname;
612 	char *failure;
613 
614 	/* We always use currprefs.mountinfo for the GUI.  The filesystem
615 	   code makes a private copy which is updated every reset.  */
616 	failure = get_filesys_unit (currprefs.mountinfo, i,
617 				    &devname, &volname, &rootdir, &readonly,
618 				    &secspertrack, &surfaces, &reserved,
619 				    &cylinders, &size, &blocksize, &pri);
620 
621 	type = hardfile_fs_type (currprefs.mountinfo, i);
622 	if (type != FILESYS_VIRTUAL) {
623 	    sprintf (texts[0], "DH%d", i );
624 	    sprintf (texts[3], "%d", surfaces);
625 	    sprintf (texts[4], "%d", cylinders);
626 	    sprintf (texts[5], "%d", secspertrack);
627 	    sprintf (texts[6], "%d", reserved);
628 	    sprintf (texts[7], "%d", size);
629 	    sprintf (texts[8], "%d", blocksize);
630 	} else {
631 	    strcpy (texts[0], volname);
632 	    strcpy (texts[3], "n/a");
633 	    strcpy (texts[4], "n/a");
634 	    strcpy (texts[5], "n/a");
635 	    strcpy (texts[6], "n/a");
636 	    strcpy (texts[7], "n/a");
637 	    strcpy (texts[8], "n/a");
638 	}
639 	strcpy (texts[1], rootdir);
640 	gtk_list_store_append (hd_store, &iter);
641 
642 	gtk_list_store_set (hd_store, &iter,
643 			    0, i,
644 			    1, texts[0],
645 			    2, texts[1],
646 			    3, readonly,
647 			    4, texts[3],
648 			    5, texts[4],
649 			    6, texts[5],
650 			    7, texts[6],
651 			    8, texts[7],
652 			    9, texts[8],
653 			    10, pri,
654 			    -1);
655 	if (volname)
656 	    free (volname);
657 	if (devname)
658 	    free (devname);
659 	if (rootdir)
660 	    free (rootdir);
661     }
662     gtk_widget_set_sensitive (hdchange_button, FALSE);
663     gtk_widget_set_sensitive (hddel_button, FALSE);
664 
665     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bootrom_widget),
666 				  changed_prefs.bootrom != 0);
667 }
668 
rom_requirements_change(void)669 static void rom_requirements_change (void)
670 {
671     int i, min_widget = 0;
672 
673     gtk_widget_hide (req68020);
674     gtk_widget_hide (req68ec020);
675     gtk_widget_hide (req68030);
676     gtk_widget_hide (reqa1000);
677     gtk_widget_hide (reqa4000);
678     if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68EC020) {
679 	min_widget = 2;
680 	gtk_widget_show (req68ec020);
681     } else if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68020) {
682 	min_widget = 3;
683 	gtk_widget_show (req68020);
684     } else if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68030) {
685 	min_widget = 4;
686 	gtk_widget_show (req68030);
687     }
688     if (rom_req & ROMREQ_A4000MB) {
689 	gtk_widget_show (reqa4000);
690 	gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), 6);
691 	gtk_widget_set_sensitive (mbtype_labelled, 0);
692     } else if (rom_req & ROMREQ_A1000) {
693 	gtk_widget_show (reqa1000);
694 	gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), 1);
695 	gtk_widget_set_sensitive (mbtype_labelled, 0);
696     } else
697 	gtk_widget_set_sensitive (mbtype_labelled, 1);
698 
699     i = find_current_toggle (cpu_widget, 7);
700     if (i < min_widget)
701 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpu_widget[min_widget]), TRUE);
702 
703     for (i = 0; i < 7; i++)
704 	gtk_widget_set_sensitive (cpu_widget[i], i >= min_widget);
705 }
706 
draw_led(int nr)707 static void draw_led (int nr)
708 {
709     GtkWidget *thing = led_widgets[nr];
710     GdkWindow *window = thing->window;
711     GdkGC *gc = gdk_gc_new (window);
712     GdkColor *col;
713 
714     if (gui_ledstate & (1 << nr))
715 	col = led_on + nr;
716     else
717 	col = led_off + nr;
718     gdk_gc_set_foreground (gc, col);
719     gdk_draw_rectangle (window, gc, 1, 0, 0, -1, -1);
720     gdk_gc_destroy (gc);
721 }
722 
set_widgets_from_config(void)723 static void set_widgets_from_config (void)
724 {
725     gfx_w = changed_prefs.gfx_w;
726     gfx_f = changed_prefs.gfx_f;
727     set_disk_state ();
728     enable_disk_buttons (1);
729     set_romlist_state ();
730     set_cpu_widget ();
731     set_cpu_state ();
732     set_gfx_state ();
733     set_joy_state ();
734     set_sound_state ();
735     set_mem_state ();
736     set_hd_state ();
737     discover_cstype ();
738     set_chipset_state ();
739     rom_requirements_change ();
740 }
741 
my_idle(void)742 static int my_idle (void)
743 {
744     unsigned int leds = gui_ledstate;
745     int i;
746 
747     if (quit_gui) {
748 	gui_active = 0;
749 	gtk_main_quit ();
750 	goto out;
751     }
752 
753     while (comm_pipe_has_data (&to_gui_pipe)) {
754 	int cmd = read_comm_pipe_int_blocking (&to_gui_pipe);
755 	int n;
756 	switch (cmd) {
757 	case GUICMD_DISKCHANGE:
758 	    n = read_comm_pipe_int_blocking (&to_gui_pipe);
759 	    gtk_label_set_text (GTK_LABEL (disk_text_widget[n]), currprefs.df[n]);
760 	    break;
761 	case GUICMD_SHOW:
762 	    gtk_widget_show (gui_window);
763 	    uae_sem_post (&gui_init_sem);
764 	    break;
765 	case GUICMD_UPDATE:
766 	    /* Initialization.  */
767 	    set_widgets_from_config ();
768 
769 	    gtk_widget_show (gui_window);
770 	    uae_sem_post (&gui_init_sem);
771 	    gui_active = 1;
772 	    break;
773 	case GUICMD_PAUSE:
774 	    /* Set Pause-Button active */
775 	    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pause_uae_widget), TRUE);
776 	    break;
777 	case GUICMD_UNPAUSE:
778 	    /* Set Pause-Button inactive */
779 	    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pause_uae_widget), FALSE);
780 	    break;
781 	case GUICMD_NEW_ROMLIST:
782 	    set_romlist_state ();
783 	    break;
784 	case GUICMD_FULLSCREEN:
785 	    set_fullscreen_state ();
786 	    break;
787 	case GUICMD_MSGBOX:
788 	    handle_message_box_request(&to_gui_pipe);
789 	    break;
790 	}
791     }
792 
793     if (gui_active) {
794 	int n = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)) == 0 ? 5 : 1;
795 	for (i = 0; i < n; i++) {
796 	    unsigned int mask = 1 << i;
797 	    unsigned int on = leds & mask;
798 
799 	    if (on == (prevledstate & mask))
800 		continue;
801 
802 	    /*	printf(": %d %d\n", i, on);*/
803 	    draw_led (i);
804 	}
805 	prevledstate = leds;
806     }
807   out:
808     return 1;
809 }
810 
gui_delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)811 static gint gui_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
812 {
813     gui_active = 0;
814     if (disk_selector)
815 	gtk_widget_destroy (disk_selector);
816     disk_selector = 0;
817     gtk_widget_hide (gui_window);
818     return TRUE;
819 }
820 
dftype_changed(GtkWidget * w,gpointer data)821 static void dftype_changed (GtkWidget *w, gpointer data)
822 {
823     int i;
824 
825     if (ignore_gui_changes)
826 	return;
827     for (i = 0; i < 4; i++) {
828 	int which = gtk_combo_box_get_active (GTK_COMBO_BOX (dftype_widget[i]));
829 	if (i == 0)
830 	    which++;
831 	changed_prefs.dfxtype[i] = (which == 0 ? DRV_NONE : which == 1 ? DRV_35_DD : DRV_35_HD);
832     }
833     enable_disk_buttons (1);
834 }
835 
kbdlang_changed(GtkWidget * w,gpointer data)836 static void kbdlang_changed (GtkWidget *w, gpointer data)
837 {
838     int which = gtk_combo_box_get_active (GTK_COMBO_BOX (kbdlang_widget));
839     changed_prefs.keyboard_lang = which;
840 }
841 
joy_changed(void)842 static void joy_changed (void)
843 {
844     int j0t, j1t;
845     if (! gui_active)
846 	return;
847 
848     j0t = find_current_toggle (joy_widget[0], 6);
849     j1t = find_current_toggle (joy_widget[1], 6);
850     changed_prefs.jport0 = (j0t == 0 || j0t == 1 ? JSEM_JOYS + j0t
851 			    : j0t == 2 ? JSEM_MICE
852 			    : JSEM_KBDLAYOUT + j0t - 3);
853     changed_prefs.jport1 = (j1t == 0 || j1t == 1 ? JSEM_JOYS + j1t
854 			    : j1t == 2 ? JSEM_MICE
855 			    : JSEM_KBDLAYOUT + j1t - 3);
856 
857     changed_prefs.input_selected_setting = GTK_TOGGLE_BUTTON (legacy_widget)->active ? 0 : 1;
858 
859     if (changed_prefs.input_selected_setting != currprefs.input_selected_setting
860 	|| changed_prefs.jport0 != currprefs.jport0
861 	|| changed_prefs.jport1 != currprefs.jport1)
862 	inputdevice_config_change ();
863 
864     set_joy_state ();
865 }
866 
coll_changed(void)867 static void coll_changed (void)
868 {
869     changed_prefs.collision_level = find_current_toggle (coll_widget, 4);
870 }
871 
cslevel_changed(void)872 static void cslevel_changed (void)
873 {
874     int t = find_current_toggle (cslevel_widget, 4);
875     int t1 = 0;
876     if (t > 0)
877 	t1 |= CSMASK_ECS_AGNUS;
878     if (t > 1)
879 	t1 |= CSMASK_ECS_DENISE;
880     if (t > 2)
881 	t1 |= CSMASK_AGA;
882     changed_prefs.chipset_mask = t1;
883     set_mem_state ();
884 }
885 
custom_changed(void)886 static void custom_changed (void)
887 {
888     if (ignore_gui_changes)
889 	return;
890     changed_prefs.gfx_framerate = framerate_adj->value;
891     changed_prefs.immediate_blits = GTK_TOGGLE_BUTTON (bimm_widget)->active;
892     changed_prefs.gfx_afullscreen = GTK_TOGGLE_BUTTON (afscr_widget)->active;
893     changed_prefs.gfx_pfullscreen = GTK_TOGGLE_BUTTON (pfscr_widget)->active;
894 #if 0
895     changed_prefs.blits_32bit_enabled = GTK_TOGGLE_BUTTON (b32_widget)->active;
896 #endif
897 }
898 
leds_changed(void)899 static void leds_changed (void)
900 {
901     int w_leds = GTK_TOGGLE_BUTTON (gw_windowed.leds)->active;
902     int f_leds = GTK_TOGGLE_BUTTON (gw_fullscreen.leds)->active;
903     gfx_w.leds_on_screen = w_leds;
904     gfx_f.leds_on_screen = f_leds;
905     write_comm_pipe_int (&from_gui_pipe, 11, 1);
906 }
907 
aspect_changed(void)908 static void aspect_changed (void)
909 {
910     int w_aspect = GTK_TOGGLE_BUTTON (gw_windowed.aspect)->active;
911     int f_aspect = GTK_TOGGLE_BUTTON (gw_fullscreen.aspect)->active;
912     int w_ldbl = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.linedbl)) + 1;
913     int f_ldbl = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.linedbl)) + 1;
914     int w_hc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.hcenter));
915     int f_hc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.hcenter));
916     int w_vc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.vcenter));
917     int f_vc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.vcenter));
918 
919     if (ignore_gui_changes)
920 	return;
921 
922     uae_sem_wait (&gui_sem);
923     gfx_w.ycenter = w_vc;
924     gfx_w.xcenter = w_hc;
925     gfx_w.correct_aspect = w_aspect;
926     gfx_w.linedbl = w_ldbl;
927     gfx_f.ycenter = f_vc;
928     gfx_f.xcenter = f_hc;
929     gfx_f.correct_aspect = f_aspect;
930     gfx_f.linedbl = f_ldbl;
931 
932     adjust_gfx_prefs (&gfx_w, &gw_windowed);
933     adjust_gfx_prefs (&gfx_f, &gw_fullscreen);
934     uae_sem_post (&gui_sem);
935     write_comm_pipe_int (&from_gui_pipe, 11, 1);
936 }
937 
screenmode_changed(void)938 static void screenmode_changed (void)
939 {
940     int w = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.modelist));
941     int f = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.modelist));
942     int need_set_w = 0, need_set_f = 0;
943 
944     if (ignore_gui_changes)
945 	return;
946 
947     uae_sem_wait (&gui_sem);
948     if (w != -1) {
949 	need_set_w = (gfx_w.width != gfx_windowed_modes[w].w
950 		      || gfx_w.height != gfx_windowed_modes[w].h);
951 	gfx_w.width = gfx_windowed_modes[w].w;
952 	gfx_w.height = gfx_windowed_modes[w].h;
953     }
954     if (f != -1) {
955 	need_set_f = (gfx_f.width != gfx_fullscreen_modes[f].w
956 		      || gfx_f.height != gfx_fullscreen_modes[f].h);
957 	gfx_f.width = gfx_fullscreen_modes[f].w;
958 	gfx_f.height = gfx_fullscreen_modes[f].h;
959     }
960     if (need_set_w) {
961 	fixup_prefs_dimensions (&gfx_w, gfx_windowed_modes, n_windowed_modes);
962     }
963     if (need_set_f) {
964 	fixup_prefs_dimensions (&gfx_f, gfx_fullscreen_modes, n_fullscreen_modes);
965     }
966     uae_sem_post (&gui_sem);
967 
968     if (!need_set_w && !need_set_f)
969 	return;
970 
971     /* We may have switched to a screenmode that has centering or other
972        modifiers enabled; re-set the members of the prefs structure
973        according to the new mode.  See comment before adjust_gfx_prefs.
974 
975        aspect_changed also sends the message to the main thread.  */
976     aspect_changed ();
977 }
978 
cpuspeed_changed(void)979 static void cpuspeed_changed (void)
980 {
981     int which = find_current_toggle (cpuspeed_widgets, 3);
982     changed_prefs.m68k_speed = (which == 0 ? -1
983 				: which == 1 ? 0
984 				: cpuspeed_adj->value);
985     set_cpu_state ();
986 }
987 
cputype_changed(void)988 static void cputype_changed (void)
989 {
990     int i, oldcl;
991     int whichtoggle;
992     if (! gui_active)
993 	return;
994 
995     whichtoggle = find_current_toggle (cpu_widget, 7);
996     changed_prefs.address_space_24 = whichtoggle < 3;
997     if (whichtoggle >= 3)
998 	whichtoggle--;
999 
1000     if (whichtoggle == 5)
1001 	whichtoggle = 6;
1002     changed_prefs.cpu_model = 68000 + 10 * whichtoggle;
1003 
1004     if (changed_prefs.cpu_model == 68060) {
1005 	changed_prefs.fpu_model = 68060;
1006 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[4]), 1);
1007     } else if (changed_prefs.cpu_model == 68040) {
1008 	changed_prefs.fpu_model = 68040;
1009 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[3]), 1);
1010     } else if ((changed_prefs.cpu_model != 68020 && changed_prefs.cpu_model != 68030)
1011 	       || changed_prefs.fpu_model == 68040
1012 	       || changed_prefs.fpu_model == 68060) {
1013 	changed_prefs.fpu_model = 0;
1014 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[0]), 1);
1015     } else {
1016 	whichtoggle = find_current_toggle (fpu_widget, 5);
1017 	changed_prefs.fpu_model = (whichtoggle == 0 ? 0
1018 				   : whichtoggle == 1 ? 68881
1019 				   : whichtoggle == 2 ? 68882
1020 				   : whichtoggle == 3 ? 68040
1021 				   : 68060);
1022     }
1023 
1024     set_cpu_state ();
1025     /* May influence bogomem size and Z3/GFXcard memory.  */
1026     set_mem_state();
1027 }
1028 
chipsize_changed(void)1029 static void chipsize_changed (void)
1030 {
1031     int t = find_current_toggle (chipsize_widget, 5);
1032     changed_prefs.chipmem_size = 0x80000 << t;
1033     for (t = 0; t < 5; t++)
1034 	gtk_widget_set_sensitive (fastsize_widget[t], changed_prefs.chipmem_size <= 0x200000);
1035     if (changed_prefs.chipmem_size > 0x200000) {
1036 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fastsize_widget[0]), 1);
1037 	changed_prefs.fastmem_size = 0;
1038     }
1039 }
1040 
bogosize_changed(void)1041 static void bogosize_changed (void)
1042 {
1043     int t = find_current_toggle (bogosize_widget, 4);
1044     changed_prefs.bogomem_size = (0x40000 << t) & ~0x40000;
1045 }
1046 
fastsize_changed(void)1047 static void fastsize_changed (void)
1048 {
1049     int t = find_current_toggle (fastsize_widget, 5);
1050     changed_prefs.fastmem_size = (0x80000 << t) & ~0x80000;
1051 }
1052 
z3size_changed(void)1053 static void z3size_changed (void)
1054 {
1055     int t = find_current_toggle (z3size_widget, 10);
1056     changed_prefs.z3fastmem_size = (0x80000 << t) & ~0x80000;
1057 }
1058 
p96size_changed(void)1059 static void p96size_changed (void)
1060 {
1061     int t = find_current_toggle (p96size_widget, 7);
1062     changed_prefs.gfxmem_size = (0x80000 << t) & ~0x80000;
1063 }
1064 
rom_combo_changed(void)1065 static void rom_combo_changed (void)
1066 {
1067     int t = gtk_combo_box_get_active (GTK_COMBO_BOX (romlist_widget));
1068     gtk_widget_set_sensitive (romsel_button, t == 0);
1069     gtk_widget_set_sensitive (rom_text_widget, t == 0);
1070 
1071     rom_req = 0;
1072 
1073     if (t == 0) {
1074 	changed_prefs.rom_crc32 = 0;
1075     } else {
1076 	struct romlist *rl = romlist_from_idx (t - 1, ROMTYPE_KICK, 1);
1077 	if (rl) {
1078 	    changed_prefs.rom_crc32 = rl->rd->crc32;
1079 	    rom_req = rl->rd->cpu;
1080 	}
1081     }
1082     rom_requirements_change ();
1083 }
1084 
sound_changed(void)1085 static void sound_changed (void)
1086 {
1087     int n;
1088 
1089     changed_prefs.produce_sound = find_current_toggle (sound_widget, 4);
1090     changed_prefs.sound_interpol = find_current_toggle (sound_interpol_widget, 3);
1091     n = find_current_toggle (sound_filter_widget, 5);
1092     if (n == 0)
1093 	changed_prefs.sound_filter = FILTER_SOUND_OFF;
1094     else {
1095 	changed_prefs.sound_filter = (n & 1) ? FILTER_SOUND_EMUL : FILTER_SOUND_ON;
1096 	changed_prefs.sound_filter_type = (n > 2 ? FILTER_SOUND_TYPE_A1200 : FILTER_SOUND_TYPE_A500);
1097     }
1098     changed_prefs.sound_mixed_stereo_delay = stereo_delay_adj->value;
1099     changed_prefs.sound_stereo_separation = stereo_sep_adj->value;
1100 }
1101 
bootrom_changed(void)1102 static void bootrom_changed (void)
1103 {
1104     changed_prefs.bootrom = GTK_TOGGLE_BUTTON (bootrom_widget)->active ? 1 : 0;
1105     set_mem_state ();
1106 }
1107 
ntsc_changed(void)1108 static void ntsc_changed (void)
1109 {
1110     changed_prefs.ntscmode = find_current_toggle (ntsc_widget, 2);
1111 }
1112 
mbtype_changed(void)1113 static void mbtype_changed (void)
1114 {
1115     int needs_aga, allows_ocs, allows_ecs;
1116     int n, cstype;
1117 
1118     if (ignore_gui_changes)
1119 	return;
1120 
1121     n = gtk_combo_box_get_active (GTK_COMBO_BOX (mbtype_widget));
1122     cstype = (n == 0 ? CP_GENERIC
1123 	      : n == 1 ? CP_A1000
1124 	      : n == 2 ? CP_A500
1125 	      : n == 3 ? CP_A600
1126 	      : n == 4 ? CP_A1200
1127 	      : n == 5 ? CP_A3000
1128 	      : CP_A4000);
1129     if (cstype != CP_GENERIC)
1130 	built_in_chipset_prefs (&changed_prefs, cstype);
1131 
1132     needs_aga = cstype == CP_A1200 || cstype == CP_A4000 || cstype == CP_A4000T || cstype == CP_CD32;
1133     allows_ocs = cstype == CP_A1000 || cstype == CP_A500 || cstype == CP_A2000;
1134     allows_ecs = !needs_aga && cstype != CP_A1000;
1135 
1136     gtk_widget_set_sensitive (cslevel_widget[0], cstype == CP_GENERIC || allows_ocs);
1137     gtk_widget_set_sensitive (cslevel_widget[1], cstype == CP_GENERIC || allows_ecs);
1138     gtk_widget_set_sensitive (cslevel_widget[2], cstype == CP_GENERIC || allows_ecs);
1139     gtk_widget_set_sensitive (cslevel_widget[3], cstype == CP_GENERIC || needs_aga);
1140 
1141     if (cstype != CP_GENERIC) {
1142 	if (needs_aga)
1143 	    changed_prefs.chipset_mask = CSMASK_AGA | CSMASK_FULL_ECS;
1144 	else if (! allows_ecs)
1145 	    changed_prefs.chipset_mask = 0;
1146     }
1147     set_chipset_state ();
1148 }
1149 
did_reset(void)1150 static void did_reset (void)
1151 {
1152     if (quit_gui)
1153 	return;
1154 
1155     write_comm_pipe_int (&from_gui_pipe, 2, 1);
1156 }
1157 
did_debug(void)1158 static void did_debug (void)
1159 {
1160     if (quit_gui)
1161 	return;
1162 
1163     write_comm_pipe_int (&from_gui_pipe, 3, 1);
1164 }
1165 
did_quit(void)1166 static void did_quit (void)
1167 {
1168     if (quit_gui)
1169 	return;
1170 
1171     write_comm_pipe_int (&from_gui_pipe, 4, 1);
1172 }
1173 
did_eject(GtkWidget * w,gpointer data_p)1174 static void did_eject (GtkWidget *w, gpointer data_p)
1175 {
1176     int data = GPOINTER_TO_INT (data_p);
1177     if (quit_gui)
1178 	return;
1179 
1180     write_comm_pipe_int (&from_gui_pipe, 0, 0);
1181     write_comm_pipe_int (&from_gui_pipe, data, 1);
1182     gtk_label_set_text (GTK_LABEL (disk_text_widget[data]), "");
1183 }
1184 
pause_uae(void)1185 static void pause_uae (void)
1186 {
1187     if (quit_gui)
1188 	return;
1189 
1190     write_comm_pipe_int (&from_gui_pipe, GTK_TOGGLE_BUTTON (pause_uae_widget)->active ? 5 : 6, 1);
1191     if (! GTK_TOGGLE_BUTTON (pause_uae_widget)->active)
1192 	gtk_widget_hide (lab_info);
1193 }
1194 
end_pause_uae(void)1195 static void end_pause_uae (void)
1196 {
1197     write_comm_pipe_int (&to_gui_pipe, GUICMD_UNPAUSE, 1);
1198 }
1199 
1200 static char fsbuffer[100];
1201 
make_file_selector(const char * title,GtkFileChooserAction action)1202 static GtkWidget *make_file_selector (const char *title,
1203 				      GtkFileChooserAction action)
1204 {
1205     GtkWidget *p = gtk_file_chooser_dialog_new (title, GTK_WINDOW (gui_window), action,
1206 						GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1207 						action == GTK_FILE_CHOOSER_ACTION_SAVE ? GTK_STOCK_SAVE : GTK_STOCK_OPEN,
1208 						GTK_RESPONSE_ACCEPT,
1209 						NULL);
1210 
1211     return p;
1212 }
1213 
filesel_set_path(GtkWidget * p,const char * path)1214 static void filesel_set_path (GtkWidget *p, const char *path)
1215 {
1216     size_t len = strlen (path);
1217     if (len > 0 && ! access (path, R_OK)) {
1218 	char *tmp = xmalloc (len + 2);
1219 	strcpy (tmp, path);
1220 	strcat (tmp, "/");
1221 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (p), tmp);
1222     }
1223 }
1224 
make_disk_selector(void)1225 static void make_disk_selector (void)
1226 {
1227     if (disk_selector)
1228 	return;
1229     disk_selector = make_file_selector ("Select a disk image file to mount",
1230 					GTK_FILE_CHOOSER_ACTION_OPEN);
1231     filesel_set_path (disk_selector, currprefs.path_floppy);
1232 }
1233 
did_insert(GtkWidget * w,gpointer data)1234 static void did_insert (GtkWidget *w, gpointer data)
1235 {
1236     int n = GPOINTER_TO_INT (data);
1237 
1238     make_disk_selector ();
1239     sprintf (fsbuffer, "Select a disk image file for DF%d", n);
1240     gtk_window_set_title (GTK_WINDOW (disk_selector), fsbuffer);
1241 
1242     if (gtk_dialog_run (GTK_DIALOG (disk_selector)) == GTK_RESPONSE_ACCEPT) {
1243 	char *filename;
1244 
1245 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (disk_selector));
1246 
1247 	uae_sem_wait (&gui_sem);
1248 	if (new_disk_string[n] != 0)
1249 	    free (new_disk_string[n]);
1250 	new_disk_string[n] = strdup (filename);
1251 	uae_sem_post (&gui_sem);
1252 	write_comm_pipe_int (&from_gui_pipe, 1, 0);
1253 	write_comm_pipe_int (&from_gui_pipe, n, 1);
1254 	gtk_label_set_text (GTK_LABEL (disk_text_widget[n]), filename);
1255 
1256 	g_free (filename);
1257     }
1258     gtk_widget_hide (disk_selector);
1259 }
1260 
driveled_event(GtkWidget * thing,GdkEvent * event)1261 static gint driveled_event (GtkWidget *thing, GdkEvent *event)
1262 {
1263     int lednr = nr_for_led (thing);
1264 
1265     switch (event->type) {
1266      case GDK_MAP:
1267 	draw_led (lednr);
1268 	break;
1269      case GDK_EXPOSE:
1270 	draw_led (lednr);
1271 	break;
1272      default:
1273 	break;
1274     }
1275 
1276   return 0;
1277 }
1278 
1279 static GtkWidget *snap_selector;
1280 
did_loadstate(void)1281 static void did_loadstate (void)
1282 {
1283     GtkWidget *dialog;
1284 
1285     dialog = make_file_selector ("Select a state file to restore", GTK_FILE_CHOOSER_ACTION_OPEN);
1286 
1287     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
1288 	char *filename;
1289 
1290 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1291 
1292 	uae_sem_wait (&gui_sem);
1293 	gui_snapname = strdup (filename);
1294 	uae_sem_post (&gui_sem);
1295 	write_comm_pipe_int (&from_gui_pipe, 7, 0);
1296 	write_comm_pipe_int (&from_gui_pipe, STATE_DORESTORE, 1);
1297 
1298 	g_free (filename);
1299     }
1300 
1301     gtk_widget_destroy (dialog);
1302 }
1303 
did_savestate(void)1304 static void did_savestate (void)
1305 {
1306     GtkWidget *dialog;
1307 
1308     dialog = make_file_selector ("Select a filename for the state file",
1309 				 GTK_FILE_CHOOSER_ACTION_SAVE);
1310 
1311     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
1312 	char *filename;
1313 
1314 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1315 
1316 	uae_sem_wait (&gui_sem);
1317 	gui_snapname = strdup (filename);
1318 	uae_sem_post (&gui_sem);
1319 	write_comm_pipe_int (&from_gui_pipe, 7, 0);
1320 	write_comm_pipe_int (&from_gui_pipe, STATE_DOSAVE, 1);
1321 
1322 	g_free (filename);
1323     }
1324 
1325     gtk_widget_destroy (dialog);
1326 }
1327 
did_rompathchange(GtkWidget * w,gpointer data)1328 static void did_rompathchange (GtkWidget *w, gpointer data)
1329 {
1330     GtkWidget *pathsel;
1331     pathsel = make_file_selector ("Select a ROM path",
1332 				  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
1333     filesel_set_path (pathsel, currprefs.path_rom);
1334     if (gtk_dialog_run (GTK_DIALOG (pathsel)) == GTK_RESPONSE_ACCEPT) {
1335 	char *filename;
1336 
1337 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pathsel));
1338 
1339 	uae_sem_wait (&gui_sem);
1340 	gui_romname = strdup (filename);
1341 	uae_sem_post (&gui_sem);
1342 	write_comm_pipe_int (&from_gui_pipe, 10, 0);
1343 	gtk_label_set_text (GTK_LABEL (rom_path_widget), gui_romname);
1344 
1345 	g_free (filename);
1346     }
1347 
1348     gtk_widget_destroy (pathsel);
1349 }
1350 
did_romchange(GtkWidget * w,gpointer data)1351 static void did_romchange (GtkWidget *w, gpointer data)
1352 {
1353     GtkWidget *romsel;
1354 
1355     romsel = make_file_selector ("Select a ROM file",
1356 				 GTK_FILE_CHOOSER_ACTION_OPEN);
1357     filesel_set_path (romsel, currprefs.path_rom);
1358     if (gtk_dialog_run (GTK_DIALOG (romsel)) == GTK_RESPONSE_ACCEPT) {
1359 	char *filename;
1360 
1361 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (romsel));
1362 	rom_req = 0;
1363 	rom_requirements_change ();
1364 
1365 	uae_sem_wait (&gui_sem);
1366 	gui_romname = strdup (filename);
1367 	uae_sem_post (&gui_sem);
1368 	write_comm_pipe_int (&from_gui_pipe, 8, 0);
1369 	gtk_label_set_text (GTK_LABEL (rom_text_widget), gui_romname);
1370 
1371 	g_free (filename);
1372     }
1373 
1374     gtk_widget_destroy (romsel);
1375 }
1376 
did_keychange(GtkWidget * w,gpointer data)1377 static void did_keychange (GtkWidget *w, gpointer data)
1378 {
1379     GtkWidget *keysel;
1380 
1381     keysel = make_file_selector ("Select a Kickstart key file",
1382 				 GTK_FILE_CHOOSER_ACTION_OPEN);
1383     filesel_set_path (keysel, currprefs.path_rom);
1384 
1385     if (gtk_dialog_run (GTK_DIALOG (keysel)) == GTK_RESPONSE_ACCEPT) {
1386 	char *filename;
1387 
1388 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (keysel));
1389 	uae_sem_wait (&gui_sem);
1390 	gui_keyname = strdup (filename);
1391 	uae_sem_post (&gui_sem);
1392 	write_comm_pipe_int (&from_gui_pipe, 9, 0);
1393 	gtk_label_set_text (GTK_LABEL (key_text_widget), gui_keyname);
1394 
1395 	g_free (filename);
1396     }
1397 
1398     gtk_widget_destroy (keysel);
1399 }
1400 
add_empty_vbox(GtkWidget * tobox)1401 static void add_empty_vbox (GtkWidget *tobox)
1402 {
1403     GtkWidget *thing = gtk_vbox_new (FALSE, 0);
1404     gtk_widget_show (thing);
1405     gtk_box_pack_start (GTK_BOX (tobox), thing, TRUE, TRUE, 0);
1406 }
1407 
add_centered_to_vbox(GtkWidget * vbox,GtkWidget * w,int vexpand)1408 static void add_centered_to_vbox (GtkWidget *vbox, GtkWidget *w, int vexpand)
1409 {
1410     GtkWidget *hbox = gtk_hbox_new (TRUE, 0);
1411     gtk_widget_show (hbox);
1412     gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, FALSE, 0);
1413     gtk_box_pack_start (GTK_BOX (vbox), hbox, vexpand, vexpand, 0);
1414 }
1415 
make_labelled_widget(const char * str,GtkWidget * thing,int expand)1416 static GtkWidget *make_labelled_widget (const char *str, GtkWidget *thing, int expand)
1417 {
1418     GtkWidget *label = gtk_label_new (str);
1419     GtkWidget *hbox2 = gtk_hbox_new (FALSE, 4);
1420 
1421     gtk_widget_show (label);
1422     gtk_widget_show (thing);
1423 
1424     gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
1425     gtk_box_pack_start (GTK_BOX (hbox2), thing, expand, TRUE, 0);
1426 
1427     return hbox2;
1428 }
1429 
add_labelled_widget_centered(const char * str,GtkWidget * thing,GtkWidget * vbox)1430 static GtkWidget *add_labelled_widget_centered (const char *str, GtkWidget *thing, GtkWidget *vbox)
1431 {
1432     GtkWidget *w = make_labelled_widget (str, thing, FALSE);
1433     gtk_widget_show (w);
1434     add_centered_to_vbox (vbox, w, 0);
1435     return w;
1436 }
1437 
make_radio_group(const char ** labels,GtkWidget * tobox,GtkWidget ** saveptr,gint t1,gint t2,void (* sigfunc)(void),int count,GSList * group)1438 static int make_radio_group (const char **labels, GtkWidget *tobox,
1439 			      GtkWidget **saveptr, gint t1, gint t2,
1440 			      void (*sigfunc) (void), int count, GSList *group)
1441 {
1442     int t = 0;
1443 
1444     while (*labels && (count == -1 || count-- > 0)) {
1445 	GtkWidget *thing = gtk_radio_button_new_with_label (group, *labels++);
1446 	group = gtk_radio_button_group (GTK_RADIO_BUTTON (thing));
1447 
1448 	*saveptr++ = thing;
1449 	gtk_widget_show (thing);
1450 	gtk_box_pack_start (GTK_BOX (tobox), thing, t1, t2, 0);
1451 	gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
1452 	t++;
1453     }
1454     return t;
1455 }
1456 
make_radio_group_box(const char * title,const char ** labels,GtkWidget ** saveptr,int horiz,void (* sigfunc)(void),GtkWidget ** boxp)1457 static GtkWidget *make_radio_group_box (const char *title, const char **labels,
1458 					GtkWidget **saveptr, int horiz,
1459 					void (*sigfunc) (void), GtkWidget **boxp)
1460 {
1461     GtkWidget *frame, *newbox;
1462 
1463     frame = gtk_frame_new (title);
1464     newbox = (horiz ? gtk_hbox_new : gtk_vbox_new) (FALSE, 4);
1465     gtk_widget_show (newbox);
1466     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1467     gtk_container_add (GTK_CONTAINER (frame), newbox);
1468     make_radio_group (labels, newbox, saveptr, horiz, !horiz, sigfunc, -1, NULL);
1469     if (boxp)
1470 	*boxp = newbox;
1471     return frame;
1472 }
1473 
make_radio_group_box_1(const char * title,const char ** labels,GtkWidget ** saveptr,int horiz,void (* sigfunc)(void),int elts_per_column)1474 static GtkWidget *make_radio_group_box_1 (const char *title, const char **labels,
1475 					  GtkWidget **saveptr, int horiz,
1476 					  void (*sigfunc) (void), int elts_per_column)
1477 {
1478     GtkWidget *frame, *newbox;
1479     GtkWidget *column;
1480     GSList *group = 0;
1481 
1482     frame = gtk_frame_new (title);
1483     column = (horiz ? gtk_vbox_new : gtk_hbox_new) (FALSE, 4);
1484     gtk_container_add (GTK_CONTAINER (frame), column);
1485     gtk_widget_show (column);
1486 
1487     while (*labels) {
1488 	int count;
1489 	newbox = (horiz ? gtk_hbox_new : gtk_vbox_new) (FALSE, 4);
1490 	gtk_widget_show (newbox);
1491 	gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1492 	gtk_container_add (GTK_CONTAINER (column), newbox);
1493 	count = make_radio_group (labels, newbox, saveptr, horiz, !horiz, sigfunc, elts_per_column, group);
1494 	labels += count;
1495 	saveptr += count;
1496 	group = gtk_radio_button_group (GTK_RADIO_BUTTON (saveptr[-1]));
1497     }
1498     return frame;
1499 }
1500 
make_led(int nr)1501 static GtkWidget *make_led (int nr)
1502 {
1503     GtkWidget *subframe, *the_led, *thing;
1504     GdkColormap *colormap;
1505 
1506     the_led = gtk_vbox_new (FALSE, 0);
1507     gtk_widget_show (the_led);
1508 
1509     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
1510     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
1511     gtk_widget_show (thing);
1512 
1513     subframe = gtk_frame_new (NULL);
1514     gtk_box_pack_start (GTK_BOX (the_led), subframe, TRUE, TRUE, 0);
1515     gtk_widget_show (subframe);
1516 
1517     thing = gtk_drawing_area_new ();
1518     gtk_drawing_area_size (GTK_DRAWING_AREA (thing), 20, 5);
1519     gtk_widget_set_events (thing, GDK_EXPOSURE_MASK);
1520     gtk_container_add (GTK_CONTAINER (subframe), thing);
1521     colormap = gtk_widget_get_colormap (thing);
1522     led_on[nr].red = nr == 0 ? 0xEEEE : 0xCCCC;
1523     led_on[nr].green = nr == 0 ? 0: 0xFFFF;
1524     led_on[nr].blue = 0;
1525     led_on[nr].pixel = 0;
1526     led_off[nr].red = 0;
1527     led_off[nr].green = 0;
1528     led_off[nr].blue = 0;
1529     led_off[nr].pixel = 0;
1530     gdk_color_alloc (colormap, led_on + nr);
1531     gdk_color_alloc (colormap, led_off + nr);
1532     led_widgets[nr] = thing;
1533     gtk_signal_connect (GTK_OBJECT (thing), "event",
1534 			(GtkSignalFunc) driveled_event, (gpointer) thing);
1535     gtk_widget_show (thing);
1536 
1537     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
1538     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
1539     gtk_widget_show (thing);
1540 
1541     return the_led;
1542 }
1543 
make_file_container(const char * title,GtkWidget * vbox,int vertical)1544 static GtkWidget *make_file_container (const char *title, GtkWidget *vbox, int vertical)
1545 {
1546     GtkWidget *thing = gtk_frame_new (title);
1547     GtkWidget *file_vbox = vertical ? gtk_vbox_new (FALSE, 4) : gtk_hbox_new (FALSE, 4);
1548 
1549     gtk_container_set_border_width (GTK_CONTAINER (file_vbox), 4);
1550     gtk_container_add (GTK_CONTAINER (thing), file_vbox);
1551     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
1552     gtk_widget_show (file_vbox);
1553     gtk_widget_show (thing);
1554 
1555     return file_vbox;
1556 }
1557 
make_file_widget(GtkWidget * buttonbox)1558 static GtkWidget *make_file_widget (GtkWidget *buttonbox)
1559 {
1560     GtkWidget *thing, *subthing;
1561     GtkWidget *subframe = gtk_frame_new (NULL);
1562 
1563     gtk_frame_set_shadow_type (GTK_FRAME (subframe), GTK_SHADOW_ETCHED_OUT);
1564     gtk_box_pack_start (GTK_BOX (buttonbox), subframe, TRUE, TRUE, 0);
1565     gtk_widget_show (subframe);
1566     subthing = gtk_vbox_new (FALSE, 0);
1567     gtk_widget_show (subthing);
1568     gtk_container_add (GTK_CONTAINER (subframe), subthing);
1569     thing = gtk_label_new ("");
1570     gtk_widget_show (thing);
1571     gtk_box_pack_start (GTK_BOX (subthing), thing, TRUE, TRUE, 0);
1572 
1573     return thing;
1574 }
1575 
make_floppy_disks(GtkWidget * vbox)1576 static void make_floppy_disks (GtkWidget *vbox)
1577 {
1578     GtkWidget *thing, *subthing, *subframe, *buttonbox, *file_vbox;
1579     char buf[5];
1580     int i;
1581 
1582     add_empty_vbox (vbox);
1583 
1584     for (i = 0; i < 4; i++) {
1585 	/* Frame with an hbox and the "DFx:" title */
1586 	sprintf (buf, "DF%d:", i);
1587 	file_vbox = make_file_container (buf, vbox, 1);
1588 
1589 	buttonbox = gtk_hbox_new (FALSE, 4);
1590 	gtk_box_pack_start (GTK_BOX (file_vbox), buttonbox, FALSE, TRUE, 0);
1591 	gtk_widget_show (buttonbox);
1592 
1593 	/* LED */
1594 	subthing = make_led (i + 1);
1595 	gtk_box_pack_start (GTK_BOX (buttonbox), subthing, FALSE, TRUE, 0);
1596 
1597 	/* Current file display */
1598 	disk_text_widget[i] = make_file_widget (buttonbox);
1599 
1600 	/* Now, the buttons.  */
1601 	thing = gtk_button_new_with_label ("Eject");
1602 	gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
1603 	gtk_widget_show (thing);
1604 	disk_eject_widget[i] = thing;
1605 	gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_eject,
1606 			    GINT_TO_POINTER (i));
1607 
1608 	thing = gtk_button_new_with_label ("Insert");
1609 	gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
1610 	gtk_widget_show (thing);
1611 	disk_insert_widget[i] = thing;
1612 	gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_insert,
1613 			    GINT_TO_POINTER (i));
1614 
1615 	buttonbox = gtk_hbox_new (FALSE, 4);
1616 	gtk_box_pack_start (GTK_BOX (file_vbox), buttonbox, FALSE, FALSE, 0);
1617 	gtk_widget_show (buttonbox);
1618 
1619 	if (i == 0)
1620 	    thing = make_chooser (2, "3.5 DD", "3.5 HD");
1621 	else
1622 	    thing = make_chooser (3, "Disabled", "3.5 DD", "3.5 HD");
1623 	gtk_signal_connect (GTK_OBJECT (thing), "changed", (GtkSignalFunc) dftype_changed,
1624 			    GINT_TO_POINTER (i));
1625 	dftype_widget[i] = thing;
1626 
1627 	thing = make_labelled_widget ("Type:", thing, 0);
1628 	gtk_box_pack_end (GTK_BOX (buttonbox), thing, FALSE, FALSE, 0);
1629 	gtk_widget_show (thing);
1630     }
1631 
1632     add_empty_vbox (vbox);
1633 }
1634 
make_cpu_speed_sel(void)1635 static GtkWidget *make_cpu_speed_sel (void)
1636 {
1637     int t;
1638     static const char *labels[] = {
1639 	"Optimize for host CPU speed", "Approximate 68000/7MHz speed", "Adjustable",
1640 	NULL
1641     };
1642     GtkWidget *frame, *newbox;
1643 
1644     frame = gtk_frame_new ("CPU speed");
1645     newbox = gtk_vbox_new (FALSE, 4);
1646     gtk_widget_show (newbox);
1647     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1648     gtk_container_add (GTK_CONTAINER (frame), newbox);
1649     make_radio_group (labels, newbox, cpuspeed_widgets, 0, 1, cpuspeed_changed, -1, NULL);
1650 
1651     t = currprefs.m68k_speed > 0 ? currprefs.m68k_speed : 4 * CYCLE_UNIT;
1652     cpuspeed_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 1.0, 5120.0, 1.0, 1.0, 1.0));
1653     gtk_signal_connect (GTK_OBJECT (cpuspeed_adj), "value_changed",
1654 			GTK_SIGNAL_FUNC (cpuspeed_changed), NULL);
1655 
1656     cpuspeed_scale = gtk_hscale_new (cpuspeed_adj);
1657     gtk_range_set_update_policy (GTK_RANGE (cpuspeed_scale), GTK_UPDATE_DELAYED);
1658     gtk_scale_set_digits (GTK_SCALE (cpuspeed_scale), 0);
1659     gtk_scale_set_value_pos (GTK_SCALE (cpuspeed_scale), GTK_POS_RIGHT);
1660     cpuspeed_scale = make_labelled_widget ("Cycles/insn:", cpuspeed_scale, TRUE);
1661     gtk_widget_show (cpuspeed_scale);
1662     gtk_box_pack_start (GTK_BOX (newbox), cpuspeed_scale, FALSE, FALSE, 0);
1663 
1664     return frame;
1665 }
1666 
make_cpu_widgets(GtkWidget * vbox)1667 static void make_cpu_widgets (GtkWidget *vbox)
1668 {
1669     int i;
1670     GtkWidget *newbox, *hbox, *frame;
1671     GtkWidget *thing, *label;
1672     static const char *cpulabels[] = {
1673 	"68000", "68010", "68EC020", "68020", "68030", "68040", "68060",
1674 	NULL
1675     };
1676     static const char *fpulabels[] = {
1677 	"None", "68881", "68882", "68040", "68060",
1678 	NULL
1679     };
1680 
1681     add_empty_vbox (vbox);
1682 
1683     hbox = gtk_hbox_new (FALSE, 0);
1684     add_empty_vbox (hbox);
1685 
1686     newbox = make_radio_group_box ("CPU type", cpulabels, cpu_widget, 0, cputype_changed, NULL);
1687     gtk_widget_show (newbox);
1688     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
1689 
1690     newbox = make_radio_group_box ("FPU type", fpulabels, fpu_widget, 0, cputype_changed, NULL);
1691     gtk_widget_show (newbox);
1692     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
1693 
1694     newbox = make_cpu_speed_sel ();
1695     gtk_widget_show (newbox);
1696     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
1697 
1698     add_empty_vbox (hbox);
1699     gtk_widget_show (hbox);
1700     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1701 
1702     req68ec020 = gtk_label_new ("The selected ROM requires at least a 68ec020.");
1703     add_centered_to_vbox (vbox, req68ec020, 0);
1704 
1705     req68020 = gtk_label_new ("The selected ROM requires at least a 68020.");
1706     add_centered_to_vbox (vbox, req68020, 0);
1707 
1708     req68030 = gtk_label_new ("The selected ROM requires at least a 68030.");
1709     add_centered_to_vbox (vbox, req68030, 0);
1710 
1711     add_empty_vbox (vbox);
1712 
1713     label = gtk_label_new ("CPU type settings take effect after the next reset.");
1714     gtk_widget_show (label);
1715     add_centered_to_vbox (vbox, label, 0);
1716 }
1717 
make_screenmode_box(const char * title,struct scrmode_widgets * mw,struct uae_rect * modes,int n_modes)1718 static GtkWidget *make_screenmode_box (const char *title, struct scrmode_widgets *mw,
1719 				       struct uae_rect *modes, int n_modes)
1720 {
1721     GtkWidget *vbox;
1722     int i;
1723 
1724     mw->frame = gtk_frame_new (title);
1725     gtk_widget_show (mw->frame);
1726 
1727     vbox = gtk_vbox_new (FALSE, 10);
1728     gtk_widget_show (vbox);
1729     gtk_container_add (GTK_CONTAINER (mw->frame), vbox);
1730     gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
1731 
1732     mw->modelist = gtk_combo_box_new_text ();
1733     gtk_widget_show (mw->modelist);
1734     gtk_box_pack_start (GTK_BOX (vbox), mw->modelist, FALSE, TRUE, 0);
1735 
1736     for (i = 0; i < n_modes; i++) {
1737 	char t[200];
1738 	sprintf (t, "%dx%d", modes[i].w, modes[i].h);
1739 	gtk_combo_box_append_text (GTK_COMBO_BOX (mw->modelist), t);
1740     }
1741     if (n_modes == 0)
1742 	gtk_widget_set_sensitive (mw->frame, FALSE);
1743 
1744     mw->hcenter = make_chooser (3, "Off", "Simple", "Smart");
1745     mw->hc_label = make_labelled_widget ("Horizontal bounds detect:", mw->hcenter, TRUE);
1746     gtk_widget_show (mw->hc_label);
1747     gtk_box_pack_start (GTK_BOX (vbox), mw->hc_label, FALSE, TRUE, 0);
1748 
1749     mw->vcenter = make_chooser (3, "Off", "Simple", "Smart");
1750     mw->vc_label = make_labelled_widget ("Vertical bounds detect:", mw->vcenter, TRUE);
1751     gtk_widget_show (mw->vc_label);
1752     gtk_box_pack_start (GTK_BOX (vbox), mw->vc_label, FALSE, TRUE, 0);
1753 
1754     mw->linedbl = make_chooser (2, "Double", "Scanlines");
1755     mw->ld_label = make_labelled_widget ("Line doubling:", mw->linedbl, TRUE);
1756     gtk_widget_show (mw->ld_label);
1757     gtk_box_pack_start (GTK_BOX (vbox), mw->ld_label, FALSE, TRUE, 0);
1758 
1759     mw->aspect = gtk_check_button_new_with_label ("Correct aspect ratio");
1760     gtk_widget_show (mw->aspect);
1761     gtk_box_pack_start (GTK_BOX (vbox), mw->aspect, FALSE, TRUE, 0);
1762 
1763     mw->leds = gtk_check_button_new_with_label ("Show LEDs on screen");
1764     gtk_widget_show (mw->leds);
1765     gtk_box_pack_start (GTK_BOX (vbox), mw->leds, FALSE, TRUE, 0);
1766 
1767     gtk_signal_connect (GTK_OBJECT (mw->leds), "clicked",
1768 			(GtkSignalFunc) leds_changed, NULL);
1769     gtk_signal_connect (GTK_OBJECT (mw->aspect), "clicked",
1770 			(GtkSignalFunc) aspect_changed, NULL);
1771     gtk_signal_connect (GTK_OBJECT (mw->linedbl), "changed",
1772 			(GtkSignalFunc) aspect_changed, NULL);
1773     gtk_signal_connect (GTK_OBJECT (mw->hcenter), "changed",
1774 			(GtkSignalFunc) aspect_changed, NULL);
1775     gtk_signal_connect (GTK_OBJECT (mw->vcenter), "changed",
1776 			(GtkSignalFunc) aspect_changed, NULL);
1777     gtk_signal_connect (GTK_OBJECT (mw->modelist), "changed",
1778 			(GtkSignalFunc) screenmode_changed, NULL);
1779 
1780     return mw->frame;
1781 }
1782 
make_gfx_widgets(GtkWidget * vbox)1783 static void make_gfx_widgets (GtkWidget *vbox)
1784 {
1785     GtkWidget *thing, *frame, *newbox, *hbox;
1786 
1787     add_empty_vbox (vbox);
1788 
1789     hbox = gtk_hbox_new (FALSE, 10);
1790     gtk_widget_show (hbox);
1791     add_centered_to_vbox (vbox, hbox, 0);
1792 
1793     thing = make_screenmode_box ("Fullscreen mode", &gw_fullscreen, gfx_fullscreen_modes, n_fullscreen_modes);
1794     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
1795     thing = make_screenmode_box ("Windowed mode", &gw_windowed, gfx_windowed_modes, n_windowed_modes);
1796     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
1797 
1798     hbox = gtk_hbox_new (FALSE, 10);
1799     gtk_widget_show (hbox);
1800     add_centered_to_vbox (vbox, hbox, 0);
1801 
1802     frame = gtk_frame_new ("Miscellaneous");
1803     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
1804 
1805     gtk_widget_show (frame);
1806     newbox = gtk_vbox_new (FALSE, 4);
1807     gtk_widget_show (newbox);
1808     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1809     gtk_container_add (GTK_CONTAINER (frame), newbox);
1810 
1811     framerate_adj = GTK_ADJUSTMENT (gtk_adjustment_new (currprefs.gfx_framerate, 1, 21, 1, 1, 1));
1812     gtk_signal_connect (GTK_OBJECT (framerate_adj), "value_changed",
1813 			GTK_SIGNAL_FUNC (custom_changed), NULL);
1814 
1815     thing = gtk_hscale_new (framerate_adj);
1816     gtk_range_set_update_policy (GTK_RANGE (thing), GTK_UPDATE_DELAYED);
1817     gtk_scale_set_digits (GTK_SCALE (thing), 0);
1818     gtk_scale_set_value_pos (GTK_SCALE (thing), GTK_POS_RIGHT);
1819     thing = make_labelled_widget ("Framerate:", thing, TRUE);
1820     gtk_widget_show (thing);
1821     gtk_box_pack_start (GTK_BOX (newbox), thing, FALSE, FALSE, 0);
1822 
1823     b32_widget = gtk_check_button_new_with_label ("32 bit blitter");
1824     add_centered_to_vbox (newbox, b32_widget, 0);
1825 #if 0
1826     gtk_widget_show (b32_widget);
1827 #endif
1828     bimm_widget = gtk_check_button_new_with_label ("Immediate blits");
1829     gtk_box_pack_start (GTK_BOX (newbox), bimm_widget, FALSE, FALSE, 0);
1830     gtk_widget_show (bimm_widget);
1831 
1832     afscr_widget = gtk_check_button_new_with_label ("Amiga modes fullscreen");
1833     gtk_box_pack_start (GTK_BOX (newbox), afscr_widget, FALSE, FALSE, 0);
1834     gtk_widget_show (afscr_widget);
1835     pfscr_widget = gtk_check_button_new_with_label ("Picasso modes fullscreen");
1836     gtk_box_pack_start (GTK_BOX (newbox), pfscr_widget, FALSE, FALSE, 0);
1837     gtk_widget_show (pfscr_widget);
1838     add_empty_vbox (vbox);
1839 
1840     gtk_signal_connect (GTK_OBJECT (bimm_widget), "clicked",
1841 			(GtkSignalFunc) custom_changed, NULL);
1842     gtk_signal_connect (GTK_OBJECT (afscr_widget), "clicked",
1843 			(GtkSignalFunc) custom_changed, NULL);
1844     gtk_signal_connect (GTK_OBJECT (pfscr_widget), "clicked",
1845 			(GtkSignalFunc) custom_changed, NULL);
1846 #if 0
1847     gtk_signal_connect (GTK_OBJECT (b32_widget), "clicked",
1848 			(GtkSignalFunc) custom_changed, NULL);
1849 #endif
1850 }
1851 
make_chipset_widgets(GtkWidget * vbox)1852 static void make_chipset_widgets (GtkWidget *vbox)
1853 {
1854     GtkWidget *newbox, *hbox, *thing, *tmpbox;
1855     static const char *colllabels[] = {
1856 	"None (fastest)", "Sprites only", "Sprites & playfields", "Full (very slow)",
1857 	NULL
1858     };
1859     static const char *cslevellabels[] = {
1860 	"OCS", "ECS Agnus", "Full ECS", "AGA", NULL
1861     };
1862     static const char *ntsclabels[] = {
1863 	"PAL (European)", "NTSC (American)", NULL
1864     };
1865 
1866     add_empty_vbox (vbox);
1867 
1868     mbtype_widget = make_chooser (7, "Generic", "A1000", "A500/A2000", "A600", "A1200", "A3000", "A4000");
1869     gtk_widget_show (mbtype_widget);
1870     gtk_signal_connect (GTK_OBJECT (mbtype_widget), "changed", (GtkSignalFunc) mbtype_changed,
1871 			NULL);
1872     mbtype_labelled = make_labelled_widget ("Motherboard type:", mbtype_widget, TRUE);
1873     gtk_widget_show (mbtype_labelled);
1874     add_centered_to_vbox (vbox, mbtype_labelled, 0);
1875 
1876     hbox = gtk_hbox_new (FALSE, 10);
1877     gtk_widget_show (hbox);
1878     add_centered_to_vbox (vbox, hbox, 0);
1879 
1880     newbox = make_radio_group_box ("Sprite collisions", colllabels, coll_widget, 0, coll_changed, NULL);
1881     gtk_widget_show (newbox);
1882     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1883 
1884     newbox = make_radio_group_box ("Chipset", cslevellabels, cslevel_widget, 0, cslevel_changed, NULL);
1885     gtk_widget_show (newbox);
1886     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1887 
1888     newbox = make_radio_group_box ("Chipset video output", ntsclabels, ntsc_widget, 0, ntsc_changed, NULL);
1889     gtk_widget_show (newbox);
1890     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1891 
1892     reqa4000 = gtk_label_new ("The selected ROM requires at least an A4000.");
1893     add_centered_to_vbox (vbox, reqa4000, 0);
1894 
1895     reqa1000 = gtk_label_new ("The selected ROM requires an A1000 motherboard.");
1896     add_centered_to_vbox (vbox, reqa1000, 0);
1897 
1898     add_empty_vbox (vbox);
1899 
1900     thing = gtk_label_new ("Chipset type settings take effect after the next reset.");
1901     gtk_widget_show (thing);
1902     add_centered_to_vbox (vbox, thing, 0);
1903 }
1904 
make_sound_widgets(GtkWidget * vbox)1905 static void make_sound_widgets (GtkWidget *vbox)
1906 {
1907     GtkWidget *frame, *newbox;
1908     int t;
1909     GtkWidget *hbox, *inner_vbox, *outer_hbox;
1910     static const char *soundlabels1[] = {
1911 	"None", "No output", "Normal", "Accurate",
1912 	NULL
1913     }, *soundlabels2[] = {
1914 	"None", "Sinc", "Anti",
1915 	NULL
1916     }, *soundlabels3[] = {
1917 	"Off", "A500 (power LED)", "A500 (always on)",
1918 	"A1200 (power LED)", "A1200 (always on)",
1919 	NULL
1920     };
1921 
1922     add_empty_vbox (vbox);
1923 
1924     outer_hbox = gtk_hbox_new (FALSE, 0);
1925     gtk_widget_show (outer_hbox);
1926     add_centered_to_vbox (vbox, outer_hbox, 0);
1927 
1928     inner_vbox = gtk_vbox_new (FALSE, 0);
1929     gtk_widget_show (inner_vbox);
1930     gtk_box_pack_start (GTK_BOX (outer_hbox), inner_vbox, FALSE, TRUE, 0);
1931 
1932     hbox = gtk_hbox_new (FALSE, 0);
1933     add_empty_vbox (hbox);
1934 
1935     newbox = make_radio_group_box ("Mode", soundlabels1, sound_widget, 0, sound_changed, NULL);
1936     gtk_widget_show (newbox);
1937     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
1938 
1939     newbox = make_radio_group_box ("Resampler", soundlabels2, sound_interpol_widget, 0, sound_changed, NULL);
1940     gtk_widget_show (newbox);
1941     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1942 
1943     newbox = make_radio_group_box ("Filter", soundlabels3, sound_filter_widget, 0, sound_changed, NULL);
1944     gtk_widget_show (newbox);
1945     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1946 
1947     add_empty_vbox (hbox);
1948     gtk_widget_show (hbox);
1949     gtk_box_pack_start (GTK_BOX (inner_vbox), hbox, FALSE, FALSE, 0);
1950 
1951     t = currprefs.sound_stereo_separation;
1952     if (t == 0)
1953 	t = MIXED_STEREO_MAX;
1954     stereo_sep_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 1, MIXED_STEREO_MAX, 1, 1, 0));
1955     gtk_signal_connect (GTK_OBJECT (stereo_sep_adj), "value_changed",
1956 			GTK_SIGNAL_FUNC (sound_changed), NULL);
1957 
1958     stereo_sep_scale = gtk_hscale_new (stereo_sep_adj);
1959     gtk_range_set_update_policy (GTK_RANGE (stereo_sep_scale), GTK_UPDATE_DELAYED);
1960     gtk_scale_set_digits (GTK_SCALE (stereo_sep_scale), 0);
1961     gtk_scale_set_value_pos (GTK_SCALE (stereo_sep_scale), GTK_POS_RIGHT);
1962     stereo_sep_scale = make_labelled_widget ("Stereo separation:", stereo_sep_scale, TRUE);
1963     gtk_widget_show (stereo_sep_scale);
1964     gtk_box_pack_start (GTK_BOX (inner_vbox), stereo_sep_scale, FALSE, FALSE, 0);
1965 
1966     t = currprefs.sound_mixed_stereo_delay;
1967     stereo_delay_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 0, SOUND_MAX_LOG_DELAY, 1, 1, 1));
1968     gtk_signal_connect (GTK_OBJECT (stereo_delay_adj), "value_changed",
1969 			GTK_SIGNAL_FUNC (sound_changed), NULL);
1970 
1971     stereo_delay_scale = gtk_hscale_new (stereo_delay_adj);
1972     gtk_range_set_update_policy (GTK_RANGE (stereo_delay_scale), GTK_UPDATE_DELAYED);
1973     gtk_scale_set_digits (GTK_SCALE (stereo_delay_scale), 0);
1974     gtk_scale_set_value_pos (GTK_SCALE (stereo_delay_scale), GTK_POS_RIGHT);
1975     stereo_delay_scale = make_labelled_widget ("Stereo mixing delay:", stereo_delay_scale, TRUE);
1976     gtk_widget_show (stereo_delay_scale);
1977     gtk_box_pack_start (GTK_BOX (inner_vbox), stereo_delay_scale, FALSE, FALSE, 0);
1978 
1979     add_empty_vbox (vbox);
1980 }
1981 
make_rom_widgets(GtkWidget * dvbox)1982 static void make_rom_widgets (GtkWidget *dvbox)
1983 {
1984     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
1985     GtkWidget *label, *frame;
1986 
1987     rom_req = 0;
1988 
1989     add_empty_vbox (dvbox);
1990 
1991     {
1992 	GtkWidget *buttonbox = make_file_container ("ROM search path:", dvbox, 0);
1993 	GtkWidget *thing = gtk_button_new_with_label ("Change");
1994 
1995 	/* Current file display */
1996 	rom_path_widget = make_file_widget (buttonbox);
1997 
1998 	gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
1999 	gtk_widget_show (thing);
2000 	gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_rompathchange, 0);
2001     }
2002 
2003     {
2004 	GtkWidget *buttonbox = make_file_container ("Kickstart ROM file:", dvbox, 1);
2005 	GtkWidget *hbox, *thing;
2006 
2007 	romlist_widget = gtk_combo_box_new_text ();
2008 	gtk_widget_show (romlist_widget);
2009 	gtk_box_pack_start (GTK_BOX (buttonbox), romlist_widget, FALSE, TRUE, 0);
2010 	gtk_combo_box_append_text (GTK_COMBO_BOX (romlist_widget),
2011 				   "Manually select a ROM file");
2012 	romlist_nr_entries = 1;
2013 	gtk_signal_connect (GTK_OBJECT (romlist_widget), "changed", (GtkSignalFunc) rom_combo_changed, 0);
2014 
2015 	hbox = gtk_hbox_new (FALSE, 0);
2016 	gtk_box_pack_start (GTK_BOX (buttonbox), hbox, FALSE, TRUE, 0);
2017 	gtk_widget_show (hbox);
2018 
2019 	/* Current file display */
2020 	rom_text_widget = make_file_widget (hbox);
2021 
2022 	romsel_button = gtk_button_new_with_label ("Change");
2023 	gtk_box_pack_start (GTK_BOX (hbox), romsel_button, FALSE, TRUE, 0);
2024 	gtk_widget_show (romsel_button);
2025 	gtk_signal_connect (GTK_OBJECT (romsel_button), "clicked", (GtkSignalFunc) did_romchange, 0);
2026     }
2027 
2028     {
2029 	GtkWidget *buttonbox = make_file_container ("ROM key file for Cloanto Amiga Forever:", dvbox, 0);
2030 	GtkWidget *thing = gtk_button_new_with_label ("Change");
2031 
2032 	/* Current file display */
2033 	key_text_widget = make_file_widget (buttonbox);
2034 
2035 	gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
2036 	gtk_widget_show (thing);
2037 	gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_keychange, 0);
2038     }
2039 
2040     label = gtk_label_new ("These settings take effect after the next reset.");
2041     gtk_widget_show (label);
2042     add_centered_to_vbox (dvbox, label, 0);
2043 
2044     add_empty_vbox (dvbox);
2045 }
2046 
make_ram_widgets(GtkWidget * dvbox)2047 static void make_ram_widgets (GtkWidget *dvbox)
2048 {
2049     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
2050     GtkWidget *label, *frame;
2051 
2052     static const char *chiplabels[] = {
2053 	"512 KB", "1 MB", "2 MB", "4 MB", "8 MB", NULL
2054     };
2055     static const char *bogolabels[] = {
2056 	"None", "512 KB", "1 MB", "1.8 MB", NULL
2057     };
2058     static const char *fastlabels[] = {
2059 	"None", "1 MB", "2 MB", "4 MB", "8 MB", NULL
2060     };
2061     static const char *z3labels[] = {
2062 	"None", "1 MB", "2 MB", "4 MB", "8 MB",
2063 	"16 MB", "32 MB", "64 MB", "128 MB", "256 MB",
2064 	NULL
2065     };
2066     static const char *p96labels[] = {
2067 	"None", "1 MB", "2 MB", "4 MB", "8 MB", "16 MB", "32 MB", NULL
2068     };
2069 
2070     add_empty_vbox (dvbox);
2071 
2072     gtk_widget_show (hbox);
2073     add_centered_to_vbox (dvbox, hbox, 0);
2074 
2075     add_empty_vbox (dvbox);
2076 
2077     label = gtk_label_new ("These settings take effect after the next reset.");
2078     gtk_widget_show (label);
2079     add_centered_to_vbox (dvbox, label, 0);
2080 
2081     frame = make_radio_group_box ("Chip Mem", chiplabels, chipsize_widget, 0, chipsize_changed, NULL);
2082     gtk_widget_show (frame);
2083     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2084 
2085     frame = make_radio_group_box ("Slow Mem", bogolabels, bogosize_widget, 0, bogosize_changed, NULL);
2086     gtk_widget_show (frame);
2087     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2088 
2089     frame = make_radio_group_box ("Fast Mem", fastlabels, fastsize_widget, 0, fastsize_changed, NULL);
2090     gtk_widget_show (frame);
2091     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2092 
2093     frame = make_radio_group_box_1 ("Z3 Mem", z3labels, z3size_widget, 0, z3size_changed, 5);
2094     gtk_widget_show (frame);
2095     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2096 
2097     frame = make_radio_group_box_1 ("P96 RAM", p96labels, p96size_widget, 0, p96size_changed, 4);
2098     gtk_widget_show (frame);
2099     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2100 }
2101 
make_joy_widgets(GtkWidget * dvbox)2102 static void make_joy_widgets (GtkWidget *dvbox)
2103 {
2104     int i;
2105     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
2106     GtkWidget *thing;
2107     static const char *joylabels[] = {
2108 	"Joystick 0", "Joystick 1", "Mouse", "Numeric pad",
2109 	"Cursor keys/Right Ctrl", "T/F/H/B/Left Alt",
2110 	NULL
2111     };
2112 
2113     add_empty_vbox (dvbox);
2114     gtk_widget_show (hbox);
2115     add_centered_to_vbox (dvbox, hbox, 0);
2116 
2117     legacy_widget = gtk_check_button_new_with_label ("Use legacy configuration");
2118     add_centered_to_vbox (dvbox, legacy_widget, 0);
2119     gtk_widget_show (legacy_widget);
2120     gtk_signal_connect (GTK_OBJECT (legacy_widget), "clicked",
2121 			(GtkSignalFunc) joy_changed, NULL);
2122 
2123     for (i = 0; i < 2; i++) {
2124 	GtkWidget *vbox, *frame;
2125 	char buffer[20];
2126 	int j;
2127 
2128 	sprintf (buffer, "Port %d", i);
2129 	frame = make_radio_group_box (buffer, joylabels, joy_widget[i], 0, joy_changed, NULL);
2130 	gtk_widget_show (frame);
2131 	gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2132     }
2133 
2134     thing = make_chooser (7, "English (QWERTY)", "Danish", "Deutsch (QWERTZ)", "Swedish",
2135 			  "Francais (AZERTY)", "Italian", "Spanish");
2136     gtk_signal_connect (GTK_OBJECT (thing), "changed", (GtkSignalFunc) kbdlang_changed,
2137 			GINT_TO_POINTER (i));
2138     kbdlang_widget = thing;
2139     thing = add_labelled_widget_centered ("Keyboard language:", thing, dvbox);
2140 
2141     add_empty_vbox (dvbox);
2142 }
2143 
leftalign(GtkWidget * thing)2144 static GtkWidget *leftalign (GtkWidget *thing)
2145 {
2146     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
2147     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
2148     return hbox;
2149 }
2150 
create_dirdlg(const char * title,int row)2151 static GtkWidget *create_dirdlg (const char *title, int row)
2152 {
2153     GtkWidget *vbox, *pathsel, *dirdlg;
2154     GtkWidget *path_entry, *volname_entry, *pri_entry;
2155 
2156     dirdlg = gtk_dialog_new_with_buttons (title, GTK_WINDOW (gui_window),
2157 					  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2158 					  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2159 					  GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2160 					  NULL);
2161 
2162     gtk_window_set_position (GTK_WINDOW (dirdlg), GTK_WIN_POS_MOUSE);
2163 
2164     vbox = GTK_DIALOG (dirdlg)->vbox;
2165 
2166     pathsel = make_file_selector ("Select a path to mount",
2167 				  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
2168 
2169     gtkutil_add_table (GTK_WIDGET (vbox),
2170 		       leftalign (gtk_label_new ("Path:")), 1, 1, GTK_FILL,
2171 		       leftalign (path_entry = gtk_file_chooser_button_new_with_dialog (pathsel)), 2, 1, GTK_FILL,
2172 		       GTKUTIL_ROW_END,
2173 		       leftalign (gtk_label_new ("Volume name:")), 1, 1, GTK_FILL,
2174 		       leftalign (volname_entry = gtk_entry_new_with_max_length (32)), 2, 1, GTK_FILL,
2175 		       GTKUTIL_ROW_END,
2176 		       leftalign (gtk_label_new ("Boot priority:")), 1, 1, GTK_FILL,
2177 		       leftalign (pri_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
2178 		       GTKUTIL_TABLE_END);
2179 
2180     if (row != -1) {
2181 	char *failure;
2182 	char t[20];
2183 	int secspertrack, surfaces, reserved, blocksize, size;
2184 	int cylinders, readonly, pri;
2185 	char *volname, *rootdir, *devname;
2186 
2187 	failure = get_filesys_unit (currprefs.mountinfo, row,
2188 				    &devname, &volname, &rootdir, &readonly,
2189 				    &secspertrack, &surfaces, &reserved,
2190 				    &cylinders, &size, &blocksize, &pri);
2191 	if (failure) {
2192 	    mkmsgbox ("Error", failure);
2193 	    goto out;
2194 	}
2195 	gtk_entry_set_text (GTK_ENTRY (volname_entry), volname);
2196 	gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (path_entry), rootdir);
2197 	sprintf (t, "%d", pri);
2198 	gtk_entry_set_text (GTK_ENTRY (pri_entry), t);
2199 	if (volname)
2200 	    free (volname);
2201 	if (devname)
2202 	    free (devname);
2203 	if (rootdir)
2204 	    free (rootdir);
2205     }
2206 
2207   retry:
2208     if (gtk_dialog_run (GTK_DIALOG (dirdlg)) == GTK_RESPONSE_ACCEPT) {
2209 	const char *failure;
2210 	const char *pathname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (path_entry));
2211 	const char *volname = gtk_entry_get_text (GTK_ENTRY (volname_entry));
2212 	const char *bprstr = gtk_entry_get_text (GTK_ENTRY (pri_entry));
2213 	char fixed_volname[256];
2214 	int n, bpr;
2215 
2216 	if (pathname == NULL || strlen (pathname) == 0 || access (pathname, R_OK) != 0) {
2217 	    mkmsgbox ("Error", "You must select a valid path.");
2218 	    goto retry;
2219 	}
2220 	n = volname == NULL ? 0 : strlen (volname);
2221 	if (n > 255) {
2222 	    mkmsgbox ("Error", "Volume name too long.");
2223 	    goto retry;
2224 	}
2225 	/* Strip colons from the end.  */
2226 	if (n > 0) {
2227 	    strcpy (fixed_volname, volname);
2228 	    if (fixed_volname[n - 1] == ':') {
2229 		fixed_volname[n - 1] = '\0';
2230 		n--;
2231 	    }
2232 	}
2233 
2234 	if (n == 0) {
2235 	    mkmsgbox ("Error", "You must enter a volume name.");
2236 	    goto retry;
2237 	}
2238 
2239 	if (strlen (bprstr) == 0) {
2240 	    mkmsgbox ("Error", "You must enter a valid number of surfaces.");
2241 	    goto retry;
2242 	}
2243 	bpr = atoi (bprstr);
2244 
2245 	if (row == -1) {
2246 	    failure = add_filesys_unit (currprefs.mountinfo, NULL, fixed_volname, pathname,
2247 					0, 0, 0, 0, 0, bpr);
2248 	} else {
2249 	    failure = set_filesys_unit (currprefs.mountinfo, row, NULL, fixed_volname, pathname,
2250 					0, 0, 0, 0, 0, bpr);
2251 	}
2252 	if (failure) {
2253 	    mkmsgbox ("Error", failure);
2254 	    goto retry;
2255 	}
2256 	set_hd_state ();
2257     }
2258 
2259   out:
2260     gtk_widget_destroy (dirdlg);
2261     return 0;
2262 }
2263 
create_hdfdlg(const char * title,int row)2264 static void create_hdfdlg (const char *title, int row)
2265 {
2266     GtkWidget *vbox, *pathsel;
2267     GtkWidget *hdfdlg;
2268     static GtkWidget *bpt_entry, *surfaces_entry, *pri_entry;
2269     static GtkWidget *blocksize_entry, *reserved_entry, *path_entry;
2270 
2271     int readonly = 0;
2272 
2273     hdfdlg = gtk_dialog_new_with_buttons (title, GTK_WINDOW (gui_window),
2274 					  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2275 					  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2276 					  GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2277 					  NULL);
2278 
2279     gtk_window_set_position (GTK_WINDOW (hdfdlg), GTK_WIN_POS_MOUSE);
2280 
2281     pathsel = make_file_selector ("Select a path to mount",
2282 				  GTK_FILE_CHOOSER_ACTION_OPEN);
2283 
2284     vbox = GTK_DIALOG (hdfdlg)->vbox;
2285 
2286     gtkutil_add_table (GTK_WIDGET (vbox),
2287 		       leftalign (gtk_label_new ("File:")), 1, 1, GTK_FILL,
2288 		       leftalign (path_entry = gtk_file_chooser_button_new_with_dialog (pathsel)), 2, 1, GTK_FILL,
2289 		       GTKUTIL_ROW_END,
2290 		       leftalign (gtk_label_new ("Reserved blocks:")), 1, 1, GTK_FILL,
2291 		       leftalign (reserved_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
2292 		       GTKUTIL_ROW_END,
2293 		       leftalign (gtk_label_new ("Surfaces:")), 1, 1, GTK_FILL,
2294 		       leftalign (surfaces_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
2295 		       GTKUTIL_ROW_END,
2296 		       leftalign (gtk_label_new ("Blocksize:")), 1, 1, GTK_FILL,
2297 		       leftalign (blocksize_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
2298 		       GTKUTIL_ROW_END,
2299 		       leftalign (gtk_label_new ("Blocks per track:")), 1, 1, GTK_FILL,
2300 		       leftalign (bpt_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
2301 		       GTKUTIL_ROW_END,
2302 		       leftalign (gtk_label_new ("Boot priority:")), 1, 1, GTK_FILL,
2303 		       leftalign (pri_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
2304 
2305 		       GTKUTIL_TABLE_END);
2306 
2307     gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (path_entry), 40);
2308 
2309     if (row != -1) {
2310 	char *failure;
2311 	char *devname, *volname, *rootdir;
2312 	int secspertrack, surfaces, reserved, blocksize, size;
2313 	int cylinders, pri;
2314 	char t[20];
2315 
2316 	failure = get_filesys_unit (currprefs.mountinfo, row,
2317 				    &devname, &volname, &rootdir, &readonly,
2318 				    &secspertrack, &surfaces, &reserved,
2319 				    &cylinders, &size, &blocksize, &pri);
2320 	if (failure) {
2321 	    mkmsgbox ("Error", failure);
2322 	    goto out;
2323 	}
2324 	gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (path_entry), rootdir);
2325 	sprintf (t, "%d", blocksize);
2326 	gtk_entry_set_text (GTK_ENTRY (blocksize_entry), t);
2327 	sprintf (t, "%d", secspertrack);
2328 	gtk_entry_set_text (GTK_ENTRY (bpt_entry), t);
2329 	sprintf (t, "%d", surfaces);
2330 	gtk_entry_set_text (GTK_ENTRY (surfaces_entry), t);
2331 	sprintf (t, "%d", reserved);
2332 	gtk_entry_set_text (GTK_ENTRY (reserved_entry), t);
2333 	sprintf (t, "%d", pri);
2334 	gtk_entry_set_text (GTK_ENTRY (pri_entry), t);
2335 	if (volname)
2336 	    free (volname);
2337 	if (devname)
2338 	    free (devname);
2339 	if (rootdir)
2340 	    free (rootdir);
2341     }
2342 
2343   retry:
2344     if (gtk_dialog_run (GTK_DIALOG (hdfdlg)) == GTK_RESPONSE_ACCEPT) {
2345 	const char *failure;
2346 	const char *new_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (path_entry));
2347 	const char *bptstr = gtk_entry_get_text (GTK_ENTRY (bpt_entry));
2348 	const char *sfstr = gtk_entry_get_text (GTK_ENTRY (surfaces_entry));
2349 	const char *bsstr = gtk_entry_get_text (GTK_ENTRY (blocksize_entry));
2350 	const char *rsrvstr = gtk_entry_get_text (GTK_ENTRY (reserved_entry));
2351 	const char *bprstr = gtk_entry_get_text (GTK_ENTRY (pri_entry));
2352 	int n, sf, bpt, bs, rsrv, bpr;
2353 
2354 	if (new_filename == NULL || strlen (new_filename) == 0) {
2355 	    mkmsgbox ("Error", "You must enter a valid filename.");
2356 	    goto retry;
2357 	}
2358 
2359 	if (strlen (bptstr) == 0 || (bpt = atoi (bptstr)) == 0) {
2360 	    mkmsgbox ("Error", "You must enter a valid number of blocks per track.");
2361 	    goto retry;
2362 	}
2363 	if (strlen (rsrvstr) == 0) {
2364 	    mkmsgbox ("Error", "You must enter the number of reserved blocks.");
2365 	    goto retry;
2366 	}
2367 	rsrv = atoi (rsrvstr);
2368 	if (strlen (sfstr) == 0 || (sf = atoi (sfstr)) == 0) {
2369 	    mkmsgbox ("Error", "You must enter a valid number of surfaces.");
2370 	    goto retry;
2371 	}
2372 	if (strlen (bsstr) == 0 || (bs = atoi (bsstr)) == 0) {
2373 	    mkmsgbox ("Error", "You must enter a valid number of surfaces.");
2374 	    goto retry;
2375 	}
2376 	if (strlen (bprstr) == 0) {
2377 	    mkmsgbox ("Error", "You must enter a valid number of surfaces.");
2378 	    goto retry;
2379 	}
2380 	bpr = atoi (bprstr);
2381 
2382 	if (row == -1) {
2383 	    failure = add_filesys_unit (currprefs.mountinfo, NULL, NULL, new_filename,
2384 					readonly, bpt, sf, rsrv, bs, bpr);
2385 	} else {
2386 	    failure = set_filesys_unit (currprefs.mountinfo, row, NULL, NULL, new_filename,
2387 					readonly, bpt, sf, rsrv, bs, bpr);
2388 	}
2389 	if (failure) {
2390 	    mkmsgbox ("Error", failure);
2391 	    goto retry;
2392 	}
2393 	set_hd_state ();
2394     }
2395   out:
2396     gtk_widget_destroy (hdfdlg);
2397     return;
2398 }
2399 
did_newdir(void)2400 static void did_newdir (void)
2401 {
2402     create_dirdlg ("Add a new mounted directory", -1);
2403 }
2404 
did_newhdf(void)2405 static void did_newhdf (void)
2406 {
2407     create_hdfdlg ("Add a new hardfile", -1);
2408 }
2409 
did_newadf(void)2410 static void did_newadf (void)
2411 {
2412     make_disk_selector ();
2413 
2414     if (gtk_dialog_run (GTK_DIALOG (disk_selector)) == GTK_RESPONSE_ACCEPT) {
2415 	char *filename;
2416 	struct zfile *f;
2417 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (disk_selector));
2418 
2419 	f = zfile_open (filename, "rb");
2420 	if (f) {
2421 	    const char *failure;
2422 	    char buf[512];
2423 	    long size;
2424 	    zfile_fread (buf, 1, 512, f);
2425 	    zfile_fseek (f, 0, SEEK_END);
2426 	    size = zfile_ftell (f);
2427 	    if (buf[0] != 'D' || buf[1] != 'O' || buf[2] != 'S'
2428 		|| (buf[3] != 0 && buf[3] != 1)
2429 		|| size != 901120)
2430 	    {
2431 		mkmsgbox ("Error", "Not an ADF diskfile.");
2432 	    } else {
2433 		failure = add_filesys_unit (currprefs.mountinfo, NULL, NULL, filename,
2434 					    0, 11, 2, 2, 512, -2);
2435 		if (failure)
2436 		    mkmsgbox ("Error", failure);
2437 		else
2438 		    set_hd_state ();
2439 	    }
2440 	    zfile_fclose (f);
2441 	}
2442 
2443 	g_free (filename);
2444     }
2445 
2446     gtk_widget_hide (disk_selector);
2447 }
2448 
did_hdchange(void)2449 static void did_hdchange (void)
2450 {
2451     GtkTreeIter iter;
2452     GtkTreeModel *model;
2453     int idx;
2454 
2455     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter))
2456 	gtk_tree_model_get (model, &iter, 0, &idx, -1);
2457     else
2458 	return;
2459 
2460     if (hardfile_fs_type (currprefs.mountinfo, idx) != FILESYS_VIRTUAL) {
2461 	create_hdfdlg ("Change a hardfile", idx);
2462     } else {
2463 	create_dirdlg ("Change a mounted directory", idx);
2464    }
2465 }
did_hddel(void)2466 static void did_hddel (void)
2467 {
2468     GtkTreeIter iter;
2469     GtkTreeModel *model;
2470     int idx;
2471 
2472     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter))
2473 	gtk_tree_model_get (model, &iter, 0, &idx, -1);
2474     else
2475 	return;
2476 
2477     kill_filesys_unit (currprefs.mountinfo, idx);
2478     set_hd_state ();
2479 }
2480 
hdsel_changed(GtkWidget * widget,gint row,gint column,GdkEventButton * bevent,gpointer user_data)2481 static void hdsel_changed (GtkWidget *widget, gint row, gint column, GdkEventButton *bevent,
2482 			   gpointer user_data)
2483 {
2484     GtkTreeIter iter;
2485     GtkTreeModel *model;
2486 
2487     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter)) {
2488 	gtk_widget_set_sensitive (hdchange_button, TRUE);
2489 	gtk_widget_set_sensitive (hddel_button, TRUE);
2490     } else {
2491 	gtk_widget_set_sensitive (hdchange_button, FALSE);
2492 	gtk_widget_set_sensitive (hddel_button, FALSE);
2493     }
2494 }
2495 
hdunselect(GtkWidget * widget,gint row,gint column,GdkEventButton * bevent,gpointer user_data)2496 static void hdunselect (GtkWidget *widget, gint row, gint column, GdkEventButton *bevent,
2497 			gpointer user_data)
2498 {
2499     gtk_widget_set_sensitive (hdchange_button, FALSE);
2500     gtk_widget_set_sensitive (hddel_button, FALSE);
2501 }
2502 
preset_changed(GtkTreeSelection * selection,gpointer data)2503 static void preset_changed (GtkTreeSelection *selection, gpointer data)
2504 {
2505     GtkTreeIter iter;
2506     GtkTreeModel *model;
2507 
2508     if (gtk_tree_selection_get_selected (selection, &model, &iter))
2509 	gtk_widget_set_sensitive (preset_button, TRUE);
2510     else
2511 	gtk_widget_set_sensitive (preset_button, FALSE);
2512 }
2513 
did_set_preset(void)2514 static void did_set_preset (void)
2515 {
2516     GtkTreeIter iter;
2517     GtkTreeModel *model;
2518     gchar *filename;
2519 
2520     if (gtk_tree_selection_get_selected (preset_selection, &model, &iter)) {
2521 	gtk_tree_model_get (model, &iter, 1, &filename, -1);
2522 
2523 	if (filename) {
2524 	    cfgfile_load (&changed_prefs, filename);
2525 	    set_widgets_from_config ();
2526 	}
2527 	g_free (filename);
2528     }
2529 }
2530 
make_buttons_1(const char * label,GtkWidget * box,void (* sigfunc)(void),GtkWidget * (* create)(const char * label),int expand)2531 static GtkWidget *make_buttons_1 (const char *label, GtkWidget *box, void (*sigfunc) (void),
2532 				  GtkWidget *(*create)(const char *label), int expand)
2533 {
2534     GtkWidget *thing = create (label);
2535     gtk_widget_show (thing);
2536     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
2537     gtk_box_pack_start (GTK_BOX (box), thing, expand, expand, 0);
2538 
2539     return thing;
2540 }
2541 #define make_buttons(label, box, sigfunc, create) make_buttons_1(label, box, sigfunc, create, 1)
2542 #define make_button(label, box, sigfunc) make_buttons(label, box, sigfunc, gtk_button_new_with_label)
2543 
new_text_cell_renderer(GtkWidget * treeview,const char * title,int colnr,int expand,int ellipsize)2544 static void new_text_cell_renderer (GtkWidget *treeview, const char *title, int colnr,
2545 				    int expand, int ellipsize)
2546 {
2547     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
2548     GtkTreeViewColumn *column;
2549     column = gtk_tree_view_column_new_with_attributes (title, renderer,
2550 						       "text", colnr, NULL);
2551     gtk_tree_view_column_set_expand (column, expand);
2552     gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2553     if (ellipsize)
2554 	g_object_set (renderer,
2555 		      "ellipsize", PANGO_ELLIPSIZE_START,
2556 		      "ellipsize-set", TRUE,
2557 		      NULL);
2558 }
2559 
make_hd_widgets(GtkWidget * dvbox)2560 static void make_hd_widgets (GtkWidget *dvbox)
2561 {
2562     GtkCellRenderer *renderer;
2563     GtkTreeViewColumn *column;
2564     GtkAdjustment *adj;
2565     GtkWidget *scrolled, *buttonbox, *vbox, *hbox;
2566     int i;
2567 
2568     hd_store = gtk_list_store_new (11,
2569 				   G_TYPE_INT,
2570 				   G_TYPE_STRING, G_TYPE_STRING,
2571 				   G_TYPE_BOOLEAN,
2572 				   G_TYPE_STRING, G_TYPE_STRING,
2573 				   G_TYPE_STRING, G_TYPE_STRING,
2574 				   G_TYPE_STRING, G_TYPE_STRING,
2575 				   G_TYPE_INT);
2576 
2577 #if 0
2578     add_empty_vbox (dvbox);
2579 #endif
2580 
2581     hbox = gtk_hbox_new (FALSE, 0);
2582     gtk_box_pack_start (GTK_BOX (dvbox), hbox, TRUE, TRUE, 20);
2583     gtk_widget_show (hbox);
2584 
2585     vbox = gtk_vbox_new (FALSE, 4);
2586     gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2587     gtk_widget_show (vbox);
2588 
2589     hdlist_widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (hd_store));
2590 
2591     new_text_cell_renderer (hdlist_widget, "Volume", 1, 0, 0);
2592     new_text_cell_renderer (hdlist_widget, "Path/File", 2, 1, 1);
2593 
2594     renderer = gtk_cell_renderer_toggle_new ();
2595     column = gtk_tree_view_column_new_with_attributes ("R/O", renderer,
2596 						       "active", 3, NULL);
2597     gtk_tree_view_column_set_expand (column, 0);
2598     gtk_tree_view_append_column (GTK_TREE_VIEW (hdlist_widget), column);
2599 
2600     new_text_cell_renderer (hdlist_widget, "Heads", 4, 0, 0);
2601     new_text_cell_renderer (hdlist_widget, "Cyl.", 5, 0, 0);
2602     new_text_cell_renderer (hdlist_widget, "Sec.", 6, 0, 0);
2603     new_text_cell_renderer (hdlist_widget, "Rsrvd", 7, 0, 0);
2604     new_text_cell_renderer (hdlist_widget, "Size", 8, 0, 0);
2605     new_text_cell_renderer (hdlist_widget, "Blksize", 9, 0, 0);
2606     new_text_cell_renderer (hdlist_widget, "Pri", 10, 0, 0);
2607 
2608     gtk_widget_show (hdlist_widget);
2609 
2610     scrolled = gtk_scrolled_window_new (NULL, NULL);
2611     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2612 				    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2613     gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
2614     gtk_widget_show (scrolled);
2615 
2616     gtk_container_add (GTK_CONTAINER (scrolled), hdlist_widget);
2617 
2618     hd_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (hdlist_widget));
2619     gtk_tree_selection_set_mode (hd_selection, GTK_SELECTION_SINGLE);
2620     g_signal_connect (G_OBJECT (hd_selection), "changed",
2621 		      G_CALLBACK (hdsel_changed), NULL);
2622 
2623     /* The buttons */
2624     buttonbox = gtk_hbox_new (FALSE, 4);
2625     gtk_widget_show (buttonbox);
2626     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
2627     make_button ("New filesystem...", buttonbox, did_newdir);
2628     make_button ("New hardfile...", buttonbox, did_newhdf);
2629     make_button ("Mount floppy as HD...", buttonbox, did_newadf);
2630 
2631     buttonbox = gtk_hbox_new (FALSE, 4);
2632     gtk_widget_show (buttonbox);
2633     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
2634     hdchange_button = make_button ("Change...", buttonbox, did_hdchange);
2635     hddel_button = make_button ("Delete", buttonbox, did_hddel);
2636 
2637     bootrom_widget = gtk_check_button_new_with_label ("Enable bootrom - needed for filesystem, Picasso96 and better mouse support;\ndisable only in case of (unlikely) compatibility issues");
2638     add_centered_to_vbox (dvbox, bootrom_widget, 0);
2639     gtk_widget_show (bootrom_widget);
2640     gtk_signal_connect (GTK_OBJECT (bootrom_widget), "clicked",
2641 			(GtkSignalFunc) bootrom_changed, NULL);
2642 #if 0
2643     add_empty_vbox (dvbox);
2644 #endif
2645 }
2646 
make_presets(GtkWidget * dvbox)2647 static void make_presets (GtkWidget *dvbox)
2648 {
2649     GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
2650     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
2651     GtkTreeViewColumn *column;
2652     GtkWidget *scrolled, *buttonbox, *vbox, *hbox;
2653     int i;
2654 
2655     add_empty_vbox (dvbox);
2656 
2657     hbox = gtk_hbox_new (FALSE, 0);
2658     gtk_box_pack_start (GTK_BOX (dvbox), hbox, TRUE, TRUE, 0);
2659     gtk_widget_show (hbox);
2660 
2661     add_empty_vbox (hbox);
2662 
2663     vbox = gtk_vbox_new (FALSE, 4);
2664     gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2665     gtk_widget_show (vbox);
2666 
2667     for (i = 0; i < n_predef_configs; i++) {
2668 	GtkTreeIter iter;
2669 	gtk_list_store_append (store, &iter);
2670 
2671 	gtk_list_store_set (store, &iter,
2672 			    0, predef_configs[i].description,
2673 			    1, predef_configs[i].filename,
2674 			    -1);
2675     }
2676     preset_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
2677     gtk_widget_show (preset_list);
2678 
2679     new_text_cell_renderer (preset_list, "Hardware configuration presets", 0, 1, 0);
2680 
2681     scrolled = gtk_scrolled_window_new (NULL, NULL);
2682     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2683 				    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2684     gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
2685     gtk_widget_show (scrolled);
2686 
2687     gtk_container_add (GTK_CONTAINER (scrolled), preset_list);
2688 
2689     preset_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (preset_list));
2690     gtk_tree_selection_set_mode (preset_selection, GTK_SELECTION_SINGLE);
2691     g_signal_connect (G_OBJECT (preset_selection), "changed",
2692 		      G_CALLBACK (preset_changed),
2693 		      NULL);
2694 
2695     /* The buttons */
2696     buttonbox = gtk_hbox_new (FALSE, 4);
2697     gtk_widget_show (buttonbox);
2698     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
2699     preset_button = make_buttons_1 ("Set configuration to chosen preset", buttonbox, did_set_preset,
2700 				    gtk_button_new_with_label, 0);
2701 
2702     add_empty_vbox (hbox);
2703 
2704     add_empty_vbox (dvbox);
2705 }
2706 
make_about_widgets(GtkWidget * dvbox)2707 static void make_about_widgets (GtkWidget *dvbox)
2708 {
2709     GtkWidget *lab_version;
2710     GtkStyle *style;
2711     GdkFont *font;
2712     char t[20];
2713 
2714     add_empty_vbox (dvbox);
2715 
2716     sprintf (t, "%s %s", PACKAGE_NAME, PACKAGE_VERSION);
2717     lab_version = gtk_label_new (t);
2718     lab_info = gtk_label_new ("Choose your settings, then deselect the Pause button to start!");
2719 
2720     style = gtk_style_copy (GTK_WIDGET (lab_version)->style);
2721     pango_font_description_free (style->font_desc);
2722     style->font_desc = pango_font_description_from_string ("Sans 24");
2723     gtk_widget_set_style (lab_version, style);
2724 
2725     add_centered_to_vbox (dvbox, lab_version, 0);
2726     add_centered_to_vbox (dvbox, lab_info, 0);
2727     gtk_widget_show (lab_version);
2728     if (currprefs.start_gui == 1)
2729 	gtk_widget_show (lab_info);
2730 
2731     add_empty_vbox (dvbox);
2732 }
2733 
create_guidlg(void)2734 static void create_guidlg (void)
2735 {
2736     GtkWidget *window;
2737     GtkWidget *buttonbox, *vbox, *hbox;
2738     GtkWidget *thing;
2739     unsigned int i;
2740     int argc = 1;
2741     char *a[] = {"UAE"};
2742     char **argv = a;
2743     static const struct _pages {
2744 	const char *title;
2745 	void (*createfunc)(GtkWidget *);
2746     } pages[] = {
2747 	/* ??? If this isn't the first page, there are errors in draw_led.  */
2748 	{ "Floppies", make_floppy_disks },
2749 	{ "ROM", make_rom_widgets },
2750 	{ "RAM", make_ram_widgets },
2751 	{ "CPU", make_cpu_widgets },
2752 	{ "Graphics", make_gfx_widgets },
2753 	{ "Chipset", make_chipset_widgets },
2754 	{ "Sound", make_sound_widgets },
2755 	{ "Input devices", make_joy_widgets },
2756 	{ "Harddisks", make_hd_widgets },
2757 	{ "Presets", make_presets },
2758 	{ "About", make_about_widgets }
2759     };
2760 
2761     gtk_init (&argc, &argv);
2762     gtk_rc_parse ("uaegtkrc");
2763 
2764     gui_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2765     gtk_window_set_title (GTK_WINDOW (gui_window), "UAE control");
2766 
2767     gtk_signal_connect (GTK_OBJECT (gui_window), "delete_event",
2768 			GTK_SIGNAL_FUNC (gui_delete_event), NULL);
2769 
2770     vbox = gtk_vbox_new (FALSE, 4);
2771     gtk_container_add (GTK_CONTAINER (gui_window), vbox);
2772     gtk_container_set_border_width (GTK_CONTAINER (gui_window), 10);
2773 
2774     /* First line - buttons and power LED */
2775     hbox = gtk_hbox_new (FALSE, 10);
2776     gtk_widget_show (hbox);
2777     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2778 
2779     /* The buttons */
2780     buttonbox = gtk_hbox_new (TRUE, 4);
2781     gtk_widget_show (buttonbox);
2782     gtk_box_pack_start (GTK_BOX (hbox), buttonbox, TRUE, TRUE, 0);
2783     make_button ("Reset", buttonbox, did_reset);
2784     make_button ("Debug", buttonbox, did_debug);
2785     make_button ("Quit", buttonbox, did_quit);
2786     make_button ("Save config", buttonbox, save_config);
2787     pause_uae_widget = make_buttons ("Pause", buttonbox, pause_uae, gtk_toggle_button_new_with_label);
2788 
2789     /* The LED */
2790     thing = make_led (0);
2791     thing = make_labelled_widget ("Power:", thing, FALSE);
2792     gtk_widget_show (thing);
2793     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, TRUE, 0);
2794 
2795     /* More buttons */
2796     buttonbox = gtk_hbox_new (TRUE, 4);
2797     gtk_widget_show (buttonbox);
2798     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, TRUE, TRUE, 0);
2799     snap_save_widget = make_button ("Save state", buttonbox, did_savestate);
2800     snap_load_widget = make_button ("Load state", buttonbox, did_loadstate);
2801 
2802     /* Place a separator below those buttons.  */
2803     thing = gtk_hseparator_new ();
2804     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
2805     gtk_widget_show (thing);
2806 
2807     /* Now the notebook */
2808     notebook = gtk_notebook_new ();
2809     gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
2810     gtk_widget_show (notebook);
2811 
2812     for (i = 0; i < sizeof pages / sizeof (struct _pages); i++) {
2813 	thing = gtk_vbox_new (FALSE, 4);
2814 	gtk_widget_show (thing);
2815 	gtk_container_set_border_width (GTK_CONTAINER (thing), 10);
2816 	pages[i].createfunc (thing);
2817 	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), thing, gtk_label_new (pages[i].title));
2818     }
2819 
2820     /* Put "about" screen first.  */
2821     gtk_notebook_set_page (GTK_NOTEBOOK (notebook), i - 1);
2822     enable_disk_buttons (1);
2823 
2824     gtk_widget_show (vbox);
2825 
2826     gtk_timeout_add (1000, (GtkFunction)my_idle, 0);
2827 }
2828 
gtk_gui_thread(void * dummy)2829 static void *gtk_gui_thread (void *dummy)
2830 {
2831     create_guidlg ();
2832     gtk_main ();
2833 
2834     gui_available = 0;
2835     uae_sem_post (&gui_quit_sem);
2836     return 0;
2837 }
2838 
gui_fps(int x)2839 void gui_fps (int x)
2840 {
2841 }
2842 
gui_display(int shortcut)2843 void gui_display (int shortcut)
2844 {
2845     if (shortcut == -1 && !gui_active) {
2846 	gui_init (0);
2847     }
2848 }
2849 
gui_led(int num,int on)2850 void gui_led (int num, int on)
2851 {
2852     if (no_gui)
2853 	return;
2854 
2855 /*    if (num == 0)
2856 	return;
2857     printf("LED %d %d\n", num, on);
2858     write_comm_pipe_int (&to_gui_pipe, 1, 0);
2859     write_comm_pipe_int (&to_gui_pipe, num == 0 ? 4 : num - 1, 0);
2860     write_comm_pipe_int (&to_gui_pipe, on, 1);
2861     printf("#LED %d %d\n", num, on);*/
2862 }
2863 
gui_filename(int num,const char * name)2864 void gui_filename (int num, const char *name)
2865 {
2866     if (no_gui)
2867 	return;
2868 
2869     write_comm_pipe_int (&to_gui_pipe, GUICMD_DISKCHANGE, 0);
2870     write_comm_pipe_int (&to_gui_pipe, num, 1);
2871 
2872 /*    gui_update ();*/
2873 }
2874 
gui_handle_events(void)2875 void gui_handle_events (void)
2876 {
2877     int pause_uae = FALSE;
2878 
2879     if (no_gui)
2880 	return;
2881 
2882     do {
2883 	while (pause_uae || comm_pipe_has_data (&from_gui_pipe)) {
2884 	    int cmd = read_comm_pipe_int_blocking (&from_gui_pipe);
2885 	    int n;
2886 	    switch (cmd) {
2887 	    case 0:
2888 		n = read_comm_pipe_int_blocking (&from_gui_pipe);
2889 		changed_prefs.df[n][0] = '\0';
2890 		break;
2891 	    case 1:
2892 		n = read_comm_pipe_int_blocking (&from_gui_pipe);
2893 		uae_sem_wait (&gui_sem);
2894 		strncpy (changed_prefs.df[n], new_disk_string[n], 255);
2895 		free (new_disk_string[n]);
2896 		new_disk_string[n] = 0;
2897 		changed_prefs.df[n][255] = '\0';
2898 		uae_sem_post (&gui_sem);
2899 		break;
2900 	    case 2:
2901 		uae_reset (1);
2902 		end_pause_uae ();
2903 		break;
2904 	    case 3:
2905 		activate_debugger ();
2906 		end_pause_uae ();
2907 		break;
2908 	    case 4:
2909 		uae_quit ();
2910 		end_pause_uae ();
2911 		break;
2912 	    case 5:
2913 		pause_uae = TRUE;
2914 		break;
2915 	    case 6:
2916 		pause_uae = FALSE;
2917 		break;
2918 	    case 7:
2919 		printf ("STATESAVE\n");
2920 		savestate_state = read_comm_pipe_int_blocking (&from_gui_pipe);
2921 		uae_sem_wait (&gui_sem);
2922 		savestate_filename = gui_snapname;
2923 		uae_sem_post (&gui_sem);
2924 		break;
2925 	    case 8:
2926 		uae_sem_wait (&gui_sem);
2927 		strncpy (changed_prefs.romfile, gui_romname, 255);
2928 		changed_prefs.romfile[255] = '\0';
2929 		free (gui_romname);
2930 		uae_sem_post (&gui_sem);
2931 		break;
2932 	    case 9:
2933 		uae_sem_wait (&gui_sem);
2934 		strncpy (changed_prefs.keyfile, gui_keyname, 255);
2935 		changed_prefs.keyfile[255] = '\0';
2936 		free (gui_keyname);
2937 		uae_sem_post (&gui_sem);
2938 		break;
2939 	    case 10:
2940 		uae_sem_wait (&gui_sem);
2941 		strncpy (changed_prefs.path_rom, gui_romname, 255);
2942 		changed_prefs.path_rom[255] = '\0';
2943 		free (gui_romname);
2944 		uae_sem_post (&gui_sem);
2945 		break;
2946 	    case 11:
2947 		uae_sem_wait (&gui_sem);
2948 		changed_prefs.gfx_w = gfx_w;
2949 		changed_prefs.gfx_f = gfx_f;
2950 		uae_sem_post (&gui_sem);
2951 		break;
2952 	    }
2953 	}
2954     } while (pause_uae);
2955 }
2956 
gui_update_gfx(void)2957 void gui_update_gfx (void)
2958 {
2959     if (no_gui)
2960 	return;
2961 
2962     write_comm_pipe_int (&to_gui_pipe, GUICMD_FULLSCREEN, 1);
2963 }
2964 
gui_update(void)2965 int gui_update (void)
2966 {
2967     if (!gui_available)
2968 	return 0;
2969 
2970     write_comm_pipe_int (&to_gui_pipe, GUICMD_UPDATE, 1);
2971     uae_sem_wait (&gui_init_sem);
2972     return 0;
2973 }
2974 
gui_show(void)2975 static void gui_show (void)
2976 {
2977     if (!gui_available)
2978 	return;
2979 
2980     write_comm_pipe_int (&to_gui_pipe, GUICMD_SHOW, 1);
2981     uae_sem_wait (&gui_init_sem);
2982     return;
2983 }
2984 
gui_romlist_changed(void)2985 void gui_romlist_changed (void)
2986 {
2987     if (!gui_available)
2988 	return;
2989 
2990     write_comm_pipe_int (&to_gui_pipe, GUICMD_NEW_ROMLIST, 1);
2991     return;
2992 }
2993 
gui_exit(void)2994 void gui_exit (void)
2995 {
2996     if (!gui_available)
2997 	return;
2998 
2999     quit_gui = 1;
3000     uae_sem_wait (&gui_quit_sem);
3001 }
3002 
gui_lock(void)3003 void gui_lock (void)
3004 {
3005     if (!gui_available)
3006 	return;
3007     uae_sem_wait (&gui_sem);
3008 }
3009 
gui_unlock(void)3010 void gui_unlock (void)
3011 {
3012     if (!gui_available)
3013 	return;
3014 
3015     uae_sem_post (&gui_sem);
3016 }
3017 
gui_init(int at_start)3018 int gui_init (int at_start)
3019 {
3020     uae_thread_id tid;
3021 
3022     if (gui_available) {
3023 	if (!gui_active) {
3024 	    gui_update ();
3025 	}
3026 	return 0;
3027     }
3028 
3029     gui_available = 1;
3030     if (at_start) {
3031 	init_comm_pipe (&to_gui_pipe, 20, 1);
3032 	init_comm_pipe (&from_gui_pipe, 20, 1);
3033 	uae_sem_init (&gui_sem, 0, 1);
3034 	uae_sem_init (&gui_init_sem, 0, 0);
3035 	uae_sem_init (&gui_quit_sem, 0, 0);
3036 
3037 	uae_start_thread (gtk_gui_thread, NULL, &tid);
3038     }
3039     gui_update ();
3040 
3041     if (at_start && currprefs.start_gui == 1) {
3042 	write_comm_pipe_int (&to_gui_pipe, GUICMD_PAUSE, 1);
3043 	write_comm_pipe_int (&from_gui_pipe, 5, 1);
3044 	/* Handle events until Pause is unchecked.  */
3045 	gui_handle_events ();
3046 	/* Quit requested?  */
3047 	if (quit_program == -1) {
3048 	    gui_exit ();
3049 	    return -2;
3050 	}
3051 	quit_program = 0;
3052     }
3053 
3054     return 1;
3055 }
3056