1 /*
2  * xcpc_athena.c - Copyright (c) 2001, 2006, 2007 Olivier Poncet
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <X11/Intrinsic.h>
25 #include <Xem/StringDefs.h>
26 #include <Xem/AppShell.h>
27 #include <Xem/DlgShell.h>
28 #include <Xem/Emulator.h>
29 #include "amstrad_cpc.h"
30 #include "xcpc.h"
31 
32 static Widget CreateGUI(Widget toplevel);
33 
34 /*
35  * command line options
36  */
37 static XrmOptionDescRec options[] = {
38   { "-version", ".xcpcAboutFlag", XrmoptionNoArg, (XPointer) "true" },
39   { "-help",    ".xcpcUsageFlag", XrmoptionNoArg, (XPointer) "true" },
40   { "-editres", ".xcpcEdresFlag", XrmoptionNoArg, (XPointer) "true" }
41 };
42 
43 /*
44  * fallback resources
45  */
46 static String fallback_resources[] = {
47   "*title: Xcpc - Amstrad CPC emulator",
48   NULL
49 };
50 
51 /*
52  * application resources
53  */
54 static XtResource application_resources[] = {
55   /* xcpcAboutFlag */ {
56     "xcpcAboutFlag", "XcpcAboutFlag", XtRBoolean,
57     sizeof(Boolean), XtOffsetOf(XcpcResourcesRec, about_flag),
58     XtRImmediate, (XtPointer) FALSE
59   },
60   /* xcpcUsageFlag */ {
61     "xcpcUsageFlag", "XcpcUsageFlag", XtRBoolean,
62     sizeof(Boolean), XtOffsetOf(XcpcResourcesRec, usage_flag),
63     XtRImmediate, (XtPointer) FALSE
64   },
65   /* xcpcEdresFlag */ {
66     "xcpcEdresFlag", "XcpcEdresFlag", XtRBoolean,
67     sizeof(Boolean), XtOffsetOf(XcpcResourcesRec, edres_flag),
68     XtRImmediate, (XtPointer) FALSE
69   }
70 };
71 
72 /*
73  * Xcpc resources
74  */
75 static XcpcResourcesRec xcpc_resources = {
76   FALSE, /* about_flag */
77   FALSE, /* usage_flag */
78   FALSE  /* edres_flag */
79 };
80 
81 /**
82  * Destroy Callback
83  *
84  * @param widget specifies the Widget instance
85  * @param widref specifies the Widget reference
86  * @param cbdata is not used
87  */
DestroyCbk(Widget widget,Widget * widref,XtPointer cbdata)88 static void DestroyCbk(Widget widget, Widget *widref, XtPointer cbdata)
89 {
90   if(XtIsApplicationShell(widget) != FALSE) {
91     XtAppSetExitFlag(XtWidgetToApplicationContext(widget));
92   }
93   if((widget != NULL) && (widref != NULL) && (widget == *widref)) {
94     *widref = NULL;
95   }
96 }
97 
98 /**
99  * main
100  *
101  * @param argc specifies the argument count
102  * @param argv specifies the argument list
103  *
104  * @return EXIT_SUCCESS or EXIT_FAILURE
105  */
main(int argc,char * argv[])106 int main(int argc, char *argv[])
107 {
108   XtAppContext appcontext;
109   String appname  = NULL;
110   String appclass = NULL;
111   Widget toplevel = NULL;
112   Widget apwindow = NULL;
113   Cardinal argcount = 0;
114   Arg arglist[4];
115 
116   (void) XtSetLanguageProc(NULL, NULL, NULL);
117   argcount = 0;
118   XtSetArg(arglist[argcount], XtNmappedWhenManaged, TRUE); argcount++;
119   XtSetArg(arglist[argcount], XtNallowShellResize, TRUE); argcount++;
120   toplevel = XtOpenApplication(&appcontext, "Xcpc", options, XtNumber(options), &argc, argv, fallback_resources, xemAppShellWidgetClass, arglist, argcount);
121   XtAddCallback(toplevel, XtNdestroyCallback, (XtCallbackProc) DestroyCbk, (XtPointer) &toplevel);
122   argcount = 0;
123   XtGetApplicationResources(toplevel, (XtPointer) &xcpc_resources, application_resources, XtNumber(application_resources), arglist, argcount);
124   XtGetApplicationNameAndClass(XtDisplay(toplevel), &appname, &appclass);
125   if(xcpc_resources.about_flag != FALSE) {
126     (void) fprintf(stdout, "%s %s\n", appname, PACKAGE_VERSION);
127     (void) fflush(stdout);
128     exit(EXIT_SUCCESS);
129   }
130   if((xcpc_resources.usage_flag != FALSE) || (amstrad_cpc_parse(&argc, &argv) == EXIT_FAILURE)) {
131     (void) fprintf(stdout, "Usage: %s [toolkit-options] [program-options]\n\n", appname);
132     (void) fprintf(stdout, "Options:\n");
133     (void) fprintf(stdout, "  -version  print version and exit.\n");
134     (void) fprintf(stdout, "  -help     display this help and exit.\n");
135     (void) fflush(stdout);
136     exit(EXIT_SUCCESS);
137   }
138   if(xcpc_resources.edres_flag != FALSE) {
139     XtAddEventHandler(toplevel, NoEventMask, TRUE, (XtEventHandler) _XEditResCheckMessages, (XtPointer) NULL);
140   }
141   /* XXX */ {
142     g_type_init(); apwindow = CreateGUI(toplevel);
143   }
144   XtManageChild(apwindow);
145   XtRealizeWidget(toplevel);
146   XtAppMainLoop(appcontext);
147   if(toplevel != NULL) {
148     XtDestroyWidget(toplevel);
149   }
150   XtDestroyApplicationContext(appcontext);
151   return(EXIT_SUCCESS);
152 }
153 
154 /*
155  * GUI instance structure
156  */
157 typedef struct _GUI {
158   Widget main_wnd;
159   Widget menu_bar;
160   Widget file_menu;
161   Widget file_pldn;
162   Widget load_snapshot;
163   Widget save_snapshot;
164   Widget separator1;
165   Widget drivea_insert;
166   Widget drivea_eject;
167   Widget separator2;
168   Widget driveb_insert;
169   Widget driveb_eject;
170   Widget separator3;
171   Widget exit_emulator;
172   Widget ctrl_menu;
173   Widget ctrl_pldn;
174   Widget pause_emu;
175   Widget reset_emu;
176   Widget help_menu;
177   Widget help_pldn;
178   Widget legal_info;
179   Widget separator4;
180   Widget about_xcpc;
181   Widget emulator;
182 } GUI;
183 
184 #include <X11/Xaw/Box.h>
185 #include <X11/Xaw/MenuButton.h>
186 #include <X11/Xaw/SimpleMenu.h>
187 #include <X11/Xaw/SmeBSB.h>
188 #include <X11/Xaw/SmeLine.h>
189 #include <X11/Xaw/Dialog.h>
190 
191 /**
192  * GUI::OnCloseCbk()
193  *
194  * @param widget specifies the Widget
195  * @param gui specifies the GUI
196  * @param cbs specifies the callback info
197  */
OnCloseCbk(Widget widget,GUI * gui,XtPointer cbs)198 static void OnCloseCbk(Widget widget, GUI *gui, XtPointer cbs)
199 {
200   while((widget != NULL) && (XtIsShell(widget) == FALSE)) {
201     widget = XtParent(widget);
202   }
203   XtPopdown(widget);
204   XtDestroyWidget(widget);
205   XtSetSensitive(gui->emulator, TRUE);
206 }
207 
208 /**
209  * GUI::OnLoadSnapshotOkCbk()
210  *
211  * @param widget specifies the Widget
212  * @param gui specifies the GUI
213  * @param cbs specifies the callback info
214  */
OnLoadSnapshotOkCbk(Widget widget,GUI * gui,XtPointer cbs)215 static void OnLoadSnapshotOkCbk(Widget widget, GUI *gui, XtPointer cbs)
216 {
217   char *value = XawDialogGetValueString(XtParent(widget));
218   if(value != NULL) {
219     amstrad_cpc_load_snapshot(value);
220   }
221   OnCloseCbk(widget, gui, cbs);
222 }
223 
224 /**
225  * GUI::OnLoadSnapshotCbk()
226  *
227  * @param widget specifies the Widget
228  * @param gui specifies the GUI
229  * @param cbs specifies the callback info
230  */
OnLoadSnapshotCbk(Widget widget,GUI * gui,XtPointer cbs)231 static void OnLoadSnapshotCbk(Widget widget, GUI *gui, XtPointer cbs)
232 {
233   Widget shell, dialog, btn_ok, cancel;
234   Arg arglist[8];
235   Cardinal argcount;
236 
237   XtSetSensitive(gui->emulator, FALSE);
238   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
239     widget = XtParent(widget);
240   }
241   /* load-snapshot-shell */
242   argcount = 0;
243   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
244   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
245   shell = XtCreatePopupShell("load-snapshot-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
246   /* load-snapshot-dialog */
247   argcount = 0;
248   XtSetArg(arglist[argcount], XtNlabel, _("Load a snapshot ...")); argcount++;
249   XtSetArg(arglist[argcount], XtNvalue, ""); argcount++;
250   dialog = XtCreateWidget("load-snapshot-dialog", dialogWidgetClass, shell, arglist, argcount);
251   XtManageChild(dialog);
252   /* load-snapshot-btn-ok */
253   argcount = 0;
254   XtSetArg(arglist[argcount], XtNlabel, _(" Load ")); argcount++;
255   btn_ok = XtCreateManagedWidget("load-snapshot-btn-ok", commandWidgetClass, dialog, arglist, argcount);
256   XtAddCallback(btn_ok, XtNcallback, (XtCallbackProc) OnLoadSnapshotOkCbk, (XtPointer) gui);
257   XtManageChild(btn_ok);
258   /* load-snapshot-cancel */
259   argcount = 0;
260   XtSetArg(arglist[argcount], XtNlabel, _("Cancel")); argcount++;
261   cancel = XtCreateManagedWidget("load-snapshot-cancel", commandWidgetClass, dialog, arglist, argcount);
262   XtAddCallback(cancel, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
263   XtManageChild(cancel);
264   /* load-snapshot-popup */
265   XtPopup(shell, XtGrabExclusive);
266 }
267 
268 /**
269  * GUI::OnSaveSnapshotOkCbk()
270  *
271  * @param widget specifies the Widget
272  * @param gui specifies the GUI
273  * @param cbs specifies the callback info
274  */
OnSaveSnapshotOkCbk(Widget widget,GUI * gui,XtPointer cbs)275 static void OnSaveSnapshotOkCbk(Widget widget, GUI *gui, XtPointer cbs)
276 {
277   char *value = XawDialogGetValueString(XtParent(widget));
278   if(value != NULL) {
279     amstrad_cpc_save_snapshot(value);
280   }
281   OnCloseCbk(widget, gui, cbs);
282 }
283 
284 /**
285  * GUI::OnSaveSnapshotCbk()
286  *
287  * @param widget specifies the Widget
288  * @param gui specifies the GUI
289  * @param cbs specifies the callback info
290  */
OnSaveSnapshotCbk(Widget widget,GUI * gui,XtPointer cbs)291 static void OnSaveSnapshotCbk(Widget widget, GUI *gui, XtPointer cbs)
292 {
293   Widget shell, dialog, btn_ok, cancel;
294   Arg arglist[8];
295   Cardinal argcount;
296 
297   XtSetSensitive(gui->emulator, FALSE);
298   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
299     widget = XtParent(widget);
300   }
301   /* save-snapshot-shell */
302   argcount = 0;
303   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
304   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
305   shell = XtCreatePopupShell("save-snapshot-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
306   /* save-snapshot-dialog */
307   argcount = 0;
308   XtSetArg(arglist[argcount], XtNlabel, _("Save a snapshot ...")); argcount++;
309   XtSetArg(arglist[argcount], XtNvalue, ""); argcount++;
310   dialog = XtCreateWidget("save-snapshot-dialog", dialogWidgetClass, shell, arglist, argcount);
311   XtManageChild(dialog);
312   /* save-snapshot-btn-ok */
313   argcount = 0;
314   XtSetArg(arglist[argcount], XtNlabel, _(" Save ")); argcount++;
315   btn_ok = XtCreateManagedWidget("save-snapshot-btn-ok", commandWidgetClass, dialog, arglist, argcount);
316   XtAddCallback(btn_ok, XtNcallback, (XtCallbackProc) OnSaveSnapshotOkCbk, (XtPointer) gui);
317   XtManageChild(btn_ok);
318   /* save-snapshot-cancel */
319   argcount = 0;
320   XtSetArg(arglist[argcount], XtNlabel, _("Cancel")); argcount++;
321   cancel = XtCreateManagedWidget("save-snapshot-cancel", commandWidgetClass, dialog, arglist, argcount);
322   XtAddCallback(cancel, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
323   XtManageChild(cancel);
324   /* save-snapshot-popup */
325   XtPopup(shell, XtGrabExclusive);
326 }
327 
328 /**
329  * GUI::OnDriveAInsertOkCbk()
330  *
331  * @param widget specifies the Widget
332  * @param gui specifies the GUI
333  * @param cbs specifies the callback info
334  */
OnDriveAInsertOkCbk(Widget widget,GUI * gui,XtPointer cbs)335 static void OnDriveAInsertOkCbk(Widget widget, GUI *gui, XtPointer cbs)
336 {
337   char *value = XawDialogGetValueString(XtParent(widget));
338   if(value != NULL) {
339     gdev_fdd765_insert(amstrad_cpc.upd765->fdd[0], value);
340   }
341   OnCloseCbk(widget, gui, cbs);
342 }
343 
344 /**
345  * GUI::OnDriveAInsertCbk()
346  *
347  * @param widget specifies the Widget
348  * @param gui specifies the GUI
349  * @param cbs specifies the callback info
350  */
OnDriveAInsertCbk(Widget widget,GUI * gui,XtPointer cbs)351 static void OnDriveAInsertCbk(Widget widget, GUI *gui, XtPointer cbs)
352 {
353   Widget shell, dialog, btn_ok, cancel;
354   Arg arglist[8];
355   Cardinal argcount;
356 
357   XtSetSensitive(gui->emulator, FALSE);
358   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
359     widget = XtParent(widget);
360   }
361   /* drivea-insert-shell */
362   argcount = 0;
363   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
364   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
365   shell = XtCreatePopupShell("drivea-insert-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
366   /* drivea-insert-dialog */
367   argcount = 0;
368   XtSetArg(arglist[argcount], XtNlabel, _("Insert disk into drive A ...")); argcount++;
369   XtSetArg(arglist[argcount], XtNvalue, ""); argcount++;
370   dialog = XtCreateWidget("drivea-insert-dialog", dialogWidgetClass, shell, arglist, argcount);
371   XtManageChild(dialog);
372   /* drivea-insert-btn-ok */
373   argcount = 0;
374   XtSetArg(arglist[argcount], XtNlabel, _("Insert")); argcount++;
375   btn_ok = XtCreateManagedWidget("drivea-insert-btn-ok", commandWidgetClass, dialog, arglist, argcount);
376   XtAddCallback(btn_ok, XtNcallback, (XtCallbackProc) OnDriveAInsertOkCbk, (XtPointer) gui);
377   XtManageChild(btn_ok);
378   /* drivea-insert-cancel */
379   argcount = 0;
380   XtSetArg(arglist[argcount], XtNlabel, _("Cancel")); argcount++;
381   cancel = XtCreateManagedWidget("drivea-insert-cancel", commandWidgetClass, dialog, arglist, argcount);
382   XtAddCallback(cancel, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
383   XtManageChild(cancel);
384   /* drivea-insert-popup */
385   XtPopup(shell, XtGrabExclusive);
386 }
387 
388 /**
389  * GUI::OnDriveAEjectCbk()
390  *
391  * @param widget specifies the Widget
392  * @param gui specifies the GUI
393  * @param cbs specifies the callback info
394  */
OnDriveAEjectCbk(Widget widget,GUI * gui,XtPointer cbs)395 static void OnDriveAEjectCbk(Widget widget, GUI *gui, XtPointer cbs)
396 {
397   gdev_fdd765_insert(amstrad_cpc.upd765->fdd[0], NULL);
398 }
399 
400 /**
401  * GUI::OnDriveBInsertOkCbk()
402  *
403  * @param widget specifies the Widget
404  * @param gui specifies the GUI
405  * @param cbs specifies the callback info
406  */
OnDriveBInsertOkCbk(Widget widget,GUI * gui,XtPointer cbs)407 static void OnDriveBInsertOkCbk(Widget widget, GUI *gui, XtPointer cbs)
408 {
409   char *value = XawDialogGetValueString(XtParent(widget));
410   if(value != NULL) {
411     gdev_fdd765_insert(amstrad_cpc.upd765->fdd[1], value);
412   }
413   OnCloseCbk(widget, gui, cbs);
414 }
415 
416 /**
417  * GUI::OnDriveBInsertCbk()
418  *
419  * @param widget specifies the Widget
420  * @param gui specifies the GUI
421  * @param cbs specifies the callback info
422  */
OnDriveBInsertCbk(Widget widget,GUI * gui,XtPointer cbs)423 static void OnDriveBInsertCbk(Widget widget, GUI *gui, XtPointer cbs)
424 {
425   Widget shell, dialog, btn_ok, cancel;
426   Arg arglist[8];
427   Cardinal argcount;
428 
429   XtSetSensitive(gui->emulator, FALSE);
430   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
431     widget = XtParent(widget);
432   }
433   /* driveb-insert-shell */
434   argcount = 0;
435   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
436   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
437   shell = XtCreatePopupShell("driveb-insert-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
438   /* driveb-insert-dialog */
439   argcount = 0;
440   XtSetArg(arglist[argcount], XtNlabel, _("Insert disk into drive B ...")); argcount++;
441   XtSetArg(arglist[argcount], XtNvalue, ""); argcount++;
442   dialog = XtCreateWidget("driveb-insert-dialog", dialogWidgetClass, shell, arglist, argcount);
443   XtManageChild(dialog);
444   /* driveb-insert-btn-ok */
445   argcount = 0;
446   XtSetArg(arglist[argcount], XtNlabel, _("Insert")); argcount++;
447   btn_ok = XtCreateManagedWidget("driveb-insert-btn-ok", commandWidgetClass, dialog, arglist, argcount);
448   XtAddCallback(btn_ok, XtNcallback, (XtCallbackProc) OnDriveBInsertOkCbk, (XtPointer) gui);
449   XtManageChild(btn_ok);
450   /* driveb-insert-cancel */
451   argcount = 0;
452   XtSetArg(arglist[argcount], XtNlabel, _("Cancel")); argcount++;
453   cancel = XtCreateManagedWidget("driveb-insert-cancel", commandWidgetClass, dialog, arglist, argcount);
454   XtAddCallback(cancel, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
455   XtManageChild(cancel);
456   /* driveb-insert-popup */
457   XtPopup(shell, XtGrabExclusive);
458 }
459 
460 /**
461  * GUI::OnDriveBEjectCbk()
462  *
463  * @param widget specifies the Widget
464  * @param gui specifies the GUI
465  * @param cbs specifies the callback info
466  */
OnDriveBEjectCbk(Widget widget,GUI * gui,XtPointer cbs)467 static void OnDriveBEjectCbk(Widget widget, GUI *gui, XtPointer cbs)
468 {
469   gdev_fdd765_insert(amstrad_cpc.upd765->fdd[1], NULL);
470 }
471 
472 /**
473  * GUI::OnExitEmulatorCbk()
474  *
475  * @param widget specifies the Widget
476  * @param gui specifies the GUI
477  * @param cbs specifies the callback info
478  */
OnExitEmulatorCbk(Widget widget,GUI * gui,XtPointer cbs)479 static void OnExitEmulatorCbk(Widget widget, GUI *gui, XtPointer cbs)
480 {
481   XtAppSetExitFlag(XtWidgetToApplicationContext(widget));
482 }
483 
484 /**
485  * GUI::OnPauseCbk()
486  *
487  * @param widget specifies the Widget
488  * @param gui specifies the GUI
489  * @param cbs specifies the callback info
490  */
OnPauseCbk(Widget widget,GUI * gui,XtPointer cbs)491 static void OnPauseCbk(Widget widget, GUI *gui, XtPointer cbs)
492 {
493   if(XtIsSensitive(gui->emulator) != FALSE) {
494     XtSetSensitive(gui->emulator, FALSE);
495   }
496   else {
497     XtSetSensitive(gui->emulator, TRUE);
498   }
499 }
500 
501 /**
502  * GUI::OnResetCbk()
503  *
504  * @param widget specifies the Widget
505  * @param gui specifies the GUI
506  * @param cbs specifies the callback info
507  */
OnResetCbk(Widget widget,GUI * gui,XtPointer cbs)508 static void OnResetCbk(Widget widget, GUI *gui, XtPointer cbs)
509 {
510   amstrad_cpc_reset();
511   XtSetSensitive(gui->emulator, TRUE);
512 }
513 
514 /**
515  * GUI::OnLegalInfoCbk()
516  *
517  * @param widget specifies the Widget
518  * @param gui specifies the GUI
519  * @param cbs specifies the callback info
520  */
OnLegalInfoCbk(Widget widget,GUI * gui,XtPointer cbs)521 static void OnLegalInfoCbk(Widget widget, GUI *gui, XtPointer cbs)
522 {
523   Widget shell, dialog, button;
524   Arg arglist[8];
525   Cardinal argcount;
526   String message = _(
527     "Amstrad has kindly given it's permission for it's copyrighted\n"
528     "material to be redistributed but Amstrad retains it's copyright.\n\n"
529     "Some of the Amstrad CPC ROM code is copyright Locomotive Software.\n\n"
530     "ROM and DISK images are protected under the copyrights of their authors,\n"
531     "and cannot be distributed in this package. You can download and/or use\n"
532     "ROM and DISK images at your own risk and responsibility."
533   );
534 
535   XtSetSensitive(gui->emulator, FALSE);
536   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
537     widget = XtParent(widget);
538   }
539   /* legal-info-shell */
540   argcount = 0;
541   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
542   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
543   shell = XtCreatePopupShell("legal-info-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
544   /* legal-info-dialog */
545   argcount = 0;
546   XtSetArg(arglist[argcount], XtNlabel, message); argcount++;
547   dialog = XtCreateWidget("legal-info-dialog", dialogWidgetClass, shell, arglist, argcount);
548   XtManageChild(dialog);
549   /* legal-info-btn-ok */
550   argcount = 0;
551   XtSetArg(arglist[argcount], XtNlabel, _("OK")); argcount++;
552   button = XtCreateManagedWidget("legal-info-btn-ok", commandWidgetClass, dialog, arglist, argcount);
553   XtAddCallback(button, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
554   XtManageChild(button);
555   /* legal-info-popup */
556   XtPopup(shell, XtGrabExclusive);
557 }
558 
559 /**
560  * GUI::OnAboutXcpcCbk()
561  *
562  * @param widget specifies the Widget
563  * @param gui specifies the GUI
564  * @param cbs specifies the callback info
565  */
OnAboutXcpcCbk(Widget widget,GUI * gui,XtPointer cbs)566 static void OnAboutXcpcCbk(Widget widget, GUI *gui, XtPointer cbs)
567 {
568   Widget shell, dialog, button;
569   Arg arglist[8];
570   Cardinal argcount;
571   String message = _(
572     PACKAGE_STRING " - Amstrad CPC Emulator - Copyright (c) 2001, 2006, 2007 Olivier Poncet\n\n"
573     "This program is free software; you can redistribute it and/or modify\n"
574     "it under the terms of the GNU General Public License as published by\n"
575     "the Free Software Foundation; either version 2 of the License, or\n"
576     "(at your option) any later version.\n\n"
577     "This program is distributed in the hope that it will be useful,\n"
578     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
579     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
580     "GNU General Public License for more details.\n\n"
581     "You should have received a copy of the GNU General Public License\n"
582     "along with this program; if not, write to the Free Software\n"
583     "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA"
584   );
585 
586   XtSetSensitive(gui->emulator, FALSE);
587   while((widget != NULL) && (XtIsTopLevelShell(widget) == FALSE)) {
588     widget = XtParent(widget);
589   }
590   /* about-xcpc-shell */
591   argcount = 0;
592   XtSetArg(arglist[argcount], XtNtransient, TRUE); argcount++;
593   XtSetArg(arglist[argcount], XtNtransientFor, widget); argcount++;
594   shell = XtCreatePopupShell("about-xcpc-shell", xemDlgShellWidgetClass, widget, arglist, argcount);
595   /* about-xcpc-dialog */
596   argcount = 0;
597   XtSetArg(arglist[argcount], XtNlabel, message); argcount++;
598   dialog = XtCreateWidget("about-xcpc-dialog", dialogWidgetClass, shell, arglist, argcount);
599   XtManageChild(dialog);
600   /* about-xcpc-btn-ok */
601   argcount = 0;
602   XtSetArg(arglist[argcount], XtNlabel, _("OK")); argcount++;
603   button = XtCreateManagedWidget("about-xcpc-btn-ok", commandWidgetClass, dialog, arglist, argcount);
604   XtAddCallback(button, XtNcallback, (XtCallbackProc) OnCloseCbk, (XtPointer) gui);
605   XtManageChild(button);
606   /* about-xcpc-popup */
607   XtPopup(shell, XtGrabExclusive);
608 }
609 
610 /**
611  * GUI::OnDropURICbk()
612  *
613  * @param widget specifies the Widget
614  * @param gui specifies the GUI
615  * @param uri specifies the callback info
616  */
OnDropURICbk(Widget widget,GUI * gui,char * uri)617 static void OnDropURICbk(Widget widget, GUI *gui, char *uri)
618 {
619   int length = 0;
620 
621   if((uri != NULL) && (strncmp(uri, "file://", 7) == 0)) {
622     char *str = &uri[7], *ptr = strstr(str, "\r\n");
623     if(ptr != NULL) {
624       *ptr = '\0';
625     }
626     if((length = strlen(str)) >= 4) {
627       if(strcmp(&str[length - 4], ".sna") == 0) {
628         amstrad_cpc_load_snapshot(str);
629       }
630       if(strcmp(&str[length - 4], ".dsk") == 0) {
631         gdev_fdd765_insert(amstrad_cpc.upd765->fdd[0], str);
632         gdev_fdd765_insert(amstrad_cpc.upd765->fdd[1], str);
633       }
634       XtSetSensitive(gui->emulator, TRUE);
635       XtSetSensitive(gui->emulator, TRUE);
636     }
637   }
638 }
639 
640 /**
641  * GUI::Create()
642  *
643  * @param toplevel specifies the TopLevel Shell
644  *
645  * @return the main-window instance
646  */
CreateGUI(Widget toplevel)647 static Widget CreateGUI(Widget toplevel)
648 {
649   GUI *gui = (GUI *) XtMalloc(sizeof(GUI));
650   Arg arglist[8];
651   Cardinal argcount;
652 
653   /* main-wnd */
654   argcount = 0;
655   gui->main_wnd = XtCreateWidget("main-wnd", boxWidgetClass, toplevel, arglist, argcount);
656   /* menu-bar */
657   argcount = 0;
658   XtSetArg(arglist[argcount], XtNorientation, XtorientHorizontal); argcount++;
659   XtSetArg(arglist[argcount], XtNborderWidth, 0); argcount++;
660   gui->menu_bar = XtCreateWidget("menu-bar", boxWidgetClass, gui->main_wnd, arglist, argcount);
661   XtManageChild(gui->menu_bar);
662   /* file-menu */
663   argcount = 0;
664   XtSetArg(arglist[argcount], XtNlabel, _("File")); argcount++;
665   XtSetArg(arglist[argcount], XtNmenuName, "file-pldn"); argcount++;
666   gui->file_menu = XtCreateWidget("file-menu", menuButtonWidgetClass, gui->menu_bar, arglist, argcount);
667   XtManageChild(gui->file_menu);
668   /* file-pldn */
669   argcount = 0;
670   gui->file_pldn = XtCreatePopupShell("file-pldn", simpleMenuWidgetClass, gui->file_menu, arglist, argcount);
671   /* load-snapshot */
672   argcount = 0;
673   XtSetArg(arglist[argcount], XtNlabel, _("Load Snapshot")); argcount++;
674   gui->load_snapshot = XtCreateWidget("load-snapshot", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
675   XtAddCallback(gui->load_snapshot, XtNcallback, (XtCallbackProc) OnLoadSnapshotCbk, (XtPointer) gui);
676   XtManageChild(gui->load_snapshot);
677   /* save-snapshot */
678   argcount = 0;
679   XtSetArg(arglist[argcount], XtNlabel, _("Save Snapshot")); argcount++;
680   gui->save_snapshot = XtCreateWidget("save-snapshot", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
681   XtAddCallback(gui->save_snapshot, XtNcallback, (XtCallbackProc) OnSaveSnapshotCbk, (XtPointer) gui);
682   XtManageChild(gui->save_snapshot);
683   /* separator1 */
684   argcount = 0;
685   gui->separator1 = XtCreateWidget("separator1", smeLineObjectClass, gui->file_pldn, arglist, argcount);
686   XtManageChild(gui->separator1);
687   /* drivea-insert */
688   argcount = 0;
689   XtSetArg(arglist[argcount], XtNlabel, _("Insert disk into drive A")); argcount++;
690   gui->drivea_insert = XtCreateWidget("drivea-insert", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
691   XtAddCallback(gui->drivea_insert, XtNcallback, (XtCallbackProc) OnDriveAInsertCbk, (XtPointer) gui);
692   XtManageChild(gui->drivea_insert);
693   /* drivea-eject */
694   argcount = 0;
695   XtSetArg(arglist[argcount], XtNlabel, _("Eject disk from drive A")); argcount++;
696   gui->drivea_eject = XtCreateWidget("drivea-eject", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
697   XtAddCallback(gui->drivea_eject, XtNcallback, (XtCallbackProc) OnDriveAEjectCbk, (XtPointer) gui);
698   XtManageChild(gui->drivea_eject);
699   /* separator2 */
700   argcount = 0;
701   gui->separator2 = XtCreateWidget("separator2", smeLineObjectClass, gui->file_pldn, arglist, argcount);
702   XtManageChild(gui->separator2);
703   /* driveb-insert */
704   argcount = 0;
705   XtSetArg(arglist[argcount], XtNlabel, _("Insert disk into drive B")); argcount++;
706   gui->driveb_insert = XtCreateWidget("driveb-insert", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
707   XtAddCallback(gui->driveb_insert, XtNcallback, (XtCallbackProc) OnDriveBInsertCbk, (XtPointer) gui);
708   XtManageChild(gui->driveb_insert);
709   /* driveb-eject */
710   argcount = 0;
711   XtSetArg(arglist[argcount], XtNlabel, _("Eject disk from drive B")); argcount++;
712   gui->driveb_eject = XtCreateWidget("driveb-eject", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
713   XtAddCallback(gui->driveb_eject, XtNcallback, (XtCallbackProc) OnDriveBEjectCbk, (XtPointer) gui);
714   XtManageChild(gui->driveb_eject);
715   /* separator3 */
716   argcount = 0;
717   gui->separator3 = XtCreateWidget("separator3", smeLineObjectClass, gui->file_pldn, arglist, argcount);
718   XtManageChild(gui->separator3);
719   /* exit-emulator */
720   argcount = 0;
721   XtSetArg(arglist[argcount], XtNlabel, _("Exit")); argcount++;
722   gui->exit_emulator = XtCreateWidget("exit-emulator", smeBSBObjectClass, gui->file_pldn, arglist, argcount);
723   XtAddCallback(gui->exit_emulator, XtNcallback, (XtCallbackProc) OnExitEmulatorCbk, (XtPointer) gui);
724   XtManageChild(gui->exit_emulator);
725   /* ctrl-menu */
726   argcount = 0;
727   XtSetArg(arglist[argcount], XtNlabel, _("Controls")); argcount++;
728   XtSetArg(arglist[argcount], XtNmenuName, "ctrl-pldn"); argcount++;
729   gui->ctrl_menu = XtCreateWidget("ctrl-menu", menuButtonWidgetClass, gui->menu_bar, arglist, argcount);
730   XtManageChild(gui->ctrl_menu);
731   /* ctrl-pldn */
732   argcount = 0;
733   gui->ctrl_pldn = XtCreatePopupShell("ctrl-pldn", simpleMenuWidgetClass, gui->ctrl_menu, arglist, argcount);
734   /* pause-emu */
735   argcount = 0;
736   XtSetArg(arglist[argcount], XtNlabel, _("Play / Pause")); argcount++;
737   gui->pause_emu = XtCreateWidget("pause-emu", smeBSBObjectClass, gui->ctrl_pldn, arglist, argcount);
738   XtAddCallback(gui->pause_emu, XtNcallback, (XtCallbackProc) OnPauseCbk, (XtPointer) gui);
739   XtManageChild(gui->pause_emu);
740   /* reset-emu */
741   argcount = 0;
742   XtSetArg(arglist[argcount], XtNlabel, _("Reset")); argcount++;
743   gui->reset_emu = XtCreateWidget("reset-emu", smeBSBObjectClass, gui->ctrl_pldn, arglist, argcount);
744   XtAddCallback(gui->reset_emu, XtNcallback, (XtCallbackProc) OnResetCbk, (XtPointer) gui);
745   XtManageChild(gui->reset_emu);
746   /* help-menu */
747   argcount = 0;
748   XtSetArg(arglist[argcount], XtNlabel, _("Help")); argcount++;
749   XtSetArg(arglist[argcount], XtNmenuName, "help-pldn"); argcount++;
750   gui->help_menu = XtCreateWidget("help-menu", menuButtonWidgetClass, gui->menu_bar, arglist, argcount);
751   XtManageChild(gui->help_menu);
752   /* help-pldn */
753   argcount = 0;
754   gui->help_pldn = XtCreatePopupShell("help-pldn", simpleMenuWidgetClass, gui->help_menu, arglist, argcount);
755   /* legal-info */
756   argcount = 0;
757   XtSetArg(arglist[argcount], XtNlabel, _("Legal Info")); argcount++;
758   gui->legal_info = XtCreateWidget("legal-info", smeBSBObjectClass, gui->help_pldn, arglist, argcount);
759   XtAddCallback(gui->legal_info, XtNcallback, (XtCallbackProc) OnLegalInfoCbk, (XtPointer) gui);
760   XtManageChild(gui->legal_info);
761   /* separator4 */
762   argcount = 0;
763   gui->separator4 = XtCreateWidget("separator4", smeLineObjectClass, gui->help_pldn, arglist, argcount);
764   XtManageChild(gui->separator4);
765   /* about-xcpc */
766   argcount = 0;
767   XtSetArg(arglist[argcount], XtNlabel, _("About Xcpc")); argcount++;
768   gui->about_xcpc = XtCreateWidget("about-xcpc", smeBSBObjectClass, gui->help_pldn, arglist, argcount);
769   XtAddCallback(gui->about_xcpc, XtNcallback, (XtCallbackProc) OnAboutXcpcCbk, (XtPointer) gui);
770   XtManageChild(gui->about_xcpc);
771   /* emulator */
772   argcount = 0;
773   XtSetArg(arglist[argcount], XtNemuStartHandler, amstrad_cpc_start_handler); argcount++;
774   XtSetArg(arglist[argcount], XtNemuClockHandler, amstrad_cpc_clock_handler); argcount++;
775   XtSetArg(arglist[argcount], XtNemuCloseHandler, amstrad_cpc_close_handler); argcount++;
776   XtSetArg(arglist[argcount], XtNemuInputHandler, amstrad_cpc_input_handler); argcount++;
777   XtSetArg(arglist[argcount], XtNemuPaintHandler, amstrad_cpc_paint_handler); argcount++;
778   gui->emulator = XemCreateEmulator(gui->main_wnd, "emulator", arglist, argcount);
779   XtManageChild(gui->emulator);
780   /* XXX */
781   XtAddCallback(toplevel, XtNdropURICallback, (XtCallbackProc) OnDropURICbk, (XtPointer) gui);
782   return(gui->main_wnd);
783 }
784