OSDN Git Service

Since the contents of Term aren't used, don't bother to call Term_activate() from...
[hengbandforosx/hengbandosx.git] / src / main-cocoa.m
index 16aada0..3cc5dff 100644 (file)
@@ -33,7 +33,7 @@
 #define kVK_ANSI_KeypadEnter 0x4C
 
 static NSString * const AngbandDirectoryNameLib = @"lib";
-static NSString * const AngbandDirectoryNameBase = @"Hengband";
+static NSString * const AngbandDirectoryNameBase = @VERSION_NAME;
 
 static NSString * const AngbandMessageCatalog = @"Localizable";
 static NSString * const AngbandTerminalsDefaultsKey = @"Terminals";
@@ -2110,6 +2110,8 @@ static NSString* get_lib_directory(void);
 static NSString* get_doc_directory(void);
 static NSString* AngbandCorrectedDirectoryPath(NSString *originalPath);
 static void prepare_paths_and_directories(void);
+static void load_prefs(void);
+static void init_windows(void);
 static void handle_open_when_ready(void);
 static void play_sound(int event);
 static BOOL check_events(int wait);
@@ -2175,15 +2177,14 @@ static bool initialized = FALSE;
 
 @implementation AngbandContext
 
-@synthesize hasSubwindowFlags=_hasSubwindowFlags;
-@synthesize windowVisibilityChecked=_windowVisibilityChecked;
-
 - (NSSize)baseSize
 {
-    /* We round the base size down. If we round it up, I believe we may end up
-        * with pixels that nobody "owns" that may accumulate garbage. In general
-        * rounding down is harmless, because any lost pixels may be sopped up by
-        * the border. */
+    /*
+     * We round the base size down. If we round it up, I believe we may end up
+     * with pixels that nobody "owns" that may accumulate garbage. In general
+     * rounding down is harmless, because any lost pixels may be sopped up by
+     * the border.
+     */
     return NSMakeSize(
        floor(self.cols * self.tileSize.width + 2 * self.borderSize.width),
        floor(self.rows * self.tileSize.height + 2 * self.borderSize.height));
@@ -2220,7 +2221,8 @@ static int compare_advances(const void *ap, const void *bp)
     for (i=0; i < GLYPH_COUNT; i++) latinString[i] = (unsigned char)i;
 
     /* Turn that into unichar. Angband uses ISO Latin 1. */
-    NSString *allCharsString = [[NSString alloc] initWithBytes:latinString length:sizeof latinString encoding:NSISOLatin1StringEncoding];
+    NSString *allCharsString = [[NSString alloc] initWithBytes:latinString
+        length:GLYPH_COUNT encoding:NSISOLatin1StringEncoding];
     unichar *unicharString = malloc(GLYPH_COUNT * sizeof(unichar));
     if (unicharString == 0) {
        free(latinString);
@@ -2272,8 +2274,10 @@ static int compare_advances(const void *ap, const void *bp)
         glyphWidths[i] = advances[i].width;
     }
 
-    /* For good non-mono-font support, use the median advance. Start by sorting
-        * all advances. */
+    /*
+     * For good non-mono-font support, use the median advance. Start by sorting
+     * all advances.
+     */
     qsort(advances, GLYPH_COUNT, sizeof *advances, compare_advances);
 
     /* Skip over any initially empty run */
@@ -2285,9 +2289,9 @@ static int compare_advances(const void *ap, const void *bp)
 
     /* Pick the center to find the median */
     CGFloat medianAdvance = 0;
+    /* In case we have all zero advances for some reason */
     if (startIdx < GLYPH_COUNT)
     {
-               /* In case we have all zero advances for some reason */
         medianAdvance = advances[(startIdx + GLYPH_COUNT)/2].width;
     }
 
@@ -2592,57 +2596,6 @@ static int compare_advances(const void *ap, const void *bp)
     self->_rows = nRow;
 }
 
-#if 0
-/* From the Linux mbstowcs(3) man page:
- *   If dest is NULL, n is ignored, and the conversion  proceeds  as  above,
- *   except  that  the converted wide characters are not written out to mem‐
- *   ory, and that no length limit exists.
- */
-static size_t Term_mbcs_cocoa(wchar_t *dest, const char *src, int n)
-{
-    int i;
-    int count = 0;
-
-    /* Unicode code point to UTF-8
-     *  0x0000-0x007f:   0xxxxxxx
-     *  0x0080-0x07ff:   110xxxxx 10xxxxxx
-     *  0x0800-0xffff:   1110xxxx 10xxxxxx 10xxxxxx
-     * 0x10000-0x1fffff: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * Note that UTF-16 limits Unicode to 0x10ffff. This code is not
-     * endian-agnostic.
-     */
-    for (i = 0; i < n || dest == NULL; i++) {
-        if ((src[i] & 0x80) == 0) {
-            if (dest != NULL) dest[count] = src[i];
-            if (src[i] == 0) break;
-        } else if ((src[i] & 0xe0) == 0xc0) {
-            if (dest != NULL) dest[count] = 
-                            (((unsigned char)src[i] & 0x1f) << 6)| 
-                            ((unsigned char)src[i+1] & 0x3f);
-            i++;
-        } else if ((src[i] & 0xf0) == 0xe0) {
-            if (dest != NULL) dest[count] = 
-                            (((unsigned char)src[i] & 0x0f) << 12) | 
-                            (((unsigned char)src[i+1] & 0x3f) << 6) |
-                            ((unsigned char)src[i+2] & 0x3f);
-            i += 2;
-        } else if ((src[i] & 0xf8) == 0xf0) {
-            if (dest != NULL) dest[count] = 
-                            (((unsigned char)src[i] & 0x0f) << 18) | 
-                            (((unsigned char)src[i+1] & 0x3f) << 12) |
-                            (((unsigned char)src[i+2] & 0x3f) << 6) |
-                            ((unsigned char)src[i+3] & 0x3f);
-            i += 3;
-        } else {
-            /* Found an invalid multibyte sequence */
-            return (size_t)-1;
-        }
-        count++;
-    }
-    return count;
-}
-#endif
-
 /**
  * For defaultFont and setDefaultFont.
  */
@@ -2705,7 +2658,6 @@ static __strong NSFont* gDefaultFont = nil;
                                  backing:NSBackingStoreBuffered defer:YES];
        }
 
-
         /* Not to be released when closed */
         [self.primaryWindow setReleasedWhenClosed:NO];
         [self.primaryWindow setExcludedFromWindowsMenu: YES]; /* we're using custom window menu handling */
@@ -3339,7 +3291,6 @@ static int compare_nsrect_yorigin_greater(const void *ap, const void *bp)
     NSGraphicsContext *nsctx = nil;
     CGContextRef ctx = 0;
     NSFont* screenFont = nil;
-    term *old = 0;
     int graf_width = 0, graf_height = 0;
     int overdraw_row = 0, overdraw_max = 0;
     wchar_t blank = 0;
@@ -3347,8 +3298,6 @@ static int compare_nsrect_yorigin_greater(const void *ap, const void *bp)
        rect.origin.x + rect.size.width > self.borderSize.width &&
        rect.origin.y < bottomY &&
        rect.origin.y + rect.size.height > self.borderSize.height) {
-       old = Term;
-       Term_activate(self->terminal);
        nsctx = [NSGraphicsContext currentContext];
        ctx = [nsctx graphicsPort];
        screenFont = [self.angbandViewFont screenFont];
@@ -3374,9 +3323,6 @@ static int compare_nsrect_yorigin_greater(const void *ap, const void *bp)
     if (overdraw_row && invalidCount > 1) {
        sortedRects = malloc(invalidCount * sizeof(NSRect));
        if (sortedRects == 0) {
-           if (old != 0) {
-               Term_activate(old);
-           }
            NSException *exc = [NSException exceptionWithName:@"OutOfMemory"
                                            reason:@"sorted rects in drawRect"
                                            userInfo:nil];
@@ -3723,9 +3669,6 @@ static int compare_nsrect_yorigin_greater(const void *ap, const void *bp)
     }
 
     free(sortedRects);
-    if (old != 0) {
-       Term_activate(old);
-    }
 }
 
 - (BOOL)isOrderedIn
@@ -4293,10 +4236,9 @@ static void Term_init_cocoa(term *t)
                 * This is a bit of a trick to allow us to display multiple
                 * windows in the "standard default" window position in OS X:
                 * the upper center of the screen.  The term sizes set in
-                * AngbandAppDelegate's loadPrefs() are based on a 5-wide by
-                * 3-high grid, with the main term being 4/5 wide by 2/3 high
-                * (hence the scaling to find what the containing rect would
-                * be).
+                * load_prefs() are based on a 5-wide by 3-high grid, with the
+                * main term being 4/5 wide by 2/3 high (hence the scaling to
+                * find what the containing rect would be).
                 */
                NSRect originalMainTermFrame = [window frame];
                NSRect scaledFrame = originalMainTermFrame;
@@ -4411,8 +4353,8 @@ static void Term_nuke_cocoa(term *t)
 }
 
 /**
- * Returns the CGImageRef corresponding to an image with the given name in the
- * resource directory, transferring ownership to the caller
+ * Returns the CGImageRef corresponding to an image with the given path.
+ * Transfers ownership to the caller.
  */
 static CGImageRef create_angband_image(NSString *path)
 {
@@ -4428,16 +4370,20 @@ static CGImageRef create_angband_image(NSString *path)
             CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, (CFDictionaryRef)options);
             if (source)
             {
-                /* We really want the largest image, but in practice there's
-                                * only going to be one */
+                /*
+                 * We really want the largest image, but in practice there's
+                 * only going to be one
+                 */
                 decodedImage = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)options);
                 CFRelease(source);
             }
         }
     }
     
-    /* Draw the sucker to defeat ImageIO's weird desire to cache and decode on
-        * demand. Our images aren't that big! */
+    /*
+     * Draw the sucker to defeat ImageIO's weird desire to cache and decode on
+     * demand. Our images aren't that big!
+     */
     if (decodedImage)
     {
         size_t width = CGImageGetWidth(decodedImage), height = CGImageGetHeight(decodedImage);
@@ -4531,7 +4477,6 @@ static errr Term_xtra_cocoa_react(void)
                        @"Could not load the tile set.  Switched back to ASCII.",
                        @"Alert informative message for failed tile set load");
                    NSAlert *alert = [[NSAlert alloc] init];
-
                    alert.messageText = msg;
                    alert.informativeText = info;
                    [alert runModal];
@@ -4792,11 +4737,15 @@ static errr Term_pict_cocoa(TERM_LEN x, TERM_LEN y, int n,
     }
 
     for (int i = x; i < x + n * step; i += step) {
-       TERM_COLOR a = *ap++;
-       char c = *cp++;
-       TERM_COLOR ta = *tap++;
-       char tc = *tcp++;
-
+       TERM_COLOR a = *ap;
+       char c = *cp;
+       TERM_COLOR ta = *tap;
+       char tc = *tcp;
+
+       ap += step;
+       cp += step;
+       tap += step;
+       tcp += step;
        if (use_graphics && (a & 0x80) && (c & 0x80)) {
            char fgdRow = ((byte)a & 0x7F) % pict_rows;
            char fgdCol = ((byte)c & 0x7F) % pict_cols;
@@ -4847,6 +4796,57 @@ static errr Term_text_cocoa(
     return 0;
 }
 
+#if 0
+/* From the Linux mbstowcs(3) man page:
+ *   If dest is NULL, n is ignored, and the conversion  proceeds  as  above,
+ *   except  that  the converted wide characters are not written out to mem‐
+ *   ory, and that no length limit exists.
+ */
+static size_t Term_mbcs_cocoa(wchar_t *dest, const char *src, int n)
+{
+    int i;
+    int count = 0;
+
+    /* Unicode code point to UTF-8
+     *  0x0000-0x007f:   0xxxxxxx
+     *  0x0080-0x07ff:   110xxxxx 10xxxxxx
+     *  0x0800-0xffff:   1110xxxx 10xxxxxx 10xxxxxx
+     * 0x10000-0x1fffff: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+     * Note that UTF-16 limits Unicode to 0x10ffff. This code is not
+     * endian-agnostic.
+     */
+    for (i = 0; i < n || dest == NULL; i++) {
+        if ((src[i] & 0x80) == 0) {
+            if (dest != NULL) dest[count] = src[i];
+            if (src[i] == 0) break;
+        } else if ((src[i] & 0xe0) == 0xc0) {
+            if (dest != NULL) dest[count] =
+                            (((unsigned char)src[i] & 0x1f) << 6)|
+                            ((unsigned char)src[i+1] & 0x3f);
+            i++;
+        } else if ((src[i] & 0xf0) == 0xe0) {
+            if (dest != NULL) dest[count] =
+                            (((unsigned char)src[i] & 0x0f) << 12) |
+                            (((unsigned char)src[i+1] & 0x3f) << 6) |
+                            ((unsigned char)src[i+2] & 0x3f);
+            i += 2;
+        } else if ((src[i] & 0xf8) == 0xf0) {
+            if (dest != NULL) dest[count] =
+                            (((unsigned char)src[i] & 0x0f) << 18) |
+                            (((unsigned char)src[i+1] & 0x3f) << 12) |
+                            (((unsigned char)src[i+2] & 0x3f) << 6) |
+                            ((unsigned char)src[i+3] & 0x3f);
+            i += 3;
+        } else {
+            /* Found an invalid multibyte sequence */
+            return (size_t)-1;
+        }
+        count++;
+    }
+    return count;
+}
+#endif
+
 /**
  * Handle redrawing for a change to the tile set, tile scaling, or main window
  * font.  Returns YES if the redrawing was initiated.  Otherwise returns NO.
@@ -5234,7 +5234,7 @@ static NSString* get_lib_directory(void)
 
     if( !libExists || !isDirectory )
     {
-       NSLog( @"Hengband: can't find %@/ in bundle: isDirectory: %d libExists: %d", AngbandDirectoryNameLib, isDirectory, libExists );
+       NSLog( @"%@: can't find %@/ in bundle: isDirectory: %d libExists: %d", @VERSION_NAME, AngbandDirectoryNameLib, isDirectory, libExists );
 
        NSString *msg = NSLocalizedStringWithDefaultValue(
            @"Error.MissingResources",
@@ -5252,7 +5252,6 @@ static NSString* get_lib_directory(void)
            @"Label.Quit", AngbandMessageCatalog, [NSBundle mainBundle],
            @"Quit", @"Quit");
        NSAlert *alert = [[NSAlert alloc] init];
-
        /*
         * Note that NSCriticalAlertStyle was deprecated in 10.10.  The
         * replacement is NSAlertStyleCritical.
@@ -5262,7 +5261,7 @@ static NSString* get_lib_directory(void)
        alert.informativeText = info;
        [alert addButtonWithTitle:quit_label];
        [alert runModal];
-       exit( 0 );
+       exit(0);
     }
 
     return bundleLibPath;
@@ -5326,6 +5325,174 @@ static void prepare_paths_and_directories(void)
 }
 
 /**
+ * Create and initialize Angband terminal number "i".
+ */
+static term *term_data_link(int i)
+{
+    NSArray *terminalDefaults = [[NSUserDefaults standardUserDefaults]
+                                   valueForKey: AngbandTerminalsDefaultsKey];
+    NSInteger rows = 24;
+    NSInteger columns = 80;
+
+    if (i < (int)[terminalDefaults count]) {
+        NSDictionary *term = [terminalDefaults objectAtIndex:i];
+        rows = [[term valueForKey: AngbandTerminalRowsDefaultsKey]
+                  integerValue];
+        columns = [[term valueForKey: AngbandTerminalColumnsDefaultsKey]
+                     integerValue];
+    }
+
+    /* Allocate */
+    term *newterm = ZNEW(term);
+
+    /* Initialize the term */
+    term_init(newterm, columns, rows, 256 /* keypresses, for some reason? */);
+
+    /* Use a "software" cursor */
+    newterm->soft_cursor = TRUE;
+
+    /* Disable the per-row flush notifications since they are not used. */
+    newterm->never_frosh = TRUE;
+
+    /*
+     * Differentiate between BS/^h, Tab/^i, ... so ^h and ^j work under the
+     * roguelike command set.
+     */
+    /* newterm->complex_input = TRUE; */
+
+    /* Erase with "white space" */
+    newterm->attr_blank = TERM_WHITE;
+    newterm->char_blank = ' ';
+
+    /* Prepare the init/nuke hooks */
+    newterm->init_hook = Term_init_cocoa;
+    newterm->nuke_hook = Term_nuke_cocoa;
+
+    /* Prepare the function hooks */
+    newterm->xtra_hook = Term_xtra_cocoa;
+    newterm->wipe_hook = Term_wipe_cocoa;
+    newterm->curs_hook = Term_curs_cocoa;
+    newterm->bigcurs_hook = Term_bigcurs_cocoa;
+    newterm->text_hook = Term_text_cocoa;
+    newterm->pict_hook = Term_pict_cocoa;
+    /* newterm->mbcs_hook = Term_mbcs_cocoa; */
+
+    /* Global pointer */
+    angband_term[i] = newterm;
+
+    return newterm;
+}
+
+/**
+ * Load preferences from preferences file for current host+current user+
+ * current application.
+ */
+static void load_prefs(void)
+{
+    NSUserDefaults *defs = [NSUserDefaults angbandDefaults];
+
+    /* Make some default defaults */
+    NSMutableArray *defaultTerms = [[NSMutableArray alloc] init];
+
+    /*
+     * The following default rows/cols were determined experimentally by first
+     * finding the ideal window/font size combinations. But because of awful
+     * temporal coupling in Term_init_cocoa(), it's impossible to set up the
+     * defaults there, so we do it this way.
+     */
+    for (NSUInteger i = 0; i < ANGBAND_TERM_MAX; i++) {
+       int columns, rows;
+       BOOL visible = YES;
+
+       switch (i) {
+       case 0:
+           columns = 129;
+           rows = 32;
+           break;
+       case 1:
+           columns = 84;
+           rows = 20;
+           break;
+       case 2:
+           columns = 42;
+           rows = 24;
+           break;
+       case 3:
+           columns = 42;
+           rows = 20;
+           break;
+       case 4:
+           columns = 42;
+           rows = 16;
+           break;
+       case 5:
+           columns = 84;
+           rows = 20;
+           break;
+       default:
+           columns = 80;
+           rows = 24;
+           visible = NO;
+           break;
+       }
+
+       NSDictionary *standardTerm =
+           [NSDictionary dictionaryWithObjectsAndKeys:
+                         [NSNumber numberWithInt: rows], AngbandTerminalRowsDefaultsKey,
+                         [NSNumber numberWithInt: columns], AngbandTerminalColumnsDefaultsKey,
+                         [NSNumber numberWithBool: visible], AngbandTerminalVisibleDefaultsKey,
+                         nil];
+        [defaultTerms addObject: standardTerm];
+    }
+
+    NSDictionary *defaults = [[NSDictionary alloc] initWithObjectsAndKeys:
+#ifdef JP
+                              @"Osaka", @"FontName",
+#else
+                              @"Menlo", @"FontName",
+#endif
+                              [NSNumber numberWithFloat:13.f], @"FontSize",
+                              [NSNumber numberWithInt:60], AngbandFrameRateDefaultsKey,
+                              [NSNumber numberWithBool:YES], AngbandSoundDefaultsKey,
+                              [NSNumber numberWithInt:GRAPHICS_NONE], AngbandGraphicsDefaultsKey,
+                              [NSNumber numberWithBool:YES], AngbandBigTileDefaultsKey,
+                              defaultTerms, AngbandTerminalsDefaultsKey,
+                              nil];
+    [defs registerDefaults:defaults];
+
+    /* Preferred graphics mode */
+    graf_mode_req = [defs integerForKey:AngbandGraphicsDefaultsKey];
+    if (graphics_will_be_enabled() &&
+       [defs boolForKey:AngbandBigTileDefaultsKey] == YES) {
+       use_bigtile = TRUE;
+       arg_bigtile = TRUE;
+    } else {
+       use_bigtile = FALSE;
+       arg_bigtile = FALSE;
+    }
+
+    /* Use sounds; set the Angband global */
+    if ([defs boolForKey:AngbandSoundDefaultsKey] == YES) {
+       use_sound = TRUE;
+       [AngbandSoundCatalog sharedSounds].enabled = YES;
+    } else {
+       use_sound = FALSE;
+       [AngbandSoundCatalog sharedSounds].enabled = NO;
+    }
+
+    /* fps */
+    frames_per_second = [defs integerForKey:AngbandFrameRateDefaultsKey];
+
+    /* Font */
+    [AngbandContext
+       setDefaultFont:[NSFont fontWithName:[defs valueForKey:@"FontName-0"]
+                              size:[defs floatForKey:@"FontSize-0"]]];
+    if (! [AngbandContext defaultFont])
+       [AngbandContext
+           setDefaultFont:[NSFont fontWithName:@"Menlo" size:13.]];
+}
+
+/**
  * Play sound effects asynchronously.  Select a sound from any available
  * for the required event, and bridge to Cocoa to play it.
  */
@@ -5335,6 +5502,24 @@ static void play_sound(int event)
 }
 
 /**
+ * Allocate the primary Angband terminal and activate it.  Allocate the other
+ * Angband terminals.
+ */
+static void init_windows(void)
+{
+    /* Create the primary window */
+    term *primary = term_data_link(0);
+
+    /* Prepare to create any additional windows */
+    for (int i = 1; i < ANGBAND_TERM_MAX; i++) {
+        term_data_link(i);
+    }
+
+    /* Activate the primary term */
+    Term_activate(primary);
+}
+
+/**
  * ------------------------------------------------------------------------
  * Main program
  * ------------------------------------------------------------------------ */
@@ -5481,185 +5666,12 @@ static void play_sound(int event)
     /* Save the game */
     do_cmd_save_game(FALSE);
     
-    /* Record the current save file so we can select it by default next time.
-        * It's a little sketchy that this only happens when we save through the
-        * menu; ideally game-triggered saves would trigger it too. */
-    record_current_savefile();
-}
-
-/**
- * Create and initialize Angband terminal number "termIndex".
- */
-- (void)linkTermData:(int)termIndex
-{
-    NSArray *terminalDefaults = [[NSUserDefaults standardUserDefaults]
-                                   valueForKey: AngbandTerminalsDefaultsKey];
-    NSInteger rows = 24;
-    NSInteger columns = 80;
-
-    if (termIndex < (int)[terminalDefaults count]) {
-        NSDictionary *term = [terminalDefaults objectAtIndex:termIndex];
-        rows = [[term valueForKey: AngbandTerminalRowsDefaultsKey]
-                  integerValue];
-        columns = [[term valueForKey: AngbandTerminalColumnsDefaultsKey]
-                     integerValue];
-    }
-
-    /* Allocate */
-    term *newterm = ZNEW(term);
-
-    /* Initialize the term */
-    term_init(newterm, columns, rows, 256 /* keypresses, for some reason? */);
-
-    /* Differentiate between BS/^h, Tab/^i, etc. */
-    /* newterm->complex_input = TRUE; */
-
-    /* Use a "software" cursor */
-    newterm->soft_cursor = TRUE;
-
-    /* Disable the per-row flush notifications since they are not used. */
-    newterm->never_frosh = TRUE;
-
-    /* Erase with "white space" */
-    newterm->attr_blank = TERM_WHITE;
-    newterm->char_blank = ' ';
-
-    /* Prepare the init/nuke hooks */
-    newterm->init_hook = Term_init_cocoa;
-    newterm->nuke_hook = Term_nuke_cocoa;
-
-    /* Prepare the function hooks */
-    newterm->xtra_hook = Term_xtra_cocoa;
-    newterm->wipe_hook = Term_wipe_cocoa;
-    newterm->curs_hook = Term_curs_cocoa;
-    newterm->bigcurs_hook = Term_bigcurs_cocoa;
-    newterm->text_hook = Term_text_cocoa;
-    newterm->pict_hook = Term_pict_cocoa;
-    /* newterm->mbcs_hook = Term_mbcs_cocoa; */
-
-    /* Global pointer */
-    angband_term[termIndex] = newterm;
-}
-
-/**
- * Allocate the primary Angband terminal and activate it.  Allocate the other
- * Angband terminals.
- */
-- (void)initWindows {
-    for (int i = 0; i < ANGBAND_TERM_MAX; i++) {
-       [self linkTermData:i];
-    }
-
-    Term_activate(angband_term[0]);
-}
-
-/**
- * Load preferences from preferences file for current host+current user+
- * current application.
- */
-- (void)loadPrefs
-{
-    NSUserDefaults *defs = [NSUserDefaults angbandDefaults];
-
-    /* Make some default defaults */
-    NSMutableArray *defaultTerms = [[NSMutableArray alloc] init];
-
     /*
-     * The following default rows/cols were determined experimentally by first
-     * finding the ideal window/font size combinations. But because of awful
-     * temporal coupling in Term_init_cocoa(), it's impossible to set up the
-     * defaults there, so we do it this way.
+     * Record the current save file so we can select it by default next time.
+     * It's a little sketchy that this only happens when we save through the
+     * menu; ideally game-triggered saves would trigger it too.
      */
-    for (NSUInteger i = 0; i < ANGBAND_TERM_MAX; i++) {
-       int columns, rows;
-       BOOL visible = YES;
-
-       switch (i) {
-       case 0:
-           columns = 129;
-           rows = 32;
-           break;
-       case 1:
-           columns = 84;
-           rows = 20;
-           break;
-       case 2:
-           columns = 42;
-           rows = 24;
-           break;
-       case 3:
-           columns = 42;
-           rows = 20;
-           break;
-       case 4:
-           columns = 42;
-           rows = 16;
-           break;
-       case 5:
-           columns = 84;
-           rows = 20;
-           break;
-       default:
-           columns = 80;
-           rows = 24;
-           visible = NO;
-           break;
-       }
-
-       NSDictionary *standardTerm =
-           [NSDictionary dictionaryWithObjectsAndKeys:
-                         [NSNumber numberWithInt: rows], AngbandTerminalRowsDefaultsKey,
-                         [NSNumber numberWithInt: columns], AngbandTerminalColumnsDefaultsKey,
-                         [NSNumber numberWithBool: visible], AngbandTerminalVisibleDefaultsKey,
-                         nil];
-        [defaultTerms addObject: standardTerm];
-    }
-
-    NSDictionary *defaults = [[NSDictionary alloc] initWithObjectsAndKeys:
-#ifdef JP
-                              @"Osaka", @"FontName",
-#else
-                              @"Menlo", @"FontName",
-#endif
-                              [NSNumber numberWithFloat:13.f], @"FontSize",
-                              [NSNumber numberWithInt:60], AngbandFrameRateDefaultsKey,
-                              [NSNumber numberWithBool:YES], AngbandSoundDefaultsKey,
-                              [NSNumber numberWithInt:GRAPHICS_NONE], AngbandGraphicsDefaultsKey,
-                              [NSNumber numberWithBool:YES], AngbandBigTileDefaultsKey,
-                              defaultTerms, AngbandTerminalsDefaultsKey,
-                              nil];
-    [defs registerDefaults:defaults];
-
-    /* Preferred graphics mode */
-    graf_mode_req = [defs integerForKey:AngbandGraphicsDefaultsKey];
-    if (graphics_will_be_enabled() &&
-       [defs boolForKey:AngbandBigTileDefaultsKey] == YES) {
-       use_bigtile = TRUE;
-       arg_bigtile = TRUE;
-    } else {
-       use_bigtile = FALSE;
-       arg_bigtile = FALSE;
-    }
-
-    /* Use sounds; set the Angband global */
-    if ([defs boolForKey:AngbandSoundDefaultsKey] == YES) {
-       use_sound = TRUE;
-       [AngbandSoundCatalog sharedSounds].enabled = YES;
-    } else {
-       use_sound = FALSE;
-       [AngbandSoundCatalog sharedSounds].enabled = NO;
-    }
-
-    /* fps */
-    frames_per_second = [defs integerForKey:AngbandFrameRateDefaultsKey];
-
-    /* Font */
-    [AngbandContext
-       setDefaultFont:[NSFont fontWithName:[defs valueForKey:@"FontName-0"]
-                              size:[defs floatForKey:@"FontSize-0"]]];
-    if (! [AngbandContext defaultFont])
-       [AngbandContext
-           setDefaultFont:[NSFont fontWithName:@"Menlo" size:13.]];
+    record_current_savefile();
 }
 
 /**
@@ -5682,10 +5694,10 @@ static void play_sound(int event)
        init_graphics_modes();
 
        /* Load preferences */
-       [self loadPrefs];
+       load_prefs();
 
        /* Prepare the windows */
-       [self initWindows];
+       init_windows();
 
        /* Set up game event handlers */
        /* init_display(); */
@@ -5693,12 +5705,13 @@ static void play_sound(int event)
        /* Register the sound hook */
        /* sound_hook = play_sound; */
 
-       /* Initialise game */
-       init_angband();
-
        /* Initialize some save file stuff */
+       player_euid = geteuid();
        player_egid = getegid();
 
+       /* Initialise game */
+       init_angband();
+
        /* We are now initialized */
        initialized = TRUE;
 
@@ -5747,7 +5760,7 @@ static void play_sound(int event)
 /**
  * Implement NSObject's validateMenuItem() method to override enabling or
  * disabling a menu item.  Note that, as of 10.14, validateMenuItem() is
- * deprecated in NSObject - it will be removed at some point and  the
+ * deprecated in NSObject - it will be removed at some point and the
  * application delegate will have to be declared as implementing the
  * NSMenuItemValidation protocol.
  */
@@ -5812,6 +5825,13 @@ static void play_sound(int event)
        [menuItem setState: ((is_on) ? NSOnState : NSOffState)];
        return YES;
     }
+    else if (sel == @selector(toggleWideTiles:)) {
+       BOOL is_on = [[NSUserDefaults standardUserDefaults]
+                        boolForKey:AngbandBigTileDefaultsKey];
+
+       [menuItem setState: ((is_on) ? NSOnState : NSOffState)];
+       return YES;
+    }
     else if( sel == @selector(sendAngbandCommand:) ||
             sel == @selector(saveGame:) )
     {