1 /* ui.c: User interface routines, but those which are independent of any UI
2 Copyright (c) 2002-2015 Philip Kendall
3 Copyright (c) 2016 Sergio Baldoví
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 Author contact information:
20
21 E-mail: philip-fuse@shadowmagic.org.uk
22
23 */
24
25 #include <config.h>
26
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include <libspectrum.h>
33
34 #include "fuse.h"
35 #include "peripherals/if1.h"
36 #include "peripherals/kempmouse.h"
37 #include "settings.h"
38 #include "tape.h"
39 #include "ui/ui.h"
40 #include "ui/uimedia.h"
41 #include "ui/widget/widget.h"
42
43 #define MESSAGE_MAX_LENGTH 256
44
45 /* We don't start in a widget */
46 int ui_widget_level = -1;
47
48 static char last_message[ MESSAGE_MAX_LENGTH ] = "";
49 static size_t frames_since_last_message = 0;
50
51 static int
52 print_error_to_stderr( ui_error_level severity, const char *message );
53
54 int
ui_error(ui_error_level severity,const char * format,...)55 ui_error( ui_error_level severity, const char *format, ... )
56 {
57 int error;
58 va_list ap;
59
60 va_start( ap, format );
61 error = ui_verror( severity, format, ap );
62 va_end( ap );
63
64 return error;
65 }
66
67 int
ui_verror(ui_error_level severity,const char * format,va_list ap)68 ui_verror( ui_error_level severity, const char *format, va_list ap )
69 {
70 char message[ MESSAGE_MAX_LENGTH ];
71
72 vsnprintf( message, MESSAGE_MAX_LENGTH, format, ap );
73
74 /* Skip the message if the same message was displayed recently */
75 if( frames_since_last_message < 50 && !strcmp( message, last_message ) ) {
76 frames_since_last_message = 0;
77 return 0;
78 }
79
80 /* And store the 'last message' */
81 strncpy( last_message, message, MESSAGE_MAX_LENGTH );
82 last_message[ MESSAGE_MAX_LENGTH - 1 ] = '\0';
83
84 print_error_to_stderr( severity, message );
85
86 /* Do any UI-specific bits as well */
87 ui_error_specific( severity, message );
88
89 return 0;
90 }
91
92 ui_confirm_save_t
ui_confirm_save(const char * format,...)93 ui_confirm_save( const char *format, ... )
94 {
95 va_list ap;
96 char message[ MESSAGE_MAX_LENGTH ];
97 ui_confirm_save_t confirm;
98
99 va_start( ap, format );
100
101 vsnprintf( message, MESSAGE_MAX_LENGTH, format, ap );
102 confirm = ui_confirm_save_specific( message );
103
104 va_end( ap );
105
106 return confirm;
107 }
108
109 static int
print_error_to_stderr(ui_error_level severity,const char * message)110 print_error_to_stderr( ui_error_level severity, const char *message )
111 {
112 /* Print the error to stderr if it's more significant than just
113 informational */
114 if( severity > UI_ERROR_INFO ) {
115
116 /* For the fb and svgalib UIs, we don't want to write to stderr if
117 it's a terminal, as it's then likely to be what we're currently
118 using for graphics output, and writing text to it isn't a good
119 idea. Things are OK if we're exiting though */
120 #if defined( UI_FB ) || defined( UI_SVGA )
121 if( isatty( STDERR_FILENO ) && !fuse_exiting ) return 1;
122 #endif /* #if defined( UI_FB ) || defined( UI_SVGA ) */
123
124 fprintf( stderr, "%s: ", fuse_progname );
125
126 switch( severity ) {
127
128 case UI_ERROR_INFO: break; /* Shouldn't happen */
129
130 case UI_ERROR_WARNING: fprintf( stderr, "warning: " ); break;
131 case UI_ERROR_ERROR: fprintf( stderr, "error: " ); break;
132 }
133
134 fprintf( stderr, "%s\n", message );
135 }
136
137 return 0;
138 }
139
140 libspectrum_error
ui_libspectrum_error(libspectrum_error error GCC_UNUSED,const char * format,va_list ap)141 ui_libspectrum_error( libspectrum_error error GCC_UNUSED, const char *format,
142 va_list ap )
143 {
144 char new_format[ 257 ];
145 snprintf( new_format, 256, "libspectrum: %s", format );
146
147 ui_verror( UI_ERROR_ERROR, new_format, ap );
148
149 return LIBSPECTRUM_ERROR_NONE;
150 }
151
152 void
ui_error_frame(void)153 ui_error_frame( void )
154 {
155 frames_since_last_message++;
156 }
157
158 int ui_mouse_present = 0;
159 int ui_mouse_grabbed = 0;
160 static int mouse_grab_suspended = 0;
161
162 void
ui_mouse_button(int button,int down)163 ui_mouse_button( int button, int down )
164 {
165 int kempston_button = !settings_current.mouse_swap_buttons;
166
167 if( !ui_mouse_grabbed && !mouse_grab_suspended ) button = 2;
168
169 /* Possibly we'll end up handling _more_ than one mouse interface... */
170 switch( button ) {
171 case 1:
172 if( ui_mouse_grabbed ) kempmouse_update( 0, 0, kempston_button, down );
173 break;
174 case 3:
175 if( ui_mouse_grabbed ) kempmouse_update( 0, 0, !kempston_button, down );
176 break;
177 case 2:
178 if( ui_mouse_present && settings_current.kempston_mouse
179 && !down && !mouse_grab_suspended )
180 ui_mouse_grabbed =
181 ui_mouse_grabbed ? ui_mouse_release( 1 ) : ui_mouse_grab( 0 );
182 break;
183 }
184 }
185
186 void
ui_mouse_motion(int x,int y)187 ui_mouse_motion( int x, int y )
188 {
189 if( ui_mouse_grabbed ) kempmouse_update( x, y, -1, 0 );
190 }
191
192 void
ui_mouse_suspend(void)193 ui_mouse_suspend( void )
194 {
195 mouse_grab_suspended = ui_mouse_grabbed ? 2 : 1;
196
197 if( ui_mouse_grabbed )
198 ui_mouse_grabbed = ui_mouse_release( 1 );
199 }
200
201 void
ui_mouse_resume(void)202 ui_mouse_resume( void )
203 {
204 if( mouse_grab_suspended == 2) ui_mouse_grabbed = ui_mouse_grab( 0 );
205 mouse_grab_suspended = 0;
206 }
207
208 struct menu_item_entries {
209 ui_menu_item item;
210 const char *string1;
211 const char *string2; int string2_inverted;
212 const char *string3; int string3_inverted;
213 const char *string4; int string4_inverted;
214 const char *string5; int string5_inverted;
215 const char *string6; int string6_inverted;
216 const char *string7; int string7_inverted;
217 };
218
219 static const struct menu_item_entries menu_item_lookup[] = {
220
221 { UI_MENU_ITEM_FILE_SVG_CAPTURE,
222 "/File/Scalable Vector Graphics/Stop capture",
223 "/File/Scalable Vector Graphics/Start capture in dot mode...", 1,
224 "/File/Scalable Vector Graphics/Start capture in line mode...", 1
225 },
226
227 { UI_MENU_ITEM_FILE_MOVIE_RECORDING, "/File/Movie/Stop",
228 "/File/Movie/Pause", 0,
229 "/File/Movie/Continue", 0,
230 "/File/Movie/Record...", 1,
231 "/File/Movie/Record from RZX...", 1
232 },
233
234 { UI_MENU_ITEM_FILE_MOVIE_PAUSE, "/File/Movie/Pause",
235 "/File/Movie/Continue", 1,
236 },
237
238 { UI_MENU_ITEM_MACHINE_PROFILER, "/Machine/Profiler/Stop",
239 "/Machine/Profiler/Start", 1 },
240
241 { UI_MENU_ITEM_MACHINE_MULTIFACE, "/Machine/Multiface Red Button" },
242
243 { UI_MENU_ITEM_MACHINE_DIDAKTIK80_SNAP, "/Machine/Didaktik SNAP" },
244
245 { UI_MENU_ITEM_MEDIA_CARTRIDGE, "/Media/Cartridge" },
246
247 { UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK, "/Media/Cartridge/Timex Dock" },
248
249 { UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK_EJECT,
250 "/Media/Cartridge/Timex Dock/Eject" },
251
252 { UI_MENU_ITEM_MEDIA_IF1, "/Media/Interface 1" },
253
254 { UI_MENU_ITEM_MEDIA_IF1_M1_EJECT,
255 "/Media/Interface 1/Microdrive 1/Eject",
256 "/Media/Interface 1/Microdrive 1/Save As...", 0,
257 "/Media/Interface 1/Microdrive 1/Save", 0,
258 "/Media/Interface 1/Microdrive 1/Write protect", 0 },
259
260 { UI_MENU_ITEM_MEDIA_IF1_M1_WP_SET,
261 "/Media/Interface 1/Microdrive 1/Write protect/Enable",
262 "/Media/Interface 1/Microdrive 1/Write protect/Disable", 1 },
263
264 { UI_MENU_ITEM_MEDIA_IF1_M2_EJECT,
265 "/Media/Interface 1/Microdrive 2/Eject",
266 "/Media/Interface 1/Microdrive 2/Save As...", 0,
267 "/Media/Interface 1/Microdrive 2/Save", 0,
268 "/Media/Interface 1/Microdrive 2/Write protect", 0 },
269
270 { UI_MENU_ITEM_MEDIA_IF1_M2_WP_SET,
271 "/Media/Interface 1/Microdrive 2/Write protect/Enable",
272 "/Media/Interface 1/Microdrive 2/Write protect/Disable", 1 },
273
274 { UI_MENU_ITEM_MEDIA_IF1_M3_EJECT,
275 "/Media/Interface 1/Microdrive 3/Eject",
276 "/Media/Interface 1/Microdrive 3/Save As...", 0,
277 "/Media/Interface 1/Microdrive 3/Save", 0,
278 "/Media/Interface 1/Microdrive 3/Write protect", 0 },
279
280 { UI_MENU_ITEM_MEDIA_IF1_M3_WP_SET,
281 "/Media/Interface 1/Microdrive 3/Write protect/Enable",
282 "/Media/Interface 1/Microdrive 3/Write protect/Disable", 1 },
283
284 { UI_MENU_ITEM_MEDIA_IF1_M4_EJECT,
285 "/Media/Interface 1/Microdrive 4/Eject",
286 "/Media/Interface 1/Microdrive 4/Save As...", 0,
287 "/Media/Interface 1/Microdrive 4/Save", 0,
288 "/Media/Interface 1/Microdrive 4/Write protect", 0 },
289
290 { UI_MENU_ITEM_MEDIA_IF1_M4_WP_SET,
291 "/Media/Interface 1/Microdrive 4/Write protect/Enable",
292 "/Media/Interface 1/Microdrive 4/Write protect/Disable", 1 },
293
294 { UI_MENU_ITEM_MEDIA_IF1_M5_EJECT,
295 "/Media/Interface 1/Microdrive 5/Eject",
296 "/Media/Interface 1/Microdrive 5/Save As...", 0,
297 "/Media/Interface 1/Microdrive 5/Save", 0,
298 "/Media/Interface 1/Microdrive 5/Write protect", 0 },
299
300 { UI_MENU_ITEM_MEDIA_IF1_M5_WP_SET,
301 "/Media/Interface 1/Microdrive 5/Write protect/Enable",
302 "/Media/Interface 1/Microdrive 5/Write protect/Disable", 1 },
303
304 { UI_MENU_ITEM_MEDIA_IF1_M6_EJECT,
305 "/Media/Interface 1/Microdrive 6/Eject",
306 "/Media/Interface 1/Microdrive 6/Save As...", 0,
307 "/Media/Interface 1/Microdrive 6/Save", 0,
308 "/Media/Interface 1/Microdrive 6/Write protect", 0 },
309
310 { UI_MENU_ITEM_MEDIA_IF1_M6_WP_SET,
311 "/Media/Interface 1/Microdrive 6/Write protect/Enable",
312 "/Media/Interface 1/Microdrive 6/Write protect/Disable", 1 },
313
314 { UI_MENU_ITEM_MEDIA_IF1_M7_EJECT,
315 "/Media/Interface 1/Microdrive 7/Eject",
316 "/Media/Interface 1/Microdrive 7/Save As...", 0,
317 "/Media/Interface 1/Microdrive 7/Save", 0,
318 "/Media/Interface 1/Microdrive 7/Write protect", 0 },
319
320 { UI_MENU_ITEM_MEDIA_IF1_M7_WP_SET,
321 "/Media/Interface 1/Microdrive 7/Write protect/Enable",
322 "/Media/Interface 1/Microdrive 7/Write protect/Disable", 1 },
323
324 { UI_MENU_ITEM_MEDIA_IF1_M8_EJECT,
325 "/Media/Interface 1/Microdrive 8/Eject",
326 "/Media/Interface 1/Microdrive 8/Save As...", 0,
327 "/Media/Interface 1/Microdrive 8/Save", 0,
328 "/Media/Interface 1/Microdrive 8/Write protect", 0 },
329
330 { UI_MENU_ITEM_MEDIA_IF1_M8_WP_SET,
331 "/Media/Interface 1/Microdrive 8/Write protect/Enable",
332 "/Media/Interface 1/Microdrive 8/Write protect/Disable", 1 },
333
334 { UI_MENU_ITEM_MEDIA_IF1_RS232_UNPLUG_R,
335 "/Media/Interface 1/RS232/Unplug RxD" },
336
337 { UI_MENU_ITEM_MEDIA_IF1_RS232_UNPLUG_T,
338 "/Media/Interface 1/RS232/Unplug TxD" },
339
340 { UI_MENU_ITEM_MEDIA_IF1_SNET_UNPLUG,
341 "/Media/Interface 1/Sinclair NET/Unplug" },
342
343 { UI_MENU_ITEM_MEDIA_CARTRIDGE_IF2, "/Media/Cartridge/Interface 2" },
344
345 { UI_MENU_ITEM_MEDIA_CARTRIDGE_IF2_EJECT,
346 "/Media/Cartridge/Interface 2/Eject" },
347
348 { UI_MENU_ITEM_MEDIA_DISK, "/Media/Disk" },
349
350 { UI_MENU_ITEM_MEDIA_DISK_PLUS3, "/Media/Disk/+3" },
351
352 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_A_EJECT,
353 "/Media/Disk/+3/Drive A:/Eject",
354 "/Media/Disk/+3/Drive A:/Save As...", 0,
355 "/Media/Disk/+3/Drive A:/Save", 0,
356 "/Media/Disk/+3/Drive A:/Flip disk", 0,
357 "/Media/Disk/+3/Drive A:/Write protect", 0 },
358
359 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_A_FLIP_SET,
360 "/Media/Disk/+3/Drive A:/Flip disk/Turn upside down",
361 "/Media/Disk/+3/Drive A:/Flip disk/Turn back", 1 },
362
363 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_A_WP_SET,
364 "/Media/Disk/+3/Drive A:/Write protect/Enable",
365 "/Media/Disk/+3/Drive A:/Write protect/Disable", 1 },
366
367 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_B, "/Media/Disk/+3/Drive B:" },
368
369 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_B_EJECT,
370 "/Media/Disk/+3/Drive B:/Eject",
371 "/Media/Disk/+3/Drive B:/Save As...", 0,
372 "/Media/Disk/+3/Drive B:/Save", 0,
373 "/Media/Disk/+3/Drive B:/Flip disk", 0,
374 "/Media/Disk/+3/Drive B:/Write protect", 0 },
375
376 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_B_FLIP_SET,
377 "/Media/Disk/+3/Drive B:/Flip disk/Turn upside down",
378 "/Media/Disk/+3/Drive B:/Flip disk/Turn back", 1 },
379
380 { UI_MENU_ITEM_MEDIA_DISK_PLUS3_B_WP_SET,
381 "/Media/Disk/+3/Drive B:/Write protect/Enable",
382 "/Media/Disk/+3/Drive B:/Write protect/Disable", 1 },
383
384 { UI_MENU_ITEM_MEDIA_DISK_BETA, "/Media/Disk/Beta" },
385
386 { UI_MENU_ITEM_MEDIA_DISK_BETA_A, "/Media/Disk/Beta/Drive A:" },
387
388 { UI_MENU_ITEM_MEDIA_DISK_BETA_A_EJECT,
389 "/Media/Disk/Beta/Drive A:/Eject",
390 "/Media/Disk/Beta/Drive A:/Save As...", 0,
391 "/Media/Disk/Beta/Drive A:/Save", 0,
392 "/Media/Disk/Beta/Drive A:/Flip disk", 0,
393 "/Media/Disk/Beta/Drive A:/Write protect", 0 },
394
395 { UI_MENU_ITEM_MEDIA_DISK_BETA_A_FLIP_SET,
396 "/Media/Disk/Beta/Drive A:/Flip disk/Turn upside down",
397 "/Media/Disk/Beta/Drive A:/Flip disk/Turn back", 1 },
398
399 { UI_MENU_ITEM_MEDIA_DISK_BETA_A_WP_SET,
400 "/Media/Disk/Beta/Drive A:/Write protect/Enable",
401 "/Media/Disk/Beta/Drive A:/Write protect/Disable", 1 },
402
403 { UI_MENU_ITEM_MEDIA_DISK_BETA_B, "/Media/Disk/Beta/Drive B:" },
404
405 { UI_MENU_ITEM_MEDIA_DISK_BETA_B_EJECT,
406 "/Media/Disk/Beta/Drive B:/Eject",
407 "/Media/Disk/Beta/Drive B:/Save As...", 0,
408 "/Media/Disk/Beta/Drive B:/Save", 0,
409 "/Media/Disk/Beta/Drive B:/Flip disk", 0,
410 "/Media/Disk/Beta/Drive B:/Write protect", 0 },
411
412 { UI_MENU_ITEM_MEDIA_DISK_BETA_B_FLIP_SET,
413 "/Media/Disk/Beta/Drive B:/Flip disk/Turn upside down",
414 "/Media/Disk/Beta/Drive B:/Flip disk/Turn back", 1 },
415
416 { UI_MENU_ITEM_MEDIA_DISK_BETA_B_WP_SET,
417 "/Media/Disk/Beta/Drive B:/Write protect/Enable",
418 "/Media/Disk/Beta/Drive B:/Write protect/Disable", 1 },
419
420 { UI_MENU_ITEM_MEDIA_DISK_BETA_C, "/Media/Disk/Beta/Drive C:" },
421
422 { UI_MENU_ITEM_MEDIA_DISK_BETA_C_EJECT,
423 "/Media/Disk/Beta/Drive C:/Eject",
424 "/Media/Disk/Beta/Drive C:/Save As...", 0,
425 "/Media/Disk/Beta/Drive C:/Save", 0,
426 "/Media/Disk/Beta/Drive C:/Flip disk", 0,
427 "/Media/Disk/Beta/Drive C:/Write protect", 0 },
428
429 { UI_MENU_ITEM_MEDIA_DISK_BETA_C_FLIP_SET,
430 "/Media/Disk/Beta/Drive C:/Flip disk/Turn upside down",
431 "/Media/Disk/Beta/Drive C:/Flip disk/Turn back", 1 },
432
433 { UI_MENU_ITEM_MEDIA_DISK_BETA_C_WP_SET,
434 "/Media/Disk/Beta/Drive C:/Write protect/Enable",
435 "/Media/Disk/Beta/Drive C:/Write protect/Disable", 1 },
436
437 { UI_MENU_ITEM_MEDIA_DISK_BETA_D, "/Media/Disk/Beta/Drive D:" },
438
439 { UI_MENU_ITEM_MEDIA_DISK_BETA_D_EJECT,
440 "/Media/Disk/Beta/Drive D:/Eject",
441 "/Media/Disk/Beta/Drive D:/Save As...", 0,
442 "/Media/Disk/Beta/Drive D:/Save", 0,
443 "/Media/Disk/Beta/Drive D:/Flip disk", 0,
444 "/Media/Disk/Beta/Drive D:/Write protect", 0 },
445
446 { UI_MENU_ITEM_MEDIA_DISK_BETA_D_FLIP_SET,
447 "/Media/Disk/Beta/Drive D:/Flip disk/Turn upside down",
448 "/Media/Disk/Beta/Drive D:/Flip disk/Turn back", 1 },
449
450 { UI_MENU_ITEM_MEDIA_DISK_BETA_D_WP_SET,
451 "/Media/Disk/Beta/Drive D:/Write protect/Enable",
452 "/Media/Disk/Beta/Drive D:/Write protect/Disable", 1 },
453
454 { UI_MENU_ITEM_MEDIA_DISK_PLUSD, "/Media/Disk/+D" },
455
456 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_1, "/Media/Disk/+D/Drive 1" },
457
458 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_1_EJECT,
459 "/Media/Disk/+D/Drive 1/Eject",
460 "/Media/Disk/+D/Drive 1/Save As...", 0,
461 "/Media/Disk/+D/Drive 1/Save", 0,
462 "/Media/Disk/+D/Drive 1/Flip disk", 0,
463 "/Media/Disk/+D/Drive 1/Write protect", 0 },
464
465 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_1_FLIP_SET,
466 "/Media/Disk/+D/Drive 1/Flip disk/Turn upside down",
467 "/Media/Disk/+D/Drive 1/Flip disk/Turn back", 1 },
468
469 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_1_WP_SET,
470 "/Media/Disk/+D/Drive 1/Write protect/Enable",
471 "/Media/Disk/+D/Drive 1/Write protect/Disable", 1 },
472
473 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_2, "/Media/Disk/+D/Drive 2" },
474
475 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_2_EJECT,
476 "/Media/Disk/+D/Drive 2/Eject",
477 "/Media/Disk/+D/Drive 2/Save As...", 0,
478 "/Media/Disk/+D/Drive 2/Save", 0,
479 "/Media/Disk/+D/Drive 2/Flip disk", 0,
480 "/Media/Disk/+D/Drive 2/Write protect", 0 },
481
482 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_2_FLIP_SET,
483 "/Media/Disk/+D/Drive 2/Flip disk/Turn upside down",
484 "/Media/Disk/+D/Drive 2/Flip disk/Turn back", 1 },
485
486 { UI_MENU_ITEM_MEDIA_DISK_PLUSD_2_WP_SET,
487 "/Media/Disk/+D/Drive 2/Write protect/Enable",
488 "/Media/Disk/+D/Drive 2/Write protect/Disable", 1 },
489
490 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK, "/Media/Disk/Didaktik 80" },
491
492 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_A, "/Media/Disk/Didaktik 80/Drive A" },
493
494 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_A_EJECT,
495 "/Media/Disk/Didaktik 80/Drive A/Eject",
496 "/Media/Disk/Didaktik 80/Drive A/Save As...", 0,
497 "/Media/Disk/Didaktik 80/Drive A/Save", 0,
498 "/Media/Disk/Didaktik 80/Drive A/Flip disk", 0,
499 "/Media/Disk/Didaktik 80/Drive A/Write protect", 0 },
500
501 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_A_FLIP_SET,
502 "/Media/Disk/Didaktik 80/Drive A/Flip disk/Turn upside down",
503 "/Media/Disk/Didaktik 80/Drive A/Flip disk/Turn back", 1 },
504
505 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_A_WP_SET,
506 "/Media/Disk/Didaktik 80/Drive A/Write protect/Enable",
507 "/Media/Disk/Didaktik 80/Drive A/Write protect/Disable", 1 },
508
509 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_B, "/Media/Disk/Didaktik 80/Drive B" },
510
511 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_B_EJECT,
512 "/Media/Disk/Didaktik 80/Drive B/Eject",
513 "/Media/Disk/Didaktik 80/Drive B/Save As...", 0,
514 "/Media/Disk/Didaktik 80/Drive B/Save", 0,
515 "/Media/Disk/Didaktik 80/Drive B/Flip disk", 0,
516 "/Media/Disk/Didaktik 80/Drive B/Write protect", 0 },
517
518 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_B_FLIP_SET,
519 "/Media/Disk/Didaktik 80/Drive B/Flip disk/Turn upside down",
520 "/Media/Disk/Didaktik 80/Drive B/Flip disk/Turn back", 1 },
521
522 { UI_MENU_ITEM_MEDIA_DISK_DIDAKTIK_B_WP_SET,
523 "/Media/Disk/Didaktik 80/Drive B/Write protect/Enable",
524 "/Media/Disk/Didaktik 80/Drive B/Write protect/Disable", 1 },
525
526 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE, "/Media/Disk/DISCiPLE" },
527
528 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_1, "/Media/Disk/DISCiPLE/Drive 1" },
529
530 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_1_EJECT,
531 "/Media/Disk/DISCiPLE/Drive 1/Eject",
532 "/Media/Disk/DISCiPLE/Drive 1/Save As...", 0,
533 "/Media/Disk/DISCiPLE/Drive 1/Save", 0,
534 "/Media/Disk/DISCiPLE/Drive 1/Flip disk", 0,
535 "/Media/Disk/DISCiPLE/Drive 1/Write protect", 0 },
536
537 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_1_FLIP_SET,
538 "/Media/Disk/DISCiPLE/Drive 1/Flip disk/Turn upside down",
539 "/Media/Disk/DISCiPLE/Drive 1/Flip disk/Turn back", 1 },
540
541 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_1_WP_SET,
542 "/Media/Disk/DISCiPLE/Drive 1/Write protect/Enable",
543 "/Media/Disk/DISCiPLE/Drive 1/Write protect/Disable", 1 },
544
545 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_2, "/Media/Disk/DISCiPLE/Drive 2" },
546
547 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_2_EJECT,
548 "/Media/Disk/DISCiPLE/Drive 2/Eject",
549 "/Media/Disk/DISCiPLE/Drive 2/Save As...", 0,
550 "/Media/Disk/DISCiPLE/Drive 2/Save", 0,
551 "/Media/Disk/DISCiPLE/Drive 2/Flip disk", 0,
552 "/Media/Disk/DISCiPLE/Drive 2/Write protect", 0 },
553
554 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_2_FLIP_SET,
555 "/Media/Disk/DISCiPLE/Drive 2/Flip disk/Turn upside down",
556 "/Media/Disk/DISCiPLE/Drive 2/Flip disk/Turn back", 1 },
557
558 { UI_MENU_ITEM_MEDIA_DISK_DISCIPLE_2_WP_SET,
559 "/Media/Disk/DISCiPLE/Drive 2/Write protect/Enable",
560 "/Media/Disk/DISCiPLE/Drive 2/Write protect/Disable", 1 },
561
562 { UI_MENU_ITEM_MEDIA_DISK_OPUS, "/Media/Disk/Opus" },
563
564 { UI_MENU_ITEM_MEDIA_DISK_OPUS_1, "/Media/Disk/Opus/Drive 1" },
565
566 { UI_MENU_ITEM_MEDIA_DISK_OPUS_1_EJECT,
567 "/Media/Disk/Opus/Drive 1/Eject",
568 "/Media/Disk/Opus/Drive 1/Save As...", 0,
569 "/Media/Disk/Opus/Drive 1/Save", 0,
570 "/Media/Disk/Opus/Drive 1/Flip disk", 0,
571 "/Media/Disk/Opus/Drive 1/Write protect", 0 },
572
573 { UI_MENU_ITEM_MEDIA_DISK_OPUS_1_FLIP_SET,
574 "/Media/Disk/Opus/Drive 1/Flip disk/Turn upside down",
575 "/Media/Disk/Opus/Drive 1/Flip disk/Turn back", 1 },
576
577 { UI_MENU_ITEM_MEDIA_DISK_OPUS_1_WP_SET,
578 "/Media/Disk/Opus/Drive 1/Write protect/Enable",
579 "/Media/Disk/Opus/Drive 1/Write protect/Disable", 1 },
580
581 { UI_MENU_ITEM_MEDIA_DISK_OPUS_2, "/Media/Disk/Opus/Drive 2" },
582
583 { UI_MENU_ITEM_MEDIA_DISK_OPUS_2_EJECT,
584 "/Media/Disk/Opus/Drive 2/Eject",
585 "/Media/Disk/Opus/Drive 2/Save As...", 0,
586 "/Media/Disk/Opus/Drive 2/Save", 0,
587 "/Media/Disk/Opus/Drive 2/Flip disk", 0,
588 "/Media/Disk/Opus/Drive 2/Write protect", 0 },
589
590 { UI_MENU_ITEM_MEDIA_DISK_OPUS_2_FLIP_SET,
591 "/Media/Disk/Opus/Drive 2/Flip disk/Turn upside down",
592 "/Media/Disk/Opus/Drive 2/Flip disk/Turn back", 1 },
593
594 { UI_MENU_ITEM_MEDIA_DISK_OPUS_2_WP_SET,
595 "/Media/Disk/Opus/Drive 2/Write protect/Enable",
596 "/Media/Disk/Opus/Drive 2/Write protect/Disable", 1 },
597
598 { UI_MENU_ITEM_MEDIA_IDE, "/Media/IDE" },
599
600 { UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT, "/Media/IDE/Simple 8-bit" },
601
602 { UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT_MASTER_EJECT,
603 "/Media/IDE/Simple 8-bit/Master/Commit",
604 "/Media/IDE/Simple 8-bit/Master/Eject", 0 },
605
606 { UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT_SLAVE_EJECT,
607 "/Media/IDE/Simple 8-bit/Slave/Commit",
608 "/Media/IDE/Simple 8-bit/Slave/Eject", 0 },
609
610 { UI_MENU_ITEM_MEDIA_IDE_ZXATASP, "/Media/IDE/ZXATASP" },
611
612 { UI_MENU_ITEM_MEDIA_IDE_ZXATASP_MASTER_EJECT,
613 "/Media/IDE/ZXATASP/Master/Commit",
614 "/Media/IDE/ZXATASP/Master/Eject", 0 },
615
616 { UI_MENU_ITEM_MEDIA_IDE_ZXATASP_SLAVE_EJECT,
617 "/Media/IDE/ZXATASP/Slave/Commit",
618 "/Media/IDE/ZXATASP/Slave/Eject", 0 },
619
620 { UI_MENU_ITEM_MEDIA_IDE_ZXCF, "/Media/IDE/ZXCF CompactFlash" },
621
622 { UI_MENU_ITEM_MEDIA_IDE_ZXCF_EJECT,
623 "/Media/IDE/ZXCF CompactFlash/Commit",
624 "/Media/IDE/ZXCF CompactFlash/Eject", 0 },
625
626 { UI_MENU_ITEM_MEDIA_IDE_DIVIDE, "/Media/IDE/DivIDE" },
627
628 { UI_MENU_ITEM_MEDIA_IDE_DIVIDE_MASTER_EJECT,
629 "/Media/IDE/DivIDE/Master/Commit",
630 "/Media/IDE/DivIDE/Master/Eject", 0 },
631
632 { UI_MENU_ITEM_MEDIA_IDE_DIVIDE_SLAVE_EJECT,
633 "/Media/IDE/DivIDE/Slave/Commit",
634 "/Media/IDE/DivIDE/Slave/Eject", 0 },
635
636 { UI_MENU_ITEM_MEDIA_IDE_DIVMMC, "/Media/IDE/DivMMC" },
637
638 { UI_MENU_ITEM_MEDIA_IDE_DIVMMC_EJECT,
639 "/Media/IDE/DivMMC/Commit",
640 "/Media/IDE/DivMMC/Eject", 0 },
641
642 { UI_MENU_ITEM_MEDIA_IDE_ZXMMC, "/Media/IDE/ZXMMC" },
643
644 { UI_MENU_ITEM_MEDIA_IDE_ZXMMC_EJECT,
645 "/Media/IDE/ZXMMC/Commit",
646 "/Media/IDE/ZXMMC/Eject", 0 },
647
648 { UI_MENU_ITEM_RECORDING,
649 "/File/Recording/Stop",
650 "/File/Recording/Record...", 1,
651 "/File/Recording/Record from snapshot...", 1,
652 "/File/Recording/Continue recording...", 1,
653 "/File/Recording/Play...", 1,
654 "/File/Recording/Finalise...", 1 },
655
656 { UI_MENU_ITEM_RECORDING_ROLLBACK,
657 "/File/Recording/Insert snapshot",
658 "/File/Recording/Rollback", 0,
659 "/File/Recording/Rollback to...", 0 },
660
661 { UI_MENU_ITEM_AY_LOGGING,
662 "/File/AY Logging/Stop",
663 "/File/AY Logging/Record...", 1, },
664
665 { UI_MENU_ITEM_TAPE_RECORDING,
666 "/Media/Tape/Record Stop",
667 "/Media/Tape/Record Start", 1,
668 "/Media/Tape/Open...", 1,
669 "/Media/Tape/Play", 1,
670 "/Media/Tape/Rewind", 1,
671 "/Media/Tape/Clear", 1,
672 "/Media/Tape/Write...", 1 },
673
674 { UI_MENU_ITEM_TAPE_RECORDING, NULL }, /* End marker */
675
676 };
677
678 int
ui_menu_activate(ui_menu_item item,int active)679 ui_menu_activate( ui_menu_item item, int active )
680 {
681 const struct menu_item_entries *ptr;
682
683 for( ptr = menu_item_lookup; ptr->string1; ptr++ ) {
684
685 if( item == ptr->item ) {
686 ui_menu_item_set_active( ptr->string1, active );
687 if( ptr->string2 )
688 ui_menu_item_set_active( ptr->string2,
689 ptr->string2_inverted ? !active : active );
690 if( ptr->string3 )
691 ui_menu_item_set_active( ptr->string3,
692 ptr->string3_inverted ? !active : active );
693 if( ptr->string4 )
694 ui_menu_item_set_active( ptr->string4,
695 ptr->string4_inverted ? !active : active );
696 if( ptr->string5 )
697 ui_menu_item_set_active( ptr->string5,
698 ptr->string5_inverted ? !active : active );
699 if( ptr->string6 )
700 ui_menu_item_set_active( ptr->string6,
701 ptr->string6_inverted ? !active : active );
702 if( ptr->string7 )
703 ui_menu_item_set_active( ptr->string7,
704 ptr->string7_inverted ? !active : active );
705 return 0;
706 }
707
708 }
709
710 ui_error( UI_ERROR_ERROR, "ui_menu_activate: unknown item %d", item );
711 return 1;
712 }
713
714 void
ui_menu_disk_update(void)715 ui_menu_disk_update( void )
716 {
717 int drives_avail;
718
719 drives_avail = ui_media_drive_any_available();
720
721 /* Set the disk menu items and statusbar appropriately */
722
723 if( drives_avail ) {
724 ui_menu_activate( UI_MENU_ITEM_MEDIA_DISK, 1 );
725 ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE );
726 } else {
727 ui_menu_activate( UI_MENU_ITEM_MEDIA_DISK, 0 );
728 ui_statusbar_update( UI_STATUSBAR_ITEM_DISK,
729 UI_STATUSBAR_STATE_NOT_AVAILABLE );
730 }
731
732 ui_media_drive_update_parent_menus();
733 }
734
735 int
ui_tape_write(void)736 ui_tape_write( void )
737 {
738 char *filename;
739
740 fuse_emulation_pause();
741
742 filename = ui_get_save_filename( "Fuse - Write Tape" );
743 if( !filename ) { fuse_emulation_unpause(); return 1; }
744
745 tape_write( filename );
746
747 libspectrum_free( filename );
748
749 fuse_emulation_unpause();
750
751 return 0;
752 }
753
754 int
ui_mdr_write(int which,int saveas)755 ui_mdr_write( int which, int saveas )
756 {
757 int err;
758 char *filename = NULL, title[80];
759
760 fuse_emulation_pause();
761
762 snprintf( title, 80, "Fuse - Write Microdrive Cartridge %i", which + 1 );
763
764 if( saveas ) {
765 filename = ui_get_save_filename( title );
766 if( !filename ) { fuse_emulation_unpause(); return 1; }
767 }
768
769 err = if1_mdr_write( which, filename );
770
771 if( saveas ) libspectrum_free( filename );
772
773 fuse_emulation_unpause();
774
775 return err;
776 }
777
778 #ifdef USE_WIDGET
779 int
ui_widget_init(void)780 ui_widget_init( void )
781 {
782 return widget_init();
783 }
784
785 int
ui_widget_end(void)786 ui_widget_end( void )
787 {
788 return widget_end();
789 }
790 #else
791 int
ui_widget_init(void)792 ui_widget_init( void )
793 {
794 return 0;
795 }
796
797 int
ui_widget_end(void)798 ui_widget_end( void )
799 {
800 return 0;
801 }
802
803 void
ui_popup_menu(int native_key)804 ui_popup_menu( int native_key )
805 {
806 }
807
808 void
ui_widget_keyhandler(int native_key)809 ui_widget_keyhandler( int native_key )
810 {
811 }
812 #endif /* #ifndef USE_WIDGET */
813