ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
(Generate patch)

Comparing BasiliskII/src/Windows/prefs_editor_gtk.cpp (file contents):
Revision 1.1 by gbeauche, 2005-06-20T08:40:34Z vs.
Revision 1.9 by gbeauche, 2005-11-29T20:54:57Z

# Line 20 | Line 20
20  
21   #include "sysdeps.h"
22  
23 #include <gtk/gtk.h>
23   #include <stdlib.h>
24 + #include <string.h>
25 + #include <fcntl.h>
26 + #include <sys/stat.h>
27 + #include <gtk/gtk.h>
28  
29   #include "user_strings.h"
30   #include "version.h"
# Line 49 | Line 52 | static void read_settings(void);
52  
53  
54   /*
55 + *  SheepShaver glue
56 + */
57 +
58 + #ifdef SHEEPSHAVER
59 + #define DISABLE_SCSI 1
60 + #define PROGRAM_NAME "SheepShaver"
61 + enum {
62 +        STR_WINDOW_LAB = STR_WINDOW_CTRL,
63 +        STR_FULLSCREEN_LAB = STR_FULLSCREEN_CTRL,
64 +        STR_SERIALA_CTRL = STR_SERPORTA_CTRL,
65 +        STR_SERIALB_CTRL = STR_SERPORTB_CTRL,
66 + };
67 + #else
68 + #define PROGRAM_NAME "BasiliskII"
69 + #endif
70 +
71 +
72 + /*
73   *  Utility functions
74   */
75  
# Line 157 | Line 178 | static GtkWidget *make_table(GtkWidget *
178          return table;
179   }
180  
181 + static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active)
182 + {
183 +        GtkWidget *label, *opt, *menu;
184 +
185 +        label = gtk_label_new(GetString(label_id));
186 +        gtk_widget_show(label);
187 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
188 +
189 +        opt = gtk_option_menu_new();
190 +        gtk_widget_show(opt);
191 +        menu = gtk_menu_new();
192 +
193 +        while (options->label_id) {
194 +                add_menu_item(menu, options->label_id, options->func);
195 +                options++;
196 +        }
197 +        gtk_menu_set_active(GTK_MENU(menu), active);
198 +
199 +        gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
200 +        gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
201 +        return menu;
202 + }
203 +
204 + static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist)
205 + {
206 +        GtkWidget *label, *combo;
207 +        char str[32];
208 +
209 +        label = gtk_label_new(GetString(label_id));
210 +        gtk_widget_show(label);
211 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
212 +        
213 +        combo = gtk_combo_new();
214 +        gtk_widget_show(combo);
215 +        gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
216 +
217 +        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
218 +        gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
219 +        
220 +        return combo;
221 + }
222 +
223 + static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options)
224 + {
225 +        GList *glist = NULL;
226 +        while (options->label_id) {
227 +                glist = g_list_append(glist, (void *)GetString(options->label_id));
228 +                options++;
229 +        }
230 +
231 +        return table_make_combobox(table, row, label_id, default_value, glist);
232 + }
233 +
234 + static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false)
235 + {
236 +        GtkWidget *box, *label, *entry, *button;
237 +
238 +        label = gtk_label_new(GetString(label_id));
239 +        gtk_widget_show(label);
240 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
241 +
242 +        const char *str = PrefsFindString(prefs_item);
243 +        if (str == NULL)
244 +                str = "";
245 +
246 +        box = gtk_hbox_new(FALSE, 4);
247 +        gtk_widget_show(box);
248 +        gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
249 +
250 +        entry = gtk_entry_new();
251 +        gtk_entry_set_text(GTK_ENTRY(entry), str);
252 +        gtk_widget_show(entry);
253 +        gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
254 +
255 +        button = make_browse_button(entry);
256 +        gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
257 +        g_object_set_data(G_OBJECT(entry), "chooser_button", button);
258 +        return entry;
259 + }
260 +
261   static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
262   {
263          GtkWidget *box, *label, *opt, *menu;
# Line 222 | Line 323 | static GtkWidget *make_checkbox(GtkWidge
323          return button;
324   }
325  
326 < static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *prefs_item, const combo_desc *options)
326 > static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, GList *glist)
327   {
328          GtkWidget *box, *label, *combo;
228        char str[32];
329  
330          box = gtk_hbox_new(FALSE, 4);
331          gtk_widget_show(box);
# Line 234 | Line 334 | static GtkWidget *make_combobox(GtkWidge
334          label = gtk_label_new(GetString(label_id));
335          gtk_widget_show(label);
336          gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
237
238        GList *glist = NULL;
239        while (options->label_id) {
240                glist = g_list_append(glist, (void *)GetString(options->label_id));
241                options++;
242        }
337          
338          combo = gtk_combo_new();
339          gtk_widget_show(combo);
340          gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
341          
342 <        sprintf(str, "%d", PrefsFindInt32(prefs_item));
249 <        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
342 >        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
343          gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
344          
345          return combo;
346   }
347  
348 + static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, const combo_desc *options)
349 + {
350 +        GList *glist = NULL;
351 +        while (options->label_id) {
352 +                glist = g_list_append(glist, (void *)GetString(options->label_id));
353 +                options++;
354 +        }
355 +
356 +        return make_combobox(top, label_id, default_value, glist);
357 + }
358 +
359  
360   /*
361   *  Show preferences editor
# Line 307 | Line 411 | static void cb_about(...)
411  
412          char str[512];
413          sprintf(str,
414 <                "Basilisk II\nVersion %d.%d\n\n"
414 >                PROGRAM_NAME "\nVersion %d.%d\n\n"
415                  "Copyright (C) 1997-2005 Christian Bauer et al.\n"
416 <                "E-mail: Christian.Bauer@uni-mainz.de\n"
417 <                "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
418 <                "Basilisk II comes with ABSOLUTELY NO\n"
416 >                "E-mail: cb@cebix.net\n"
417 > #ifdef SHEEPSHAVER
418 >                "http://sheepshaver.cebix.net/\n\n"
419 > #else
420 >                "http://basilisk.cebix.net/\n\n"
421 > #endif
422 >                PROGRAM_NAME " comes with ABSOLUTELY NO\n"
423                  "WARRANTY. This is free software, and\n"
424                  "you are welcome to redistribute it\n"
425                  "under the terms of the GNU General\n"
# Line 341 | Line 449 | static void cb_about(...)
449   // Menu item descriptions
450   static GtkItemFactoryEntry menu_items[] = {
451          {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK),           NULL,                   NULL,                                                   0, "<Branch>"},
452 <        {(gchar *)GetString(STR_PREFS_ITEM_START_GTK),          NULL,                   GTK_SIGNAL_FUNC(cb_start),              0, NULL},
452 >        {(gchar *)GetString(STR_PREFS_ITEM_START_GTK),          "<control>S",   GTK_SIGNAL_FUNC(cb_start),              0, NULL},
453          {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK),       NULL,                   GTK_SIGNAL_FUNC(cb_zap_pram),   0, NULL},
454          {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK),           NULL,                   NULL,                                                   0, "<Separator>"},
455          {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK),           "<control>Q",   GTK_SIGNAL_FUNC(cb_quit),               0, NULL},
456          {(gchar *)GetString(STR_HELP_MENU_GTK),                         NULL,                   NULL,                                                   0, "<LastBranch>"},
457 <        {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK),           NULL,                   GTK_SIGNAL_FUNC(cb_about),              0, NULL}
457 >        {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK),           "<control>H",   GTK_SIGNAL_FUNC(cb_about),              0, NULL}
458   };
459  
460   bool PrefsEditor(void)
# Line 381 | Line 489 | bool PrefsEditor(void)
489          gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
490  
491          create_volumes_pane(notebook);
492 <        create_scsi_pane(notebook);
492 > //      create_scsi_pane(notebook); XXX not ready yet (merge scsi_windows.cpp from original B2/Win)
493          create_graphics_pane(notebook);
494          create_input_pane(notebook);
495          create_serial_pane(notebook);
# Line 391 | Line 499 | bool PrefsEditor(void)
499  
500          static const opt_desc buttons[] = {
501                  {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
394                {STR_PREFS_ITEM_ZAP_PRAM, GTK_SIGNAL_FUNC(cb_zap_pram)},
395                {STR_ABOUT_BUTTON, GTK_SIGNAL_FUNC(cb_about)},
502                  {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
503                  {0, NULL}
504          };
# Line 409 | Line 515 | bool PrefsEditor(void)
515   *  "Volumes" pane
516   */
517  
518 + static GtkWidget *w_enableextfs, *w_extdrives, *w_cdrom_drive;
519   static GtkWidget *volume_list;
520   static int selected_volume;
521  
522 + // Set sensitivity of widgets
523 + static void set_volumes_sensitive(void)
524 + {
525 +        const bool enable_extfs = PrefsFindBool("enableextfs");
526 +        gtk_widget_set_sensitive(w_extdrives, enable_extfs);
527 +        const bool no_cdrom = PrefsFindBool("nocdrom");
528 +        gtk_widget_set_sensitive(w_cdrom_drive, !no_cdrom);
529 + }
530 +
531   // Volume in list selected
532   static void cl_selected(GtkWidget *list, int row, int column)
533   {
# Line 433 | Line 549 | static void create_volume_ok(GtkWidget *
549          gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
550  
551          const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
552 <        int size = atoi(str);
552 >        size_t size = atoi(str) << 20;
553  
554 <        char cmd[1024];
555 <        sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
556 <        int ret = system(cmd);
441 <        if (ret == 0)
554 >        int fd = _open(file, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE);
555 >        if (fd >= 0) {
556 >          if (_chsize(fd, size) == 0)
557                  gtk_clist_append(GTK_CLIST(volume_list), &file);
558 +          _close(fd);
559 +        }
560          gtk_widget_destroy(GTK_WIDGET(assoc->req));
561          delete assoc;
562   }
# Line 488 | Line 605 | static void cb_remove_volume(...)
605   static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
606   static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
607  
608 + // "Enable external file system" button toggled
609 + static void tb_enableextfs(GtkWidget *widget)
610 + {
611 +        PrefsReplaceBool("enableextfs", GTK_TOGGLE_BUTTON(widget)->active);
612 +        set_volumes_sensitive();
613 + }
614 +
615   // "No CD-ROM Driver" button toggled
616   static void tb_nocdrom(GtkWidget *widget)
617   {
618          PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
619 +        set_volumes_sensitive();
620 + }
621 +
622 + // Add names of CD-ROM devices
623 + static GList *add_cdrom_names(void)
624 + {
625 +        GList *glist = NULL;
626 +
627 +        char rootdir[4] = "X:\\";
628 +        for (char letter = 'C'; letter <= 'Z'; letter++) {
629 +                rootdir[0] = letter;
630 +                if (GetDriveType(rootdir) == DRIVE_CDROM)
631 +                        glist = g_list_append(glist, strdup(rootdir));
632 +        }
633 +
634 +        return glist;
635 + }
636 +
637 + // "Enable polling" button toggled
638 + static void tb_pollmedia(GtkWidget *widget)
639 + {
640 +        PrefsReplaceBool("pollmedia", GTK_TOGGLE_BUTTON(widget)->active);
641   }
642  
643   // Read settings from widgets and set preferences
# Line 505 | Line 651 | static void read_volumes_settings(void)
651                  gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
652                  PrefsAddString("disk", str);
653          }
654 +
655 +        const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_cdrom_drive)->entry));
656 +        if (str && strlen(str))
657 +                PrefsReplaceString("cdrom", str);
658 +        else
659 +                PrefsRemoveItem("cdrom");
660 +
661 +        PrefsReplaceString("extdrives", get_file_entry_path(w_extdrives));
662   }
663  
664   // Create "Volumes" pane
# Line 553 | Line 707 | static void create_volumes_pane(GtkWidge
707          menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
708  
709          make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
710 +
711 +        GList *glist = add_cdrom_names();
712 +        str = const_cast<char *>(PrefsFindString("cdrom"));
713 +        if (str == NULL)
714 +                str = "";
715 +        w_cdrom_drive = make_combobox(box, STR_CDROM_DRIVE_CTRL, str, glist);
716 +
717 +        make_checkbox(box, STR_POLLMEDIA_CTRL, "pollmedia", GTK_SIGNAL_FUNC(tb_pollmedia));
718 +
719 +        make_separator(box);
720 +        w_enableextfs = make_checkbox(box, STR_EXTFS_ENABLE_CTRL, "enableextfs", GTK_SIGNAL_FUNC(tb_enableextfs));
721 +        w_extdrives = make_file_entry(box, STR_EXTFS_DRIVES_CTRL, "extdrives", true);
722 +
723 +        set_volumes_sensitive();
724   }
725  
726  
# Line 560 | Line 728 | static void create_volumes_pane(GtkWidge
728   *  "JIT Compiler" pane
729   */
730  
731 + #ifndef SHEEPSHAVER
732   static GtkWidget *w_jit_fpu;
733   static GtkWidget *w_jit_atraps;
734   static GtkWidget *w_jit_cache_size;
735   static GtkWidget *w_jit_lazy_flush;
736   static GtkWidget *w_jit_follow_const_jumps;
737 + #endif
738  
739   // Set sensitivity of widgets
740   static void set_jit_sensitive(void)
741   {
742 + #ifndef SHEEPSHAVER
743          const bool jit_enabled = PrefsFindBool("jit");
744          gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
745          gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
746          gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
747          gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
748 + #endif
749   }
750  
751   // "Use JIT Compiler" button toggled
# Line 584 | Line 756 | static void tb_jit(GtkWidget *widget)
756   }
757  
758   // "Compile FPU Instructions" button toggled
759 + #ifndef SHEEPSHAVER
760   static void tb_jit_fpu(GtkWidget *widget)
761   {
762          PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
763   }
764 + #endif
765  
766   // "Lazy translation cache invalidation" button toggled
767 + #ifndef SHEEPSHAVER
768   static void tb_jit_lazy_flush(GtkWidget *widget)
769   {
770          PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
771   }
772 + #endif
773  
774   // "Translate through constant jumps (inline blocks)" button toggled
775 + #ifndef SHEEPSHAVER
776   static void tb_jit_follow_const_jumps(GtkWidget *widget)
777   {
778          PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
779   }
780 + #endif
781  
782   // Read settings from widgets and set preferences
783   static void read_jit_settings(void)
# Line 607 | Line 785 | static void read_jit_settings(void)
785   #if USE_JIT
786          bool jit_enabled = PrefsFindBool("jit");
787          if (jit_enabled) {
788 + #ifndef SHEEPSHAVER
789                  const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
790                  PrefsReplaceInt32("jitcachesize", atoi(str));
791 + #endif
792          }
793   #endif
794   }
795  
796 + // "Use built-in 68k DR emulator" button toggled
797 + #ifdef SHEEPSHAVER
798 + static void tb_jit_68k(GtkWidget *widget)
799 + {
800 +        PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active);
801 + }
802 + #endif
803 +
804   // Create "JIT Compiler" pane
805   static void create_jit_pane(GtkWidget *top)
806   {
# Line 623 | Line 811 | static void create_jit_pane(GtkWidget *t
811          box = make_pane(top, STR_JIT_PANE_TITLE);
812          make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
813          
814 + #ifndef SHEEPSHAVER
815          w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
816          
817          // Translation cache size
# Line 633 | Line 822 | static void create_jit_pane(GtkWidget *t
822                  STR_JIT_CACHE_SIZE_16MB_LAB,
823                  0
824          };
825 <        w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
825 >        sprintf(str, "%d", PrefsFindInt32("jitcachesize"));
826 >        w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, str, options);
827          
828          // Lazy translation cache invalidation
829          w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
830  
831          // Follow constant jumps (inline basic blocks)
832          w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
833 + #endif
834  
835          set_jit_sensitive();
836   #endif
837 +
838 + #ifdef SHEEPSHAVER
839 +        make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k));
840 + #endif
841   }
842  
843   /*
# Line 654 | Line 849 | static GtkWidget *w_scsi[7];
849   // Read settings from widgets and set preferences
850   static void read_scsi_settings(void)
851   {
852 + #ifndef DISABLE_SCSI
853          for (int id=0; id<7; id++) {
854                  char prefs_name[32];
855                  sprintf(prefs_name, "scsi%d", id);
# Line 663 | Line 859 | static void read_scsi_settings(void)
859                  else
860                          PrefsRemoveItem(prefs_name);
861          }
862 + #endif
863   }
864  
865   // Create "SCSI" pane
866   static void create_scsi_pane(GtkWidget *top)
867   {
868 + #ifndef DISABLE_SCSI
869          GtkWidget *box;
870  
871          box = make_pane(top, STR_SCSI_PANE_TITLE);
# Line 677 | Line 875 | static void create_scsi_pane(GtkWidget *
875                  sprintf(prefs_name, "scsi%d", id);
876                  w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
877          }
878 + #endif
879   }
880  
881  
# Line 720 | Line 919 | static void mn_fullscreen(...)
919   {
920          display_type = DISPLAY_SCREEN;
921          hide_show_graphics_widgets();
922 +        PrefsReplaceInt32("frameskip", 1);
923   }
924  
925   // "5 Hz".."60Hz" selected
# Line 731 | Line 931 | static void mn_30hz(...) {PrefsReplaceIn
931   static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
932   static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
933  
934 + // QuickDraw acceleration
935 + #ifdef SHEEPSHAVER
936 + static void tb_gfxaccel(GtkWidget *widget)
937 + {
938 +        PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
939 + }
940 + #endif
941 +
942   // Set sensitivity of widgets
943   static void set_graphics_sensitive(void)
944   {
# Line 748 | Line 956 | static void tb_nosound(GtkWidget *widget
956   static void parse_graphics_prefs(void)
957   {
958          display_type = DISPLAY_WINDOW;
959 + #ifdef SHEEPSHAVER
960 +        dis_width = 640;
961 +        dis_height = 480;
962 + #else
963          dis_width = 512;
964          dis_height = 384;
965 + #endif
966  
967          const char *str = PrefsFindString("screen");
968          if (str) {
# Line 889 | Line 1102 | static void create_graphics_pane(GtkWidg
1102          gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1103          w_display_y = GTK_COMBO(combo)->entry;
1104  
1105 + #ifdef SHEEPSHAVER
1106 +        make_checkbox(box, STR_GFXACCEL_CTRL, "gfxaccel", GTK_SIGNAL_FUNC(tb_gfxaccel));
1107 + #endif
1108 +
1109          make_separator(box);
1110          make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
1111  
# Line 908 | Line 1125 | static GtkWidget *w_mouse_wheel_lines;
1125   // Set sensitivity of widgets
1126   static void set_input_sensitive(void)
1127   {
1128 <        gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
1128 >        const bool use_keycodes = PrefsFindBool("keycodes");
1129 >        gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1130 >        gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1131          gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1132   }
1133  
# Line 938 | Line 1157 | static void read_input_settings(void)
1157   // Create "Input" pane
1158   static void create_input_pane(GtkWidget *top)
1159   {
1160 <        GtkWidget *box, *hbox, *menu, *label;
1160 >        GtkWidget *box, *hbox, *menu, *label, *button;
1161          GtkObject *adj;
1162  
1163          box = make_pane(top, STR_INPUT_PANE_TITLE);
1164  
1165          make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1166 <        w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1166 >
1167 >        hbox = gtk_hbox_new(FALSE, 4);
1168 >        gtk_widget_show(hbox);
1169 >        gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1170 >
1171 >        label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1172 >        gtk_widget_show(label);
1173 >        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1174 >
1175 >        const char *str = PrefsFindString("keycodefile");
1176 >        if (str == NULL)
1177 >                str = "";
1178 >
1179 >        w_keycode_file = gtk_entry_new();
1180 >        gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1181 >        gtk_widget_show(w_keycode_file);
1182 >        gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1183 >
1184 >        button = make_browse_button(w_keycode_file);
1185 >        gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1186 >        g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1187  
1188          make_separator(box);
1189  
# Line 978 | Line 1217 | static void create_input_pane(GtkWidget
1217  
1218  
1219   /*
1220 < *  "Ports" pane
1220 > *  "Serial" pane
1221   */
1222  
1223 < static GtkWidget *w_seriala, *w_portfile0, *w_portfile0_browse;
1224 < static GtkWidget *w_serialb, *w_portfile1, *w_portfile1_browse;
1223 > static GtkWidget *w_seriala, *w_portfile0;
1224 > static GtkWidget *w_serialb, *w_portfile1;
1225  
1226   // Set sensitivity of widgets
1227   static void set_serial_sensitive(void)
# Line 993 | Line 1232 | static void set_serial_sensitive(void)
1232          str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1233          is_file = strcmp(str, "FILE") == 0;
1234          gtk_widget_set_sensitive(w_portfile0, is_file);
1235 <        gtk_widget_set_sensitive(w_portfile0_browse, is_file);
1235 >        gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile0), "chooser_button")), is_file);
1236  
1237          str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1238          is_file = strcmp(str, "FILE") == 0;
1239          gtk_widget_set_sensitive(w_portfile1, is_file);
1240 <        gtk_widget_set_sensitive(w_portfile1_browse, is_file);
1240 >        gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile1), "chooser_button")), is_file);
1241   }
1242  
1243   // Read settings from widgets and set preferences
# Line 1022 | Line 1261 | static void read_serial_settings(void)
1261   // Port changed in combo
1262   static void cb_serial_port_changed(...)
1263   {
1025        printf("serial port changed\n");
1264          set_serial_sensitive();
1265   }
1266  
# Line 1044 | Line 1282 | static GList *add_serial_names(void)
1282          return glist;
1283   }
1284  
1285 < // Create "Ports" pane
1285 > // Create "Serial" pane
1286   static void create_serial_pane(GtkWidget *top)
1287   {
1288          GtkWidget *box, *hbox, *table, *label, *combo, *sep, *entry;
# Line 1053 | Line 1291 | static void create_serial_pane(GtkWidget
1291          box = make_pane(top, STR_SERIAL_PANE_TITLE);
1292          table = make_table(box, 2, 5);
1293  
1056        label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1057        gtk_widget_show(label);
1058        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1059
1294          GList *glist = add_serial_names();
1061        combo = gtk_combo_new();
1062        gtk_widget_show(combo);
1063        gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1295          const char *str = PrefsFindString("seriala");
1296 <        if (str == NULL)
1066 <                str = "";
1067 <        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1068 <        gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1296 >        combo = table_make_combobox(table, 0, STR_SERIALA_CTRL, str, glist);
1297          w_seriala = GTK_COMBO(combo)->entry;
1298          gtk_signal_connect(GTK_OBJECT(w_seriala), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1299  
1300 <        label = gtk_label_new(GetString(STR_FILE_CTRL));
1073 <        gtk_widget_show(label);
1074 <        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1075 <
1076 <        hbox = gtk_hbox_new(FALSE, 4);
1077 <        gtk_widget_show(hbox);
1078 <        gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1079 <
1080 <        w_portfile0 = gtk_entry_new();
1081 <        str = PrefsFindString("portfile0");
1082 <        if (str == NULL)
1083 <                str = "C:\\B2TEMP0.OUT";
1084 <        gtk_entry_set_text(GTK_ENTRY(w_portfile0), str);
1085 <        gtk_widget_show(w_portfile0);
1086 <        gtk_box_pack_start(GTK_BOX(hbox), w_portfile0, TRUE, TRUE, 0);
1087 <
1088 <        w_portfile0_browse = make_browse_button(w_portfile0);
1089 <        gtk_box_pack_start(GTK_BOX(hbox), w_portfile0_browse, FALSE, FALSE, 0);
1300 >        w_portfile0 = table_make_file_entry(table, 1, STR_FILE_CTRL, "portfile0");
1301  
1302          sep = gtk_hseparator_new();
1303          gtk_widget_show(sep);
1304          gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1305  
1095        label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1096        gtk_widget_show(label);
1097        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1098
1099        combo = gtk_combo_new();
1100        gtk_widget_show(combo);
1101        gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1306          str = PrefsFindString("serialb");
1307 <        if (str == NULL)
1104 <                str = "";
1105 <        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1106 <        gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1307 >        combo = table_make_combobox(table, 3, STR_SERIALB_CTRL, str, glist);
1308          w_serialb = GTK_COMBO(combo)->entry;
1309          gtk_signal_connect(GTK_OBJECT(w_serialb), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1310  
1311 <        label = gtk_label_new(GetString(STR_FILE_CTRL));
1111 <        gtk_widget_show(label);
1112 <        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1113 <
1114 <        hbox = gtk_hbox_new(FALSE, 4);
1115 <        gtk_widget_show(hbox);
1116 <        gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 4, 5, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1117 <
1118 <        w_portfile1 = gtk_entry_new();
1119 <        str = PrefsFindString("portfile1");
1120 <        if (str == NULL)
1121 <                str = "C:\\B2TEMP1.OUT";
1122 <        gtk_entry_set_text(GTK_ENTRY(w_portfile1), str);
1123 <        gtk_widget_show(w_portfile1);
1124 <        gtk_box_pack_start(GTK_BOX(hbox), w_portfile1, TRUE, TRUE, 0);
1125 <
1126 <        w_portfile1_browse = make_browse_button(w_portfile1);
1127 <        gtk_box_pack_start(GTK_BOX(hbox), w_portfile1_browse, FALSE, FALSE, 0);
1311 >        w_portfile1 = table_make_file_entry(table, 4, STR_FILE_CTRL, "portfile1");
1312  
1313          set_serial_sensitive();
1314   }
# Line 1134 | Line 1318 | static void create_serial_pane(GtkWidget
1318   *  "Ethernet" pane
1319   */
1320  
1321 < static GtkWidget *w_ether, *w_udp_port;
1321 > static GtkWidget *w_ether;
1322 > static GtkWidget *w_ftp_port_list, *w_tcp_port_list;
1323 > static const char s_nat_router[] = "NAT/Router module";
1324  
1325   // Set sensitivity of widgets
1326   static void set_ethernet_sensitive(void)
1327   {
1328 +        const char *str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1329 +
1330 +        bool is_nat_router = strcmp(str, s_nat_router) == 0;
1331 +        gtk_widget_set_sensitive(w_ftp_port_list, is_nat_router);
1332 +        gtk_widget_set_sensitive(w_tcp_port_list, is_nat_router);
1333   }
1334  
1335   // Read settings from widgets and set preferences
1336   static void read_ethernet_settings(void)
1337   {
1338          const char *str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1339 <        if (str && strlen(str))
1340 <                PrefsReplaceString("ether", str);
1339 >        if (str && strlen(str) > 6 && strncmp(str, "NDIS: ", 6) == 0)
1340 >                PrefsReplaceString("ether", &str[6]);
1341          else
1342                  PrefsRemoveItem("ether");
1343 +
1344 +        const bool router_enabled = str && strcmp(str, s_nat_router) == 0;
1345 +        PrefsReplaceBool("routerenabled", router_enabled);
1346 +        if (router_enabled) {
1347 +                str = gtk_entry_get_text(GTK_ENTRY(w_ftp_port_list));
1348 +                PrefsReplaceString("ftp_port_list", str);
1349 +                str = gtk_entry_get_text(GTK_ENTRY(w_tcp_port_list));
1350 +                PrefsReplaceString("tcp_port", str);
1351 +        }
1352 + }
1353 +
1354 + // Ethernet emulation type changed in menulist
1355 + static void cb_ether_changed(...)
1356 + {
1357 +        set_ethernet_sensitive();
1358   }
1359  
1360   // Add names of ethernet interfaces
# Line 1157 | Line 1363 | static GList *add_ether_names(void)
1363          GList *glist = NULL;
1364  
1365          // TODO: Get list of all Ethernet interfaces
1366 < #ifdef HAVE_SLIRP
1367 <        static char s_slirp[] = "slirp";
1162 <        glist = g_list_append(glist, s_slirp);
1163 < #endif
1164 < #if 0
1165 <        if (glist)
1166 <                g_list_sort(glist, gl_str_cmp);
1167 <        else
1168 < #endif
1169 <                glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1366 >        glist = g_list_append(glist, (void *)s_nat_router);
1367 >        glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1368          return glist;
1369   }
1370  
# Line 1188 | Line 1386 | static void create_ethernet_pane(GtkWidg
1386          gtk_widget_show(combo);
1387          gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1388          const char *str = PrefsFindString("ether");
1389 <        if (str == NULL)
1390 <                str = "";
1389 >        if (str == NULL || str[0] == '\0') {
1390 >                if (PrefsFindBool("routerenabled"))
1391 >                        str = s_nat_router;
1392 >                else
1393 >                        str = GetString(STR_NONE_LAB);
1394 >        }
1395          gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1396          gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1397          w_ether = GTK_COMBO(combo)->entry;
1398 +        gtk_signal_connect(GTK_OBJECT(w_ether), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL);
1399 +
1400 +        sep = gtk_hseparator_new();
1401 +        gtk_widget_show(sep);
1402 +        gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1403 +
1404 +        label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL));
1405 +        gtk_widget_show(label);
1406 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1407 +
1408 +        entry = gtk_entry_new();
1409 +        str = PrefsFindString("ftp_port_list");
1410 +        if (str == NULL)
1411 +                str = "";
1412 +        gtk_entry_set_text(GTK_ENTRY(entry), str);
1413 +        gtk_widget_show(entry);
1414 +        gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1415 +        w_ftp_port_list = entry;
1416 +
1417 +        label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL));
1418 +        gtk_widget_show(label);
1419 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1420 +
1421 +        entry = gtk_entry_new();
1422 +        str = PrefsFindString("tcp_port");
1423 +        if (str == NULL)
1424 +                str = "";
1425 +        gtk_entry_set_text(GTK_ENTRY(entry), str);
1426 +        gtk_widget_show(entry);
1427 +        gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1428 +        w_tcp_port_list = entry;
1429  
1430          set_ethernet_sensitive();
1431   }
# Line 1202 | Line 1435 | static void create_ethernet_pane(GtkWidg
1435   *  "Memory/Misc" pane
1436   */
1437  
1438 < static GtkObject *w_ramsize_adj;
1438 > static GtkWidget *w_ramsize;
1439   static GtkWidget *w_rom_file;
1440  
1441 + // Don't use CPU when idle?
1442 + #ifdef SHEEPSHAVER
1443 + static void tb_idlewait(GtkWidget *widget)
1444 + {
1445 +        PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1446 + }
1447 + #endif
1448 +
1449   // "Ignore SEGV" button toggled
1450   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1451   static void tb_ignoresegv(GtkWidget *widget)
# Line 1227 | Line 1468 | static void mn_cpu_68040(...) {PrefsRepl
1468   // Read settings from widgets and set preferences
1469   static void read_memory_settings(void)
1470   {
1471 <        PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1471 >        const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1472 >        PrefsReplaceInt32("ramsize", atoi(str) << 20);
1473  
1474 <        const char *str = get_file_entry_path(w_rom_file);
1474 >        str = get_file_entry_path(w_rom_file);
1475          if (str && strlen(str))
1476                  PrefsReplaceString("rom", str);
1477          else
# Line 1240 | Line 1482 | static void read_memory_settings(void)
1482   // Create "Memory/Misc" pane
1483   static void create_memory_pane(GtkWidget *top)
1484   {
1485 <        GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1485 >        GtkWidget *box, *hbox, *table, *label, *scale, *menu;
1486  
1487          box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1488 +        table = make_table(box, 2, 5);
1489  
1490 <        hbox = gtk_hbox_new(FALSE, 4);
1491 <        gtk_widget_show(hbox);
1492 <
1493 <        label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1494 <        gtk_widget_show(label);
1495 <        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1496 <
1497 <        vbox = gtk_vbox_new(FALSE, 4);
1498 <        gtk_widget_show(vbox);
1499 <
1500 <        gfloat min, max;
1501 <        min = 1;
1502 <        max = 1024;
1503 <        w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1504 <        gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1505 <
1506 <        scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1507 <        gtk_widget_show(scale);
1508 <        gtk_scale_set_digits(GTK_SCALE(scale), 0);
1509 <        gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1267 <
1268 <        hbox2 = gtk_hbox_new(FALSE, 4);
1269 <        gtk_widget_show(hbox2);
1270 <
1271 <        char val[32];
1272 <        sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1273 <        label = gtk_label_new(val);
1274 <        gtk_widget_show(label);
1275 <        gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1276 <
1277 <        sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1278 <        label = gtk_label_new(val);
1279 <        gtk_widget_show(label);
1280 <        gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1281 <        gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1282 <        gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1283 <        gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1490 >        static const combo_desc options[] = {
1491 > #ifndef SHEEPSHAVER
1492 >                STR_RAMSIZE_2MB_LAB,
1493 > #endif
1494 >                STR_RAMSIZE_4MB_LAB,
1495 >                STR_RAMSIZE_8MB_LAB,
1496 >                STR_RAMSIZE_16MB_LAB,
1497 >                STR_RAMSIZE_32MB_LAB,
1498 >                STR_RAMSIZE_64MB_LAB,
1499 >                STR_RAMSIZE_128MB_LAB,
1500 >                STR_RAMSIZE_256MB_LAB,
1501 >                STR_RAMSIZE_512MB_LAB,
1502 > #ifndef SHEEPSHAVER
1503 >                STR_RAMSIZE_1024MB_LAB,
1504 > #endif
1505 >                0
1506 >        };
1507 >        char default_ramsize[10];
1508 >        sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1509 >        w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1510  
1511 + #ifndef SHEEPSHAVER
1512          static const opt_desc model_options[] = {
1513                  {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1514                  {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
# Line 1292 | Line 1519 | static void create_memory_pane(GtkWidget
1519                  case 5: active = 0; break;
1520                  case 14: active = 1; break;
1521          }
1522 <        make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1522 >        table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1523 > #endif
1524  
1525   #if EMULATED_68K
1526          static const opt_desc cpu_options[] = {
# Line 1311 | Line 1539 | static void create_memory_pane(GtkWidget
1539                  case 3: active = fpu ? 3 : 2; break;
1540                  case 4: active = 4;
1541          }
1542 <        make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1542 >        table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1543   #endif
1544  
1545 <        w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1545 >        w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1546  
1547   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1548          make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1549   #endif
1550 +
1551 + #ifdef SHEEPSHAVER
1552 +        make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1553 + #endif
1554   }
1555  
1556  
# Line 1361 | Line 1593 | void SysAddSerialPrefs(void)
1593  
1594  
1595   /*
1596 + *  Display alerts
1597 + */
1598 +
1599 + static void display_alert(int title_id, const char *text, int flags)
1600 + {
1601 +        MessageBox(NULL, text, GetString(title_id), MB_OK | flags);
1602 + }
1603 +
1604 + static void ErrorAlert(const char *text)
1605 + {
1606 +        display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP);
1607 + }
1608 +
1609 +
1610 + /*
1611   *  Start standalone GUI
1612   */
1613  
# Line 1379 | Line 1626 | int main(int argc, char *argv[])
1626          // Exit preferences
1627          PrefsExit();
1628  
1629 <        // Transfer control to the Basilisk II executable
1629 >        // Transfer control to the executable
1630          if (start) {
1631 <                printf("Start Basilisk II\n");
1631 >                char path[_MAX_PATH];
1632 >                bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0;
1633 >                if (ok) {
1634 >                        char b2_path[_MAX_PATH];
1635 >                        char *p = strrchr(path, '\\');
1636 >                        *++p = '\0';
1637 >                        SetCurrentDirectory(path);
1638 >                        strcpy(b2_path, path);
1639 >                        strcat(b2_path, PROGRAM_NAME);
1640 >                        strcat(b2_path, ".exe");
1641 >                        HINSTANCE h = ShellExecute(GetDesktopWindow(), "open",
1642 >                                                                           b2_path, "", path, SW_SHOWNORMAL);
1643 >                        if ((int)h <= 32)
1644 >                                ok = false;
1645 >                }
1646 >                if (!ok) {
1647 >                        ErrorAlert("Coult not start " PROGRAM_NAME " executable");
1648 >                        return 1;
1649 >                }
1650          }
1651  
1652          return 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines