5873b26a82
bochs.h already not include iodev.h which reduces compilation dependences for almost all cpu and fpu files, now cpu files will not be recompiled if iodev includes was changed
1711 lines
53 KiB
C++
1711 lines
53 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
|
// $Id: macintosh.cc,v 1.24 2004-06-19 15:20:09 sshwarts Exp $
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2001 MandrakeSoft S.A.
|
|
//
|
|
// MandrakeSoft S.A.
|
|
// 43, rue d'Aboukir
|
|
// 75002 Paris - France
|
|
// http://www.linux-mandrake.com/
|
|
// http://www.mandrakesoft.com/
|
|
//
|
|
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "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 vga_bpp=8;
|
|
static EventModifiers oldMods = 0;
|
|
|
|
// 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) ( vga_bpp==24?32:(((vga_bpp+1)>>1)<<1) ) * ((long) (srcTileRect.right-srcTileRect.left)) + 31) >> 5) << 2);
|
|
|
|
// if (bx_options.Oprivate_colormap->get ())
|
|
// {
|
|
GetGWorld(&savePort, &saveDevice);
|
|
switch(vga_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, vga_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, BeOS, ...) 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, BeOS options,...)
|
|
//
|
|
// tilewidth, tileheight: for optimization, graphics_tile_update() passes
|
|
// only updated regions of the screen to the gui code to be redrawn.
|
|
// These define the dimensions of a region (tile).
|
|
// 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 tilewidth, unsigned tileheight,
|
|
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, tilewidth, tileheight);
|
|
|
|
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();
|
|
}
|
|
else
|
|
{
|
|
}
|
|
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, mouse_button_state);
|
|
|
|
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 80*nrows*2 bytes long.
|
|
// This represents 80 characters wide by 'nrows' high, with
|
|
// each character being 2 bytes. The first by is the
|
|
// character value, the second is the attribute byte.
|
|
// I currently don't handle the attribute byte.
|
|
//
|
|
// cursor_x: new x location of cursor
|
|
// cursor_y: new y location of cursor
|
|
|
|
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, unsigned nrows)
|
|
{
|
|
int i;
|
|
unsigned char achar;
|
|
int x, y;
|
|
static int previ;
|
|
int cursori;
|
|
Rect destRect;
|
|
RGBColor fgColor, bgColor;
|
|
GrafPtr oldPort;
|
|
unsigned nchars, ncols;
|
|
OSErr theError;
|
|
|
|
GetPort(&oldPort);
|
|
|
|
SetPort(win);
|
|
|
|
ncols = width/8;
|
|
|
|
//current cursor position
|
|
cursori = (cursor_y*ncols + cursor_x)*2;
|
|
|
|
// Number of characters on screen, variable number of rows
|
|
nchars = ncols*nrows;
|
|
|
|
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 (bx_options.Oprivate_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) % ncols)*FONT_WIDTH;
|
|
y = ((i/2) / ncols)*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(unsigned index, unsigned red, unsigned green, unsigned blue)
|
|
{
|
|
PaletteHandle thePal, oldpal;
|
|
GDHandle saveDevice;
|
|
CGrafPtr savePort;
|
|
GrafPtr oldPort;
|
|
|
|
/* if (gOffWorld != NULL) //(bx_options.Oprivate_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) //(bx_options.Oprivate_colormap->get ())
|
|
SetGWorld(savePort, saveDevice);*/
|
|
if (bx_options.Oprivate_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 'tilewidth' & 'tileheight' parameters to
|
|
// ::specific_init(). 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 (vga_bpp == 24 || vga_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)*(vga_bpp>>3)];
|
|
iA[iX*4 + 2] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(vga_bpp>>3) + 1];
|
|
iA[iX*4 + 1] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(vga_bpp>>3) + 2];
|
|
iA[iX*4] = vga_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));
|
|
}
|
|
if (bpp != vga_bpp)
|
|
{
|
|
free(gMyBuffer);
|
|
if ((**gTile).pixelType == RGBDirect)
|
|
gCTable = GetCTable(128);
|
|
DisposeGWorld(gOffWorld);
|
|
vga_bpp = bpp;
|
|
CreateTile();
|
|
}
|
|
if (fheight > 0) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
// ::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 */
|