OSDN Git Service

Merge branch 'master' of git://git.osdn.net/gitroot/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / main-cocoa.m
index c675622..f8b5087 100644 (file)
@@ -395,6 +395,9 @@ static int resize_pending_changes(struct PendingChanges* pc, int nrow)
      */
     int ncol_pre, ncol_post;
 
+    /* Flags whether or not a fullscreen transition is in progress. */
+    BOOL in_fullscreen_transition;
+
 @private
 
     BOOL _hasSubwindowFlags;
@@ -1019,7 +1022,7 @@ static int compare_advances(const void *ap, const void *bp)
 
     textMatrix = CGAffineTransformScale( textMatrix, 1.0, -1.0 );
     CGContextSetTextMatrix(ctx, textMatrix);
-    CGContextShowGlyphsWithAdvances(ctx, &glyph, &CGSizeZero, 1);
+    CGContextShowGlyphsAtPositions(ctx, &glyph, &CGPointZero, 1);
     
     /* Restore the text matrix if we messed with the compression ratio */
     if (compressionRatio != 1.)
@@ -1109,9 +1112,6 @@ static int compare_advances(const void *ap, const void *bp)
 
     /* Update our image */
     [self updateImage];
-    
-    /* Get redrawn */
-    [self requestRedraw];
 }
 
 - (id)init
@@ -1135,6 +1135,8 @@ static int compare_advances(const void *ap, const void *bp)
        self->ncol_pre = 0;
        self->ncol_post = 0;
 
+       self->in_fullscreen_transition = NO;
+
         /* Make the image. Since we have no views, it'll just be a puny 1x1 image. */
         [self updateImage];
 
@@ -1357,9 +1359,15 @@ static size_t Term_mbcs_cocoa(wchar_t *dest, const char *src, int n)
     /* 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();
     
@@ -1372,12 +1380,6 @@ static size_t Term_mbcs_cocoa(wchar_t *dest, const char *src, int n)
     /* Initialise game */
     init_angband();
 
-    /* This is not incorporated into Hengband's init_angband() yet. */
-    init_graphics_modes();
-
-    /* Note the "system" */
-    ANGBAND_SYS = "mac";
-    
     /* Initialize some save file stuff */
     player_egid = getegid();
     
@@ -1750,24 +1752,36 @@ static NSMenuItem *superitem(NSMenuItem *self)
 {
     NSWindow *window = [notification object];
     NSRect contentRect = [window contentRectForFrameRect: [window frame]];
-    [self resizeTerminalWithContentRect: contentRect saveToDefaults: YES];
+    [self resizeTerminalWithContentRect: contentRect saveToDefaults: !(self->in_fullscreen_transition)];
 }
 
 /*- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
 {
 } */
 
+- (void)windowWillEnterFullScreen: (NSNotification *)notification
+{
+    self->in_fullscreen_transition = YES;
+}
+
 - (void)windowDidEnterFullScreen: (NSNotification *)notification
 {
     NSWindow *window = [notification object];
     NSRect contentRect = [window contentRectForFrameRect: [window frame]];
+    self->in_fullscreen_transition = NO;
     [self resizeTerminalWithContentRect: contentRect saveToDefaults: NO];
 }
 
+- (void)windowWillExitFullScreen: (NSNotification *)notification
+{
+    self->in_fullscreen_transition = YES;
+}
+
 - (void)windowDidExitFullScreen: (NSNotification *)notification
 {
     NSWindow *window = [notification object];
     NSRect contentRect = [window contentRectForFrameRect: [window frame]];
+    self->in_fullscreen_transition = NO;
     [self resizeTerminalWithContentRect: contentRect saveToDefaults: NO];
 }
 
@@ -2007,6 +2021,7 @@ static void Term_init_cocoa(term *t)
 
     /* Get the window */
     NSWindow *window = [context makePrimaryWindow];
+
     /* Set its title and, for auxiliary terms, tentative size */
     NSString *title = [NSString stringWithCString:angband_term_name[termIdx]
 #ifdef JP
@@ -2257,10 +2272,6 @@ static errr Term_xtra_cocoa_react(void)
         
         /* Record what we did */
         use_graphics = new_mode ? new_mode->grafID : 0;
-#if 0
-       /* This global is not in Hengband. */
-        use_transparency = (new_mode != NULL);
-#endif
         ANGBAND_GRAF = (new_mode ? new_mode->graf : "ascii");
         current_graphics_mode = new_mode;
         
@@ -2287,6 +2298,7 @@ static errr Term_xtra_cocoa_react(void)
             reset_visuals();
         }
     }
+
     [pool drain];
     
     /* Success */
@@ -2529,21 +2541,28 @@ static void Term_xtra_cocoa_fresh(AngbandContext* angbandContext)
     int graf_width, graf_height, alphablend;
 
     if (angbandContext->changes->has_pict) {
+       CGImageAlphaInfo ainfo = CGImageGetAlphaInfo(pict_image);
+
        graf_width = current_graphics_mode->cell_width;
        graf_height = current_graphics_mode->cell_height;
        /*
-        * Transparency effect. We really want to check
-        * current_graphics_mode->alphablend, but as of this writing
-        * that's  never set, so we do something lame.
+        * As of this writing, a value of zero for
+        * current_graphics_mode->alphablend can mean either that the tile set
+        * doesn't have an alpha channel or it does but it only takes on values
+        * of 0 or 255.  For main-cocoa.m's purposes, the latter is rendered
+        * using the same procedure as if alphablend was nonzero.  The former
+        * is handled differently, but alphablend doesn't distinguish it from
+        * the latter.  So ignore alphablend and directly test whether an
+        * alpha channel is present.
         */
-       /* alphablend = current_graphics_mode->alphablend */
-       alphablend = (graf_width > 8 || graf_height > 8);
+       alphablend = (ainfo & (kCGImageAlphaPremultipliedFirst |
+                              kCGImageAlphaPremultipliedLast)) ? 1 : 0;
     } else {
        graf_width = 0;
        graf_height = 0;
        alphablend = 0;
     }
+
     CGContextRef ctx = [angbandContext lockFocus];
 
     if (angbandContext->changes->has_text ||
@@ -2615,13 +2634,20 @@ static void Term_xtra_cocoa_fresh(AngbandContext* angbandContext)
                                terrainRect,
                                destinationRect,
                                NSCompositeCopy);
-                           draw_image_tile(
-                               nsContext,
-                               ctx,
-                               pict_image,
-                               sourceRect,
-                               destinationRect,
-                               NSCompositeSourceOver);
+                           /*
+                            * Skip drawing the foreground if it is the same
+                            * as the background.
+                            */
+                           if (sourceRect.origin.x != terrainRect.origin.x ||
+                               sourceRect.origin.y != terrainRect.origin.y) {
+                               draw_image_tile(
+                                   nsContext,
+                                   ctx,
+                                   pict_image,
+                                   sourceRect,
+                                   destinationRect,
+                                   NSCompositeSourceOver);
+                           }
                        } else {
                            draw_image_tile(
                                nsContext,
@@ -2685,7 +2711,7 @@ static void Term_xtra_cocoa_fresh(AngbandContext* angbandContext)
                    /* Save the state since the clipping will be modified. */
                    CGContextSaveGState(ctx);
 
-                   /* Clear the area that where rendering will be done. */
+                   /* Clear the area where rendering will be done. */
                    r = [angbandContext rectInImageForTileAtX:isrend Y:iy];
                    r.size.width = angbandContext->tileSize.width *
                        (ierend - isrend + 1);
@@ -3036,8 +3062,8 @@ static errr Term_pict_cocoa(int x, int y, int n, TERM_COLOR *ap,
        if (use_graphics && (a & 0x80) && (c & 0x80)) {
            pc->c.c = ((byte)c & 0x7F) % pict_cols;
            pc->a = ((byte)a & 0x7F) % pict_rows;
-           pc->tcol = ((byte)tc & 0x7F) & pict_cols;
-           pc->trow = ((byte)ta & 0x7F) & pict_rows;
+           pc->tcol = ((byte)tc & 0x7F) % pict_cols;
+           pc->trow = ((byte)ta & 0x7F) % pict_rows;
            pc->change_type = CELL_CHANGE_PICT;
            any_change = 1;
        }
@@ -3564,8 +3590,7 @@ static void quit_calmly(void)
         /* Save the game */
         do_cmd_save_game(FALSE);
         record_current_savefile();
-        
-        
+
         /* Quit */
         quit(NULL);
     }
@@ -3684,10 +3709,6 @@ static BOOL send_event(NSEvent *event)
             
             
             /* Extract some modifiers */
-#if 0
-           /* Caught above so don't do anything with it here. */
-            int mx = !! (modifiers & NSCommandKeyMask);
-#endif            
             int mc = !! (modifiers & NSControlKeyMask);
             int ms = !! (modifiers & NSShiftKeyMask);
             int mo = !! (modifiers & NSAlternateKeyMask);
@@ -3697,32 +3718,22 @@ static BOOL send_event(NSEvent *event)
             /* Get the Angband char corresponding to this unichar */
             unichar c = [[event characters] characterAtIndex:0];
             char ch;
-            switch (c) {
+           /*
+            * Have anything from the numeric keypad generate a macro
+            * trigger so that shift or control modifiers can be passed.
+            */
+           if (c <= 0x7F && !kp)
+           {
+               ch = (char) c;
+           }
+           else {
                /*
-                * Convert some special keys to what would be the normal
-                * alternative in the original keyset or, for things lke
-                * Delete, Return, and Escape, what one might use from ASCII.
                 * The rest of Hengband uses Angband 2.7's or so key handling:
                 * so for the rest do something like the encoding that
                 * main-win.c does:  send a macro trigger with the Unicode
-                * value encoded into printable ASCII characters.  Since
-                * macro triggers appear to assume at most two keys plus the
-                * modifiers, can only handle values of c below 4096 with
-                * 64 values per key.
+                * value encoded into printable ASCII characters.
                 */
-               case NSUpArrowFunctionKey: ch = '8'; kp = 0; break;
-               case NSDownArrowFunctionKey: ch = '2'; kp = 0; break;
-               case NSLeftArrowFunctionKey: ch = '4'; kp = 0; break;
-               case NSRightArrowFunctionKey: ch = '6'; kp = 0; break;
-               case NSHelpFunctionKey: ch = '?'; break;
-               case NSDeleteFunctionKey: ch = '\b'; break;
-                    
-                default:
-                    if (c <= 0x7F)
-                        ch = (char)c;
-                    else
-                        ch = '\0';
-                    break;
+               ch = '\0';
             }
             
             /* override special keys */
@@ -3740,22 +3751,18 @@ static BOOL send_event(NSEvent *event)
             /* Enqueue it */
             if (ch != '\0')
             {
-                
-                /* Enqueue the keypress */
-#if 0
-                byte mods = 0;
-                if (mo) mods |= KC_MOD_ALT;
-                if (mx) mods |= KC_MOD_META;
-                if (mc && MODS_INCLUDE_CONTROL(ch)) mods |= KC_MOD_CONTROL;
-                if (ms && MODS_INCLUDE_SHIFT(ch)) mods |= KC_MOD_SHIFT;
-                if (kp) mods |= KC_MOD_KEYPAD;
-                Term_keypress(ch, mods);
-#else
                 Term_keypress(ch);
-#endif
-            } else if (c < 4096 || (c >= 0xF700 && c <= 0xF77F)) {
-               unichar part;
-               char cenc;
+            }
+           else
+           {
+               /*
+                * Could use the hexsym global but some characters overlap with
+                * those used to indicate modifiers.
+                */
+               const char encoded[16] = {
+                   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
+                   'c', 'd', 'e', 'f'
+               };
 
                /* Begin the macro trigger. */
                Term_keypress(31);
@@ -3763,36 +3770,13 @@ static BOOL send_event(NSEvent *event)
                /* Send the modifiers. */
                if (mc) Term_keypress('C');
                if (ms) Term_keypress('S');
-               if (mo) Term_keypress('A');
+               if (mo) Term_keypress('O');
                if (kp) Term_keypress('K');
 
-               /*
-                * Put part of the range Apple reserves for special keys
-                * into 0 - 127 since that range has been handled normally.
-                */
-               if (c >= 0xF700) {
-                   c -= 0xF700;
-               }
-
-               /* Encode the value as two printable characters. */
-               part = (c >> 6) & 63;
-               if (part > 38) {
-                   cenc = 'a' + (part - 38);
-               } else if (part > 12) {
-                   cenc = 'A' + (part - 12);
-               } else {
-                   cenc = '0' + part;
-               }
-               Term_keypress(cenc);
-               part = c & 63;
-               if (part > 38) {
-                   cenc = 'a' + (part - 38);
-               } else if (part > 12) {
-                   cenc = 'A' + (part - 12);
-               } else {
-                   cenc = '0' + part;
-               }
-               Term_keypress(cenc);
+               do {
+                   Term_keypress(encoded[c & 0xF]);
+                   c >>= 4;
+               } while (c > 0);
 
                /* End the macro trigger. */
                Term_keypress(13);
@@ -4002,6 +3986,14 @@ static void hook_quit(const char * str)
     [(id)angbandContext setSelectionFont:newFont adjustTerminal: YES];
     
     NSEnableScreenUpdates();
+
+    if (mainTerm == 0 && game_in_progress) {
+       /* Mimics the logic in setGraphicsMode(). */
+       do_cmd_redraw();
+       wakeup_event_loop();
+    } else {
+       [(id)angbandContext requestRedraw];
+    }
 }
 
 - (IBAction)openGame:sender
@@ -4132,10 +4124,14 @@ static void hook_quit(const char * str)
        [menuItem setState: ((is_on) ? NSOnState : NSOffState)];
        return YES;
     }
-    else if( sel == @selector(sendAngbandCommand:) )
+    else if( sel == @selector(sendAngbandCommand:) ||
+            sel == @selector(saveGame:) )
     {
-        /* we only want to be able to send commands during an active game */
-        return !!game_in_progress;
+        /*
+         * we only want to be able to send commands during an active game
+         * after the birth screens
+         */
+        return !!game_in_progress && character_generated;
     }
     else return YES;
 }