1 /** \file uimachinemenu.c
2 * \brief Native GTK3 menus for machine emulators (not vsid)
3 *
4 * \author Marcus Sutton <loggedoubt@gmail.com>
5 * \author Bas Wassink <b.wassink@ziggo.nl>
6 */
7
8 /*
9 * $VICERES WarpMode all
10 * $VICERES KeySetEnable -vsid
11 * $VICERES Mouse -vsid
12 * $VICERES DtvBlitterLog x64dtv
13 * $VICERES DtvDMALog x64dtv
14 * $VICERES DtvFlashLog x64dtv
15 */
16
17 /*
18 * This file is part of VICE, the Versatile Commodore Emulator.
19 * See README for copyright notice.
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
34 * 02111-1307 USA.
35 *
36 */
37
38
39 #include "vice.h"
40
41 #include <stdlib.h>
42 #include <gtk/gtk.h>
43
44 #include "vice_gtk3.h"
45 #include "archdep.h"
46 #include "debug_gtk3.h"
47 #include "datasette.h"
48 #include "debug.h"
49 #include "machine.h"
50 #include "resources.h"
51 #include "ui.h"
52 #include "uiabout.h"
53 #include "uicart.h"
54 #include "uicmdline.h"
55 #include "uicommands.h"
56 #include "uicompiletimefeatures.h"
57 #include "uidatasette.h"
58 #include "uidebug.h"
59 #include "uidiskattach.h"
60 #include "uiedit.h"
61 #include "uifliplist.h"
62 #include "uimachinemenu.h"
63 #include "uimedia.h"
64 #include "uimenu.h"
65 #include "uimonarch.h"
66 #include "uidiskcreate.h"
67 #include "uitapecreate.h"
68
69 #ifdef HAVE_NETWORK
70 # include "uinetplay.h"
71 # include "uinetplay_new.h"
72 #endif
73
74 #include "uisettings.h"
75 #include "uismartattach.h"
76 #include "uisnapshot.h"
77 #include "uitapeattach.h"
78
79 /*
80 * The following are translation unit local so we can create functions that
81 * modify menu contents or even functions that alter the top bar itself.
82 */
83
84
85 /** \brief Main menu bar widget
86 *
87 * Contains the submenus on the menu main bar
88 *
89 * This one lives until ui_exit() or thereabouts
90 */
91 static GtkWidget *main_menu_bar = NULL;
92
93
94 /** \brief File submenu
95 */
96 static GtkWidget *file_submenu = NULL;
97
98
99 /** \brief Edit submenu
100 */
101 static GtkWidget *edit_submenu = NULL;
102
103
104 /** \brief Snapshot submenu
105 */
106 static GtkWidget *snapshot_submenu = NULL;
107
108
109 /** \brief Settings submenu
110 */
111 static GtkWidget *settings_submenu = NULL;
112
113
114 #ifdef DEBUG
115 /** \brief Debug submenu, only available when --enable-debug was specified
116 */
117 static GtkWidget *debug_submenu = NULL;
118 #endif
119
120
121 /** \brief Help submenu
122 */
123 static GtkWidget *help_submenu = NULL;
124
125
126 /** \brief Load settings from default file
127 *
128 * \param[in] widget menu item triggering the event (ignored)
129 * \param[in] data extra even data (ignored)
130 */
settings_load_callback(GtkWidget * widget,gpointer data)131 static void settings_load_callback(GtkWidget *widget, gpointer data)
132 {
133 if (resources_load(NULL) != 0) {
134 vice_gtk3_message_error("VICE core error",
135 "Failed to load default settings file");
136 }
137 }
138
139
140 /** \brief Load settings from user-specified file
141 *
142 * \param[in] widget menu item triggering the event (ignored)
143 * \param[in] data extra even data (ignored)
144 */
settings_load_custom_callback(GtkWidget * widget,gpointer data)145 static void settings_load_custom_callback(GtkWidget *widget, gpointer data)
146 {
147 gchar *filename = vice_gtk3_open_file_dialog("Load settings file",
148 NULL, NULL, NULL);
149 if (filename!= NULL) {
150 if (resources_load(filename) != 0) {
151 vice_gtk3_message_error("VICE core error",
152 "Failed to load settings from '%s'", filename);
153 }
154 }
155 }
156
157
158 /** \brief Save settings to default file
159 *
160 * \param[in] widget menu item triggering the event (ignored)
161 * \param[in] data extra even data (ignored)
162 */
settings_save_callback(GtkWidget * widget,gpointer data)163 static void settings_save_callback(GtkWidget *widget, gpointer data)
164 {
165 if (resources_save(NULL) != 0) {
166 vice_gtk3_message_error("VICE core error",
167 "Failed to save default settings file");
168 }
169 }
170
171
172 /** \brief Save settings to user-specified file
173 *
174 * \param[in] widget menu item triggering the event (ignored)
175 * \param[in] data extra even data (ignored)
176 */
settings_save_custom_callback(GtkWidget * widget,gpointer data)177 static void settings_save_custom_callback(GtkWidget *widget, gpointer data)
178 {
179 gchar *filename = vice_gtk3_save_file_dialog("Save settings as ...",
180 NULL, TRUE, NULL);
181 if (filename!= NULL) {
182 if (resources_save(filename) != 0) {
183 vice_gtk3_message_error("VICE core error",
184 "Failed to save settings as '%s'", filename);
185 }
186 g_free(filename);
187 }
188 }
189
190
191
192 /** \brief File->Detach disk submenu
193 */
194 static ui_menu_item_t detach_submenu[] = {
195 { "Drive #8", UI_MENU_TYPE_ITEM_ACTION,
196 "detach-drive8", ui_disk_detach_callback, GINT_TO_POINTER(8),
197 0, 0 },
198 { "Drive #9", UI_MENU_TYPE_ITEM_ACTION,
199 "detach-drive9", ui_disk_detach_callback, GINT_TO_POINTER(9),
200 0, 0 },
201 { "Drive #10", UI_MENU_TYPE_ITEM_ACTION,
202 "detach-drive10", ui_disk_detach_callback, GINT_TO_POINTER(10),
203 0, 0 },
204 { "Drive #11", UI_MENU_TYPE_ITEM_ACTION,
205 "detach-drive11", ui_disk_detach_callback, GINT_TO_POINTER(11),
206 0, 0 },
207
208 { "Detach all", UI_MENU_TYPE_ITEM_ACTION,
209 "detach-all", ui_disk_detach_all_callback, NULL,
210 0, 0 },
211
212 UI_MENU_TERMINATOR
213 };
214
215
216 /** \brief File->Attach disk submenu
217 */
218 static ui_menu_item_t attach_submenu[] = {
219 { "Drive #8", UI_MENU_TYPE_ITEM_ACTION,
220 "attach-drive8", ui_disk_attach_callback, GINT_TO_POINTER(8),
221 GDK_KEY_8, VICE_MOD_MASK },
222 { "Drive #9", UI_MENU_TYPE_ITEM_ACTION,
223 "attach-drive9", ui_disk_attach_callback, GINT_TO_POINTER(9),
224 GDK_KEY_9, VICE_MOD_MASK },
225 { "Drive #10", UI_MENU_TYPE_ITEM_ACTION,
226 "attach-drive10", ui_disk_attach_callback, GINT_TO_POINTER(10),
227 GDK_KEY_0, VICE_MOD_MASK },
228 { "Drive #11", UI_MENU_TYPE_ITEM_ACTION,
229 "attach-drive11", ui_disk_attach_callback, GINT_TO_POINTER(11),
230 GDK_KEY_1, VICE_MOD_MASK },
231
232 UI_MENU_TERMINATOR
233 };
234
235
236
237 /** \brief File->Flip list submenu
238 */
239 static ui_menu_item_t fliplist_submenu[] = {
240 { "Add current image (Unit #8)", UI_MENU_TYPE_ITEM_ACTION,
241 "fliplist-add", ui_fliplist_add_current_cb, GINT_TO_POINTER(8),
242 GDK_KEY_I, VICE_MOD_MASK },
243 { "Remove current image (Unit #8)", UI_MENU_TYPE_ITEM_ACTION,
244 "fliplist-remove", ui_fliplist_remove_current_cb, GINT_TO_POINTER(8),
245 GDK_KEY_K, VICE_MOD_MASK },
246 { "Attach next image (Unit #8)", UI_MENU_TYPE_ITEM_ACTION,
247 "fliplist-next", ui_fliplist_next_cb, GINT_TO_POINTER(8),
248 GDK_KEY_N, VICE_MOD_MASK },
249 { "Attach previous image (Unit #8)", UI_MENU_TYPE_ITEM_ACTION,
250 "fliplist-prev", ui_fliplist_prev_cb, GINT_TO_POINTER(8),
251 GDK_KEY_N, VICE_MOD_MASK | GDK_SHIFT_MASK },
252 { "Load flip list file...", UI_MENU_TYPE_ITEM_ACTION,
253 "fliplist-load", ui_fliplist_load_callback, GINT_TO_POINTER(8),
254 0, 0 },
255 { "Save flip list file...", UI_MENU_TYPE_ITEM_ACTION,
256 "fliplist-save", ui_fliplist_save_callback, GINT_TO_POINTER(8),
257 0, 0 },
258
259 UI_MENU_TERMINATOR
260 };
261
262 /** \brief File->Datasette control submenu
263 */
264
265 static ui_menu_item_t datasette_control_submenu[] = {
266 { "Stop", UI_MENU_TYPE_ITEM_ACTION,
267 "tape-stop", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_STOP),
268 0, 0 },
269 { "Start", UI_MENU_TYPE_ITEM_ACTION,
270 "tape-start", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_START),
271 0, 0 },
272 { "Forward", UI_MENU_TYPE_ITEM_ACTION,
273 "tape-ff", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_FORWARD),
274 0, 0 },
275 { "Rewind", UI_MENU_TYPE_ITEM_ACTION,
276 "tape-rew", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_REWIND),
277 0, 0 },
278 { "Record", UI_MENU_TYPE_ITEM_ACTION,
279 "tape-record", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_RECORD),
280 0, 0 },
281 { "Reset", UI_MENU_TYPE_ITEM_ACTION,
282 "tape-reset", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_RESET),
283 0, 0 },
284 { "Reset Counter", UI_MENU_TYPE_ITEM_ACTION,
285 "tape-counter", ui_datasette_tape_action_cb, GINT_TO_POINTER(DATASETTE_CONTROL_RESET_COUNTER),
286 0, 0 },
287 UI_MENU_TERMINATOR
288 };
289
290 #if 0
291 /** \brief 'File->Cartridge attach' submenu
292 */
293 static ui_menu_item_t cart_attach_submenu[] = {
294 { "Smart attach cart image ... ", UI_MENU_TYPE_ITEM_ACTION,
295 "attach-cart", (void *)uicart_smart_attach_dialog, NULL,
296 GDK_KEY_C, VICE_MOD_MASK },
297 UI_MENU_TERMINATOR
298 };
299 #endif
300
301
302 /** \brief File->Reset submenu
303 */
304 static ui_menu_item_t reset_submenu[] = {
305 { "Soft reset", UI_MENU_TYPE_ITEM_ACTION,
306 "reset-soft", ui_machine_reset_callback, GINT_TO_POINTER(MACHINE_RESET_MODE_SOFT),
307 GDK_KEY_F9, VICE_MOD_MASK },
308 { "Hard reset", UI_MENU_TYPE_ITEM_ACTION,
309 "reset-hard", ui_machine_reset_callback, GINT_TO_POINTER(MACHINE_RESET_MODE_HARD),
310 GDK_KEY_F12, VICE_MOD_MASK },
311
312 UI_MENU_SEPARATOR,
313
314 { "Reset drive #8", UI_MENU_TYPE_ITEM_ACTION,
315 "reset-drive8", ui_drive_reset_callback, GINT_TO_POINTER(8),
316 0, 0 },
317 { "Reset drive #9", UI_MENU_TYPE_ITEM_ACTION,
318 "reset-drive9", ui_drive_reset_callback, GINT_TO_POINTER(9),
319 0, 0 },
320 { "Reset drive #10", UI_MENU_TYPE_ITEM_ACTION,
321 "reset-drive10", ui_drive_reset_callback, GINT_TO_POINTER(10),
322 0, 0 },
323 { "Reset drive #11", UI_MENU_TYPE_ITEM_ACTION,
324 "reset-drive11", ui_drive_reset_callback, GINT_TO_POINTER(11),
325 0, 0 },
326
327 UI_MENU_TERMINATOR
328 };
329
330
331 /** \brief 'File' menu - head section
332 */
333 static ui_menu_item_t file_menu_head[] = {
334 { "Smart attach disk/tape ...", UI_MENU_TYPE_ITEM_ACTION,
335 "smart-attach", ui_smart_attach_callback, NULL,
336 GDK_KEY_A, VICE_MOD_MASK },
337
338 UI_MENU_SEPARATOR,
339
340 /* disk */
341 { "Attach disk image", UI_MENU_TYPE_SUBMENU,
342 NULL, NULL, attach_submenu,
343 GDK_KEY_8, VICE_MOD_MASK },
344 { "Create and attach an empty disk image ...", UI_MENU_TYPE_ITEM_ACTION,
345 "create-disk", uidiskcreate_dialog_show, GINT_TO_POINTER(8),
346 0, 0 },
347 { "Detach disk image", UI_MENU_TYPE_SUBMENU,
348 NULL, NULL, detach_submenu,
349 0, 0 },
350 { "Flip list", UI_MENU_TYPE_SUBMENU,
351 NULL, NULL, fliplist_submenu,
352 0, 0 },
353
354 UI_MENU_SEPARATOR,
355
356 UI_MENU_TERMINATOR
357 };
358
359
360 /** \brief 'File' menu - tape section pointer
361 *
362 * Set by ...
363 */
364 static ui_menu_item_t *file_menu_tape_section = NULL;
365
366
367 /** \brief 'File' menu - tape section
368 */
369 static ui_menu_item_t file_menu_tape[] = {
370 { "Attach tape image ...", UI_MENU_TYPE_ITEM_ACTION,
371 "attach-tape", ui_tape_attach_callback, NULL,
372 GDK_KEY_T, VICE_MOD_MASK },
373 { "Create and attach an empty tape image ...", UI_MENU_TYPE_ITEM_ACTION,
374 "create-tape", uitapecreate_dialog_show, NULL,
375 0, 0 },
376 { "Detach tape image", UI_MENU_TYPE_ITEM_ACTION,
377 "detach-tape", ui_tape_detach_callback, NULL,
378 0, 0 },
379 { "Datasette controls", UI_MENU_TYPE_SUBMENU,
380 NULL, NULL, datasette_control_submenu,
381 0, 0 },
382
383 UI_MENU_SEPARATOR,
384
385 UI_MENU_TERMINATOR
386 };
387
388
389 /** \brief 'File' menu - tail section
390 */
391 static ui_menu_item_t file_menu_tail[] = {
392 /* cart */
393 { "Attach cartridge image ...", UI_MENU_TYPE_ITEM_ACTION,
394 "cart-attach", uicart_show_dialog, NULL,
395 GDK_KEY_C, VICE_MOD_MASK },
396 { "Detach cartridge image(s)", UI_MENU_TYPE_ITEM_ACTION,
397 "cart-detach", (void *)uicart_detach, NULL,
398 0, 0 },
399 { "Cartridge freeze", UI_MENU_TYPE_ITEM_ACTION,
400 "cart-freeze", (void *)uicart_trigger_freeze, NULL,
401 GDK_KEY_Z, VICE_MOD_MASK },
402
403 UI_MENU_SEPARATOR,
404
405 /* monitor */
406 { "Activate monitor", UI_MENU_TYPE_ITEM_ACTION,
407 "monitor", ui_monitor_activate_callback, NULL,
408 #ifdef MACOSX_SUPPORT
409 /* use Command-Option-M on Mac */
410 GDK_KEY_M, VICE_MOD_MASK | GDK_MOD1_MASK
411 #else
412 GDK_KEY_H, VICE_MOD_MASK
413 #endif
414 },
415
416 UI_MENU_SEPARATOR,
417
418 #ifdef HAVE_NETWORK
419 { "Netplay ...", UI_MENU_TYPE_ITEM_ACTION,
420 #if 0
421 "netplay", ui_netplay_dialog_new, NULL,
422 #else
423 "netplay", ui_netplay_dialog, NULL,
424 #endif
425 0, 0 },
426
427 UI_MENU_SEPARATOR,
428 #endif
429
430 { "Reset", UI_MENU_TYPE_SUBMENU,
431 NULL, NULL, reset_submenu,
432 0, 0 },
433
434 UI_MENU_SEPARATOR,
435
436 { "Exit emulator", UI_MENU_TYPE_ITEM_ACTION,
437 "exit", ui_close_callback, NULL,
438 GDK_KEY_Q, VICE_MOD_MASK },
439
440 UI_MENU_TERMINATOR
441 };
442
443
444 /** \brief 'Edit' menu
445 */
446 static ui_menu_item_t edit_menu[] = {
447 { "Copy", UI_MENU_TYPE_ITEM_ACTION,
448 "copy", (void *)ui_copy_callback, NULL,
449 GDK_KEY_Delete, VICE_MOD_MASK },
450 { "Paste", UI_MENU_TYPE_ITEM_ACTION,
451 "paste", (void *)ui_paste_callback, NULL,
452 GDK_KEY_Insert, VICE_MOD_MASK },
453
454 UI_MENU_TERMINATOR
455 };
456
457
458 /** \brief 'Snapshot' menu
459 */
460 static ui_menu_item_t snapshot_menu[] = {
461 { "Load snapshot image ...", UI_MENU_TYPE_ITEM_ACTION,
462 "snapshot-load", uisnapshot_open_file, NULL,
463 GDK_KEY_L, VICE_MOD_MASK },
464 { "Save snapshot image ...", UI_MENU_TYPE_ITEM_ACTION,
465 "snapshot-save", uisnapshot_save_file, NULL,
466 GDK_KEY_S, VICE_MOD_MASK },
467
468 UI_MENU_SEPARATOR,
469
470 { "Quickload snapshot", UI_MENU_TYPE_ITEM_ACTION,
471 "snapshot-quickload", uisnapshot_quickload_snapshot, NULL,
472 GDK_KEY_F10, VICE_MOD_MASK }, /* Shortcut doesn't work in MATE, key
473 is mapped to Maximize Window. Using
474 the menu to active this item does
475 work though -- compyx */
476 { "Quicksave snapshot", UI_MENU_TYPE_ITEM_ACTION,
477 "snapshot-quicksave", uisnapshot_quicksave_snapshot, NULL,
478 GDK_KEY_F11, VICE_MOD_MASK },
479
480 UI_MENU_SEPARATOR,
481 #if 0
482 { "Select history directory ...", UI_MENU_TYPE_ITEM_ACTION,
483 "history-select-dir", uisnapshot_history_select_dir, "0:3",
484 0, 0 },
485 #endif
486 { "Start recording events", UI_MENU_TYPE_ITEM_ACTION,
487 "history-record-start", uisnapshot_history_record_start, NULL,
488 0, 0 },
489 { "Stop recording events", UI_MENU_TYPE_ITEM_ACTION,
490 "history-record-stop", uisnapshot_history_record_stop, NULL,
491 0, 0 },
492 { "Start playing back events", UI_MENU_TYPE_ITEM_ACTION,
493 "history-playback-start", uisnapshot_history_playback_start, NULL,
494 0, 0 },
495 { "Stop playing back events", UI_MENU_TYPE_ITEM_ACTION,
496 "history-playback-stop", uisnapshot_history_playback_stop, NULL,
497 0, 0 },
498 { "Set recording milestone", UI_MENU_TYPE_ITEM_ACTION,
499 "history-milestone-set", uisnapshot_history_milestone_set, NULL,
500 GDK_KEY_E, VICE_MOD_MASK },
501 { "Return to milestone", UI_MENU_TYPE_ITEM_ACTION,
502 "history-milestone-reset", uisnapshot_history_milestone_reset, NULL,
503 GDK_KEY_U, VICE_MOD_MASK },
504
505 UI_MENU_SEPARATOR,
506 #if 0
507 { "Recording start mode ...", UI_MENU_TYPE_ITEM_ACTION,
508 "history-recording-start-mode", ui_settings_dialog_create, "20,0",
509 0, 0 },
510
511 UI_MENU_SEPARATOR,
512 #endif
513
514 { "Save media file ...", UI_MENU_TYPE_ITEM_ACTION,
515 "media-save", uimedia_dialog_show, NULL,
516 GDK_KEY_R, VICE_MOD_MASK | GDK_SHIFT_MASK },
517
518 { "Stop media recording", UI_MENU_TYPE_ITEM_ACTION,
519 "media-stop", (void *)uimedia_stop_recording, NULL,
520 GDK_KEY_S, VICE_MOD_MASK | GDK_SHIFT_MASK },
521
522 UI_MENU_TERMINATOR
523 };
524
525
526 /** \brief 'Settings' menu - head section
527 */
528 static ui_menu_item_t settings_menu_head[] = {
529 { "Toggle fullscreen", UI_MENU_TYPE_ITEM_ACTION,
530 "fullscreen", ui_fullscreen_callback, NULL,
531 GDK_KEY_D, VICE_MOD_MASK },
532 #if 1
533 { "Show menu/status in fullscreen", UI_MENU_TYPE_ITEM_ACTION,
534 "fullscreen-widgets", ui_fullscreen_decorations_callback, NULL,
535 GDK_KEY_B, VICE_MOD_MASK },
536 #else
537 /* Mac menubar version */
538 { "Show statusbar in fullscreen", UI_MENU_TYPE_ITEM_ACTION,
539 "fullscreen-widgets", ui_fullscreen_decorations_callback, NULL,
540 GDK_KEY_B, VICE_MOD_MASK },
541 #endif
542
543 #if 0
544 UI_MENU_SEPARATOR,
545 { "Toggle warp mode", UI_MENU_TYPE_ITEM_CHECK,
546 "warp", (void *)(ui_toggle_resource), (void *)"WarpMode",
547 GDK_KEY_W, VICE_MOD_MASK },
548 { "Pause emulation", UI_MENU_TYPE_ITEM_CHECK,
549 "pause", (void *)(ui_toggle_pause), NULL,
550 GDK_KEY_P, VICE_MOD_MASK },
551 { "Advance frame", UI_MENU_TYPE_ITEM_ACTION,
552 "frame-advance", (void *)(ui_advance_frame), NULL,
553 GDK_KEY_P, VICE_MOD_MASK | GDK_SHIFT_MASK },
554 #endif
555 UI_MENU_SEPARATOR,
556
557 UI_MENU_TERMINATOR
558 };
559
560
561 /** \brief 'Settings' menu - joystick section pointer
562 *
563 * Set by ...
564 */
565 static ui_menu_item_t *settings_menu_joy_section = NULL;
566
567
568 /** \brief 'Settings' menu - all joystick items
569 *
570 * Only valid for x64/x64sc/xscpu64/x128/xplus4
571 */
572 static ui_menu_item_t settings_menu_all_joy[] = {
573
574 { "Swap joysticks", UI_MENU_TYPE_ITEM_ACTION,
575 "joystick-swap", (void *)(ui_swap_joysticks_callback), NULL,
576 GDK_KEY_J, VICE_MOD_MASK },
577 { "Swap userport joysticks", UI_MENU_TYPE_ITEM_ACTION,
578 "userportjoy-swap", (void *)(ui_swap_userport_joysticks_callback), NULL,
579 GDK_KEY_U, VICE_MOD_MASK | GDK_SHIFT_MASK },
580 { "Allow keyset joystick", UI_MENU_TYPE_ITEM_CHECK,
581 "keyset", (void *)(ui_toggle_resource), (void *)"KeySetEnable",
582 GDK_KEY_J, VICE_MOD_MASK | GDK_SHIFT_MASK },
583 { "Enable mouse grab", UI_MENU_TYPE_ITEM_CHECK,
584 "mouse", (void *)(ui_toggle_resource), (void *)"Mouse",
585 GDK_KEY_M, VICE_MOD_MASK },
586
587 UI_MENU_TERMINATOR
588 };
589
590 /** \brief 'Settings' menu - control port joystick items
591 *
592 * Only valid for x64dtv/xcbm5x0
593 */
594 static ui_menu_item_t settings_menu_cbm5x0_joy[] = {
595
596 { "Swap joysticks", UI_MENU_TYPE_ITEM_ACTION,
597 "joystick-swap", (void *)(ui_swap_joysticks_callback), NULL,
598 GDK_KEY_J, VICE_MOD_MASK },
599 { "Allow keyset joystick", UI_MENU_TYPE_ITEM_CHECK,
600 "keyset", (void *)(ui_toggle_resource), (void *)"KeySetEnable",
601 GDK_KEY_J, VICE_MOD_MASK | GDK_SHIFT_MASK },
602 { "Enable mouse grab", UI_MENU_TYPE_ITEM_CHECK,
603 "mouse", (void *)(ui_toggle_resource), (void *)"Mouse",
604 GDK_KEY_M, VICE_MOD_MASK },
605
606 UI_MENU_TERMINATOR
607 };
608
609 /** \brief 'Settings' menu - userport joystick items
610 *
611 * Only valid for xvic/xpet/xcbm2
612 */
613 static ui_menu_item_t settings_menu_userport_joy[] = {
614 { "Swap userport joysticks", UI_MENU_TYPE_ITEM_ACTION,
615 "userportjoy-swap", (void *)(ui_swap_userport_joysticks_callback), NULL,
616 GDK_KEY_U, VICE_MOD_MASK | GDK_SHIFT_MASK },
617 { "Allow keyset joystick", UI_MENU_TYPE_ITEM_CHECK,
618 "keyset", (void *)(ui_toggle_resource), (void *)"KeySetEnable",
619 GDK_KEY_J, VICE_MOD_MASK | GDK_SHIFT_MASK },
620 { "Enable mouse grab", UI_MENU_TYPE_ITEM_CHECK,
621 "mouse", (void *)(ui_toggle_resource), (void *)"Mouse",
622 GDK_KEY_M, VICE_MOD_MASK },
623
624 UI_MENU_TERMINATOR
625 };
626
627 /** \brief 'Settings' menu tail section
628 */
629 static ui_menu_item_t settings_menu_tail[] = {
630
631 UI_MENU_SEPARATOR,
632
633 /* the settings dialog */
634 { "Settings ...", UI_MENU_TYPE_ITEM_ACTION,
635 "settings", (void *)ui_settings_dialog_create, NULL,
636 GDK_KEY_O, VICE_MOD_MASK },
637 { "Load settings", UI_MENU_TYPE_ITEM_ACTION,
638 "settings-load", settings_load_callback, NULL,
639 0, 0 },
640 { "Load custom settings ...", UI_MENU_TYPE_ITEM_ACTION,
641 "settings-load-custom", settings_load_custom_callback, NULL,
642 0, 0 },
643 { "Save settings", UI_MENU_TYPE_ITEM_ACTION,
644 "settings-save", settings_save_callback, NULL,
645 0, 0 },
646 { "Save custom settings ...", UI_MENU_TYPE_ITEM_ACTION,
647 "settings-save-custom", settings_save_custom_callback, NULL,
648 0, 0 },
649 UI_MENU_TERMINATOR
650 };
651
652
653 #ifdef DEBUG
654
655 /** \brief 'Debug' menu items for emu's except x64dtv
656 */
657 static ui_menu_item_t debug_menu[] = {
658 { "Trace mode ...", UI_MENU_TYPE_ITEM_ACTION,
659 "tracemode", uidebug_trace_mode_callback, NULL,
660 0, 0 },
661
662 UI_MENU_SEPARATOR,
663
664 { "Main CPU trace", UI_MENU_TYPE_ITEM_CHECK,
665 "trace-maincpu", (void *)(ui_toggle_resource), (void *)"MainCPU_TRACE",
666 0, 0 },
667
668 UI_MENU_SEPARATOR,
669
670 { "Drive #8 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
671 "trace-drive8", (void *)(ui_toggle_resource), (void *)"Drive0CPU_TRACE",
672 0, 0 },
673 { "Drive #9 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
674 "trace-drive9", (void *)(ui_toggle_resource), (void *)"Drive1CPU_TRACE",
675 0, 0 },
676 { "Drive #10 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
677 "trace-drive10", (void *)(ui_toggle_resource), (void *)"Drive2CPU_TRACE",
678 0, 0 },
679 { "Drive #11 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
680 "trace-drive11", (void *)(ui_toggle_resource), (void *)"Drive3CPU_TRACE",
681 0, 0 },
682
683 UI_MENU_SEPARATOR,
684
685 { "Autoplay playback frames ...", UI_MENU_TYPE_ITEM_ACTION,
686 "playframes", uidebug_playback_frames_callback, NULL,
687 0, 0 },
688 { "Save core dump", UI_MENU_TYPE_ITEM_CHECK,
689 "coredump", (void *)(ui_toggle_resource), (void *)"DoCoreDump",
690 0, 0 },
691
692 UI_MENU_TERMINATOR
693 };
694
695
696 /** \brief 'Debug' menu items for x64dtv
697 */
698 static ui_menu_item_t debug_menu_c64dtv[] = {
699 { "Trace mode ...", UI_MENU_TYPE_ITEM_ACTION,
700 "tracemode", uidebug_trace_mode_callback, NULL,
701 0, 0 },
702
703 UI_MENU_SEPARATOR,
704
705 { "Main CPU trace", UI_MENU_TYPE_ITEM_CHECK,
706 "trace-maincpu", (void *)(ui_toggle_resource), (void *)"MainCPU_TRACE",
707 0, 0 },
708
709 UI_MENU_SEPARATOR,
710
711 { "Drive #8 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
712 "trace-drive8", (void *)(ui_toggle_resource), (void *)"Drive0CPU_TRACE",
713 0, 0 },
714 { "Drive #9 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
715 "trace-drive9", (void *)(ui_toggle_resource), (void *)"Drive1CPU_TRACE",
716 0, 0 },
717 { "Drive #10 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
718 "trace-drive10", (void *)(ui_toggle_resource), (void *)"Drive2CPU_TRACE",
719 0, 0 },
720 { "Drive #11 CPU trace", UI_MENU_TYPE_ITEM_CHECK,
721 "trace-drive11", (void *)(ui_toggle_resource), (void *)"Drive3CPU_TRACE",
722 0, 0 },
723
724 UI_MENU_SEPARATOR,
725
726 { "Blitter log", UI_MENU_TYPE_ITEM_CHECK,
727 "blitter-log", (void *)ui_toggle_resource, (void *)"DtvBlitterLog",
728 0, 0 },
729 { "DMA log", UI_MENU_TYPE_ITEM_CHECK,
730 "dma-log", (void *)ui_toggle_resource, (void *)"DtvDMALog",
731 0, 0 },
732 { "Flash log", UI_MENU_TYPE_ITEM_CHECK,
733 "flash-log", (void *)ui_toggle_resource, (void*)"DtvFlashLog",
734 0, 0 },
735
736 UI_MENU_SEPARATOR,
737
738 { "Autoplay playback frames ...", UI_MENU_TYPE_ITEM_ACTION,
739 "playframes", uidebug_playback_frames_callback, NULL,
740 0, 0 },
741 { "Save core dump", UI_MENU_TYPE_ITEM_CHECK,
742 "coredump", (void *)(ui_toggle_resource), (void *)"DoCoreDump",
743 0, 0 },
744
745 UI_MENU_TERMINATOR
746 };
747
748 #endif
749
750
751 /** \brief 'Help' menu items
752 */
753 static ui_menu_item_t help_menu[] = {
754 { "Browse manual", UI_MENU_TYPE_ITEM_ACTION,
755 "manual", ui_open_manual_callback, NULL,
756 0, 0 },
757 { "Command line options ...", UI_MENU_TYPE_ITEM_ACTION,
758 "cmdline", uicmdline_dialog_show, NULL,
759 0, 0 },
760 { "Compile time features ...", UI_MENU_TYPE_ITEM_ACTION,
761 "features", uicompiletimefeatures_dialog_show, NULL,
762 0, 0 },
763 { "About VICE", UI_MENU_TYPE_ITEM_ACTION,
764 "about", ui_about_dialog_callback, NULL,
765 0, 0 },
766
767 UI_MENU_TERMINATOR
768 };
769
770
771 /** \brief Create the top menu bar with standard submenus
772 *
773 * \return GtkMenuBar
774 */
ui_machine_menu_bar_create(void)775 GtkWidget *ui_machine_menu_bar_create(void)
776 {
777 GtkWidget *menu_bar;
778
779 /* create the top menu bar */
780 menu_bar = gtk_menu_bar_new();
781
782 /* create the top-level 'File' menu */
783 file_submenu = ui_menu_submenu_create(menu_bar, "File");
784
785 /* create the top-level 'Edit' menu */
786 edit_submenu = ui_menu_submenu_create(menu_bar, "Edit");
787
788 /* create the top-level 'Snapshot' menu */
789 snapshot_submenu = ui_menu_submenu_create(menu_bar, "Snapshot");
790
791 /* create the top-level 'Settings' menu */
792 settings_submenu = ui_menu_submenu_create(menu_bar, "Settings");
793
794 #ifdef DEBUG
795 /* create the top-level 'Debug' menu (when --enable-debug is used) */
796 debug_submenu = ui_menu_submenu_create(menu_bar, "Debug");
797 #endif
798
799 /* create the top-level 'Help' menu */
800 help_submenu = ui_menu_submenu_create(menu_bar, "Help");
801
802 /* determine which joystick swap menu items should be added */
803 switch (machine_class) {
804 case VICE_MACHINE_C64: /* fall through */
805 case VICE_MACHINE_C64SC: /* fall through */
806 case VICE_MACHINE_C128: /* fall through */
807 case VICE_MACHINE_PLUS4:
808 /* add tape section */
809 file_menu_tape_section = file_menu_tape;
810 /* fall through */
811 case VICE_MACHINE_SCPU64:
812 /* add both swap-joy and swap-userport-joy */
813 settings_menu_joy_section = settings_menu_all_joy;
814 break;
815 case VICE_MACHINE_CBM5x0:
816 /* add tape section */
817 file_menu_tape_section = file_menu_tape;
818 /* fall through */
819 case VICE_MACHINE_C64DTV:
820 /* only add swap-joy */
821 settings_menu_joy_section = settings_menu_cbm5x0_joy;
822 break;
823 case VICE_MACHINE_PET: /* fall through */
824 case VICE_MACHINE_VIC20: /* fall through */
825 case VICE_MACHINE_CBM6x0:
826 /* add tape section */
827 file_menu_tape_section = file_menu_tape;
828 /* only add swap-userport-joy */
829 settings_menu_joy_section = settings_menu_userport_joy;
830 break;
831 case VICE_MACHINE_VSID:
832 archdep_vice_exit(1);
833 break;
834 default:
835 break;
836 }
837
838 /* add items to the File menu */
839 ui_menu_add(file_submenu, file_menu_head);
840 if (file_menu_tape_section != NULL) {
841 ui_menu_add(file_submenu, file_menu_tape_section);
842 }
843 ui_menu_add(file_submenu, file_menu_tail);
844
845 /* add items to the Edit menu */
846 ui_menu_add(edit_submenu, edit_menu);
847 /* add items to the Snapshot menu */
848 ui_menu_add(snapshot_submenu, snapshot_menu);
849
850 /* add items to the Settings menu */
851 ui_menu_add(settings_submenu, settings_menu_head);
852 if (settings_menu_joy_section != NULL) {
853 ui_menu_add(settings_submenu, settings_menu_joy_section);
854 }
855 ui_menu_add(settings_submenu, settings_menu_tail);
856
857 #ifdef DEBUG
858 /* add items to the Debug menu */
859 if (machine_class == VICE_MACHINE_C64DTV) {
860 ui_menu_add(debug_submenu, debug_menu_c64dtv);
861 } else {
862 ui_menu_add(debug_submenu, debug_menu);
863 }
864 #endif
865
866 /* add items to the Help menu */
867 ui_menu_add(help_submenu, help_menu);
868
869 main_menu_bar = menu_bar; /* XXX: do I need g_object_ref()/g_object_unref()
870 for this */
871 return menu_bar;
872 }
873