32
32
#include <stdlib.h>
33
33
#include <string.h>
36
35
#include "archdep.h"
38
#include "autostart.h"
40
#include "imagecontents.h"
38
#include "fullscreenarch.h"
42
39
#include "interrupt.h"
44
43
#include "machine.h"
49
45
#include "resources.h"
53
48
#include "uicommands.h"
55
49
#include "uimenu.h"
56
#include "uisettings.h"
57
50
#include "uisnapshot.h"
58
51
#include "uidrive.h"
61
#ifdef USE_XF86_EXTENSIONS
62
#include "fullscreen.h"
65
static int selection_from_image = 0;
67
/* ------------------------------------------------------------------------- */
68
void ui_set_selected_file(int num)
70
selection_from_image = num;
73
/* ------------------------------------------------------------------------- */
75
static char *read_disk_image_contents(const char *name)
77
image_contents_t *contents;
80
contents = image_contents_read_disk(name);
85
s = image_contents_to_string(contents, IMAGE_CONTENTS_STRING_PETSCII);
87
s = image_contents_to_string(contents, IMAGE_CONTENTS_STRING_ASCII);
90
image_contents_destroy(contents);
95
static UI_CALLBACK(attach_disk)
97
int unit = (int)UI_MENU_CB_PARAM;
98
char *filename, *title;
100
static char *last_dir;
103
vsync_suspend_speed_eval();
104
title = xmsprintf(_("Attach Disk Image as unit #%d"), unit);
105
filename = ui_select_file(title, read_disk_image_contents,
106
unit == 8 ? True : False, last_dir,
107
"*.[gdxGDX]*", &button, True, &attach_wp);
111
printf("Write protect attach requested.\n");
112
resources_set_sprintf("AttachDevice%dReadonly",
113
(resource_value_t)attach_wp, unit);
118
if (file_system_attach_disk(unit, filename) < 0)
119
ui_error(_("Invalid Disk Image"));
122
util_fname_split(filename, &last_dir, NULL);
124
case UI_BUTTON_AUTOSTART:
125
if (autostart_disk(filename, NULL, selection_from_image,
126
AUTOSTART_MODE_RUN) < 0)
127
ui_error(_("Invalid Disk Image or Filename"));
130
util_fname_split(filename, &last_dir, NULL);
133
/* Do nothing special. */
137
if (filename != NULL)
141
static UI_CALLBACK(attach_empty_disk)
143
int unit = (int)UI_MENU_CB_PARAM;
144
/* Where does the 1024 come from? */
147
vsync_suspend_speed_eval();
149
/* The following code depends on a zeroed filename. */
150
memset(filename, 0, 1024);
152
if (ui_empty_disk_dialog(filename) < 0)
155
if (file_system_attach_disk(unit, filename) < 0)
156
ui_error(_("Invalid Disk Image"));
159
static UI_CALLBACK(detach_disk)
161
int unit = (int)UI_MENU_CB_PARAM;
163
vsync_suspend_speed_eval();
164
file_system_detach_disk(unit);
167
/* ------------------------------------------------------------------------- */
169
static char *read_tape_image_contents(const char *name)
171
image_contents_t *contents;
174
contents = image_contents_read_tape(name);
175
if (contents == NULL)
179
s = image_contents_to_string(contents, IMAGE_CONTENTS_STRING_PETSCII);
181
s = image_contents_to_string(contents, IMAGE_CONTENTS_STRING_ASCII);
184
image_contents_destroy(contents);
189
static UI_CALLBACK(attach_tape)
193
static char *last_dir;
195
vsync_suspend_speed_eval();
197
filename = ui_select_file(_("Attach a tape image"),
198
read_tape_image_contents,
199
True, last_dir, "*.[tT]*", &button, True, NULL);
203
if (tape_attach_image(filename) < 0)
204
ui_error(_("Invalid Tape Image"));
207
util_fname_split(filename, &last_dir, NULL);
209
case UI_BUTTON_AUTOSTART:
210
if (autostart_tape(filename, NULL, selection_from_image,
211
AUTOSTART_MODE_RUN) < 0)
212
ui_error(_("Invalid Tape Image"));
215
util_fname_split(filename, &last_dir, NULL);
218
/* Do nothing special. */
221
if (filename != NULL)
225
static UI_CALLBACK(detach_tape)
230
/* ------------------------------------------------------------------------- */
232
static char *read_disk_or_tape_image_contents(const char *fname)
236
tmp = read_disk_image_contents(fname);
239
return read_tape_image_contents(fname);
242
static UI_CALLBACK(smart_attach)
246
static char *last_dir;
248
vsync_suspend_speed_eval();
250
filename = ui_select_file(_("Smart-attach a file"),
251
read_disk_or_tape_image_contents,
252
True, last_dir, NULL, &button, True, NULL);
256
if (file_system_attach_disk(8, filename) < 0
257
&& tape_attach_image(filename) < 0) {
258
ui_error(_("Unknown image type"));
262
util_fname_split(filename, &last_dir, NULL);
264
case UI_BUTTON_AUTOSTART:
265
if (autostart_autodetect(filename, NULL, selection_from_image,
266
AUTOSTART_MODE_RUN) < 0)
267
ui_error(_("Unknown image type"));
270
util_fname_split(filename, &last_dir, NULL);
273
/* Do nothing special. */
276
if (filename != NULL)
280
/* ------------------------------------------------------------------------- */
282
56
static UI_CALLBACK(change_working_directory)
285
wd = xmalloc(MAXPATHLEN);
287
getcwd(wd, MAXPATHLEN);
61
len = ioutil_maxpathlen();
64
ioutil_getcwd(wd, len);
288
65
vsync_suspend_speed_eval();
289
66
if (ui_input_string(_("VICE setting"),
290
67
_("Change current working directory"),
291
wd, MAXPATHLEN) == UI_BUTTON_OK) {
68
wd, len) == UI_BUTTON_OK) {
69
if (ioutil_chdir(wd) < 0)
293
70
ui_error(_("Directory not found"));
298
static void mon_trap(ADDRESS addr, void *unused_data)
303
75
static UI_CALLBACK(activate_monitor)
305
77
#ifdef USE_XF86_EXTENSIONS
306
fullscreen_mode_off();
78
fullscreen_suspend(0);
308
80
vsync_suspend_speed_eval();
309
81
ui_dispatch_events(); /* popdown the menu */
310
82
ui_autorepeat_on();
312
87
if (!ui_emulation_is_paused())
313
maincpu_trigger_trap(mon_trap, (void *)0);
88
monitor_startup_trap();
315
mon_trap(MOS6510_REGS_GET_PC(&maincpu_regs), 0);
318
93
static UI_CALLBACK(run_c1541)
320
95
#ifdef USE_XF86_EXTENSIONS
321
fullscreen_mode_off();
96
fullscreen_suspend(0);
323
98
vsync_suspend_speed_eval();
516
299
static UI_CALLBACK(save_snapshot)
518
maincpu_trigger_trap(save_snapshot_trap, (void *) 0);
301
interrupt_maincpu_trigger_trap(save_snapshot_trap, (void *)0);
521
304
static UI_CALLBACK(save_quicksnap)
523
char *fname = concat(archdep_home_path(), "/", VICEUSERDIR, "/",
306
char *fname = util_concat(archdep_home_path(), "/", VICEUSERDIR, "/",
524
307
machine_name, ".vsf", NULL);
526
maincpu_trigger_trap(save_snapshot_trap, (void *) fname);
529
/* fliplist commands */
530
extern char last_attached_images[NUM_DRIVES][256];
531
extern ui_drive_enable_t enabled_drives;
535
long data; /* should be enough for a pointer */
539
CBD_NEXT, CBD_PREV, CBD_ADD, CBD_REMOVE
542
static UI_CALLBACK(attach_from_fliplist)
544
flip_attach_head(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit,
545
(int) ((struct cb_data_t *) UI_MENU_CB_PARAM)->data);
548
static UI_CALLBACK(attach_from_fliplist2)
550
file_system_attach_disk(flip_get_unit((void *) UI_MENU_CB_PARAM),
551
flip_get_image((void *) UI_MENU_CB_PARAM));
554
static UI_CALLBACK(attach_from_fliplist3)
556
flip_attach_head(8, (int) UI_MENU_CB_PARAM);
559
static UI_CALLBACK(add2fliplist)
562
ui_update_flip_menus(8, 8);
565
static UI_CALLBACK(add2fliplist2)
567
flip_set_current(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit,
568
(char *) ((struct cb_data_t *) UI_MENU_CB_PARAM)->data);
569
flip_add_image(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit);
570
ui_update_flip_menus(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit,
571
((struct cb_data_t *) UI_MENU_CB_PARAM)->unit);
574
static UI_CALLBACK(remove_from_fliplist)
576
flip_remove(8, NULL);
577
ui_update_flip_menus(8, 8);
580
static UI_CALLBACK(remove_from_fliplist2)
582
flip_remove(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit,
583
(char *) ((struct cb_data_t *) UI_MENU_CB_PARAM)->data);
584
ui_update_flip_menus(((struct cb_data_t *) UI_MENU_CB_PARAM)->unit,
585
((struct cb_data_t *) UI_MENU_CB_PARAM)->unit);
589
UI_MENU_DEFINE_TOGGLE(AttachDevice8Readonly)
590
UI_MENU_DEFINE_TOGGLE(AttachDevice9Readonly)
593
#define FLIPLIST_MENU_LIMIT 256
594
void ui_update_flip_menus(int from_unit, int to_unit)
596
/* Yick, allocate dynamically */
597
static ui_menu_entry_t flipmenu[NUM_DRIVES][FLIPLIST_MENU_LIMIT];
598
static struct cb_data_t cb_data[NUM_DRIVES][sizeof(cbd_enum_t)];
600
char *image = NULL, *t0 = NULL, *t1 = NULL, *t2 = NULL, *t3 = NULL;
601
char *t4 = NULL, *t5 = NULL, *dir;
603
int i, drive, true_emu, fliplist_start = 0;
604
static int name_count = 0;
607
resources_get_value("DriveTrueEmulation",
608
(resource_value_t *)&true_emu);
610
for (drive = from_unit - 8;
611
(drive <= to_unit - 8) && (drive < NUM_DRIVES);
615
t0 = t1 = t2 = t3 = t4 = t5 = NULL;
617
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
618
t0 = xmsprintf(_("Attach #%d"), drive + 8);
619
flipmenu[drive][i].string = t0;
620
flipmenu[drive][i].callback = (ui_callback_t)attach_disk;
621
flipmenu[drive][i].callback_data = (ui_callback_data_t)(drive + 8);
624
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
625
t5 = xmsprintf(_("Detach #%d"), drive + 8);
626
flipmenu[drive][i].string = t5;
627
flipmenu[drive][i].callback = (ui_callback_t)detach_disk;
628
flipmenu[drive][i].callback_data = (ui_callback_data_t)(drive + 8);
633
/* this won't work so far for Xaw, because the checkmarks
634
aren't updated when a menu is destroyed, as the flipmenu is
635
dynamically regenerated; The Gnome code is already fixed. */
636
memcpy(&flipmenu[drive][i], (const char *)ui_drive_settings_menu,
637
sizeof (ui_menu_entry_t));
639
/* Write protext UI controll */
640
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
641
flipmenu[drive][i].string = "*Write Protect";
643
flipmenu[drive][i].callback = toggle_AttachDevice8Readonly;
645
flipmenu[drive][i].callback = toggle_AttachDevice9Readonly;
649
fliplist_start = i; /* if we take the goto don't free anythin */
651
/* don't update menu deeply when drive has not been enabled
652
or nothing has been attached */
654
if (! ((1 << drive) & enabled_drives))
657
if (strcmp(last_attached_images[drive], "") == 0)
661
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
662
flipmenu[drive][i].string = "--";
665
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
666
util_fname_split(flip_get_next(drive + 8), &dir, &image);
667
t1 = concat(_("Next: "), image ? image : _("<empty>"), NULL);
668
flipmenu[drive][i].string = t1;
669
flipmenu[drive][i].callback = (ui_callback_t)attach_from_fliplist;
670
cb_data[drive][CBD_NEXT].unit = drive + 8;
671
cb_data[drive][CBD_NEXT].data = 1;
672
flipmenu[drive][i].callback_data =
673
(ui_callback_data_t)&(cb_data[drive][CBD_NEXT]);
680
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
681
util_fname_split(flip_get_prev(drive + 8), &dir, &image);
682
t2 = concat(_("Previous: "), image ? image : _("<empty>"), NULL);
683
flipmenu[drive][i].string = t2;
684
flipmenu[drive][i].callback = (ui_callback_t)attach_from_fliplist;
685
cb_data[drive][CBD_PREV].unit = drive + 8;
686
cb_data[drive][CBD_PREV].data = 0;
687
flipmenu[drive][i].callback_data =
688
(ui_callback_data_t)&(cb_data[drive][CBD_PREV]);
695
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
696
util_fname_split(last_attached_images[drive], &dir, &image);
697
t3 = concat(_("Add: "), image, NULL);
698
flipmenu[drive][i].string = t3;
699
flipmenu[drive][i].callback = (ui_callback_t)add2fliplist2;
700
cb_data[drive][CBD_ADD].unit = drive + 8;
701
cb_data[drive][CBD_ADD].data = (long) last_attached_images[drive];
702
flipmenu[drive][i].callback_data =
703
(ui_callback_data_t)&(cb_data[drive][CBD_ADD]);
710
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
711
util_fname_split(last_attached_images[drive], &dir, &image);
712
t4 = concat(_("Remove: "), image, NULL);
713
flipmenu[drive][i].string = t4;
714
flipmenu[drive][i].callback = (ui_callback_t)remove_from_fliplist2;
715
cb_data[drive][CBD_REMOVE].unit = drive + 8;
716
cb_data[drive][CBD_REMOVE].data = (long) last_attached_images[drive];
717
flipmenu[drive][i].callback_data =
718
(ui_callback_data_t)&(cb_data[drive][CBD_REMOVE]);
725
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
726
flipmenu[drive][i].string = "--";
729
/* Now collect current fliplist */
730
fl_iterator=flip_init_iterate(drive + 8);
732
while (fl_iterator) {
733
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
734
util_fname_split(flip_get_image(fl_iterator), &dir, &image);
735
flipmenu[drive][i].string = concat(NO_TRANS, image, NULL);
736
flipmenu[drive][i].callback =
737
(ui_callback_t)attach_from_fliplist2;
738
flipmenu[drive][i].callback_data =
739
(ui_callback_data_t)fl_iterator;
741
fl_iterator = flip_next_iterate(drive + 8);
747
if (i >= (FLIPLIST_MENU_LIMIT - 1)) {
748
/* the end delimitor must fit */
749
log_warning(LOG_DEFAULT,
750
"Number of fliplist menu entries exceeded."
751
"Cutting after %d entries.", i);
757
/* make sure the menu is well terminated */
758
memset(&(flipmenu[drive][i]), 0, sizeof(ui_menu_entry_t));
760
menuname = xmsprintf("LeftDrive%iMenu%i", drive + 8, name_count);
765
ui_destroy_drive8_menu();
766
/* FIXME: Make sure the widget is really destroyed! */
767
ui_set_drive8_menu(ui_menu_create(menuname /*"LeftDrive8Menu"*/,
768
flipmenu[drive], NULL));
772
ui_destroy_drive9_menu();
773
/* FIXME: Make sure the widget is really destroyed! */
774
ui_set_drive9_menu(ui_menu_create(menuname /*"LeftDrive9Menu"*/,
775
flipmenu[drive], NULL));
792
while (fliplist_start < i) {
793
if (flipmenu[drive][fliplist_start].string)
794
free(flipmenu[drive][fliplist_start].string);
309
interrupt_maincpu_trigger_trap(save_snapshot_trap, (void *)fname);
312
static UI_CALLBACK(events_select_dir)
315
unsigned int i, is_dir;
318
len = ioutil_maxpathlen();
319
wd = lib_malloc(len);
321
ioutil_getcwd(wd, len);
322
vsync_suspend_speed_eval();
323
if (ui_input_string(_("VICE setting"),
324
_("Select history directory"),
325
wd, len) == UI_BUTTON_OK) {
326
ioutil_stat(wd, &i, &is_dir);
328
ui_error(_("Directory not found"));
330
resources_set_value("EventSnapshotDir", (resource_value_t)wd);
336
static UI_CALLBACK(record_events_start)
338
event_record_start();
341
static UI_CALLBACK(record_events_stop)
346
static UI_CALLBACK(playback_events_start)
348
event_playback_start();
351
static UI_CALLBACK(playback_events_stop)
353
event_playback_stop();
356
static UI_CALLBACK(events_set_ms)
358
event_record_set_milestone();
361
static UI_CALLBACK(events_return_ms)
363
event_record_reset_milestone();
366
static UI_CALLBACK(sound_record)
370
const char *devicename;
372
vsync_suspend_speed_eval();
374
resources_get_value("SoundRecordDeviceName",(void *) &devicename);
375
if (devicename && !strcmp(devicename,"wav")) {
376
/* the recording is active; stop it */
377
resources_set_value("SoundRecordDeviceName", "");
378
/* ui_display_statustext("");*/
380
s = ui_select_file(_("Record sound to file"), NULL, 0, False, NULL,
381
"*.wav", &button, False, NULL);
382
if (button == UI_BUTTON_OK && s != NULL) {
383
util_add_extension(&s, "wav");
384
resources_set_value("SoundRecordDeviceArg", s);
385
resources_set_value("SoundRecordDeviceName", "wav");
386
resources_set_value("Sound", (resource_value_t)1);
388
/* ui_display_statustext("Recording wav...");*/
800
393
/* ------------------------------------------------------------------------- */
802
static ui_menu_entry_t attach_empty_disk_image_submenu[] = {
804
(ui_callback_t) attach_empty_disk, (ui_callback_data_t) 8, NULL, },
806
(ui_callback_t) attach_empty_disk, (ui_callback_data_t) 9, NULL, },
808
(ui_callback_t) attach_empty_disk, (ui_callback_data_t) 10, NULL, },
810
(ui_callback_t) attach_empty_disk, (ui_callback_data_t) 11, NULL, },
814
static ui_menu_entry_t attach_disk_image_submenu[] = {
816
(ui_callback_t) attach_disk, (ui_callback_data_t) 8, NULL,
817
XK_8, UI_HOTMOD_META },
819
(ui_callback_t) attach_disk, (ui_callback_data_t) 9, NULL,
820
XK_9, UI_HOTMOD_META },
822
(ui_callback_t) attach_disk, (ui_callback_data_t) 10, NULL,
823
XK_0, UI_HOTMOD_META },
825
(ui_callback_t) attach_disk, (ui_callback_data_t) 11, NULL,
826
XK_1, UI_HOTMOD_META },
830
static ui_menu_entry_t detach_disk_image_submenu[] = {
832
(ui_callback_t) detach_disk, (ui_callback_data_t) 8, NULL },
834
(ui_callback_t) detach_disk, (ui_callback_data_t) 9, NULL },
836
(ui_callback_t) detach_disk, (ui_callback_data_t) 10, NULL },
838
(ui_callback_t) detach_disk, (ui_callback_data_t) 11, NULL },
841
(ui_callback_t) detach_disk, (ui_callback_data_t) -1, NULL },
845
395
static ui_menu_entry_t reset_submenu[] = {
847
(ui_callback_t) reset, NULL, NULL,
397
(ui_callback_t)reset, NULL, NULL,
848
398
XK_F9, UI_HOTMOD_META },
850
(ui_callback_t) powerup_reset, NULL, NULL,
400
(ui_callback_t)powerup_reset, NULL, NULL,
851
401
XK_F12, UI_HOTMOD_META },
855
static ui_menu_entry_t flip_submenu[] = {
856
{ N_("Add current image"),
857
(ui_callback_t) add2fliplist, (ui_callback_data_t) 0, NULL,
858
XK_i, UI_HOTMOD_META },
859
{ N_("Remove current image"),
860
(ui_callback_t) remove_from_fliplist, (ui_callback_data_t) 0, NULL,
861
XK_k, UI_HOTMOD_META },
862
{ N_("Attach next image"),
863
(ui_callback_t) attach_from_fliplist3, (ui_callback_data_t) 1, NULL,
864
XK_n, UI_HOTMOD_META },
865
{ N_("Attach previous image"),
866
(ui_callback_t) attach_from_fliplist3, (ui_callback_data_t) 0, NULL,
867
XK_N, UI_HOTMOD_META },
871
ui_menu_entry_t ui_disk_commands_menu[] = {
872
{ N_("Attach a disk image"),
873
NULL, NULL, attach_disk_image_submenu },
874
{ N_("Create and attach an empty disk"),
875
NULL, NULL, attach_empty_disk_image_submenu },
876
{ N_("Detach disk image"),
877
NULL, NULL, detach_disk_image_submenu },
878
{ N_("Fliplist for drive #8"),
879
NULL, NULL, flip_submenu },
883
ui_menu_entry_t ui_tape_commands_menu[] = {
884
{ N_("Attach a tape image..."),
885
(ui_callback_t) attach_tape, NULL, NULL,
886
XK_t, UI_HOTMOD_META},
887
{ N_("Detach tape image"),
888
(ui_callback_t) detach_tape, NULL, NULL },
892
ui_menu_entry_t ui_smart_attach_commands_menu[] = {
893
{ N_("Smart-attach disk/tape..."),
894
(ui_callback_t) smart_attach, NULL, NULL,
895
XK_a, UI_HOTMOD_META },
404
(ui_callback_t)drive_reset, (ui_callback_data_t)0, NULL },
406
(ui_callback_t)drive_reset, (ui_callback_data_t)1, NULL },
408
(ui_callback_t)drive_reset, (ui_callback_data_t)2, NULL },
410
(ui_callback_t)drive_reset, (ui_callback_data_t)3, NULL },
899
414
ui_menu_entry_t ui_directory_commands_menu[] = {
900
415
{ N_("Change working directory..."),
901
(ui_callback_t) change_working_directory, NULL, NULL },
416
(ui_callback_t)change_working_directory, NULL, NULL },
420
UI_MENU_DEFINE_RADIO(EventStartMode)
422
static ui_menu_entry_t set_event_start_mode_submenu[] = {
423
{ N_("*Save new snapshot"), (ui_callback_t)radio_EventStartMode,
424
(ui_callback_data_t)EVENT_START_MODE_FILE_SAVE, NULL },
425
{ N_("*Load existing snapshot"), (ui_callback_t)radio_EventStartMode,
426
(ui_callback_data_t)EVENT_START_MODE_FILE_LOAD, NULL },
427
{ N_("*Start with reset"), (ui_callback_t)radio_EventStartMode,
428
(ui_callback_data_t)EVENT_START_MODE_RESET, NULL },
429
{ N_("*Overwrite running playback"), (ui_callback_t)radio_EventStartMode,
430
(ui_callback_data_t)EVENT_START_MODE_PLAYBACK, NULL },
905
434
ui_menu_entry_t ui_snapshot_commands_submenu[] = {
906
435
{ N_("Load snapshot..."),
907
(ui_callback_t) load_snapshot, NULL, NULL,
436
(ui_callback_t)load_snapshot, NULL, NULL,
908
437
XK_l, UI_HOTMOD_META },
909
438
{ N_("Save snapshot..."),
910
(ui_callback_t) save_snapshot, NULL, NULL,
439
(ui_callback_t)save_snapshot, NULL, NULL,
911
440
XK_s, UI_HOTMOD_META },
913
442
{ N_("Quickload snapshot"),
914
(ui_callback_t) load_quicksnap, NULL, NULL,
443
(ui_callback_t)load_quicksnap, NULL, NULL,
915
444
XK_F10, UI_HOTMOD_META },
916
445
{ N_("Quicksave snapshot"),
917
(ui_callback_t) save_quicksnap, NULL, NULL,
446
(ui_callback_t)save_quicksnap, NULL, NULL,
918
447
XK_F11, UI_HOTMOD_META },
449
{ N_("Select history directory"),
450
(ui_callback_t)events_select_dir, NULL, NULL },
451
{ N_("Start recording events"),
452
(ui_callback_t)record_events_start, NULL, NULL },
453
{ N_("Stop recording events"),
454
(ui_callback_t)record_events_stop, NULL, NULL },
455
{ N_("Start playing back events"),
456
(ui_callback_t)playback_events_start, NULL, NULL },
457
{ N_("Stop playing back events"),
458
(ui_callback_t)playback_events_stop, NULL, NULL },
459
{ N_("Set recording milestone"),
460
(ui_callback_t)events_set_ms, NULL, NULL, XK_e, UI_HOTMOD_META },
461
{ N_("Return to milestone"),
462
(ui_callback_t)events_return_ms, NULL, NULL, XK_u, UI_HOTMOD_META },
464
{ N_("Recording start mode"),
465
NULL, NULL, set_event_start_mode_submenu },