// 'area' may be NULL to copy the entire CONTEXT cliprect // 'area' is relative to the CONTEXT cliprect DRAWABLE CopyContextRect (const RECT* area) { RECT clipRect; RECT fgRect; RECT r; if (!ContextActive () || !_CurFramePtr) return NULL; fgRect = _get_context_fg_rect (); GetContextClipRect (&clipRect); r = clipRect; if (area) { // a portion of the context r.corner.x += area->corner.x; r.corner.y += area->corner.y; r.extent = area->extent; } // TODO: Should this take CONTEXT origin into account too? // validate the rect if (!BoxIntersect (&r, &fgRect, &r)) return NULL; if (_CurFramePtr->Type == SCREEN_DRAWABLE) return LoadDisplayPixmap (&r, NULL); else return CopyFrameRect (_CurFramePtr, &r); }
// Maybe move to elsewhere, where it can be reused? static FRAME getScreen (void) { CONTEXT oldContext = SetContext (ScreenContext); FRAME savedFrame; RECT screenRect; screenRect.corner.x = 0; screenRect.corner.y = 0; screenRect.extent.width = ScreenWidth; screenRect.extent.height = ScreenHeight; savedFrame = CaptureDrawable (LoadDisplayPixmap (&screenRect, (FRAME) 0)); (void) SetContext (oldContext); return savedFrame; }
void DoPopupWindow(const char *msg) { stringbank *bank = StringBank_Create (); const char *lines[30]; WIDGET_LABEL label; RECT r; STAMP s; FRAME F; CONTEXT oldContext; RECT oldRect; POPUP_STATE state; MENU_SOUND_FLAGS s0, s1; if (!bank) { log_add (log_Fatal, "FATAL: Memory exhaustion when preparing popup window"); exit (EXIT_FAILURE); } label.tag = WIDGET_TYPE_LABEL; label.parent = NULL; label.handleEvent = Widget_HandleEventIgnoreAll; label.receiveFocus = Widget_ReceiveFocusRefuseFocus; label.draw = Widget_DrawLabel; label.height = Widget_HeightLabel; label.width = Widget_WidthFullScreen; label.line_count = SplitString (msg, '\n', 30, lines, bank); label.lines = lines; LockMutex (GraphicsLock); oldContext = SetContext (ScreenContext); GetContextClipRect (&oldRect); SetContextClipRect (NULL_PTR); /* TODO: Better measure of dimensions than this */ r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); s.origin = r.corner; s.frame = F; DrawLabelAsWindow (&label); GetMenuSounds (&s0, &s1); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); state.InputFunc = DoPopup; DoInput (&state, TRUE); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); FlushInput (); SetContextClipRect (&oldRect); SetContext (oldContext); UnlockMutex (GraphicsLock); SetMenuSounds (s0, s1); StringBank_Free (bank); }
/* This code assumes that you aren't in Character Mode. This is * currently safe because VControl doesn't see keystrokes when you * are, and thus cannot conclude that an exit is necessary. */ BOOLEAN DoConfirmExit (void) { BOOLEAN result; static BOOLEAN in_confirm = FALSE; if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE && !(LastActivity & CHECK_RESTART)) SuspendGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) PauseTrack (); LockMutex (GraphicsLock); if (in_confirm) { result = FALSE; ExitRequested = FALSE; } else { RECT r; STAMP s; FRAME F; CONTEXT oldContext; RECT oldRect; BOOLEAN response = FALSE, done; in_confirm = TRUE; oldContext = SetContext (ScreenContext); GetContextClipRect (&oldRect); SetContextClipRect (NULL_PTR); r.extent.width = CONFIRM_WIN_WIDTH + 4; r.extent.height = CONFIRM_WIN_HEIGHT + 4; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; s.origin = r.corner; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); SetSystemRect (&r); DrawConfirmationWindow (response); // Releasing the lock lets the rotate_planet_task // draw a frame. PauseRotate can still allow one more frame // to be drawn, so it is safer to just not release the lock //UnlockMutex (GraphicsLock); FlushGraphics (); //LockMutex (GraphicsLock); GLOBAL (CurrentActivity) |= CHECK_ABORT; FlushInput (); done = FALSE; do { // Forbid recursive calls or pausing here! ExitRequested = FALSE; GamePaused = FALSE; UpdateInputState (); if (PulsedInputState.menu[KEY_MENU_SELECT]) { done = TRUE; PlayMenuSound (MENU_SOUND_SUCCESS); } else if (PulsedInputState.menu[KEY_MENU_CANCEL]) { done = TRUE; response = FALSE; } else if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]) { response = !response; DrawConfirmationWindow (response); PlayMenuSound (MENU_SOUND_MOVE); } TaskSwitch (); } while (!done); s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); ClearSystemRect (); if (response) { result = TRUE; } else { result = FALSE; GLOBAL (CurrentActivity) &= ~CHECK_ABORT; } ExitRequested = FALSE; GamePaused = FALSE; FlushInput (); SetContextClipRect (&oldRect); SetContext (oldContext); } UnlockMutex (GraphicsLock); if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE && !(LastActivity & CHECK_RESTART)) ResumeGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) { ResumeTrack (); if (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE) do_subtitles ((void *)~0); } in_confirm = FALSE; return (result); }
BOOLEAN PauseGame (void) { RECT r; STAMP s; BOOLEAN ClockActive; CONTEXT OldContext; FRAME F; HOT_SPOT OldHot; if (ActivityFrame == 0 || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_PAUSE)) || (LastActivity & (CHECK_LOAD | CHECK_RESTART))) return (FALSE); GLOBAL (CurrentActivity) |= CHECK_PAUSE; ClockActive = (BOOLEAN)( LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && GameClockRunning () ); if (ClockActive) SuspendGameClock (); else if (CommData.ConversationPhrases && PlayingTrack ()) PauseTrack (); SetSemaphore (GraphicsSem); OldContext = SetContext (ScreenContext); OldHot = SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); GetFrameRect (ActivityFrame, &r); r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; s.origin = r.corner; s.frame = ActivityFrame; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); DrawStamp (&s); FlushGraphics (); { BYTE scan; scan = KBDToUNICODE (SK_F1); while (KeyDown (scan)) TaskSwitch (); } FlushInput (); while (KeyHit () != SK_F1) TaskSwitch (); s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); SetFrameHot (Screen, OldHot); SetContext (OldContext); WaitForNoInput (ONE_SECOND / 4); FlushInput (); ClearSemaphore (GraphicsSem); if (ClockActive) ResumeGameClock (); else if (CommData.ConversationPhrases && PlayingTrack ()) ResumeTrack (); TaskSwitch (); GLOBAL (CurrentActivity) &= ~CHECK_PAUSE; return (TRUE); }