Bochs/bochs/gui/macintosh.cc
Volker Ruppert 1fd6745aea Started rewrite of the gui code to make the graphics snapshot independent from
the display adapter code. When ready, the common gui code should handle it
completely. The snapshot handler should set a flag 'snapshot_mode' and then it
should force a display update. The graphics update code should be redirected to
some code that 'draws' to a snapshot buffer. These first steps are done:

- store some guest display settings in the gui code (text / graphics switch,
  x / y resolution and bpp)
- split 8 bpp palette update code in a common and a specific part and store the
  palette values in the gui code
2012-10-14 18:29:44 +00:00

1693 lines
41 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2012 The Bochs Project
//
// 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 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
/////////////////////////////////////////////////////////////////////////
// macintosh.cc -- bochs GUI file for the Macintosh
// written by David Batterham <drbatter@progsoc.uts.edu.au>
// with contributions from Tim Senecal
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
// BOCHS INCLUDES
#include <MacTypes.h>
#include "param_names.h"
#include "bochs.h"
#include "iodev.h"
// decide whether to enable this file or not
#if BX_WITH_MACOS
#include "icon_bochs.h"
#include "font/vga.bitmap.h"
// MAC OS INCLUDES
#undef ACCESSOR_CALLS_ARE_FUNCTIONS
#define ACCESSOR_CALLS_ARE_FUNCTIONS 1
#include <Quickdraw.h>
#include <QuickdrawText.h>
#include <QDOffscreen.h>
#include <Icons.h>
#include <ImageCompression.h>
#include <Palettes.h>
#include <Windows.h>
#include <Memory.h>
#include <Events.h>
#include <TextUtils.h>
#include <ToolUtils.h>
#include <Dialogs.h>
#include <LowMem.h>
#include <Disks.h>
#include <CursorDevices.h>
#include <Menus.h>
#include <Sound.h>
#include <SIOUX.h>
#include <Devices.h>
// CONSTANTS
#define rMBarID 128
#define mApple 128
#define iAbout 1
#define mFile 129
#define iQuit 1
#define mEdit 130
#define mBochs 131
#define iFloppy 1
#define iCursor 3
#define iTool 4
#define iMenuBar 5
#define iFullScreen 6
#define iConsole 7
#define iSnapshot 9
#define iReset 10
#define SLEEP_TIME 0 // Number of ticks to surrender the processor during a WaitNextEvent()
// Change this to 15 or higher if you don't want Bochs to hog the processor!
#define FONT_WIDTH 8
#define FONT_HEIGHT 16
#define WINBITMAP(w) (((GrafPtr)(w))->portBits)
#define ASCII_1_MASK 0x00FF0000
#define ASCII_2_MASK 0x000000FF
const RGBColor black = {0, 0, 0};
const RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
const RGBColor medGrey = {0xCCCC, 0xCCCC, 0xCCCC};
const RGBColor ltGrey = {0xEEEE, 0xEEEE, 0xEEEE};
class bx_macintosh_gui_c : public bx_gui_c {
public:
bx_macintosh_gui_c (void) {}
DECLARE_GUI_VIRTUAL_METHODS()
};
// declare one instance of the gui object and call macro to insert the
// plugin code
static bx_macintosh_gui_c *theGui = NULL;
IMPLEMENT_GUI_PLUGIN_CODE(macintosh)
#define LOG_THIS theGui->
// GLOBALS
WindowPtr win, toolwin, fullwin, backdrop, hidden, SouixWin;
SInt16 gOldMBarHeight;
bx_bool menubarVisible = true, cursorVisible = true;
RgnHandle mBarRgn, cnrRgn;
unsigned mouse_button_state = 0;
CTabHandle gCTable;
PixMapHandle gTile;
BitMap *vgafont[256];
Rect srcTextRect, srcTileRect;
Point scrCenter = {320, 240};
Ptr KCHR;
short gheaderbar_y;
Point prevPt;
unsigned width, height, gMinTop, gMaxTop, gLeft;
GWorldPtr gOffWorld;
Ptr gMyBuffer;
static unsigned disp_bpp=8;
static EventModifiers oldMods = 0;
static unsigned int text_rows=25, text_cols=80;
// HEADERBAR STUFF
int numPixMaps = 0, toolPixMaps = 0;
unsigned bx_bitmap_left_xorigin = 2; // pixels from left
unsigned bx_bitmap_right_xorigin = 2; // pixels from right
//PixMapHandle bx_pixmap[BX_MAX_PIXMAPS];
CIconHandle bx_cicn[BX_MAX_PIXMAPS];
struct {
CIconHandle cicn;
// PixMapHandle pm;
unsigned xdim;
unsigned ydim;
unsigned xorigin;
unsigned yorigin;
unsigned alignment;
void (*f)(void);
} bx_tool_pixmap[BX_MAX_PIXMAPS];
// Event handlers
BX_CPP_INLINE void HandleKey(EventRecord *event, Bit32u keyState);
BX_CPP_INLINE void HandleToolClick(Point where);
void HandleMenuChoice(long menuChoice);
BX_CPP_INLINE void HandleClick(EventRecord *event);
// Update routines
void UpdateWindow(WindowPtr window);
void UpdateRgn(RgnHandle rgn);
// Show/hide UI elements
void HidePointer(void);
void ShowPointer(void);
void HideTools(void);
void ShowTools(void);
void HideMenubar(void);
void ShowMenubar(void);
void HideConsole(void);
void ShowConsole(void);
// Initialisation
void FixWindow(void);
void MacPanic(void);
void InitToolbox(void);
void CreateTile(void);
void CreateMenus(void);
void CreateWindows(void);
void CreateKeyMap(void);
void CreateVGAFont(void);
BitMap *CreateBitMap(unsigned width, unsigned height);
PixMapHandle CreatePixMap(unsigned left, unsigned top, unsigned width,
unsigned height, unsigned depth, CTabHandle clut);
unsigned char reverse_bitorder(unsigned char);
//this routine moves the initial window position so that it is entirely onscreen
//it is needed for os 8.x with appearance managaer
void FixWindow(void)
{
RgnHandle wStruct;
Region *wRgn;
CWindowRecord *thing;
Rect wRect;
RgnHandle tStruct;
Region *tRgn;
Rect tRect;
short MinVal;
thing = (CWindowRecord *)win;
wStruct = thing->strucRgn;
wRgn = (Region *)*wStruct;
wRect = wRgn->rgnBBox;
thing = (CWindowRecord *)toolwin;
tStruct = thing->strucRgn;
tRgn = (Region *)*tStruct;
tRect = tRgn->rgnBBox;
if (wRect.left < 2)
{
gLeft = gLeft + (2 - wRect.left);
}
MinVal = tRect.bottom+2;
//MinVal = MinVal + GetMBarHeight();
if (wRect.top < MinVal)
{
// gMinTop = gMinTop + (MinVal - wRect.top);
gMaxTop = gMaxTop + (MinVal - wRect.top);
}
MoveWindow(win, gLeft, gMaxTop, false);
}
void MacPanic(void)
{
StopAlert(200, NULL);
}
void InitToolbox(void)
{
InitGraf(&qd.thePort);
InitWindows();
InitMenus();
InitDialogs(nil);
InitCursor();
MaxApplZone();
// Initialise the toolbox
}
void CreateTile(void)
{
GDHandle saveDevice;
CGrafPtr savePort;
OSErr err;
unsigned long p_f;
long theRowBytes = ((((long) (disp_bpp==24?32:(((disp_bpp+1)>>1)<<1)) * ((long) (srcTileRect.right-srcTileRect.left)) + 31) >> 5) << 2);
//if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
//{
GetGWorld(&savePort, &saveDevice);
switch (disp_bpp) {
case 1:
p_f = k1MonochromePixelFormat;
break;
case 2:
p_f = k2IndexedPixelFormat;
break;
case 4:
p_f = k4IndexedPixelFormat;
break;
case 8:
p_f = k8IndexedPixelFormat;
break;
case 15:
p_f = k16LE555PixelFormat;
break;
case 16:
p_f = k16LE565PixelFormat;
break;
case 24:
//p_f = k24BGRPixelFormat;
//break;
case 32:
p_f = k32ARGBPixelFormat;//k32BGRAPixelFormat;
break;
}
BX_ASSERT((gMyBuffer = (Ptr)malloc(theRowBytes * (srcTileRect.bottom - srcTileRect.top))) != NULL);
err = QTNewGWorldFromPtr(&gOffWorld, p_f,
&srcTileRect, disp_bpp>8 ? NULL : gCTable, NULL, keepLocal, gMyBuffer, theRowBytes);
if (err != noErr || gOffWorld == NULL)
BX_PANIC(("mac: can't create gOffWorld; err=%hd", err));
SetGWorld(gOffWorld, NULL);
RGBForeColor(&black);
RGBBackColor(&white);
gTile = GetGWorldPixMap(gOffWorld);
if (gTile != NULL)
{
NoPurgePixels(gTile);
if (!LockPixels(gTile))
BX_ERROR(("mac: can't LockPixels gTile"));
if ((**gTile).pixelType != RGBDirect && (**gTile).pmTable != gCTable)
{
DisposeCTable(gCTable);
gCTable = (**gTile).pmTable;
}
(**gCTable).ctFlags |= 0x4000; //use palette manager indexes
CTabChanged(gCTable);
}
else
BX_PANIC(("mac: can't create gTile"));
SetGWorld(savePort, saveDevice);
/*}
else
{
gOffWorld = NULL;
gTile = CreatePixMap(0, 0, srcTileRect.right, srcTileRect.bottom, 8, gCTable);
if (gTile == NULL)
BX_PANIC(("mac: can't create gTile"));
}*/
}
void CreateMenus(void)
{
Handle menu;
menu = GetNewMBar(rMBarID); // get our menus from resource
if (menu != nil)
{
SetMenuBar(menu);
DisposeHandle(menu);
AppendResMenu(GetMenuHandle(mApple), 'DRVR'); // add apple menu items
DrawMenuBar();
}
else
BX_PANIC(("can't create menu"));
}
void CreateWindows(void)
{
int l, t, r, b;
Rect winRect;
SetRect(&winRect, 0, 0, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom);
backdrop = NewWindow(NULL, &winRect, "\p", false, plainDBox, (WindowPtr)-1, false, 0);
width = 640;
height = 480;
gLeft = 4;
gMinTop = 44;
gMaxTop = 44 + gheaderbar_y;
l = (qd.screenBits.bounds.right - width)/2;
r = l + width;
t = (qd.screenBits.bounds.bottom - height)/2;
b = t + height;
SetRect(&winRect, 0, 20, qd.screenBits.bounds.right, 22+gheaderbar_y);
toolwin = NewCWindow(NULL, &winRect, "\pMacBochs 586", true, floatProc,
(WindowPtr)-1, false, 0);
if (toolwin == NULL)
BX_PANIC(("mac: can't create tool window"));
// Create a moveable tool window for the "headerbar"
SetRect(&winRect, l, t, r, b);
fullwin = NewCWindow(NULL, &winRect, "\p", false, plainDBox, (WindowPtr)-1, false, 1);
SetRect(&winRect, gLeft, gMaxTop, gLeft+width, gMaxTop+height);
win = NewCWindow(NULL, &winRect, "\pMacBochs 586", true, documentProc,
(WindowPtr)-1, true, 1);
if (win == NULL)
BX_PANIC(("mac: can't create emulator window"));
FixWindow();
hidden = fullwin;
HiliteWindow(win, true);
SetPort(win);
}
// ::SPECIFIC_INIT()
//
// Called from gui.cc, once upon program startup, to allow for the
// specific GUI code (X11, Win32, ...) to be initialized.
//
// argc, argv: not used right now, but the intention is to pass native GUI
// specific options from the command line. (X11 options, Win32 options,...)
//
// headerbar_y: A headerbar (toolbar) is display on the top of the
// VGA window, showing floppy status, and other information. It
// always assumes the width of the current VGA mode width, but
// it's height is defined by this parameter.
void bx_macintosh_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
{
put("MGUI");
InitToolbox();
//SouixWin = FrontWindow();
atexit(MacPanic);
gheaderbar_y = headerbar_y;
CreateKeyMap();
gCTable = GetCTable(128);
BX_ASSERT (gCTable != NULL);
CTabChanged(gCTable); //(*gCTable)->ctSeed = GetCTSeed();
SetRect(&srcTextRect, 0, 0, FONT_WIDTH, FONT_HEIGHT);
SetRect(&srcTileRect, 0, 0, x_tilesize, y_tilesize);
CreateMenus();
CreateVGAFont();
CreateTile();
CreateWindows();
GetMouse(&prevPt);
SetEventMask(everyEvent);
SIOUXSettings.setupmenus = false;
SIOUXSettings.autocloseonquit = true;
SIOUXSettings.asktosaveonclose = false;
SIOUXSettings.standalone = false;
UNUSED(argc);
UNUSED(argv);
//HideWindow(SouixWin);
}
// HandleKey()
//
// Handles keyboard-related events.
BX_CPP_INLINE void HandleKey(EventRecord *event, Bit32u keyState)
{
UInt32 key;
UInt32 trans;
static UInt32 transState = 0;
key = event->message & charCodeMask;
if (event->modifiers & cmdKey)
{
HandleMenuChoice(MenuKey(key));
}
//else if (FrontWindow() == SouixWin)
//{
// SIOUXHandleOneEvent(event);
//}
else
{
/* if (event->modifiers & shiftKey)
DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | keyState);
if (event->modifiers & controlKey)
DEV_kbd_gen_scancode(BX_KEY_CTRL_L | keyState);
if (event->modifiers & optionKey)
DEV_kbd_gen_scancode(BX_KEY_ALT_L | keyState);*/
key = (event->message & keyCodeMask) >> 8;
trans = KeyTranslate(KCHR, key, &transState);
if ((trans == BX_KEY_PRINT) && ((oldMods & optionKey) || (oldMods & rightOptionKey)))
trans = BX_KEY_ALT_SYSREQ;
if ((trans == BX_KEY_PAUSE) && ((oldMods & controlKey) || (oldMods & rightControlKey)))
trans = BX_KEY_CTRL_BREAK;
// KeyTranslate maps Mac virtual key codes to any type of character code
// you like (in this case, Bochs key codes). Much nicer than a huge switch
// statement!
if (trans > 0)
DEV_kbd_gen_scancode(trans | keyState);
/* if (event->modifiers & shiftKey)
DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | BX_KEY_RELEASED);
if (event->modifiers & controlKey)
DEV_kbd_gen_scancode(BX_KEY_CTRL_L | BX_KEY_RELEASED);
if (event->modifiers & optionKey)
DEV_kbd_gen_scancode(BX_KEY_ALT_L | BX_KEY_RELEASED);*/
}
}
// HandleToolClick()
//
// Handles mouse clicks in the Bochs tool window
BX_CPP_INLINE void HandleToolClick(Point where)
{
unsigned i;
int xorigin;
Rect bounds;
SetPort(toolwin);
GlobalToLocal(&where);
for (i=0; i<toolPixMaps; i++)
{
if (bx_tool_pixmap[i].alignment == BX_GRAVITY_LEFT)
xorigin = bx_tool_pixmap[i].xorigin;
else
xorigin = toolwin->portRect.right - bx_tool_pixmap[i].xorigin;
SetRect(&bounds, xorigin, 0, xorigin+32, 32);
if (PtInRect(where, &bounds))
bx_tool_pixmap[i].f();
}
theGui->show_headerbar();
}
BX_CPP_INLINE void ResetPointer(void)
{
#if 0
CursorDevice *theMouse;
if (true)
{
theMouse = NULL;
CrsrDevNextDevice(&theMouse);
CrsrDevMoveTo(theMouse, (long)scrCenter.h, (long)scrCenter.v);
}
#endif
#define MouseCur 0x082C
#define MouseTemp 0x0828
#define MouseNew 0x08CE
#define MouseAttached 0x08CF
*(Point *)MouseCur = scrCenter;
*(Point *)MouseTemp = scrCenter;
*(Ptr)MouseNew = *(Ptr)MouseAttached;
//*(char *)CrsrNew = 0xFF;
}
// HandleClick()
//
// Handles mouse click events.
void HandleMenuChoice(long menuChoice)
{
OSErr err = noErr;
short item, menu, i;
short daRefNum;
Rect bounds;
Str255 daName;
WindowRef newWindow;
DialogPtr theDlog;
item = LoWord(menuChoice);
menu = HiWord(menuChoice);
switch(menu) {
case mApple:
switch(item) {
case iAbout:
theDlog = GetNewDialog(128, NULL, (WindowPtr)-1);
ModalDialog(NULL, &i);
DisposeDialog(theDlog);
break;
default:
GetMenuItemText(GetMenuHandle(mApple), item, daName);
daRefNum = OpenDeskAcc(daName);
break;
}
break;
case mFile:
switch(item) {
case iQuit:
BX_PANIC(("User terminated"));
break;
default:
break;
}
break;
case mBochs:
switch(item) {
case iFloppy:
DiskEject(1);
break;
case iCursor:
if (cursorVisible)
HidePointer();
else
ShowPointer();
break;
case iTool:
if (IsWindowVisible(toolwin))
HideTools();
else
ShowTools();
break;
case iMenuBar:
if (menubarVisible)
HideMenubar();
else
ShowMenubar();
break;
case iFullScreen:
if (cursorVisible || IsWindowVisible(toolwin) || menubarVisible)
{
if (cursorVisible)
HidePointer();
if (menubarVisible)
HideMenubar();
if (IsWindowVisible(toolwin))
HideTools();
}
else
{
if (!cursorVisible)
ShowPointer();
if (!menubarVisible)
ShowMenubar();
if (!IsWindowVisible(toolwin))
ShowTools();
}
break;
case iConsole:
if (IsWindowVisible(SouixWin))
HideConsole();
else
ShowConsole();
break;
case iSnapshot:
// the following will break if snapshot is not last bitmap button instantiated
bx_tool_pixmap[toolPixMaps-1].f();
break;
}
default:
break;
}
HiliteMenu(0);
}
BX_CPP_INLINE void HandleClick(EventRecord *event)
{
short part;
WindowPtr whichWindow;
Rect dRect;
part = FindWindow(event->where, &whichWindow);
switch(part)
{
case inContent:
if (whichWindow == win)
{
if (win != FrontWindow())
SelectWindow(win);
if (event->modifiers & cmdKey)
mouse_button_state |= 0x02;
else
mouse_button_state |= 0x01;
}
else if (whichWindow == toolwin)
{
HiliteWindow(win, true);
HandleToolClick(event->where);
}
else if (whichWindow == backdrop)
{
SelectWindow(win);
}
else if (whichWindow == SouixWin)
{
SelectWindow(SouixWin);
}
break;
case inDrag:
dRect = qd.screenBits.bounds;
if (IsWindowVisible(toolwin))
dRect.top = gMaxTop;
DragWindow(whichWindow, event->where, &dRect);
break;
case inMenuBar:
HandleMenuChoice(MenuSelect(event->where));
break;
}
}
void UpdateWindow(WindowPtr window)
{
GrafPtr oldPort;
Rect box;
GetPort(&oldPort);
SetPort(window);
BeginUpdate(window);
if (window == win)
{
box = window->portRect;
DEV_vga_redraw_area(box.left, box.top, box.right, box.bottom);
}
else if (window == backdrop)
{
box = window->portRect;
FillRect(&box, &qd.black);
}
else if (window == toolwin)
{
theGui->show_headerbar();
}
EndUpdate(window);
SetPort(oldPort);
}
// ::HANDLE_EVENTS()
//
// Called periodically (vga_update_interval in .bochsrc) so the
// the gui code can poll for keyboard, mouse, and other
// relevant events.
void bx_macintosh_gui_c::handle_events(void)
{
EventRecord event;
Point mousePt;
int dx, dy;
int oldMods1=0;
EventModifiers newMods;
unsigned curstate;
GrafPtr oldport;
curstate = mouse_button_state; //so we can compare the old and the new mouse state
if (WaitNextEvent(everyEvent, &event, SLEEP_TIME, NULL))
{
switch(event.what)
{
case nullEvent:
break;
case mouseDown:
HandleClick(&event);
break;
case mouseUp:
if (event.modifiers & cmdKey)
mouse_button_state &= ~0x02;
else
mouse_button_state &= ~0x01;
break;
case keyDown:
case autoKey:
oldMods1 = event.modifiers;
HandleKey(&event, BX_KEY_PRESSED);
break;
case keyUp:
event.modifiers = oldMods1;
HandleKey(&event, BX_KEY_RELEASED);
break;
case updateEvt:
if ((WindowPtr)event.message == SouixWin)
SIOUXHandleOneEvent(&event);
else
UpdateWindow((WindowPtr)event.message);
break;
case diskEvt:
floppyA_handler();
default:
break;
}
}
else if (oldMods != (newMods = (event.modifiers & 0xfe00)))
{
if ((newMods ^ oldMods) & shiftKey)
DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | ((newMods & shiftKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & alphaLock)
DEV_kbd_gen_scancode(BX_KEY_CAPS_LOCK | ((newMods & alphaLock)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & optionKey)
DEV_kbd_gen_scancode(BX_KEY_ALT_L | ((newMods & optionKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & controlKey)
DEV_kbd_gen_scancode(BX_KEY_CTRL_L | ((newMods & controlKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & rightShiftKey)
DEV_kbd_gen_scancode(BX_KEY_SHIFT_R | ((newMods & rightShiftKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & rightOptionKey)
DEV_kbd_gen_scancode(BX_KEY_ALT_R | ((newMods & rightOptionKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
if ((newMods ^ oldMods) & rightControlKey)
DEV_kbd_gen_scancode(BX_KEY_CTRL_R | ((newMods & rightControlKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
oldMods = newMods;
}
GetPort(&oldport);
SetPort(win);
GetMouse(&mousePt);
//if mouse has moved, or button has changed state
if ((!EqualPt(mousePt, prevPt)) || (curstate != mouse_button_state))
{
dx = mousePt.h - prevPt.h;
dy = prevPt.v - mousePt.v;
DEV_mouse_motion(dx, dy, 0, mouse_button_state, 0);
if (!cursorVisible)
{
SetPt(&scrCenter, 320, 240);
LocalToGlobal(&scrCenter);
ResetPointer(); //next getmouse should be 320, 240
SetPt(&mousePt, 320, 240);
}
}
prevPt = mousePt;
SetPort(oldport);
}
// ::FLUSH()
//
// Called periodically, requesting that the gui code flush all pending
// screen update requests.
void bx_macintosh_gui_c::flush(void)
{
// an opportunity to make the Window Manager happy.
// not needed on the macintosh....
}
// ::CLEAR_SCREEN()
//
// Called to request that the VGA region is cleared. Don't
// clear the area that defines the headerbar.
void bx_macintosh_gui_c::clear_screen(void)
{
SetPort(win);
RGBForeColor(&black);
RGBBackColor(&white);
FillRect(&win->portRect, &qd.black);
}
// ::TEXT_UPDATE()
//
// Called in a VGA text mode, to update the screen with
// new content.
//
// old_text: array of character/attributes making up the contents
// of the screen from the last call. See below
// new_text: array of character/attributes making up the current
// contents, which should now be displayed. See below
//
// format of old_text & new_text: each is tm_info->line_offset*text_rows
// bytes long. Each character consists of 2 bytes. The first by is
// the character value, the second is the attribute byte.
//
// cursor_x: new x location of cursor
// cursor_y: new y location of cursor
// tm_info: this structure contains information for additional
// features in text mode (cursor shape, line offset,...)
void bx_macintosh_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
unsigned long cursor_x, unsigned long cursor_y,
bx_vga_tminfo_t *tm_info)
{
int i;
unsigned char achar;
int x, y;
static int previ;
int cursori;
Rect destRect;
RGBColor fgColor, bgColor;
GrafPtr oldPort;
unsigned nchars;
OSErr theError;
GetPort(&oldPort);
SetPort(win);
//current cursor position
cursori = (cursor_y * text_cols + cursor_x) * 2;
// Number of characters on screen, variable number of rows
nchars = text_cols * text_rows;
for (i=0; i<nchars*2; i+=2)
{
if (i == cursori || i == previ || new_text[i] != old_text[i] || new_text[i+1] != old_text[i+1])
{
achar = new_text[i];
// fgColor = (**gCTable).ctTable[new_text[i+1] & 0x0F].rgb;
// bgColor = (**gCTable).ctTable[(new_text[i+1] & 0xF0) >> 4].rgb;
// RGBForeColor(&fgColor);
// RGBBackColor(&bgColor);
if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
{
PmForeColor(new_text[i+1] & 0x0F);
PmBackColor((new_text[i+1] & 0xF0) >> 4);
}
else
{
fgColor = (**gCTable).ctTable[new_text[i+1] & 0x0F].rgb;
bgColor = (**gCTable).ctTable[(new_text[i+1] & 0xF0) >> 4].rgb;
RGBForeColor(&fgColor);
RGBBackColor(&bgColor);
}
x = ((i/2) % text_cols)*FONT_WIDTH;
y = ((i/2) / text_cols)*FONT_HEIGHT;
SetRect(&destRect, x, y, x+FONT_WIDTH, y+FONT_HEIGHT);
CopyBits(vgafont[achar], &WINBITMAP(win),
&srcTextRect, &destRect, srcCopy, NULL);
if ((theError = QDError()) != noErr)
BX_ERROR(("mac: CopyBits returned %hd", theError));
if (i == cursori) //invert the current cursor block
{
InvertRect(&destRect);
}
}
}
//previous cursor position
previ = cursori;
SetPort(oldPort);
}
int bx_macintosh_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
{
return 0;
}
int bx_macintosh_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
{
return 0;
}
// ::PALETTE_CHANGE()
//
// Allocate a color in the native GUI, for this color, and put
// it in the colormap location 'index'.
// returns: 0=no screen update needed (color map change has direct effect)
// 1=screen updated needed (redraw using current colormap)
bx_bool bx_macintosh_gui_c::palette_change(Bit8u index, Bit8u red, Bit8u green, Bit8u blue)
{
PaletteHandle thePal, oldpal;
GDHandle saveDevice;
CGrafPtr savePort;
GrafPtr oldPort;
/*if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
{
GetGWorld(&savePort, &saveDevice);
SetGWorld(gOffWorld, NULL);
}*/
if ((**gTile).pixelType != RGBDirect)
{
GetPort(&oldPort);
SetPort(win);
(**gCTable).ctTable[index].value = index;
(**gCTable).ctTable[index].rgb.red = (red << 8);
(**gCTable).ctTable[index].rgb.green = (green << 8);
(**gCTable).ctTable[index].rgb.blue = (blue << 8);
SetEntries(index, index, (**gCTable).ctTable);
CTabChanged(gCTable);
SetPort(oldPort);
}
/*if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
SetGWorld(savePort, saveDevice);*/
if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
{
thePal = NewPalette(index, gCTable, pmTolerant, 0x5000);
oldpal = GetPalette(win);
SetPalette(win, thePal, false);
SetPalette(fullwin, thePal, false);
SetPalette(hidden, thePal, false);
return(1);
}
return((**gTile).pixelType != RGBDirect);
}
// ::GRAPHICS_TILE_UPDATE()
//
// Called to request that a tile of graphics be drawn to the
// screen, since info in this region has changed.
//
// tile: array of 8bit values representing a block of pixels with
// dimension equal to the 'x_tilesize' & 'y_tilesize' members.
// Each value specifies an index into the
// array of colors you allocated for ::palette_change()
// x0: x origin of tile
// y0: y origin of tile
//
// note: origin of tile and of window based on (0,0) being in the upper
// left of the window.
void bx_macintosh_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
{
Rect destRect;
OSErr theError;
Ptr theBaseAddr;
GrafPtr oldPort;
/*GDHandle saveDevice;
CGrafPtr savePort;
GetGWorld(&savePort, &saveDevice);
SetGWorld(gOffWorld, NULL); */
GetPort(&oldPort);
SetPort(win);
destRect = srcTileRect;
OffsetRect(&destRect, x0, y0);
//(**gTile).baseAddr = (Ptr)tile;
if ((theBaseAddr = GetPixBaseAddr(gTile)) == NULL)
BX_PANIC(("mac: gTile has NULL baseAddr (offscreen buffer purged)"));
else if (disp_bpp == 24 || disp_bpp == 32) {
for (unsigned iY = 0; iY < (srcTileRect.bottom-srcTileRect.top); iY++) {
Bit8u *iA = ((Bit8u *)theBaseAddr) + iY * GetPixRowBytes(gTile);
for (unsigned iX = 0; iX < (srcTileRect.right-srcTileRect.left); iX++) {
iA[iX*4 + 3] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(disp_bpp>>3)];
iA[iX*4 + 2] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(disp_bpp>>3) + 1];
iA[iX*4 + 1] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(disp_bpp>>3) + 2];
iA[iX*4] = disp_bpp == 24 ? 0 : tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*4 + 3];
}
}
} else {
BlockMoveData(tile, theBaseAddr, (srcTileRect.bottom-srcTileRect.top) * GetPixRowBytes(gTile));
}
RGBForeColor(&black);
RGBBackColor(&white);
CopyBits(GetPortBitMapForCopyBits(gOffWorld), &WINBITMAP(win),
&srcTileRect, &destRect, srcCopy, NULL);
if ((theError = QDError()) != noErr)
BX_ERROR(("mac: CopyBits returned %hd", theError));
SetPort(oldPort);
//SetGWorld(savePort, saveDevice);
}
// ::DIMENSION_UPDATE()
//
// Called when the VGA mode changes it's X,Y dimensions.
// Resize the window to this size, but you need to add on
// the height of the headerbar to the Y value.
//
// x: new VGA x size
// y: new VGA y size (add headerbar_y parameter from ::specific_init().
// fheight: new VGA character height in text mode
// fwidth : new VGA character width in text mode
// bpp : bits per pixel in graphics mode
void bx_macintosh_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
{
if ((bpp != 1) && (bpp != 2) && (bpp != 4) && (bpp != 8) && (bpp != 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) {
BX_PANIC(("%d bpp graphics mode not supported yet", bpp));
}
guest_textmode = (fheight > 0);
guest_xres = x;
guest_yres = y;
guest_bpp = bpp;
if (bpp != disp_bpp) {
free(gMyBuffer);
if ((**gTile).pixelType == RGBDirect)
gCTable = GetCTable(128);
DisposeGWorld(gOffWorld);
disp_bpp = bpp;
CreateTile();
}
if (guest_textmode) {
text_cols = x / fwidth;
text_rows = y / fheight;
if (fwidth != 8) {
x = x * 8 / fwidth;
}
if (fheight != 16) {
y = y * 16 / fheight;
}
}
if (x != width || y != height)
{
SizeWindow(win, x, y, false);
SizeWindow(fullwin, x, y, false);
SizeWindow(hidden, x, y, false);
width = x;
height = y;
}
host_xres = x;
host_yres = y;
host_bpp = bpp;
}
// ::CREATE_BITMAP()
//
// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
// be drawn in the headerbar. Return an integer ID to the bitmap,
// with which the bitmap can be referenced later.
//
// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
// bit0 is the left most pixel, bit7 is the right most pixel.
// xdim: x dimension of bitmap
// ydim: y dimension of bitmap
// rewritten by tim senecal to use the cicn (color icon) resources instead
unsigned bx_macintosh_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
{
unsigned i;
unsigned char *data;
long row_bytes, bytecount;
bx_cicn[numPixMaps] = GetCIcon(numPixMaps+128);
BX_ASSERT(bx_cicn[numPixMaps]);
numPixMaps++;
return(numPixMaps-1);
}
// ::HEADERBAR_BITMAP()
//
// Called to install a bitmap in the bochs headerbar (toolbar).
//
// bmap_id: will correspond to an ID returned from
// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
// available leftmost or rightmost space.
// f: a 'C' function pointer to callback when the mouse is clicked in
// the boundaries of this bitmap.
unsigned bx_macintosh_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
{
unsigned hb_index;
toolPixMaps++;
hb_index = toolPixMaps-1;
//bx_tool_pixmap[hb_index].pm = bx_pixmap[bmap_id];
bx_tool_pixmap[hb_index].cicn = bx_cicn[bmap_id];
bx_tool_pixmap[hb_index].alignment = alignment;
bx_tool_pixmap[hb_index].f = f;
if (alignment == BX_GRAVITY_LEFT)
{
bx_tool_pixmap[hb_index].xorigin = bx_bitmap_left_xorigin;
bx_tool_pixmap[hb_index].yorigin = 0;
// bx_bitmap_left_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
bx_bitmap_left_xorigin += 34;
}
else
{
// bx_bitmap_right_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
bx_bitmap_right_xorigin += 34;
bx_tool_pixmap[hb_index].xorigin = bx_bitmap_right_xorigin;
bx_tool_pixmap[hb_index].yorigin = 0;
}
return(hb_index);
}
// ::SHOW_HEADERBAR()
//
// Show (redraw) the current headerbar, which is composed of
// currently installed bitmaps.
void bx_macintosh_gui_c::show_headerbar(void)
{
Rect destRect;
int i, xorigin;
SetPort(toolwin);
RGBForeColor(&medGrey);
FillRect(&toolwin->portRect, &qd.black);
for (i=0; i<toolPixMaps; i++)
{
if (bx_tool_pixmap[i].alignment == BX_GRAVITY_LEFT)
xorigin = bx_tool_pixmap[i].xorigin;
else
xorigin = toolwin->portRect.right - bx_tool_pixmap[i].xorigin;
SetRect(&destRect, xorigin, 0, xorigin+32, 32);
//changed, simply plot the cicn for that button, in the prescribed rectangle
PlotCIcon(&destRect, bx_tool_pixmap[i].cicn);
}
RGBForeColor(&black);
}
// ::REPLACE_BITMAP()
//
// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
// with the one specified by 'bmap_id'. 'bmap_id' will have
// been generated by ::create_bitmap(). The old and new bitmap
// must be of the same size. This allows the bitmap the user
// sees to change, when some action occurs. For example when
// the user presses on the floppy icon, it then displays
// the ejected status.
//
// hbar_id: headerbar slot ID
// bmap_id: bitmap ID
void bx_macintosh_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
{
//bx_tool_pixmap[hbar_id].pm = bx_pixmap[bmap_id];
bx_tool_pixmap[hbar_id].cicn = bx_cicn[bmap_id];
show_headerbar();
}
// ::EXIT()
//
// Called before bochs terminates, to allow for a graceful
// exit from the native GUI mechanism.
void bx_macintosh_gui_c::exit(void)
{
if (!menubarVisible)
ShowMenubar(); // Make the menubar visible again
InitCursor();
}
#if 0
void bx_macintosh_gui_c::snapshot_handler(void)
{
PicHandle ScreenShot;
long val;
SetPort(win);
ScreenShot = OpenPicture(&win->portRect);
CopyBits(&win->portBits, &win->portBits, &win->portRect, &win->portRect, srcCopy, NULL);
ClosePicture();
val = ZeroScrap();
HLock((Handle)ScreenShot);
PutScrap(GetHandleSize((Handle)ScreenShot), 'PICT', *ScreenShot);
HUnlock((Handle)ScreenShot);
KillPicture(ScreenShot);
}
#endif
// UpdateRgn()
//
// Updates the screen after the menubar and round corners have been hidden
void UpdateRgn(RgnHandle rgn)
{
WindowPtr window;
window = FrontWindow();
PaintBehind(window, rgn);
CalcVisBehind(window, rgn);
}
// HidePointer()
//
// Hides the Mac mouse pointer
void HidePointer()
{
HiliteMenu(0);
HideCursor();
SetPort(win);
SetPt(&scrCenter, 320, 240);
LocalToGlobal(&scrCenter);
ResetPointer();
GetMouse(&prevPt);
cursorVisible = false;
CheckItem(GetMenuHandle(mBochs), iCursor, false);
}
// ShowPointer()
//
// Shows the Mac mouse pointer
void ShowPointer()
{
InitCursor();
cursorVisible = true;
CheckItem(GetMenuHandle(mBochs), iCursor, true);
}
// HideTools()
//
// Hides the Bochs toolbar
void HideTools()
{
HideWindow(toolwin);
if (menubarVisible)
{
MoveWindow(win, gLeft, gMinTop, false);
}
else
{
MoveWindow(hidden, gLeft, gMinTop, false);
}
CheckItem(GetMenuHandle(mBochs), iTool, false);
HiliteWindow(win, true);
}
// ShowTools()
//
// Shows the Bochs toolbar
void ShowTools()
{
if (menubarVisible)
{
MoveWindow(win, gLeft, gMaxTop, false);
}
else
{
MoveWindow(hidden, gLeft, gMaxTop, false);
}
ShowWindow(toolwin);
BringToFront(toolwin);
SelectWindow(toolwin);
HiliteWindow(win, true);
//theGui->show_headerbar();
CheckItem(GetMenuHandle(mBochs), iTool, true);
HiliteWindow(win, true);
}
// HideMenubar()
//
// Hides the menubar (obviously)
void HideMenubar()
{
Rect mBarRect;
RgnHandle grayRgn;
grayRgn = LMGetGrayRgn();
gOldMBarHeight = GetMBarHeight();
LMSetMBarHeight(0);
mBarRgn = NewRgn();
mBarRect = qd.screenBits.bounds;
mBarRect.bottom = mBarRect.top + gOldMBarHeight;
RectRgn(mBarRgn, &mBarRect);
UnionRgn(grayRgn, mBarRgn, grayRgn);
UpdateRgn(mBarRgn);
cnrRgn = NewRgn();
RectRgn(cnrRgn, &qd.screenBits.bounds);
DiffRgn(cnrRgn, grayRgn, cnrRgn);
UnionRgn(grayRgn, cnrRgn, grayRgn);
UpdateRgn(mBarRgn);
HideWindow(win);
ShowWindow(backdrop);
SelectWindow(backdrop);
hidden = win;
win = fullwin;
ShowWindow(win);
SelectWindow(win);
menubarVisible = false;
CheckItem(GetMenuHandle(mBochs), iMenuBar, false);
}
// ShowMenubar()
//
// Makes the menubar visible again so other programs will display correctly.
void ShowMenubar()
{
RgnHandle grayRgn;
GrafPtr savePort;
grayRgn = LMGetGrayRgn();
LMSetMBarHeight(gOldMBarHeight);
DiffRgn(grayRgn, mBarRgn, grayRgn);
DisposeRgn(mBarRgn);
DrawMenuBar();
GetPort(&savePort);
SetPort(LMGetWMgrPort());
SetClip(cnrRgn);
FillRgn(cnrRgn, &qd.black);
SetPort(savePort);
DiffRgn(grayRgn, cnrRgn, grayRgn);
DisposeRgn(cnrRgn);
HideWindow(backdrop);
win = hidden;
hidden = fullwin;
HideWindow(hidden);
ShowWindow(win);
HiliteWindow(win, true);
menubarVisible = true;
CheckItem(GetMenuHandle(mBochs), iMenuBar, true);
}
void HideConsole()
{
HideWindow(SouixWin);
CheckItem(GetMenuHandle(mBochs), iConsole, false);
}
void ShowConsole()
{
ShowWindow(SouixWin);
SelectWindow(SouixWin);
CheckItem(GetMenuHandle(mBochs), iConsole, true);
}
// CreateKeyMap()
//
// Create a KCHR data structure to map Mac virtual key codes to Bochs key codes
void CreateKeyMap(void)
{
const unsigned char KCHRHeader [258] = { 0, 1 };
const unsigned char KCHRTable [130] = {
0,
1,
BX_KEY_A,
BX_KEY_S,
BX_KEY_D,
BX_KEY_F,
BX_KEY_H,
BX_KEY_G,
BX_KEY_Z,
BX_KEY_X,
BX_KEY_C,
BX_KEY_V,
BX_KEY_LEFT_BACKSLASH,
BX_KEY_B,
BX_KEY_Q,
BX_KEY_W,
BX_KEY_E,
BX_KEY_R,
BX_KEY_Y,
BX_KEY_T,
BX_KEY_1,
BX_KEY_2,
BX_KEY_3,
BX_KEY_4,
BX_KEY_6,
BX_KEY_5,
BX_KEY_EQUALS,
BX_KEY_9,
BX_KEY_7,
BX_KEY_MINUS,
BX_KEY_8,
BX_KEY_0,
BX_KEY_RIGHT_BRACKET,
BX_KEY_O,
BX_KEY_U,
BX_KEY_LEFT_BRACKET,
BX_KEY_I,
BX_KEY_P,
BX_KEY_ENTER,
BX_KEY_L,
BX_KEY_J,
BX_KEY_SINGLE_QUOTE,
BX_KEY_K,
BX_KEY_SEMICOLON,
BX_KEY_BACKSLASH,
BX_KEY_COMMA,
BX_KEY_SLASH,
BX_KEY_N,
BX_KEY_M,
BX_KEY_PERIOD,
BX_KEY_TAB,
BX_KEY_SPACE,
BX_KEY_GRAVE,
BX_KEY_BACKSPACE,
BX_KEY_KP_ENTER,
BX_KEY_ESC,
0, // 0x36 (record button)
0, // 0x37 (cmd key)
0, // 0x38 (left shift)
0, // 0x39 (caps lock)
0, // 0x3A (left option/alt)
0, // 0x3B (left ctrl)
0, // 0x3C (right shift)
0, // 0x3D (right option/alt)
0, // 0x3E (right ctrl)
0, // 0x3F (fn key -- laptops)
0, // 0x40
BX_KEY_KP_DELETE, // KP_PERIOD
0, // 0x42 (move right/multiply)
BX_KEY_KP_MULTIPLY,
0, // 0x44
BX_KEY_KP_ADD,
0, // 0x46 (move left/add)
BX_KEY_NUM_LOCK,
0, // 0x48 (move down/equals)
0, // 0x49
0, // 0x4A
BX_KEY_KP_DIVIDE,
BX_KEY_KP_ENTER,
0, // 0x4D (move up/divide)
BX_KEY_KP_SUBTRACT,
0, // 0x4F
0, // 0x50
BX_KEY_EQUALS, // 0x51 (kp equals)
BX_KEY_KP_INSERT, // 0x52 (kp 0)
BX_KEY_KP_END, // 0x53 (kp 1)
BX_KEY_KP_DOWN, // 0x54 (kp 2)
BX_KEY_KP_PAGE_DOWN, // 0x55 (kp 3)
BX_KEY_KP_LEFT, // 0x56 (kp 4)
BX_KEY_KP_5,
BX_KEY_KP_RIGHT, // 0x58 (kp 6)
BX_KEY_KP_HOME, // 0x59 (kp 7)
0, // 0x5A
BX_KEY_KP_UP, // 0x5B (kp 8)
BX_KEY_KP_PAGE_UP, // 0x5C (kp 9)
0, // 0x5D
0, // 0x5E
0, // 0x5F
BX_KEY_F5,
BX_KEY_F6,
BX_KEY_F7,
BX_KEY_F3,
BX_KEY_F8,
BX_KEY_F9,
0, // 0x66
BX_KEY_F11,
0, // 0x68
BX_KEY_PRINT, // 0x69 (print screen)
0, // 0x6A
BX_KEY_SCRL_LOCK, // 0x6B (scroll lock)
0, // 0x6C
BX_KEY_F10,
BX_KEY_MENU, // 0x6E
BX_KEY_F12,
0, // 0x70
BX_KEY_PAUSE, // 0x71 (pause)
BX_KEY_INSERT,
BX_KEY_HOME,
BX_KEY_PAGE_UP,
BX_KEY_DELETE,
BX_KEY_F4,
BX_KEY_END,
BX_KEY_F2,
BX_KEY_PAGE_DOWN,
BX_KEY_F1,
BX_KEY_LEFT,
BX_KEY_RIGHT,
BX_KEY_DOWN,
BX_KEY_UP
};
KCHR = NewPtrClear(390);
if (KCHR == NULL)
BX_PANIC(("mac: can't allocate memory for key map"));
BlockMove(KCHRHeader, KCHR, sizeof(KCHRHeader));
BlockMove(KCHRTable, Ptr(KCHR + sizeof(KCHRHeader)), sizeof(KCHRTable));
}
// CreateVGAFont()
//
// Create an array of PixMaps for the PC screen font
void CreateVGAFont(void)
{
int i, x;
unsigned char *fontData, curPixel;
long row_bytes, bytecount;
for (i=0; i<256; i++)
{
vgafont[i] = CreateBitMap(FONT_WIDTH, FONT_HEIGHT);
row_bytes = (*(vgafont[i])).rowBytes;
bytecount = row_bytes * FONT_HEIGHT;
fontData = (unsigned char *)NewPtrClear(bytecount);
for (x=0; x<16; x++)
{
//curPixel = ~(bx_vgafont[i].data[x]);
curPixel = (bx_vgafont[i].data[x]);
fontData[x*row_bytes] = reverse_bitorder(curPixel);
}
vgafont[i]->baseAddr = Ptr(fontData);
}
}
// CreateBitMap()
// Allocate a new bitmap and fill in the fields with appropriate
// values.
BitMap *CreateBitMap(unsigned width, unsigned height)
{
BitMap *bm;
long row_bytes;
row_bytes = ((width + 31) >> 5) << 2;
bm = (BitMap *)calloc(1, sizeof(BitMap));
if (bm == NULL)
BX_PANIC(("mac: can't allocate memory for pixmap"));
SetRect(&bm->bounds, 0, 0, width, height);
bm->rowBytes = row_bytes;
// Quickdraw allocates a new color table by default, but we want to
// use one we created earlier.
return bm;
}
// CreatePixMap()
// Allocate a new pixmap handle and fill in the fields with appropriate
// values.
PixMapHandle CreatePixMap(unsigned left, unsigned top, unsigned width,
unsigned height, unsigned depth, CTabHandle clut)
{
PixMapHandle pm;
long row_bytes;
row_bytes = (((long) depth * ((long) width) + 31) >> 5) << 2;
pm = NewPixMap();
if (pm == NULL)
BX_PANIC(("mac: can't allocate memory for pixmap"));
(**pm).bounds.left = left;
(**pm).bounds.top = top;
(**pm).bounds.right = left+width;
(**pm).bounds.bottom = top+height;
(**pm).pixelSize = depth;
(**pm).rowBytes = row_bytes | 0x8000;
DisposeCTable((**pm).pmTable);
(**pm).pmTable = clut;
// Quickdraw allocates a new color table by default, but we want to
// use one we created earlier.
return pm;
}
unsigned char reverse_bitorder(unsigned char b)
{
unsigned char ret=0;
for (unsigned i=0; i<8; i++)
{
ret |= (b & 0x01) << (7-i);
b >>= 1;
}
return(ret);
}
void bx_macintosh_gui_c::mouse_enabled_changed_specific (bx_bool val)
{
}
#endif /* if BX_WITH_MACOS */