static NSString * const AngbandTerminalColumnsDefaultsKey = @"Columns";
static NSString * const AngbandTerminalVisibleDefaultsKey = @"Visible";
static NSString * const AngbandGraphicsDefaultsKey = @"GraphicsID";
+static NSString * const AngbandBigTileDefaultsKey = @"UseBigTiles";
static NSString * const AngbandFrameRateDefaultsKey = @"FramesPerSecond";
static NSString * const AngbandSoundDefaultsKey = @"AllowSound";
static NSInteger const AngbandWindowMenuItemTagBase = 1000;
- (void)saveWindowVisibleToDefaults: (BOOL)windowVisible;
- (BOOL)windowVisibleUsingDefaults;
-/* Class methods */
-
-/* Begins an Angband game. This is the entry point for starting off. */
-+ (void)beginGame;
-
/* Internal method */
- (AngbandView *)activeView;
static void wakeup_event_loop(void);
static void hook_plog(const char *str);
static void hook_quit(const char * str);
+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 load_sounds(void);
static void init_windows(void);
[super dealloc];
}
-
-
-#pragma mark -
-#pragma mark Directories and Paths Setup
-
-/**
- * Return the path for Angband's lib directory and bail if it isn't found. The
- * lib directory should be in the bundle's resources directory, since it's
- * copied when built.
- */
-+ (NSString *)libDirectoryPath
-{
- NSString *bundleLibPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: AngbandDirectoryNameLib];
- BOOL isDirectory = NO;
- BOOL libExists = [[NSFileManager defaultManager] fileExistsAtPath: bundleLibPath isDirectory: &isDirectory];
-
- if( !libExists || !isDirectory )
- {
- NSLog( @"[%@ %@]: can't find %@/ in bundle: isDirectory: %d libExists: %d", NSStringFromClass( [self class] ), NSStringFromSelector( _cmd ), AngbandDirectoryNameLib, isDirectory, libExists );
-
- NSString *msg = NSLocalizedStringWithDefaultValue(
- @"Error.MissingResources",
- AngbandMessageCatalog,
- [NSBundle mainBundle],
- @"Missing Resources",
- @"Alert text for missing resources");
- NSString *info = NSLocalizedStringWithDefaultValue(
- @"Error.MissingAngbandLib",
- AngbandMessageCatalog,
- [NSBundle mainBundle],
- @"Hengband was unable to find required resources and must quit. Please report a bug on the Angband forums.",
- @"Alert informative message for missing Angband lib/ folder");
- NSString *quit_label = NSLocalizedStringWithDefaultValue(
- @"Label.Quit", AngbandMessageCatalog, [NSBundle mainBundle],
- @"Quit", @"Quit");
- NSAlert *alert = [[NSAlert alloc] init];
-
- /*
- * Note that NSCriticalAlertStyle was deprecated in 10.10. The
- * replacement is NSAlertStyleCritical.
- */
- alert.alertStyle = NSCriticalAlertStyle;
- alert.messageText = msg;
- alert.informativeText = info;
- [alert addButtonWithTitle:quit_label];
- NSModalResponse result = [alert runModal];
- [alert release];
- exit( 0 );
- }
-
- return bundleLibPath;
-}
-
-/**
- * Return the path for the directory where Angband should look for its standard
- * user file tree.
- */
-+ (NSString *)angbandDocumentsPath
-{
- NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
-
-#if defined(SAFE_DIRECTORY)
- NSString *versionedDirectory = [NSString stringWithFormat: @"%@-%s", AngbandDirectoryNameBase, VERSION_STRING];
- return [documents stringByAppendingPathComponent: versionedDirectory];
-#else
- return [documents stringByAppendingPathComponent: AngbandDirectoryNameBase];
-#endif
-}
-
-/**
- * Adjust directory paths as needed to correct for any differences needed by
- * Angband. \c init_file_paths() currently requires that all paths provided have
- * a trailing slash and all other platforms honor this.
- *
- * \param originalPath The directory path to adjust.
- * \return A path suitable for Angband or nil if an error occurred.
- */
-static NSString *AngbandCorrectedDirectoryPath(NSString *originalPath)
-{
- if ([originalPath length] == 0) {
- return nil;
- }
-
- if (![originalPath hasSuffix: @"/"]) {
- return [originalPath stringByAppendingString: @"/"];
- }
-
- return originalPath;
-}
-
-/**
- * Give Angband the base paths that should be used for the various directories
- * it needs. It will create any needed directories.
- */
-+ (void)prepareFilePathsAndDirectories
-{
- char libpath[PATH_MAX + 1] = "\0";
- NSString *libDirectoryPath = AngbandCorrectedDirectoryPath([self libDirectoryPath]);
- [libDirectoryPath getFileSystemRepresentation: libpath maxLength: sizeof(libpath)];
-
- char basepath[PATH_MAX + 1] = "\0";
- NSString *angbandDocumentsPath = AngbandCorrectedDirectoryPath([self angbandDocumentsPath]);
- [angbandDocumentsPath getFileSystemRepresentation: basepath maxLength: sizeof(basepath)];
-
- init_file_paths(libpath, basepath);
- create_needed_dirs();
-}
-
-#pragma mark -
-
#if 0
/* From the Linux mbstowcs(3) man page:
* If dest is NULL, n is ignored, and the conversion proceeds as above,
}
#endif
-/**
- * Entry point for initializing Angband
- */
-+ (void)beginGame
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- /* Hooks in some "z-util.c" hooks */
- plog_aux = hook_plog;
- quit_aux = hook_quit;
-
- /* Initialize file paths */
- [self prepareFilePathsAndDirectories];
-
- /* Note the "system" */
- ANGBAND_SYS = "coc";
-
- /* Load preferences */
- load_prefs();
-
- /* Load possible graphics modes */
- init_graphics_modes();
-
- /* Prepare the windows */
- init_windows();
-
- /* Set up game event handlers */
- /* init_display(); */
-
- /* Register the sound hook */
- /* sound_hook = play_sound; */
-
- /* Initialise game */
- init_angband();
-
- /* Initialize some save file stuff */
- player_egid = getegid();
-
- /* We are now initialized */
- initialized = TRUE;
-
- /* Handle "open_when_ready" */
- handle_open_when_ready();
-
- /* Handle pending events (most notably update) and flush input */
- Term_flush();
-
- /* Prompt the user. */
- int message_row = (Term->hgt - 23) / 5 + 23;
- Term_erase(0, message_row, 255);
- put_str(
-#ifdef JP
- "['ファイル' メニューから '新' または '開く' を選択します]",
- message_row, (Term->wid - 57) / 2
-#else
- "[Choose 'New' or 'Open' from the 'File' menu]",
- message_row, (Term->wid - 45) / 2
-#endif
- );
- Term_fresh();
-
- /*
- * Play a game -- "new_game" is set by "new", "open" or the open document
- * even handler as appropriate
- */
-
- [pool drain];
-
- while (!game_in_progress) {
- NSAutoreleasePool *splashScreenPool = [[NSAutoreleasePool alloc] init];
- NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES];
- if (event) [NSApp sendEvent:event];
- [splashScreenPool drain];
- }
-
- Term_fresh();
- play_game(new_game);
-
- quit(NULL);
-}
-
- (void)addAngbandView:(AngbandView *)view
{
if (! [angbandViews containsObject:view])
/* If we failed to create the image, revert to ASCII. */
if (! pict_image) {
new_mode = NULL;
+ if (use_bigtile) {
+ arg_bigtile = FALSE;
+ }
[[NSUserDefaults angbandDefaults]
setInteger:GRAPHICS_NONE
forKey:AngbandGraphicsDefaultsKey];
}
/* Reset visuals */
- if (initialized && game_in_progress)
+ if (arg_bigtile == use_bigtile)
{
reset_visuals();
}
}
+ if (arg_bigtile != use_bigtile) {
+ /* Reset visuals */
+ reset_visuals();
+
+ Term_activate(angband_term[0]);
+ Term_resize(angband_term[0]->wid, angband_term[0]->hgt);
+ }
+
[pool drain];
/* Success */
*/
break;
} else if (prc->cell_changes[i].change_type == CELL_CHANGE_NONE) {
- /* It has not changed so inquire what it is. */
+ /*
+ * It has not changed (or using big tile mode and it is within
+ * a changed tile but is not the left cell for that tile) so
+ * inquire what it is.
+ */
TERM_COLOR a[2];
char c[2];
*/
break;
}
+ if (use_bigtile && i > 0) {
+ Term_what(i - 1, iy, a, c);
+ if (use_graphics && (a[0] & 0x80) && (c[0] & 0x80)) {
+ /*
+ * It is the right cell of a location rendered with a tile.
+ * Do not want to modify its contents so the clipping and
+ * rendering region can not be exteded.
+ */
+ break;
+ }
+ }
/*
* It is unchanged text. A character from the changed region
* may have extended into it so render it to clear that.
NSGraphicsContext *nsContext =
[NSGraphicsContext currentContext];
NSCompositingOperation op = nsContext.compositingOperation;
+ int step = (use_bigtile) ? 2 : 1;
jx = ix;
while (jx <= prc->xmax &&
[angbandContext rectInImageForTileAtX:jx Y:iy];
NSRect sourceRect, terrainRect;
+ destinationRect.size.width *= step;
sourceRect.origin.x = graf_width *
prc->cell_changes[jx].c.c;
sourceRect.origin.y = graf_height *
destinationRect,
NSCompositeCopy);
}
- ++jx;
+ jx += step;
}
[nsContext setCompositingOperation:op];
return result;
}
-static errr Term_curs_cocoa(int x, int y)
+static errr Term_curs_cocoa(TERM_LEN x, TERM_LEN y)
{
AngbandContext *angbandContext = Term->data;
* the cursor points at a kanji character, irregardless of whether operating
* in big tile mode.
*/
-static errr Term_bigcurs_cocoa(int x, int y)
+static errr Term_bigcurs_cocoa(TERM_LEN x, TERM_LEN y)
{
AngbandContext *angbandContext = Term->data;
*
* Erase "n" characters starting at (x,y)
*/
-static errr Term_wipe_cocoa(int x, int y, int n)
+static errr Term_wipe_cocoa(TERM_LEN x, TERM_LEN y, int n)
{
AngbandContext *angbandContext = Term->data;
struct PendingCellChange *pc;
return (0);
}
-static errr Term_pict_cocoa(int x, int y, int n, TERM_COLOR *ap,
- const char *cp, const TERM_COLOR *tap,
- const char *tcp)
+static errr Term_pict_cocoa(TERM_LEN x, TERM_LEN y, int n,
+ TERM_COLOR *ap, concptr cp,
+ const TERM_COLOR *tap, concptr tcp)
{
/* Paranoia: Bail if we don't have a current graphics mode */
*
* Draw several ("n") chars, with an attr, at a given location.
*/
-static errr Term_text_cocoa(int x, int y, int n, byte_hack a, concptr cp)
+static errr Term_text_cocoa(
+ TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, concptr cp)
{
AngbandContext* angbandContext = Term->data;
struct PendingCellChange *pc;
[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 (graf_mode_req != GRAPHICS_NONE &&
+ get_graphics_mode(graf_mode_req)->grafID != GRAPHICS_NONE &&
+ [defs boolForKey:AngbandBigTileDefaultsKey] == YES) {
+ use_bigtile = TRUE;
+ arg_bigtile = TRUE;
+ } else {
+ use_bigtile = FALSE;
+ arg_bigtile = FALSE;
+ }
+
/* Use sounds; set the Angband global */
use_sound = ([defs boolForKey:AngbandSoundDefaultsKey] == YES) ? TRUE : FALSE;
}
/**
+ * Return the path for Angband's lib directory and bail if it isn't found. The
+ * lib directory should be in the bundle's resources directory, since it's
+ * copied when built.
+ */
+static NSString* get_lib_directory(void)
+{
+ NSString *bundleLibPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: AngbandDirectoryNameLib];
+ BOOL isDirectory = NO;
+ BOOL libExists = [[NSFileManager defaultManager] fileExistsAtPath: bundleLibPath isDirectory: &isDirectory];
+
+ if( !libExists || !isDirectory )
+ {
+ NSLog( @"Hengband: can't find %@/ in bundle: isDirectory: %d libExists: %d", AngbandDirectoryNameLib, isDirectory, libExists );
+
+ NSString *msg = NSLocalizedStringWithDefaultValue(
+ @"Error.MissingResources",
+ AngbandMessageCatalog,
+ [NSBundle mainBundle],
+ @"Missing Resources",
+ @"Alert text for missing resources");
+ NSString *info = NSLocalizedStringWithDefaultValue(
+ @"Error.MissingAngbandLib",
+ AngbandMessageCatalog,
+ [NSBundle mainBundle],
+ @"Hengband was unable to find required resources and must quit. Please report a bug on the Angband forums.",
+ @"Alert informative message for missing Angband lib/ folder");
+ NSString *quit_label = NSLocalizedStringWithDefaultValue(
+ @"Label.Quit", AngbandMessageCatalog, [NSBundle mainBundle],
+ @"Quit", @"Quit");
+ NSAlert *alert = [[NSAlert alloc] init];
+
+ /*
+ * Note that NSCriticalAlertStyle was deprecated in 10.10. The
+ * replacement is NSAlertStyleCritical.
+ */
+ alert.alertStyle = NSCriticalAlertStyle;
+ alert.messageText = msg;
+ alert.informativeText = info;
+ [alert addButtonWithTitle:quit_label];
+ NSModalResponse result = [alert runModal];
+ [alert release];
+ exit( 0 );
+ }
+
+ return bundleLibPath;
+}
+
+/**
+ * Return the path for the directory where Angband should look for its standard
+ * user file tree.
+ */
+static NSString* get_doc_directory(void)
+{
+ NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
+
+#if defined(SAFE_DIRECTORY)
+ NSString *versionedDirectory = [NSString stringWithFormat: @"%@-%s", AngbandDirectoryNameBase, VERSION_STRING];
+ return [documents stringByAppendingPathComponent: versionedDirectory];
+#else
+ return [documents stringByAppendingPathComponent: AngbandDirectoryNameBase];
+#endif
+}
+
+/**
+ * Adjust directory paths as needed to correct for any differences needed by
+ * Angband. init_file_paths() currently requires that all paths provided have
+ * a trailing slash and all other platforms honor this.
+ *
+ * \param originalPath The directory path to adjust.
+ * \return A path suitable for Angband or nil if an error occurred.
+ */
+static NSString* AngbandCorrectedDirectoryPath(NSString *originalPath)
+{
+ if ([originalPath length] == 0) {
+ return nil;
+ }
+
+ if (![originalPath hasSuffix: @"/"]) {
+ return [originalPath stringByAppendingString: @"/"];
+ }
+
+ return originalPath;
+}
+
+/**
+ * Give Angband the base paths that should be used for the various directories
+ * it needs. It will create any needed directories.
+ */
+static void prepare_paths_and_directories(void)
+{
+ char libpath[PATH_MAX + 1] = "\0";
+ NSString *libDirectoryPath =
+ AngbandCorrectedDirectoryPath(get_lib_directory());
+ [libDirectoryPath getFileSystemRepresentation: libpath maxLength: sizeof(libpath)];
+
+ char basepath[PATH_MAX + 1] = "\0";
+ NSString *angbandDocumentsPath =
+ AngbandCorrectedDirectoryPath(get_doc_directory());
+ [angbandDocumentsPath getFileSystemRepresentation: basepath maxLength: sizeof(basepath)];
+
+ init_file_paths(libpath, basepath);
+ create_needed_dirs();
+}
+
+/**
* ------------------------------------------------------------------------
* Main program
* ------------------------------------------------------------------------ */
}
/**
+ * Entry point for initializing Angband
+ */
+- (void)beginGame
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ /* Hooks in some "z-util.c" hooks */
+ plog_aux = hook_plog;
+ quit_aux = hook_quit;
+
+ /* Initialize file paths */
+ prepare_paths_and_directories();
+
+ /* Note the "system" */
+ ANGBAND_SYS = "coc";
+
+ /* Load possible graphics modes */
+ init_graphics_modes();
+
+ /* Load preferences */
+ load_prefs();
+
+ /* Prepare the windows */
+ init_windows();
+
+ /* Set up game event handlers */
+ /* init_display(); */
+
+ /* Register the sound hook */
+ /* sound_hook = play_sound; */
+
+ /* Initialise game */
+ init_angband();
+
+ /* Initialize some save file stuff */
+ player_egid = getegid();
+
+ /* We are now initialized */
+ initialized = TRUE;
+
+ /* Handle "open_when_ready" */
+ handle_open_when_ready();
+
+ /* Handle pending events (most notably update) and flush input */
+ Term_flush();
+
+ /* Prompt the user. */
+ int message_row = (Term->hgt - 23) / 5 + 23;
+ Term_erase(0, message_row, 255);
+ put_str(
+#ifdef JP
+ "['ファイル' メニューから '新' または '開く' を選択します]",
+ message_row, (Term->wid - 57) / 2
+#else
+ "[Choose 'New' or 'Open' from the 'File' menu]",
+ message_row, (Term->wid - 45) / 2
+#endif
+ );
+ Term_fresh();
+
+ [pool drain];
+
+ while (!game_in_progress) {
+ NSAutoreleasePool *splashScreenPool = [[NSAutoreleasePool alloc] init];
+ NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES];
+ if (event) [NSApp sendEvent:event];
+ [splashScreenPool drain];
+ }
+
+ /*
+ * Play a game -- "new_game" is set by "new", "open" or the open document
+ * even handler as appropriate
+ */
+ Term_fresh();
+ play_game(new_game);
+
+ quit(NULL);
+}
+
+/**
* 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
[[NSUserDefaults angbandDefaults] setInteger:graf_mode_req forKey:AngbandGraphicsDefaultsKey];
[[NSUserDefaults angbandDefaults] synchronize];
+ if (graf_mode_req == GRAPHICS_NONE ||
+ get_graphics_mode(graf_mode_req) == GRAPHICS_NONE) {
+ if (use_bigtile) {
+ arg_bigtile = FALSE;
+ }
+ } else if ([[NSUserDefaults angbandDefaults] boolForKey:AngbandBigTileDefaultsKey] == YES &&
+ ! use_bigtile) {
+ arg_bigtile = TRUE;
+ }
+
if (game_in_progress)
{
+ if (arg_bigtile != use_bigtile) {
+ Term_activate(angband_term[0]);
+ Term_resize(angband_term[0]->wid, angband_term[0]->hgt);
+ }
+
/* Hack -- Force redraw */
do_cmd_redraw();
forKey:AngbandSoundDefaultsKey];
}
+- (IBAction)toggleWideTiles:(NSMenuItem *) sender
+{
+ BOOL is_on = (sender.state == NSOnState);
+
+ /* Toggle the state and update the Angband globals and preferences. */
+ sender.state = (is_on) ? NSOffState : NSOnState;
+ [[NSUserDefaults angbandDefaults] setBool:(! is_on)
+ forKey:AngbandBigTileDefaultsKey];
+ [[NSUserDefaults angbandDefaults] synchronize];
+ if (graphics_are_enabled()) {
+ arg_bigtile = (is_on) ? FALSE : TRUE;
+ /* Mimics the logic in setGraphicsMode(). */
+ if (game_in_progress && arg_bigtile != use_bigtile) {
+ Term_activate(angband_term[0]);
+ Term_resize(angband_term[0]->wid, angband_term[0]->hgt);
+ do_cmd_redraw();
+ wakeup_event_loop();
+ }
+ }
+}
+
/**
* Send a command to Angband via a menu item. This places the appropriate key
* down events into the queue so that it seems like the user pressed them
- (void)applicationDidFinishLaunching:sender
{
- [AngbandContext beginGame];
+ [self beginGame];
/* Once beginGame finished, the game is over - that's how Angband works,
* and we should quit */