view src/video/macrom/SDL_romvideo.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents 14717b52abc0
children 4da1ee79c9af
line wrap: on
line source

/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2006 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Sam Lantinga
    slouken@libsdl.org
*/
#include "SDL_config.h"

#if defined(__APPLE__) && defined(__MACH__)
#include <Carbon/Carbon.h>
#if USE_QUICKTIME
#include <QuickTime/Movies.h>
#endif
#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
#include <Carbon.h>
/* The fullscreen code requires the QuickTime framework, and the window
   is still at the back on Mac OS X, which is where this code is needed.
 */
#if USE_QUICKTIME
#include <Movies.h>
#endif
#else
#include <Quickdraw.h>
#include <LowMem.h>
#include <Gestalt.h>
#include <Devices.h>
#include <DiskInit.h>
#include <QDOffscreen.h>
#endif

#include "SDL_video.h"
#include "SDL_syswm.h"
#include "../SDL_sysvideo.h"
#include "SDL_romvideo.h"
#include "../maccommon/SDL_macgl_c.h"
#include "../maccommon/SDL_macwm_c.h"
#include "../maccommon/SDL_macmouse_c.h"
#include "../maccommon/SDL_macevents_c.h"

/* Initialization/Query functions */
static int ROM_VideoInit (_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **ROM_ListModes (_THIS, SDL_PixelFormat * format,
                                 Uint32 flags);
static SDL_Surface *ROM_SetVideoMode (_THIS, SDL_Surface * current, int width,
                                      int height, int bpp, Uint32 flags);
static int ROM_SetColors (_THIS, int firstcolor, int ncolors,
                          SDL_Color * colors);
static void ROM_VideoQuit (_THIS);

/* Hardware surface functions */
static int ROM_AllocHWSurface (_THIS, SDL_Surface * surface);
static int ROM_LockHWSurface (_THIS, SDL_Surface * surface);
static void ROM_UnlockHWSurface (_THIS, SDL_Surface * surface);
static void ROM_FreeHWSurface (_THIS, SDL_Surface * surface);

#if !TARGET_API_MAC_CARBON      /* This seems not to be available? -sts Aug 2000 */
/* Saved state for the menu bar */
static RgnHandle gSaveGrayRgn = nil;
static short gSaveMenuBar = 0;
static Boolean gSaveCSVis = true;

#if powerc
/* Mixed mode glue to activate the 68K emulator and twiddle a register */
#define ONEWORDSTUB(p1) \
		{ 0x41FA, 0x0010, 0x209F, (p1), 0x41FA, \
		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }

#define TWOWORDSTUB(p1,p2) \
		{ 0x41FA, 0x0012, 0x209F, (p1), (p2), 0x41FA, \
		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }

#define THREEWORDSTUB(p1,p2,p3) \
		{ 0x41FA, 0x0014, 0x209F, (p1), (p2), (p3), 0x41FA, \
		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }

/* ControlStrip inline glue for PowerPC */
static pascal Boolean
SBIsControlStripVisible (void)
{
    static short procData[] = TWOWORDSTUB (0x7000, 0xAAF2);
    ProcInfoType procInfo = kD0DispatchedPascalStackBased
        | RESULT_SIZE (SIZE_CODE (sizeof (Boolean)))
        | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE (kFourByteCode);

    return ((Boolean)
            CallUniversalProc ((UniversalProcPtr) procData, procInfo, 0x00));
}

static pascal void
SBShowHideControlStrip (Boolean showIt)
{
    static short procData[] = THREEWORDSTUB (0x303C, 0x0101, 0xAAF2);
    ProcInfoType procInfo = kD0DispatchedPascalStackBased
        | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE (kFourByteCode)
        | DISPATCHED_STACK_ROUTINE_PARAMETER (1,
                                              SIZE_CODE (sizeof (Boolean)));

    CallUniversalProc ((UniversalProcPtr) procData, procInfo, 0x01, showIt);
}
#endif /* powerc */
#endif /* !TARGET_API_MAC_CARBON */

/* Macintosh toolbox driver bootstrap functions */

static int
ROM_Available (void)
{
    return (1);
}

static void
ROM_DeleteDevice (SDL_VideoDevice * device)
{
    SDL_free (device->hidden);
    SDL_free (device);
}

static SDL_VideoDevice *
ROM_CreateDevice (int devindex)
{
    SDL_VideoDevice *device;

    /* Initialize all variables that we clean on shutdown */
    device = (SDL_VideoDevice *) SDL_malloc (sizeof (SDL_VideoDevice));
    if (device) {
        SDL_memset (device, 0, (sizeof *device));
        device->hidden = (struct SDL_PrivateVideoData *)
            SDL_malloc ((sizeof *device->hidden));
    }
    if ((device == NULL) || (device->hidden == NULL)) {
        SDL_OutOfMemory ();
        if (device) {
            SDL_free (device);
        }
        return (0);
    }
    SDL_memset (device->hidden, 0, (sizeof *device->hidden));

    /* Set the function pointers */
    device->VideoInit = ROM_VideoInit;
    device->ListModes = ROM_ListModes;
    device->SetVideoMode = ROM_SetVideoMode;
    device->SetColors = ROM_SetColors;
    device->UpdateRects = NULL;
    device->VideoQuit = ROM_VideoQuit;
    device->AllocHWSurface = ROM_AllocHWSurface;
    device->CheckHWBlit = NULL;
    device->FillHWRect = NULL;
    device->SetHWColorKey = NULL;
    device->SetHWAlpha = NULL;
    device->LockHWSurface = ROM_LockHWSurface;
    device->UnlockHWSurface = ROM_UnlockHWSurface;
    device->FlipHWSurface = NULL;
    device->FreeHWSurface = ROM_FreeHWSurface;
#if SDL_VIDEO_OPENGL
    device->GL_MakeCurrent = Mac_GL_MakeCurrent;
    device->GL_SwapBuffers = Mac_GL_SwapBuffers;
    device->GL_LoadLibrary = Mac_GL_LoadLibrary;
    device->GL_GetProcAddress = Mac_GL_GetProcAddress;
#endif // Have OpenGL
    device->SetCaption = Mac_SetCaption;
    device->SetIcon = NULL;
    device->IconifyWindow = NULL;
    device->GrabInput = NULL;
    device->GetWMInfo = NULL;
    device->FreeWMCursor = Mac_FreeWMCursor;
    device->CreateWMCursor = Mac_CreateWMCursor;
    device->ShowWMCursor = Mac_ShowWMCursor;
    device->WarpWMCursor = Mac_WarpWMCursor;
    device->InitOSKeymap = Mac_InitOSKeymap;
    device->PumpEvents = Mac_PumpEvents;

    device->free = ROM_DeleteDevice;

    return device;
}

VideoBootStrap TOOLBOX_bootstrap = {
    "toolbox", "MacOS ROM Toolbox",
    ROM_Available, ROM_CreateDevice
};


static int
ROM_VideoInit (_THIS, SDL_PixelFormat * vformat)
{
    long info;

    /* Check out some things about the system */
    Gestalt (gestaltQuickdrawVersion, &info);
    if (info == gestaltOriginalQD) {
        SDL_SetError ("Color Quickdraw not available");
        return (-1);
    }

    /* Start ROMintosh events */
    Mac_InitEvents (this);

    /* Get a handle to the main monitor */
    SDL_Display = GetMainDevice ();

    /* Determine the current screen size */
    this->info.current_w = (**SDL_Display).gdRect.right;
    this->info.current_h = (**SDL_Display).gdRect.bottom;

    /* Determine pixel format */
    vformat->BitsPerPixel = (**(**SDL_Display).gdPMap).pixelSize;
    switch (vformat->BitsPerPixel) {
    case 16:                   /* 5-5-5 RGB */
        vformat->Rmask = 0x00007c00;
        vformat->Gmask = 0x000003e0;
        vformat->Bmask = 0x0000001f;
        break;
    default:
        break;
    }

    /* Create our palette */
    SDL_CTab = (CTabHandle) NewHandle (sizeof (ColorSpec) * 256 + 8);
    if (SDL_CTab == nil) {
        SDL_OutOfMemory ();
        return (-1);
    }
    (**SDL_CTab).ctSeed = GetCTSeed ();
    (**SDL_CTab).ctFlags = 0;
    (**SDL_CTab).ctSize = 255;
    CTabChanged (SDL_CTab);
    SDL_CPal = NewPalette (256, SDL_CTab, pmExplicit + pmTolerant, 0);

    /* Get a list of available fullscreen modes */
    SDL_modelist = (SDL_Rect **) SDL_malloc ((1 + 1) * sizeof (SDL_Rect *));
    if (SDL_modelist) {
        SDL_modelist[0] = (SDL_Rect *) SDL_malloc (sizeof (SDL_Rect));
        if (SDL_modelist[0]) {
            SDL_modelist[0]->x = 0;
            SDL_modelist[0]->y = 0;
            SDL_modelist[0]->w = (**SDL_Display).gdRect.right;
            SDL_modelist[0]->h = (**SDL_Display).gdRect.bottom;
        }
        SDL_modelist[1] = NULL;
    }

    /* Fill in some window manager capabilities */
    this->info.wm_available = 1;

    /* We're done! */
    return (0);
}

static SDL_Rect **
ROM_ListModes (_THIS, SDL_PixelFormat * format, Uint32 flags)
{
    if (this->screen->format->BitsPerPixel == format->BitsPerPixel) {
        if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
            return (SDL_modelist);
        } else {
            return ((SDL_Rect **) - 1);
        }
    } else {
        return ((SDL_Rect **) 0);
    }
}

static void
ROM_HideMenuBar (_THIS)
{
#if !TARGET_API_MAC_CARBON      /* This seems not to be available? -sts Aug 2000 */
    RgnHandle drawRgn = nil;
    RgnHandle tempRgn = nil;
    RgnHandle grayRgn = nil;
    WindowPtr window = nil;
    GDHandle gd = nil;
    GrafPtr savePort;
    long response;
    short height;
    EventRecord theEvent;

    height = GetMBarHeight ();

    if (height > 0) {
        tempRgn = NewRgn ();
        drawRgn = NewRgn ();
        gSaveGrayRgn = NewRgn ();
        if (!tempRgn || !drawRgn || !gSaveGrayRgn) {
            goto CLEANUP;
        }
        grayRgn = GetGrayRgn ();        /* No need to check for this */

        GetPort (&savePort);

        /* Hide the control strip if it's present, and record its 
           previous position into the dirty region for redrawing. 
           This isn't necessary, but may help catch stray bits. */
        CopyRgn (grayRgn, tempRgn);
        if (!Gestalt (gestaltControlStripAttr, &response) &&
            (response & (1L << gestaltControlStripExists))) {
            gSaveCSVis = SBIsControlStripVisible ();
            if (gSaveCSVis)
                SBShowHideControlStrip (false);
        }
        DiffRgn (grayRgn, tempRgn, drawRgn);

        /* Save the gray region once the control strip is hidden */
        CopyRgn (grayRgn, gSaveGrayRgn);

        /* Change the menu height in lowmem */
        gSaveMenuBar = height;
        LMSetMBarHeight (0);

        /* Walk the monitor rectangles, and combine any pieces that
           aren't in GrayRgn: menubar, round corners, fake floaters. */
        for (gd = GetDeviceList (); gd; gd = GetNextDevice (gd)) {
            if (!TestDeviceAttribute (gd, screenDevice))
                continue;
            if (!TestDeviceAttribute (gd, screenActive))
                continue;

            RectRgn (tempRgn, &(*gd)->gdRect);  /* Get the whole screen */
            DiffRgn (tempRgn, grayRgn, tempRgn);        /* Subtract out GrayRgn */
            UnionRgn (tempRgn, drawRgn, drawRgn);       /* Combine all the bits */
        }

        /* Add the bits into the GrayRgn */
        UnionRgn (drawRgn, grayRgn, grayRgn);

        /* Modify the vis regions of exposed windows */
        window = (FrontWindow ())? FrontWindow () : (WindowPtr) - 1L;
        PaintBehind (window, drawRgn);
        CalcVisBehind (window, drawRgn);

        SetPort (savePort);

        /* Yield time so that floaters can catch up */
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
    }

  CLEANUP:

    if (tempRgn)
        DisposeRgn (tempRgn);
    if (drawRgn)
        DisposeRgn (drawRgn);
#endif /* !TARGET_API_MAC_CARBON */
}

static void
ROM_ShowMenuBar (_THIS)
{
#if !TARGET_API_MAC_CARBON      /* This seems not to be available? -sts Aug 2000 */
    RgnHandle drawRgn = nil;
    RgnHandle menuRgn = nil;
    RgnHandle tempRgn = nil;
    RgnHandle grayRgn = nil;
    WindowPtr window = nil;
    GrafPtr wMgrPort;
    GrafPtr savePort;
    Rect menuRect;
    long response;
    short height;
    EventRecord theEvent;
    RGBColor saveRGB;
    RGBColor blackRGB = { 0, 0, 0 };

    height = GetMBarHeight ();

    if ((height <= 0) && (gSaveMenuBar > 0)) {
        drawRgn = NewRgn ();
        menuRgn = NewRgn ();
        tempRgn = NewRgn ();
        if (!tempRgn || !drawRgn || !gSaveGrayRgn) {
            goto CLEANUP;
        }
        grayRgn = GetGrayRgn ();        /* No need to check for this */

        GetPort (&savePort);
        GetWMgrPort (&wMgrPort);

        /* Set the height properly */
        LMSetMBarHeight (gSaveMenuBar);

        /* Restore the old GrayRgn: rounded corners, etc, but not
           the menubar -- subtract that out first! */
        if (gSaveGrayRgn) {
            menuRect = (*GetMainDevice ())->gdRect;
            menuRect.bottom = menuRect.top + gSaveMenuBar;
            RectRgn (menuRgn, &menuRect);

            DiffRgn (grayRgn, gSaveGrayRgn, drawRgn);   /* What do we inval? */
            DiffRgn (drawRgn, menuRgn, drawRgn);        /* Clip out the menu */

            /* Now redraw the corners and other bits black */
            SetPort (wMgrPort);
            GetClip (tempRgn);
            SetClip (drawRgn);
            GetForeColor (&saveRGB);
            RGBForeColor (&blackRGB);
            PaintRgn (drawRgn);
            RGBForeColor (&saveRGB);
            SetClip (tempRgn);
            SetPort (savePort);

            UnionRgn (drawRgn, menuRgn, drawRgn);       /* Put back the menu */

            /* Now actually restore the GrayRgn */
            CopyRgn (gSaveGrayRgn, grayRgn);
            DisposeRgn (gSaveGrayRgn);
            gSaveGrayRgn = nil;
        }

        /* Modify the vis regions of exposed windows and draw menubar */
        window = (FrontWindow ())? FrontWindow () : (WindowPtr) - 1L;
        PaintBehind (window, drawRgn);
        CalcVisBehind (window, drawRgn);
        DrawMenuBar ();

        SetPort (savePort);
        gSaveMenuBar = 0;

        /* Now show the control strip if it's present */
        if (!Gestalt (gestaltControlStripAttr, &response) &&
            (response & (1L << gestaltControlStripExists))) {
            if (gSaveCSVis && !SBIsControlStripVisible ())
                SBShowHideControlStrip (true);
            gSaveCSVis = true;
        }

        /* Yield time so that floaters can catch up */
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
        EventAvail (0, &theEvent);
    }

  CLEANUP:

    if (drawRgn)
        DisposeRgn (drawRgn);
    if (menuRgn)
        DisposeRgn (menuRgn);
    if (tempRgn)
        DisposeRgn (tempRgn);
#endif /* !TARGET_API_MAC_CARBON */
}

/* Various screen update functions available */
static void ROM_DirectUpdate (_THIS, int numrects, SDL_Rect * rects);
static void ROM_WindowUpdate (_THIS, int numrects, SDL_Rect * rects);

static void
ROM_UnsetVideoMode (_THIS, SDL_Surface * current)
{
    /* Free the current window, if any */
    if (SDL_Window != nil) {
        GWorldPtr memworld;

        /* Handle OpenGL support */
        Mac_GL_Quit (this);

        memworld = (GWorldPtr) GetWRefCon (SDL_Window);
        if (memworld != nil) {
            UnlockPixels (GetGWorldPixMap (memworld));
            DisposeGWorld (memworld);
        }
        if ((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
#if USE_QUICKTIME
            EndFullScreen (fullscreen_ctx, nil);
            SDL_Window = nil;
#else
            ROM_ShowMenuBar (this);
#endif
        }
    }
    current->pixels = NULL;
    current->flags &= ~(SDL_HWSURFACE | SDL_FULLSCREEN);
}

static SDL_Surface *
ROM_SetVideoMode (_THIS, SDL_Surface * current,
                  int width, int height, int bpp, Uint32 flags)
{
    Rect wrect, orect;
#if TARGET_API_MAC_CARBON
    Rect tmprect;
#endif

    /* Free any previous video mode */
    ROM_UnsetVideoMode (this, current);

    /* Create the ROM window and SDL video surface */
    current->flags = 0;         /* Clear flags */
    current->w = width;
    current->h = height;
    SetRect (&wrect, 0, 0, width, height);
    if (SDL_Window) {
        /* If we recreate the window, don't move it around */
#if TARGET_API_MAC_CARBON
        orect = *GetWindowPortBounds (SDL_Window, &tmprect);
#else
        orect = SDL_Window->portRect;
#endif
        OffsetRect (&wrect, orect.left, orect.top);
    } else {
        /* Center the window the first time we show it */
        OffsetRect (&wrect,
                    (SDL_modelist[0]->w - width) / 2,
                    (SDL_modelist[0]->h - height) / 2);
    }

#if defined(__MACOSX__) && !USE_QUICKTIME
    /* Hum.. fullscreen mode is broken */
    flags &= ~SDL_FULLSCREEN;
#endif
    if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
        /* Create the fullscreen window and use screen bits */
        current->flags |= SDL_HWSURFACE | SDL_FULLSCREEN;
        if (SDL_Window) {
            DisposeWindow (SDL_Window);
        }
#if USE_QUICKTIME
        BeginFullScreen (&fullscreen_ctx, nil, 0, 0, &SDL_Window, nil, 0);
#else
        SDL_Window = NewCWindow (nil, &wrect, "\p", true, plainDBox,
                                 (WindowPtr) - 1, false, 0);
        ROM_HideMenuBar (this);
#endif
        current->pitch = (**(**SDL_Display).gdPMap).rowBytes & 0x3FFF;
        current->pixels = (**(**SDL_Display).gdPMap).baseAddr;
        this->UpdateRects = ROM_DirectUpdate;
    } else {
        GWorldPtr memworld;
        PixMapHandle pixmap;
        int style;

        style = noGrowDocProc;
        if (flags & SDL_NOFRAME) {
            style = plainDBox;
            current->flags |= SDL_NOFRAME;
        } else if (flags & SDL_RESIZABLE) {
            style = zoomDocProc;
            current->flags |= SDL_RESIZABLE;
        }
        if (SDL_Window && (style == current_style)) {
            /* Resize existing window, if necessary */
            if (((orect.right - orect.left) != width) ||
                ((orect.bottom - orect.top) != height)) {
                SizeWindow (SDL_Window, width, height, false);
            }
        } else {
            /* Recreate the window in the new style */
            if (SDL_Window) {
                DisposeWindow (SDL_Window);
            }
            SDL_Window = NewCWindow (nil, &wrect, "\p", true,
                                     style, (WindowPtr) - 1, true, 0);

            /* Set the window title, if any */
            {
                char *title;
                SDL_WM_GetCaption (&title, NULL);
                if (title) {
                    Mac_SetCaption (this, title, NULL);
                }
            }
        }
        current_style = style;
        SetPalette (SDL_Window, SDL_CPal, false);
        ActivatePalette (SDL_Window);
        if (NewGWorld (&memworld, 0,
#if TARGET_API_MAC_CARBON
                       GetWindowPortBounds (SDL_Window, &tmprect),
#else
                       &SDL_Window->portRect,
#endif
                       SDL_CTab, nil, 0) != noErr) {
            SDL_SetError ("NewGWorld() failed");
            return (NULL);
        }
        SetWRefCon (SDL_Window, (long) memworld);
        pixmap = GetGWorldPixMap (memworld);
        LockPixels (pixmap);
        current->pitch = (**pixmap).rowBytes & 0x3FFF;
        current->pixels = GetPixBaseAddr (pixmap);
        this->UpdateRects = ROM_WindowUpdate;
    }
    SetPortWindowPort (SDL_Window);
    SelectWindow (SDL_Window);

    /* Handle OpenGL support */
    if (flags & SDL_INTERNALOPENGL) {
        if (Mac_GL_Init (this) == 0) {
            current->flags |= SDL_INTERNALOPENGL;
        } else {
            current = NULL;
        }
    }

    if ((flags & SDL_HWPALETTE) && (flags & SDL_FULLSCREEN))
        current->flags |= SDL_HWPALETTE;

    /* We're live! */
    return (current);
}

/* We don't actually allow hardware surfaces other than the main one */
static int
ROM_AllocHWSurface (_THIS, SDL_Surface * surface)
{
    return (-1);
}
static void
ROM_FreeHWSurface (_THIS, SDL_Surface * surface)
{
    return;
}
static int
ROM_LockHWSurface (_THIS, SDL_Surface * surface)
{
    return (0);
}
static void
ROM_UnlockHWSurface (_THIS, SDL_Surface * surface)
{
    return;
}

static void
ROM_DirectUpdate (_THIS, int numrects, SDL_Rect * rects)
{
    /* The application is already updating the visible video memory */
    return;
}

static void
ROM_WindowUpdate (_THIS, int numrects, SDL_Rect * rects)
{
    GWorldPtr memworld;
    GrafPtr saveport;
    CGrafPtr thePort;
    const BitMap *memBits;
    const BitMap *winBits;
    int i;
    Rect update;

    /* Copy from the offscreen GWorld to the window port */
    GetPort (&saveport);
    SetPortWindowPort (SDL_Window);
    thePort = GetWindowPort (SDL_Window);
    memworld = (GWorldPtr) GetWRefCon (SDL_Window);
#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
    memBits = GetPortBitMapForCopyBits ((CGrafPtr) memworld);
#else
    memBits = &((GrafPtr) memworld)->portBits;
#endif
#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
    winBits = GetPortBitMapForCopyBits (thePort);
#else
    winBits = &SDL_Window->portBits;
#endif
    for (i = 0; i < numrects; ++i) {
        update.left = rects[i].x;
        update.right = rects[i].x + rects[i].w;
        update.top = rects[i].y;
        update.bottom = rects[i].y + rects[i].h;
        CopyBits (memBits, winBits, &update, &update, srcCopy, nil);
    }
#if TARGET_API_MAC_CARBON
    if (QDIsPortBuffered (thePort)) {
        QDFlushPortBuffer (thePort, NULL);
    }
#endif
    SetPort (saveport);
}

static int
ROM_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors)
{
    CTabHandle cTab;
    int i;

    /* Get the colortable from the either the display or window */
    if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
        cTab = (**(**SDL_Display).gdPMap).pmTable;
    } else {
        cTab = SDL_CTab;
    }

    /* Verify the range of colors */
    if ((firstcolor + ncolors) > ((**cTab).ctSize + 1)) {
        return (0);
    }

    /* Set the screen palette and update the display */
    for (i = 0; i < ncolors; ++i) {
        int j = firstcolor + i;
        (**cTab).ctTable[j].value = j;
        (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r;
        (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g;
        (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b;
    }
//      if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) 
    {
        GDevice **odisplay;
        odisplay = GetGDevice ();
        SetGDevice (SDL_Display);
        SetEntries (0, (**cTab).ctSize, (ColorSpec *) & (**cTab).ctTable);
        SetGDevice (odisplay);
    }
    return (1);
}

void
ROM_VideoQuit (_THIS)
{
    int i;

    /* Free current video mode */
    ROM_UnsetVideoMode (this, this->screen);
    if (SDL_Window) {
        DisposeWindow (SDL_Window);
        SDL_Window = nil;
    }

    /* Free palette and restore original one */
    if (SDL_CTab != nil) {
        DisposeHandle ((Handle) SDL_CTab);
        SDL_CTab = nil;
    }
    if (SDL_CPal != nil) {
        DisposePalette (SDL_CPal);
        SDL_CPal = nil;
    }
    RestoreDeviceClut (GetMainDevice ());

    /* Free list of video modes */
    if (SDL_modelist != NULL) {
        for (i = 0; SDL_modelist[i]; ++i) {
            SDL_free (SDL_modelist[i]);
        }
        SDL_free (SDL_modelist);
        SDL_modelist = NULL;
    }
}

/* vi: set ts=4 sw=4 expandtab: */