- added instructions how to update the online documentation
[bochs-mirror.git] / gui / carbon.cc
blob47f263f0ec6a914b18d6c27c32a13e84c9b40750
1 ////////////////////////////////////////////////////////////////////////
2 // $Id: carbon.cc,v 1.39 2008/03/14 18:23:33 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 ////////////////////////////////////////////////////////////////////////
29 // carbon.cc -- bochs GUI file for MacOS X with Carbon API
30 // written by David Batterham <drbatter@progsoc.uts.edu.au>
31 // with contributions from Tim Senecal
32 // port to Carbon API by Emmanuel Maillard <e.rsz@libertysurf.fr>
33 // Carbon polishing by Jeremy Parsons (Br'fin) <brefin@mac.com>
34 // slight overhaul of Carbon key event, graphics and window handling
35 // and SIM->notify alert support by Chris Thomas <cjack@cjack.com>
37 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
38 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
39 // is used to know when we are exporting symbols and when we are importing.
40 #define BX_PLUGGABLE
43 // BOCHS INCLUDES
44 #define Float32 KLUDGE_Float32
45 #define Float64 KLUDGE_Float64
46 #include "bochs.h"
47 #include "iodev.h"
48 #undef Float32
49 #undef Float64
51 #if BX_WITH_CARBON
53 #include "icon_bochs.h"
54 #include "font/vga.bitmap.h"
55 #include "bxversion.h"
57 // MAC OS INCLUDES
58 #include <Carbon/Carbon.h>
59 #include <ApplicationServices/ApplicationServices.h>
61 // NOTE about use of Boolean versus bx_bool:
62 // Boolean is defined as unsigned char in the Carbon headers, so when
63 // you are talking to the Carbon API, it expects to find Boolean variables
64 // and pointers to Booleans. The rest of Bochs uses bx_bool to represent
65 // booleans, which are defined to be 32 bit unsigned, so member function
66 // definitions and booleans outside this file will be bx_bools. "Boolean"
67 // should only be used in Carbon specific code such as in this file.
69 // CONSTANTS
71 #define rMBarID 128
72 #define mApple 128
73 #define iAbout 1
74 #define mFile 129
75 #define iQuit 1
76 #define mEdit 130
77 #define iUndo 1
78 #define iCut 3
79 #define iCopy 4
80 #define iPaste 5
81 #define iClear 6
82 #define mBochs 131
83 #define iFloppy 1
84 #define iCursor 3
85 #define iTool 4
86 #define iMenuBar 5
87 #define iFullScreen 6
88 #define iConsole 7
89 #define iSnapshot 9
90 #define iReset 10
92 enum {
93 RESET_TOOL_BUTTON = 5,
94 CONFIGURE_TOOL_BUTTON,
95 SNAPSHOT_TOOL_BUTTON,
96 PASTE_TOOL_BUTTON,
97 COPY_TOOL_BUTTON,
98 USER_TOOL_BUTTON
101 const MenuCommand kCommandFloppy = FOUR_CHAR_CODE ('FLPY');
102 const MenuCommand kCommandCursor = FOUR_CHAR_CODE ('CRSR');
103 const MenuCommand kCommandTool = FOUR_CHAR_CODE ('TOOL');
104 const MenuCommand kCommandMenuBar = FOUR_CHAR_CODE ('MENU');
105 const MenuCommand kCommandFullScreen = FOUR_CHAR_CODE ('SCRN');
106 const MenuCommand kCommandSnapshot = FOUR_CHAR_CODE ('SNAP');
107 const MenuCommand kCommandReset = FOUR_CHAR_CODE ('RSET');
109 #define SLEEP_TIME 0 // Number of ticks to surrender the processor during a WaitNextEvent()
110 // Change this to 15 or higher if you don't want Bochs to hog the processor!
112 int font_width;
113 int font_height;
115 #define WINBITMAP(w) GetPortBitMapForCopyBits(GetWindowPort(w)) // (((GrafPtr)(w))->portBits)
117 #define ASCII_1_MASK 0x00FF0000
118 #define ASCII_2_MASK 0x000000FF
120 const RGBColor black = {0, 0, 0};
121 const RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
122 const RGBColor medGrey = {0xCCCC, 0xCCCC, 0xCCCC};
123 const RGBColor ltGrey = {0xEEEE, 0xEEEE, 0xEEEE};
125 // GLOBALS
127 WindowPtr win, toolwin, fullwin, backdrop, hidden, SouixWin;
128 WindowGroupRef fullwinGroup;
129 SInt16 gOldMBarHeight;
130 Boolean menubarVisible = true, cursorVisible = true;
131 Boolean windowUpdatesPending = true, mouseMoved = false;
132 RgnHandle mBarRgn, cnrRgn;
133 unsigned mouse_button_state = 0;
134 CTabHandle gCTable;
135 PixMapHandle gTile;
136 BitMap *vgafont[256];
137 Rect srcTextRect, srcTileRect;
138 Point scrCenter = {300, 240};
139 Ptr KCHR;
140 short gheaderbar_y;
141 Point prevPt;
142 unsigned width, height, gMinTop, gMaxTop, gLeft;
143 GWorldPtr gOffWorld;
144 Ptr gMyBuffer;
145 ProcessSerialNumber gProcessSerNum;
146 static unsigned vga_bpp=8;
147 static EventModifiers oldMods = 0;
148 static unsigned int text_rows=25, text_cols=80;
150 enum {
151 TEXT_MODE,
152 GRAPHIC_MODE
153 } last_screen_state = TEXT_MODE, screen_state = TEXT_MODE;
155 // HEADERBAR STUFF
156 #define TOOL_SPACING 10
157 #define TOOL_MARGIN_SPACE 4
158 int numPixMaps = 0, toolPixMaps = 0;
159 unsigned bx_bitmap_left_xorigin = 2+TOOL_SPACING; // pixels from left
160 unsigned bx_bitmap_right_xorigin = 2+TOOL_SPACING; // pixels from right
161 //PixMapHandle bx_pixmap[BX_MAX_PIXMAPS];
162 CIconHandle bx_cicn[BX_MAX_PIXMAPS];
164 struct __bx_tool_pixmap {
165 // CIconHandle cicn;
166 // PixMapHandle pm;
167 ControlRef control;
168 unsigned xdim;
169 unsigned ydim;
170 unsigned xorigin;
171 unsigned yorigin;
172 unsigned alignment;
173 void (*f)(void);
174 } bx_tool_pixmap[BX_MAX_PIXMAPS];
176 // Carbon Event Handlers
177 pascal OSStatus CEvtHandleWindowToolCommand (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
178 pascal OSStatus CEvtHandleWindowToolUpdate (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
179 pascal OSStatus CEvtHandleWindowBackdropUpdate (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
180 pascal OSStatus CEvtHandleWindowEmulatorClick (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
181 pascal OSStatus CEvtHandleWindowEmulatorUpdate (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
182 pascal OSStatus CEvtHandleWindowEmulatorKeys (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
183 pascal OSStatus CEvtHandleApplicationAppleEvent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
184 pascal OSStatus CEvtHandleApplicationMouseMoved (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
185 pascal OSStatus CEvtHandleApplicationMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
186 pascal OSStatus CEvtHandleApplicationMenuClick (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
187 pascal OSStatus CEvtHandleApplicationMenus (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
189 // Event handlers
190 OSStatus HandleKey(EventRef theEvent, Bit32u keyState);
191 static BxEvent * CarbonSiminterfaceCallback(void *theClass, BxEvent *event);
192 static bxevent_handler old_callback = NULL;
193 static void *old_callback_arg = NULL;
195 // Show/hide UI elements
196 void HidePointer(void);
197 void ShowPointer(void);
198 void HideTools(void);
199 void ShowTools(void);
200 void HideMenubar(void);
201 void ShowMenubar(void);
202 // void HideConsole(void);
203 // void ShowConsole(void);
205 void UpdateTools(void);
207 // Initialisation
208 void InitToolbox(void);
209 void CreateTile(void);
210 void CreateMenus(void);
211 void CreateWindows(void);
212 void CreateKeyMap(void);
213 void CreateVGAFont(unsigned char *vga_charmap);
214 BitMap *CreateBitMap(unsigned width, unsigned height);
215 PixMapHandle CreatePixMap(unsigned left, unsigned top, unsigned width,
216 unsigned height, unsigned depth, CTabHandle clut);
217 unsigned char reverse_bitorder(unsigned char);
219 static pascal OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, SInt32 refcon);
221 class bx_carbon_gui_c : public bx_gui_c {
222 public:
223 bx_carbon_gui_c (void) {}
224 DECLARE_GUI_VIRTUAL_METHODS()
225 virtual void beep_on(float frequency);
226 virtual void beep_off();
229 // declare one instance of the gui object and call macro to insert the
230 // plugin code
231 static bx_carbon_gui_c *theGui = NULL;
232 IMPLEMENT_GUI_PLUGIN_CODE(carbon)
234 #define LOG_THIS theGui->
236 // Carbon Event Handlers
238 pascal OSStatus CEvtHandleWindowToolCommand (EventHandlerCallRef nextHandler,
239 EventRef theEvent,
240 void* userData)
242 HICommand commandStruct;
243 UInt32 theCommandID;
245 GetEventParameter (theEvent, kEventParamDirectObject,
246 typeHICommand, NULL, sizeof(HICommand),
247 NULL, &commandStruct);
249 theCommandID = commandStruct.commandID;
251 if(theCommandID < toolPixMaps) {
252 bx_tool_pixmap[theCommandID].f();
255 return noErr; // Report success
258 pascal OSStatus CEvtHandleWindowToolUpdate (EventHandlerCallRef nextHandler,
259 EventRef theEvent,
260 void* userData)
262 theGui->show_headerbar();
264 return noErr; // Report success
267 pascal OSStatus CEvtHandleWindowBackdropUpdate (EventHandlerCallRef nextHandler,
268 EventRef theEvent,
269 void* userData)
271 Rect box;
273 WindowRef myWindow;
274 GetEventParameter (theEvent, kEventParamDirectObject, typeWindowRef,
275 NULL, sizeof(WindowRef), NULL, &myWindow);
277 GetWindowPortBounds(myWindow, &box);
278 BackColor(blackColor);
279 EraseRect(&box);
281 return noErr; // Report success
284 // Translate MouseDowns in a handled window into Bochs events
285 // Main ::HANDLE_EVENTS will feed all mouse updates to Bochs
286 pascal OSStatus CEvtHandleWindowEmulatorClick (EventHandlerCallRef nextHandler,
287 EventRef theEvent,
288 void* userData)
290 UInt32 keyModifiers;
291 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32,
292 NULL, sizeof(UInt32), NULL, &keyModifiers);
294 //if (!IsWindowActive(win))
296 // SelectWindow(win);
299 if (keyModifiers & cmdKey)
300 mouse_button_state |= 0x02;
301 else
302 mouse_button_state |= 0x01;
304 return noErr; // Report success
307 pascal OSStatus CEvtHandleWindowEmulatorUpdate (EventHandlerCallRef nextHandler,
308 EventRef theEvent,
309 void* userData)
311 Rect box;
312 Pattern qdBlackPattern;
314 WindowRef myWindow;
315 GetEventParameter (theEvent, kEventParamDirectObject, typeWindowRef,
316 NULL, sizeof(WindowRef), NULL, &myWindow);
318 GetWindowPortBounds(myWindow, &box);
319 DEV_vga_redraw_area(box.left, box.top, box.right, box.bottom);
321 return noErr; // Report success
324 pascal OSStatus CEvtHandleWindowEmulatorKeys (EventHandlerCallRef nextHandler,
325 EventRef theEvent,
326 void* userData)
328 UInt32 kind;
329 OSStatus outStatus = eventNotHandledErr;
331 kind = GetEventKind(theEvent);
332 switch(kind)
334 case kEventRawKeyDown:
335 case kEventRawKeyRepeat:
336 outStatus = HandleKey(theEvent, BX_KEY_PRESSED);
337 break;
338 case kEventRawKeyUp:
339 outStatus = HandleKey(theEvent, BX_KEY_RELEASED);
340 break;
343 return outStatus;
346 #if 0
347 // This stuff does work... it gets called, but converting the record
348 // and then calling AEProcessAppleEvent consistently results in noOutstandingHLE(err result -608)
349 // And its going to take more work to get RunApplicationLoop to work...
350 pascal OSStatus CEvtHandleApplicationAppleEvent (EventHandlerCallRef nextHandler,
351 EventRef theEvent,
352 void* userData)
354 EventRecord eventRec;
356 fprintf(stderr, "# Carbon apple event handler called\n");
357 if(ConvertEventRefToEventRecord(theEvent, &eventRec))
359 fprintf(stderr, "# Calling AEProcessAppleEvent\n");
360 OSStatus result = AEProcessAppleEvent(&eventRec);
361 fprintf(stderr, "# Received AE result: %i\n", result);
362 returm result;
364 else
365 BX_PANIC(("Can't convert apple event"));
367 return noErr; // Report success
369 #endif
371 // Only have our application deal with mouseEvents when we catch the movement
372 pascal OSStatus CEvtHandleApplicationMouseMoved (EventHandlerCallRef nextHandler,
373 EventRef theEvent,
374 void* userData)
376 mouseMoved = true;
378 return eventNotHandledErr;
381 pascal OSStatus CEvtHandleApplicationMouseUp (EventHandlerCallRef nextHandler,
382 EventRef theEvent,
383 void* userData)
385 UInt32 keyModifiers;
386 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32,
387 NULL, sizeof(UInt32), NULL, &keyModifiers);
389 if (keyModifiers & cmdKey)
390 mouse_button_state &= ~0x02;
391 else
392 mouse_button_state &= ~0x01;
394 return eventNotHandledErr; // Don't want to eat all the mouseups
397 // Catch MouseDown's in the menubar, trigger menu browsing
398 pascal OSStatus CEvtHandleApplicationMenuClick (EventHandlerCallRef nextHandler,
399 EventRef theEvent,
400 void* userData)
402 short part;
403 WindowPtr whichWindow;
405 Point wheresMyMouse;
406 GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint,
407 NULL, sizeof(Point), NULL, &wheresMyMouse);
409 part = FindWindow(wheresMyMouse, &whichWindow);
411 if(part == inMenuBar)
413 // MenuSelect will actually trigger an event cascade,
414 // Triggering command events for any selected menu item
415 MenuSelect(wheresMyMouse);
416 return noErr;
419 return eventNotHandledErr; // Don't want to eat all the clicks
422 pascal OSStatus CEvtHandleApplicationMenus (EventHandlerCallRef nextHandler,
423 EventRef theEvent,
424 void* userData)
426 HICommand commandStruct;
428 OSErr err = noErr;
429 short i;
431 GetEventParameter (theEvent, kEventParamDirectObject,
432 typeHICommand, NULL, sizeof(HICommand),
433 NULL, &commandStruct);
435 switch(commandStruct.commandID)
437 case kHICommandAbout:
439 DialogRef aboutDialog;
440 DialogItemIndex index;
441 CFStringRef cf_version;
442 char version[256];
443 sprintf(version, "Bochs x86 Emulator version %s (MacOS X port)", VER_STRING);
444 cf_version = CFStringCreateWithCString(NULL, version, kCFStringEncodingASCII);
446 AlertStdCFStringAlertParamRec aboutParam = {0};
447 aboutParam.version = kStdCFStringAlertVersionOne;
448 aboutParam.position = kWindowDefaultPosition;
449 aboutParam.defaultButton = kAlertStdAlertOKButton;
451 CreateStandardAlert(
452 kAlertNoteAlert,
453 cf_version,
454 NULL, /* can be NULL */
455 &aboutParam, /* can be NULL */
456 &aboutDialog);
458 RunStandardAlert(
459 aboutDialog,
460 NULL, /* can be NULL */
461 &index);
462 CFRelease(cf_version);
464 break;
466 case kHICommandQuit:
467 BX_EXIT(0);
468 break;
470 case kCommandFloppy:
471 //DiskEject(1);
472 break;
474 case kCommandCursor:
475 if (cursorVisible)
476 HidePointer();
477 else
478 ShowPointer();
479 break;
481 case kCommandTool:
482 if (IsWindowVisible(toolwin))
483 HideTools();
484 else
485 ShowTools();
486 break;
488 case kCommandMenuBar:
489 if (menubarVisible)
490 HideMenubar();
491 else
492 ShowMenubar();
493 break;
495 case kCommandFullScreen:
496 if (IsWindowVisible(toolwin) || menubarVisible)
498 if (menubarVisible)
499 HideMenubar();
500 if (IsWindowVisible(toolwin))
501 HideTools();
503 else
505 if (!menubarVisible)
506 ShowMenubar();
507 if (!IsWindowVisible(toolwin))
508 ShowTools();
510 break;
513 // Codewarrior programatic console that isn't available under Carbon without Codewarrior
514 case iConsole:
515 if (IsWindowVisible(SouixWin))
516 HideConsole();
517 else
518 ShowConsole();
519 break;
521 case kCommandSnapshot:
522 bx_tool_pixmap[SNAPSHOT_TOOL_BUTTON].f();
523 break;
525 case kCommandReset:
526 bx_tool_pixmap[RESET_TOOL_BUTTON].f();
527 break;
529 case kHICommandCopy:
530 bx_tool_pixmap[COPY_TOOL_BUTTON].f();
531 break;
533 case kHICommandPaste:
534 bx_tool_pixmap[PASTE_TOOL_BUTTON].f();
535 break;
538 return noErr; // Report success
541 void MacPanic(void)
543 StopAlert(200, NULL);
546 void InitToolbox(void)
548 OSErr err;
549 // gQuitFlag = false;
551 InitCursor();
553 #if 0
554 // Our handler gets called... but I can't AEProcesAppleEvent successfully upon it?
555 EventTypeSpec appleEvent = { kEventClassAppleEvent, kEventAppleEvent };
556 InstallApplicationEventHandler(NewEventHandlerUPP(CEvtHandleApplicationAppleEvent),
557 1, &appleEvent, 0, NULL);
558 #endif
560 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
561 NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false);
562 if (err != noErr)
563 ExitToShell();
566 static pascal OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, SInt32 refcon)
568 //gQuitFlag = true;
569 BX_PANIC(("User terminated"));
570 return (noErr);
573 void CreateTile(void)
575 GDHandle saveDevice;
576 CGrafPtr savePort;
577 OSErr err;
578 unsigned long p_f;
579 long theRowBytes = ((((long) (vga_bpp==24?32:(((vga_bpp+1)>>1)<<1)) * ((long) (srcTileRect.right-srcTileRect.left)) + 31) >> 5) << 2);
581 // if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
582 // {
583 GetGWorld(&savePort, &saveDevice);
584 switch(vga_bpp)
586 case 1:
587 p_f = k1MonochromePixelFormat;
588 break;
589 case 2:
590 p_f = k2IndexedPixelFormat;
591 break;
592 case 4:
593 p_f = k4IndexedPixelFormat;
594 break;
595 case 8:
596 p_f = k8IndexedPixelFormat;
597 break;
598 case 15:
599 p_f = k16LE555PixelFormat;
600 break;
601 case 16:
602 p_f = k16LE565PixelFormat;
603 break;
604 case 24:
605 //p_f = k24BGRPixelFormat;
606 //break;
607 case 32:
608 p_f = k32ARGBPixelFormat;//k32BGRAPixelFormat;
609 break;
612 BX_ASSERT((gMyBuffer = (Ptr)malloc(theRowBytes * (srcTileRect.bottom - srcTileRect.top))) != NULL);
613 err = NewGWorldFromPtr(&gOffWorld, p_f,
614 &srcTileRect, vga_bpp>8 ? NULL : gCTable, NULL, keepLocal, gMyBuffer, theRowBytes);
615 if (err != noErr || gOffWorld == NULL)
616 BX_PANIC(("mac: can't create gOffWorld; err=%hd", err));
618 SetGWorld(gOffWorld, NULL);
619 RGBForeColor(&black);
620 RGBBackColor(&white);
622 gTile = GetGWorldPixMap(gOffWorld);
624 if (gTile != NULL)
626 NoPurgePixels(gTile);
627 if (!LockPixels(gTile))
628 BX_ERROR(("mac: can't LockPixels gTile"));
629 if ((**gTile).pixelType != RGBDirect && (**gTile).pmTable != gCTable)
631 DisposeCTable(gCTable);
632 gCTable = (**gTile).pmTable;
635 (**gCTable).ctFlags |= 0x4000; //use palette manager indexes
636 CTabChanged(gCTable);
638 else
639 BX_PANIC(("mac: can't create gTile"));
641 SetGWorld(savePort, saveDevice);
642 /* }
643 else
645 gOffWorld = NULL;
646 gTile = CreatePixMap(0, 0, srcTileRect.right, srcTileRect.bottom, 8, gCTable);
647 if (gTile == NULL)
648 BX_PANIC(("mac: can't create gTile"));
652 void CreateMenus(void)
654 Handle menu;
656 menu = GetNewMBar(rMBarID); // get our menus from resource
657 if (menu != nil)
659 SetMenuBar(menu);
660 DrawMenuBar();
662 else
663 BX_PANIC(("can't create menu"));
665 SetMenuItemCommandID (GetMenuRef(mApple), iAbout, kHICommandAbout);
666 SetMenuItemCommandID (GetMenuRef(mFile), iQuit, kHICommandQuit);
667 SetMenuItemCommandID (GetMenuRef(mEdit), iCopy, kHICommandCopy);
668 SetMenuItemCommandID (GetMenuRef(mEdit), iPaste, kHICommandPaste);
669 SetMenuItemCommandID (GetMenuRef(mBochs), iFloppy, kCommandFloppy);
670 SetMenuItemCommandID (GetMenuRef(mBochs), iCursor, kCommandCursor);
671 SetMenuItemCommandID (GetMenuRef(mBochs), iTool, kCommandTool);
672 SetMenuItemCommandID (GetMenuRef(mBochs), iMenuBar, kCommandMenuBar);
673 SetMenuItemCommandID (GetMenuRef(mBochs), iFullScreen, kCommandFullScreen);
674 SetMenuItemCommandID (GetMenuRef(mBochs), iSnapshot, kCommandSnapshot);
675 SetMenuItemCommandID (GetMenuRef(mBochs), iReset, kCommandReset);
677 DisableMenuItem(GetMenuRef(mEdit), iUndo);
678 DisableMenuItem(GetMenuRef(mEdit), iCut);
679 DisableMenuItem(GetMenuRef(mEdit), iClear);
680 DisableMenuItem(GetMenuRef(mBochs), iFloppy);
682 EventTypeSpec commandEvents = {kEventClassCommand, kEventCommandProcess};
683 EventTypeSpec menuEvents = {kEventClassMouse, kEventMouseDown};
684 InstallApplicationEventHandler(NewEventHandlerUPP(CEvtHandleApplicationMenus),
685 1, &commandEvents, 0, NULL);
686 InstallApplicationEventHandler(NewEventHandlerUPP(CEvtHandleApplicationMenuClick),
687 1, &menuEvents, 0, NULL);
690 void CreateWindows(void)
692 Rect winRect;
693 Rect screenBounds;
694 Rect positioningBounds;
696 EventTypeSpec eventClick = { kEventClassWindow, kEventWindowHandleContentClick };
697 EventTypeSpec eventUpdate = { kEventClassWindow, kEventWindowDrawContent };
698 EventTypeSpec keyboardEvents[3] = {
699 { kEventClassKeyboard, kEventRawKeyDown }, { kEventClassKeyboard, kEventRawKeyRepeat },
700 { kEventClassKeyboard, kEventRawKeyUp }};
701 EventTypeSpec eventCommand = { kEventClassCommand, kEventCommandProcess };
703 // Create a backdrop window for fullscreen mode
704 // GetRegionBounds(GetGrayRgn(), &screenBounds);
706 // Fullscreen mode only really wants to be on one screen
707 screenBounds = (**GetMainDevice()).gdRect;
708 GetAvailableWindowPositioningBounds(GetMainDevice(), &positioningBounds);
710 SetRect(&winRect, 0, 0, screenBounds.right, screenBounds.bottom + GetMBarHeight());
711 CreateNewWindow(kPlainWindowClass, (kWindowStandardHandlerAttribute), &winRect, &backdrop);
712 if (backdrop == NULL)
713 {BX_PANIC(("mac: can't create backdrop window"));}
714 InstallWindowEventHandler(backdrop, NewEventHandlerUPP(CEvtHandleWindowBackdropUpdate), 1, &eventUpdate, NULL, NULL);
715 InstallWindowEventHandler(backdrop, NewEventHandlerUPP(CEvtHandleWindowEmulatorClick), 1, &eventClick, NULL, NULL);
716 InstallWindowEventHandler(backdrop, NewEventHandlerUPP(CEvtHandleWindowEmulatorKeys), 3, keyboardEvents, 0, NULL);
718 width = 640;
719 height = 480;
720 gLeft = positioningBounds.left;
721 gMinTop = positioningBounds.top;
722 gMaxTop = gMinTop + gheaderbar_y;
724 // Create a moveable tool window for the "headerbar"
725 winRect.top = positioningBounds.top + 10;
726 winRect.left = positioningBounds.left;
727 winRect.bottom = winRect.top + gheaderbar_y;
728 winRect.right = positioningBounds.right;
730 CreateNewWindow(kFloatingWindowClass, kWindowStandardHandlerAttribute, &winRect, &toolwin);
731 if (toolwin == NULL)
732 {BX_PANIC(("mac: can't create tool window"));}
734 // Use an Aqua-savvy window background
735 SetThemeWindowBackground(toolwin, kThemeBrushUtilityWindowBackgroundActive, false);
737 SetWindowTitleWithCFString (toolwin, CFSTR("MacBochs Hardware Controls")); // Set title
738 //InstallWindowEventHandler(toolwin, NewEventHandlerUPP(CEvtHandleWindowToolClick), 1, &eventClick, NULL, NULL);
739 InstallWindowEventHandler(toolwin, NewEventHandlerUPP(CEvtHandleWindowToolCommand), 1, &eventCommand, NULL, NULL);
740 InstallWindowEventHandler(toolwin, NewEventHandlerUPP(CEvtHandleWindowToolUpdate), 1, &eventUpdate, NULL, NULL);
742 // Create the emulator window for full screen mode
743 winRect.left = (screenBounds.right - width) /2; //(qd.screenBits.bounds.right - width)/2;
744 winRect.right = winRect.left + width;
745 winRect.top = (screenBounds.bottom - height)/2;
746 winRect.bottom = winRect.top + height;
748 CreateNewWindow(kPlainWindowClass, (kWindowStandardHandlerAttribute), &winRect, &fullwin);
749 if (fullwin == NULL)
750 BX_PANIC(("mac: can't create fullscreen emulator window"));
752 InstallWindowEventHandler(fullwin, NewEventHandlerUPP(CEvtHandleWindowEmulatorUpdate), 1, &eventUpdate, NULL, NULL);
753 InstallWindowEventHandler(fullwin, NewEventHandlerUPP(CEvtHandleWindowEmulatorClick), 1, &eventClick, NULL, NULL); InstallWindowEventHandler(fullwin, NewEventHandlerUPP(CEvtHandleWindowEmulatorKeys), 3, keyboardEvents, 0, NULL);
755 // Create the regular emulator window
756 winRect.left = gLeft;
757 winRect.top = gMaxTop;
758 winRect.right = winRect.left + width;
759 winRect.bottom = winRect.top + height;
761 CreateNewWindow(kDocumentWindowClass,
762 (kWindowStandardHandlerAttribute | kWindowCollapseBoxAttribute),
763 &winRect, &win);
764 if (win == NULL)
765 BX_PANIC(("mac: can't create emulator window"));
767 SetWindowTitleWithCFString (win, CFSTR("MacBochs x86 PC")); // Set title
768 InstallWindowEventHandler(win, NewEventHandlerUPP(CEvtHandleWindowEmulatorUpdate), 1, &eventUpdate, NULL, NULL);
769 InstallWindowEventHandler(win, NewEventHandlerUPP(CEvtHandleWindowEmulatorClick), 1, &eventClick, NULL, NULL);
770 InstallWindowEventHandler(win, NewEventHandlerUPP(CEvtHandleWindowEmulatorKeys), 3, keyboardEvents, 0, NULL);
772 // Group the fullscreen and backdrop windows together, since they also share the same click
773 // event handler they will effectively act as a single window for layering and events
775 CreateWindowGroup((kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation), &fullwinGroup);
776 SetWindowGroupName(fullwinGroup, CFSTR("net.sourceforge.bochs.windowgroups.fullscreen"));
778 // This *can't* be the right way, then again groups aren't yet the right way
779 // For the life of me I couldn't find a right way of making sure my created group stayed
780 // below the layer of Floating Windows. But with the windows we have there's no current
781 // harm from making it part of the same group.
782 SetWindowGroup(toolwin, fullwinGroup);
783 SetWindowGroup(fullwin, fullwinGroup);
784 SetWindowGroup(backdrop, fullwinGroup);
786 RepositionWindow(win, NULL, kWindowCenterOnMainScreen);
788 hidden = fullwin;
790 ShowWindow(toolwin);
791 ShowWindow(win);
793 SetPortWindowPort(win);
796 // ::SPECIFIC_INIT()
798 // Called from gui.cc, once upon program startup, to allow for the
799 // specific GUI code (X11, BeOS, ...) to be initialized.
801 // argc, argv: not used right now, but the intention is to pass native GUI
802 // specific options from the command line. (X11 options, BeOS options,...)
804 // tilewidth, tileheight: for optimization, graphics_tile_update() passes
805 // only updated regions of the screen to the gui code to be redrawn.
806 // These define the dimensions of a region (tile).
807 // headerbar_y: A headerbar (toolbar) is display on the top of the
808 // VGA window, showing floppy status, and other information. It
809 // always assumes the width of the current VGA mode width, but
810 // it's height is defined by this parameter.
812 void bx_carbon_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight,
813 unsigned headerbar_y)
815 int i;
817 put("MGUI");
818 InitToolbox();
820 font_width = 8;
821 font_height = 16;
823 gheaderbar_y = headerbar_y + TOOL_MARGIN_SPACE + TOOL_MARGIN_SPACE;
825 CreateKeyMap();
827 gCTable = GetCTable(128);
828 BX_ASSERT (gCTable != NULL);
829 CTabChanged(gCTable); //(*gCTable)->ctSeed = GetCTSeed();
830 SetRect(&srcTileRect, 0, 0, tilewidth, tileheight);
832 for(i=0; i<256; i++) {
833 vgafont[i] = NULL;
835 CreateMenus();
836 CreateVGAFont(vga_charmap);
837 CreateTile();
838 CreateWindows();
840 EventTypeSpec mouseUpEvent = { kEventClassMouse, kEventMouseUp };
841 EventTypeSpec mouseMoved[2] = { { kEventClassMouse, kEventMouseMoved },
842 { kEventClassMouse, kEventMouseDragged } };
843 InstallApplicationEventHandler(NewEventHandlerUPP(CEvtHandleApplicationMouseUp),
844 1, &mouseUpEvent, 0, NULL);
845 InstallApplicationEventHandler(NewEventHandlerUPP(CEvtHandleApplicationMouseMoved),
846 2, mouseMoved, 0, NULL);
848 if (GetCurrentProcess(&gProcessSerNum) == noErr)
849 SetFrontProcess(&gProcessSerNum);
851 GetMouse(&prevPt);
853 // redirect notify callback to X11 specific code
854 SIM->get_notify_callback(&old_callback, &old_callback_arg);
855 SIM->set_notify_callback(CarbonSiminterfaceCallback, NULL);
857 UNUSED(argc);
858 UNUSED(argv);
860 // loads keymap for x11
861 if (SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
862 bx_keymap.loadKeymap(NULL); // I have no function to convert X windows symbols
866 // HandleKey()
868 // Handles keyboard-related events.
870 OSStatus HandleKey(EventRef theEvent, Bit32u keyState)
872 UInt32 key;
873 UInt32 trans;
874 OSStatus status;
875 UInt32 modifiers;
877 static UInt32 transState = 0;
879 status = GetEventParameter (theEvent,
880 kEventParamKeyModifiers,
881 typeUInt32, NULL,
882 sizeof(UInt32), NULL,
883 &modifiers);
884 if(status == noErr)
886 status = GetEventParameter (theEvent,
887 kEventParamKeyCode,
888 typeUInt32, NULL,
889 sizeof(UInt32), NULL,
890 &key);
891 if(status == noErr)
894 // key = event->message & charCodeMask;
896 // Let our menus process command keys
897 if(modifiers & cmdKey)
899 status = eventNotHandledErr;
901 else
903 /* if (modifiers & shiftKey)
904 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | keyState);
905 if (modifiers & controlKey)
906 DEV_kbd_gen_scancode(BX_KEY_CTRL_L | keyState);
907 if (modifiers & optionKey)
908 DEV_kbd_gen_scancode(BX_KEY_ALT_L | keyState);*/
910 // key = (event->message & keyCodeMask) >> 8;
912 trans = KeyTranslate(KCHR, key, &transState);
913 if ((trans == BX_KEY_PRINT) && ((oldMods & optionKey) || (oldMods & rightOptionKey)))
914 trans = BX_KEY_ALT_SYSREQ;
915 if ((trans == BX_KEY_PAUSE) && ((oldMods & controlKey) || (oldMods & rightControlKey)))
916 trans = BX_KEY_CTRL_BREAK;
917 // KeyTranslate maps Mac virtual key codes to any type of character code
918 // you like (in this case, Bochs key codes). Much nicer than a huge switch
919 // statement!
921 if (trans > 0)
922 DEV_kbd_gen_scancode(trans | keyState);
924 /* if (modifiers & shiftKey)
925 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | BX_KEY_RELEASED);
926 if (modifiers & controlKey)
927 DEV_kbd_gen_scancode(BX_KEY_CTRL_L | BX_KEY_RELEASED);
928 if (modifiers & optionKey)
929 DEV_kbd_gen_scancode(BX_KEY_ALT_L | BX_KEY_RELEASED);*/
934 return status;
937 BX_CPP_INLINE void ResetPointer(void)
939 // this appears to work well, especially when combined with
940 // mouse processing on the MouseMoved events
941 if(CGWarpMouseCursorPosition(CGPointMake(scrCenter.h, scrCenter.v)))
943 fprintf(stderr, "# Failed to warp cursor");
947 // ::HANDLE_EVENTS()
949 // Called periodically (vga_update_interval in .bochsrc) so the
950 // the gui code can poll for keyboard, mouse, and other
951 // relevant events.
953 void bx_carbon_gui_c::handle_events(void)
955 EventRecord event;
956 Point mousePt;
957 int dx, dy;
958 EventModifiers newMods;
959 unsigned curstate;
960 GrafPtr oldport;
962 curstate = mouse_button_state; //so we can compare the old and the new mouse state
964 if (WaitNextEvent(everyEvent, &event, SLEEP_TIME, NULL))
966 switch(event.what)
969 // This event is just redundant
970 case nullEvent:
972 // These events are all covered by installed carbon event handlers
973 case mouseDown:
974 case mouseUp:
975 case keyDown:
976 case autoKey:
977 case keyUp:
978 case updateEvt:
979 break;
981 case diskEvt:
982 // floppyA_handler();
983 break;
985 case kHighLevelEvent:
986 // fprintf(stderr, "# Classic apple event handler called\n");
987 AEProcessAppleEvent(&event);
988 show_headerbar(); // Update if necessary (example, clipboard change)
989 break;
991 default:
992 break;
995 else if (oldMods != (newMods = (event.modifiers & 0xfe00)))
997 if ((newMods ^ oldMods) & shiftKey)
998 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | ((newMods & shiftKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
999 if ((newMods ^ oldMods) & alphaLock)
1000 DEV_kbd_gen_scancode(BX_KEY_CAPS_LOCK | ((newMods & alphaLock)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1001 if ((newMods ^ oldMods) & optionKey)
1002 DEV_kbd_gen_scancode(BX_KEY_ALT_L | ((newMods & optionKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1003 if ((newMods ^ oldMods) & controlKey)
1004 DEV_kbd_gen_scancode(BX_KEY_CTRL_L | ((newMods & controlKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1005 if ((newMods ^ oldMods) & rightShiftKey)
1006 DEV_kbd_gen_scancode(BX_KEY_SHIFT_R | ((newMods & rightShiftKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1007 if ((newMods ^ oldMods) & rightOptionKey)
1008 DEV_kbd_gen_scancode(BX_KEY_ALT_R | ((newMods & rightOptionKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1009 if ((newMods ^ oldMods) & rightControlKey)
1010 DEV_kbd_gen_scancode(BX_KEY_CTRL_R | ((newMods & rightControlKey)?BX_KEY_PRESSED:BX_KEY_RELEASED));
1011 oldMods = newMods;
1015 // Only update mouse if we're not in the dock
1016 // and we are the frontmost app.
1017 ProcessSerialNumber frontProcessSerNum;
1018 Boolean isSameProcess;
1020 GetFrontProcess(&frontProcessSerNum);
1021 SameProcess(&frontProcessSerNum, &gProcessSerNum, &isSameProcess);
1023 if(isSameProcess && !IsWindowCollapsed(win))
1025 GetPort(&oldport);
1026 SetPortWindowPort(win);
1028 GetMouse(&mousePt);
1030 if(menubarVisible && cursorVisible)
1032 // Don't track the mouse if we're working with the main window
1033 // and we're outside the window
1034 if(mouseMoved &&
1035 (mousePt.v < 0 || mousePt.v > height || mousePt.h < 0 || mousePt.h > width) &&
1036 (prevPt.v < 0 || prevPt.v > height || prevPt.h < 0 || prevPt.h > width))
1038 mouseMoved = false;
1041 // Limit mouse action to window
1042 // Grr, any better ways to sync host and bochs cursor?
1043 if(mousePt.h < 0) { mousePt.h = 0; }
1044 else if(mousePt.h > width) { mousePt.h = width; }
1045 if(mousePt.v < 0) { mousePt.v = 0; }
1046 else if(mousePt.v > height) { mousePt.v = height; }
1050 //if mouse has moved, or button has changed state
1051 if (mouseMoved || (curstate != mouse_button_state))
1053 if(mouseMoved)
1055 CGMouseDelta CGdX, CGdY;
1056 CGGetLastMouseDelta(&CGdX, &CGdY);
1057 dx = CGdX;
1058 dy = - CGdY; // Windows has an opposing grid
1060 else
1062 dx = 0;
1063 dy = 0;
1066 DEV_mouse_motion(dx, dy, mouse_button_state);
1068 if (!cursorVisible && mouseMoved)
1070 SetPt(&scrCenter, 300, 240);
1071 LocalToGlobal(&scrCenter);
1072 ResetPointer(); //next getmouse should be 300, 240
1073 SetPt(&mousePt, 300, 240);
1075 mouseMoved = false;
1078 prevPt = mousePt;
1080 SetPort(oldport);
1085 // ::FLUSH()
1087 // Called periodically, requesting that the gui code flush all pending
1088 // screen update requests.
1090 void bx_carbon_gui_c::flush(void)
1092 // an opportunity to make the Window Manager happy.
1093 // not needed on the macintosh....
1095 // Unless you don't want to needlessly update the dock icon
1096 // umpteen zillion times a second for each tile.
1097 // A further note, UpdateCollapsedWindowDockTile is not
1098 // recommended for animation. Setup like this my performance
1099 // seems reasonable for little fuss.
1100 if(windowUpdatesPending)
1102 if(IsWindowCollapsed(win))
1104 UpdateCollapsedWindowDockTile(win);
1106 if(last_screen_state != screen_state)
1108 last_screen_state = screen_state;
1109 UpdateTools();
1112 windowUpdatesPending = false;
1116 // ::CLEAR_SCREEN()
1118 // Called to request that the VGA region is cleared. Don't
1119 // clear the area that defines the headerbar.
1121 void bx_carbon_gui_c::clear_screen(void)
1123 Rect r;
1125 SetPortWindowPort(win);
1127 RGBForeColor(&black);
1128 RGBBackColor(&white);
1129 GetWindowPortBounds(win, &r);
1130 PaintRect (&r);
1132 windowUpdatesPending = true;
1137 // ::TEXT_UPDATE()
1139 // Called in a VGA text mode, to update the screen with
1140 // new content.
1142 // old_text: array of character/attributes making up the contents
1143 // of the screen from the last call. See below
1144 // new_text: array of character/attributes making up the current
1145 // contents, which should now be displayed. See below
1147 // format of old_text & new_text: each is tm_info.line_offset*text_rows
1148 // bytes long. Each character consists of 2 bytes. The first by is
1149 // the character value, the second is the attribute byte.
1151 // cursor_x: new x location of cursor
1152 // cursor_y: new y location of cursor
1153 // tm_info: this structure contains information for additional
1154 // features in text mode (cursor shape, line offset,...)
1156 void bx_carbon_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
1157 unsigned long cursor_x, unsigned long cursor_y,
1158 bx_vga_tminfo_t tm_info)
1160 unsigned char cAttr, cChar;
1161 Rect destRect;
1162 RGBColor fgColor, bgColor;
1163 GrafPtr oldPort, savePort;
1164 GDHandle saveDevice;
1165 GrafPtr winGrafPtr = GetWindowPort(win);
1166 OSErr theError;
1167 Bit8u *old_line, *new_line;
1168 unsigned int curs, hchars, offset, rows, x, xc, y, yc;
1169 bx_bool forceUpdate = 0, blink_mode, blink_state;
1170 static unsigned prev_cursor_x=0;
1171 static unsigned prev_cursor_y=0;
1173 screen_state = TEXT_MODE;
1175 // first check if the screen needs to be redrawn completely
1176 blink_mode = (tm_info.blink_flags & BX_TEXT_BLINK_MODE) > 0;
1177 blink_state = (tm_info.blink_flags & BX_TEXT_BLINK_STATE) > 0;
1178 if (blink_mode) {
1179 if (tm_info.blink_flags & BX_TEXT_BLINK_TOGGLE)
1180 forceUpdate = 1;
1182 if (charmap_updated == 1) {
1183 CreateVGAFont(vga_charmap);
1184 charmap_updated = 0;
1185 forceUpdate = 1;
1188 // invalidate character at previous and new cursor location
1189 if((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols)) {
1190 curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
1191 old_text[curs] = ~new_text[curs];
1193 if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height) &&
1194 (cursor_y < text_rows) && (cursor_x < text_cols)) {
1195 curs = cursor_y * tm_info.line_offset + cursor_x * 2;
1196 old_text[curs] = ~new_text[curs];
1197 } else {
1198 curs = 0xffff;
1201 GetPort(&oldPort);
1203 SetPortWindowPort(win);
1205 rows = text_rows;
1206 y = 0;
1207 do {
1208 hchars = text_cols;
1209 new_line = new_text;
1210 old_line = old_text;
1211 x = 0;
1212 offset = y * tm_info.line_offset;
1213 do {
1214 if (forceUpdate || (old_text[0] != new_text[0])
1215 || (old_text[1] != new_text[1])) {
1216 cChar = new_text[0];
1217 cAttr = new_text[1];
1219 if (blink_mode) {
1220 cAttr = new_text[1] & 0x7F;
1221 if (!blink_state && (new_text[1] & 0x80))
1222 cAttr = (cAttr & 0x70) | (cAttr >> 4);
1224 if (offset == curs) {
1225 cAttr = (cAttr >> 4) | (cAttr << 4);
1228 if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()) {
1229 PmForeColor(new_text[1] & 0x0F);
1230 if (blink_mode) {
1231 PmBackColor((new_text[1] & 0x70) >> 4);
1232 if (!blink_state && (new_text[1] & 0x80))
1233 PmForeColor((new_text[1] & 0x70) >> 4);
1234 } else {
1235 PmBackColor((new_text[1] & 0xF0) >> 4);
1237 } else {
1238 fgColor = (**gCTable).ctTable[new_text[1] & 0x0F].rgb;
1239 bgColor = (**gCTable).ctTable[(new_text[1] & 0xF0) >> 4].rgb;
1241 RGBForeColor(&fgColor);
1242 RGBBackColor(&bgColor);
1245 xc = x * font_width;
1246 yc = y * font_height;
1248 SetRect(&destRect, xc, yc,
1249 xc+font_width, yc+font_height);
1251 CopyBits(vgafont[cChar], WINBITMAP(win),
1252 &srcTextRect, &destRect, srcCopy, NULL);
1254 if ((theError = QDError()) != noErr)
1255 BX_ERROR(("mac: CopyBits returned %hd", theError));
1257 x++;
1258 new_text+=2;
1259 old_text+=2;
1260 offset+=2;
1261 } while (--hchars);
1262 y++;
1263 new_text = new_line + tm_info.line_offset;
1264 old_text = old_line + tm_info.line_offset;
1265 } while (--rows);
1267 //previous cursor position
1268 prev_cursor_x = cursor_x;
1269 prev_cursor_y = cursor_y;
1271 SetPort(oldPort);
1273 windowUpdatesPending = true;
1276 int bx_carbon_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
1278 ScrapRef theScrap;
1279 ScrapFlavorFlags theScrapFlags;
1280 Size theScrapSize;
1281 OSStatus err;
1283 GetCurrentScrap(&theScrap);
1285 // Make sure there is text to paste
1286 err= GetScrapFlavorFlags(theScrap, kScrapFlavorTypeText, &theScrapFlags);
1287 if(err == noErr)
1289 GetScrapFlavorSize(theScrap, kScrapFlavorTypeText, &theScrapSize);
1290 *nbytes = theScrapSize;
1291 *bytes = new Bit8u[1 + *nbytes];
1292 BX_INFO (("found %d bytes on the clipboard", *nbytes));
1293 err= GetScrapFlavorData(theScrap, kScrapFlavorTypeText, &theScrapSize, *bytes);
1294 BX_INFO (("first byte is 0x%02x", *bytes[0]));
1296 else
1298 BX_INFO (("No text found on clipboard..."));
1300 return (err == noErr);
1303 int bx_carbon_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
1305 ScrapRef theScrap;
1307 // Clear out the existing clipboard
1308 ClearCurrentScrap();
1310 GetCurrentScrap(&theScrap);
1311 PutScrapFlavor (theScrap, kScrapFlavorTypeText, kScrapFlavorMaskNone, len, text_snapshot);
1313 return 1;
1316 // ::PALETTE_CHANGE()
1318 // Allocate a color in the native GUI, for this color, and put
1319 // it in the colormap location 'index'.
1320 // returns: 0=no screen update needed (color map change has direct effect)
1321 // 1=screen updated needed (redraw using current colormap)
1323 bx_bool bx_carbon_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
1325 PaletteHandle thePal, oldpal;
1326 GDHandle saveDevice;
1327 CGrafPtr savePort;
1328 GrafPtr oldPort;
1330 /* if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
1332 GetGWorld(&savePort, &saveDevice);
1334 SetGWorld(gOffWorld, NULL);
1336 if ((**gTile).pixelType != RGBDirect)
1338 GetPort(&oldPort);
1339 SetPortWindowPort(win);
1341 (**gCTable).ctTable[index].value = index;
1342 (**gCTable).ctTable[index].rgb.red = (red << 8);
1343 (**gCTable).ctTable[index].rgb.green = (green << 8);
1344 (**gCTable).ctTable[index].rgb.blue = (blue << 8);
1346 SetEntries(index, index, (**gCTable).ctTable);
1348 CTabChanged(gCTable);
1350 SetPort(oldPort);
1352 /* if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
1353 SetGWorld(savePort, saveDevice);*/
1354 if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
1357 thePal = NewPalette(index, gCTable, pmTolerant, 0x5000);
1358 oldpal = GetPalette(win);
1360 SetPalette(win, thePal, false);
1361 SetPalette(fullwin, thePal, false);
1362 SetPalette(hidden, thePal, false);
1363 return(1);
1366 return((**gTile).pixelType != RGBDirect);
1370 // ::GRAPHICS_TILE_UPDATE()
1372 // Called to request that a tile of graphics be drawn to the
1373 // screen, since info in this region has changed.
1375 // tile: array of 8bit values representing a block of pixels with
1376 // dimension equal to the 'tilewidth' & 'tileheight' parameters to
1377 // ::specific_init(). Each value specifies an index into the
1378 // array of colors you allocated for ::palette_change()
1379 // x0: x origin of tile
1380 // y0: y origin of tile
1382 // note: origin of tile and of window based on (0,0) being in the upper
1383 // left of the window.
1385 void bx_carbon_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
1387 Rect destRect;
1388 OSErr theError;
1389 Ptr theBaseAddr;
1390 GDHandle saveDevice;
1391 CGrafPtr savePort;
1392 GrafPtr oldPort;
1394 /* if (gOffWorld != NULL)
1396 GetGWorld(&savePort, &saveDevice);
1398 SetGWorld(gOffWorld, NULL);
1401 screen_state = GRAPHIC_MODE;
1403 // SetPort - Otherwise an update happens to the headerbar and ooomph, we're drawing weirdly on the screen
1404 GetPort(&oldPort);
1405 SetPortWindowPort(win);
1406 destRect = srcTileRect;
1407 OffsetRect(&destRect, x0, y0);
1409 //(**gTile).baseAddr = (Ptr)tile;
1410 if ((theError = LockPortBits(gOffWorld)) != noErr)
1411 BX_PANIC(("mac: LockPortBits returned %hd", theError));
1412 if ((theBaseAddr = GetPixBaseAddr(gTile)) == NULL)
1413 BX_PANIC(("mac: gTile has NULL baseAddr (offscreen buffer purged)"));
1414 else if (vga_bpp == 24 || vga_bpp == 32)
1416 for (unsigned iY = 0; iY < (srcTileRect.bottom-srcTileRect.top); iY++)
1418 Bit8u *iA = ((Bit8u *)theBaseAddr) + iY * GetPixRowBytes(gTile);
1419 for (unsigned iX = 0; iX < (srcTileRect.right-srcTileRect.left); iX++)
1421 iA[iX*4 + 3] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(vga_bpp>>3)];
1422 iA[iX*4 + 2] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(vga_bpp>>3) + 1];
1423 iA[iX*4 + 1] = tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*(vga_bpp>>3) + 2];
1424 iA[iX*4] = vga_bpp == 24 ? 0 : tile[((srcTileRect.right-srcTileRect.left)*iY+iX)*4 + 3];
1428 else
1429 BlockMoveData(tile, theBaseAddr, (srcTileRect.bottom-srcTileRect.top) * GetPixRowBytes(gTile));
1430 if ((theError = UnlockPortBits(gOffWorld)) != noErr)
1431 BX_ERROR(("mac: UnlockPortBits returned %hd", theError));
1432 RGBForeColor(&black);
1433 RGBBackColor(&white);
1434 CopyBits(GetPortBitMapForCopyBits(gOffWorld), WINBITMAP(win),
1435 &srcTileRect, &destRect, srcCopy, NULL);
1436 if ((theError = QDError()) != noErr)
1437 BX_ERROR(("mac: CopyBits returned %hd", theError));
1438 SetPort(oldPort);
1439 windowUpdatesPending = true;
1440 /* if (gOffWorld != NULL)
1441 SetGWorld(savePort, saveDevice);*/
1446 // ::DIMENSION_UPDATE()
1448 // Called when the VGA mode changes it's X,Y dimensions.
1449 // Resize the window to this size, but you need to add on
1450 // the height of the headerbar to the Y value.
1452 // x: new VGA x size
1453 // y: new VGA y size (add headerbar_y parameter from ::specific_init().
1454 // fheight: new VGA character height in text mode
1455 // fwidth : new VGA character width in text mode
1456 // bpp : bits per pixel in graphics mode
1458 void bx_carbon_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
1460 if ((bpp != 1) && (bpp != 2) && (bpp != 4) && (bpp != 8) && (bpp != 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) {
1461 BX_PANIC(("%d bpp graphics mode not supported yet", bpp));
1463 if (bpp != vga_bpp)
1465 free(gMyBuffer);
1466 DisposeGWorld(gOffWorld);
1467 if ((gCTable == NULL) || (*gCTable == NULL) || (*gCTable == (void *)-1))
1468 gCTable = GetCTable(128);
1469 vga_bpp = bpp;
1470 CreateTile();
1473 if (fheight > 0) {
1474 text_cols = x / fwidth;
1475 text_rows = y / fheight;
1476 if(fwidth != font_width || fheight != font_height) {
1477 font_width = fwidth;
1478 font_height = fheight;
1479 CreateVGAFont(vga_charmap);
1483 if (x != width || y != height)
1485 #if 1
1486 SizeWindow(win, x, y, false);
1487 #endif
1489 #if 0
1490 // Animates the resizing, cute, but gratuitous
1491 Rect box, frame;
1492 GetWindowBounds(win, kWindowStructureRgn, &frame);
1493 GetWindowPortBounds(win, &box);
1494 frame.right = frame.right - box.right + x;
1495 frame.bottom = frame.bottom - box.bottom + y;
1497 TransitionWindow(win, kWindowSlideTransitionEffect, kWindowResizeTransitionAction, &frame);
1498 #endif
1499 SizeWindow(fullwin, x, y, false);
1500 SizeWindow(hidden, x, y, false);
1501 width = x;
1502 height = y;
1505 windowUpdatesPending = true;
1507 host_xres = x;
1508 host_yres = y;
1509 host_bpp = bpp;
1513 // ::CREATE_BITMAP()
1515 // Create a monochrome bitmap of size 'xdim' by 'ydim', which will
1516 // be drawn in the headerbar. Return an integer ID to the bitmap,
1517 // with which the bitmap can be referenced later.
1519 // bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
1520 // bit0 is the left most pixel, bit7 is the right most pixel.
1521 // xdim: x dimension of bitmap
1522 // ydim: y dimension of bitmap
1524 // rewritten by tim senecal to use the cicn (color icon) resources instead
1526 // We need to have a cicn resource for each and every call to create_bitmap
1527 // If this fails, it is probably because more icons were added to bochs and
1528 // we need to create more cicns in bochs.r to match with create_bitmap calls in
1529 // gui.cc
1530 unsigned bx_carbon_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
1532 unsigned i;
1533 unsigned char *data;
1534 long row_bytes, bytecount;
1536 bx_cicn[numPixMaps] = GetCIcon(numPixMaps+128);
1537 // BX_ASSERT(bx_cicn[numPixMaps]);
1539 numPixMaps++;
1541 return(numPixMaps-1);
1545 // ::HEADERBAR_BITMAP()
1547 // Called to install a bitmap in the bochs headerbar (toolbar).
1549 // bmap_id: will correspond to an ID returned from
1550 // ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
1551 // or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
1552 // available leftmost or rightmost space.
1553 // f: a 'C' function pointer to callback when the mouse is clicked in
1554 // the boundaries of this bitmap.
1556 unsigned bx_carbon_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
1558 unsigned hb_index;
1559 Rect destRect, r;
1560 GetWindowPortBounds(toolwin, &r);
1561 int xorigin, yorigin = TOOL_MARGIN_SPACE;
1562 ControlButtonContentInfo info;
1564 toolPixMaps++;
1565 hb_index = toolPixMaps-1;
1566 //bx_tool_pixmap[hb_index].pm = bx_pixmap[bmap_id];
1567 //bx_tool_pixmap[hb_index].cicn = bx_cicn[bmap_id];
1568 bx_tool_pixmap[hb_index].alignment = alignment;
1569 bx_tool_pixmap[hb_index].f = f;
1571 if (alignment == BX_GRAVITY_LEFT)
1573 bx_tool_pixmap[hb_index].xorigin = bx_bitmap_left_xorigin;
1574 bx_tool_pixmap[hb_index].yorigin = TOOL_MARGIN_SPACE;
1575 // bx_bitmap_left_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
1576 bx_bitmap_left_xorigin += 32 + TOOL_SPACING;
1577 xorigin = bx_tool_pixmap[hb_index].xorigin;
1579 else
1581 // bx_bitmap_right_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
1582 bx_bitmap_right_xorigin += 32;
1583 bx_tool_pixmap[hb_index].xorigin = bx_bitmap_right_xorigin;
1584 bx_tool_pixmap[hb_index].yorigin = TOOL_MARGIN_SPACE;
1585 xorigin = r.right - bx_tool_pixmap[hb_index].xorigin;
1586 bx_bitmap_right_xorigin += TOOL_SPACING;
1589 SetRect(&destRect, xorigin, yorigin, xorigin+32, yorigin+32);
1591 info.contentType = kControlContentCIconHandle;
1592 info.u.cIconHandle = bx_cicn[bmap_id];
1594 CreateIconControl(toolwin, &destRect, &info, false, &(bx_tool_pixmap[hb_index].control));
1595 SetControlCommandID(bx_tool_pixmap[hb_index].control, hb_index);
1596 return(hb_index);
1599 // ::SHOW_HEADERBAR()
1601 // Show (redraw) the current headerbar, which is composed of
1602 // currently installed bitmaps.
1604 void bx_carbon_gui_c::show_headerbar(void)
1606 UpdateTools();
1607 DrawControls(toolwin);
1611 // ::REPLACE_BITMAP()
1613 // Replace the bitmap installed in the headerbar ID slot 'hbar_id',
1614 // with the one specified by 'bmap_id'. 'bmap_id' will have
1615 // been generated by ::create_bitmap(). The old and new bitmap
1616 // must be of the same size. This allows the bitmap the user
1617 // sees to change, when some action occurs. For example when
1618 // the user presses on the floppy icon, it then displays
1619 // the ejected status.
1621 // hbar_id: headerbar slot ID
1622 // bmap_id: bitmap ID
1624 void bx_carbon_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
1626 //bx_tool_pixmap[hbar_id].pm = bx_pixmap[bmap_id];
1627 //bx_tool_pixmap[hbar_id].cicn = bx_cicn[bmap_id];
1628 ControlButtonContentInfo info;
1630 info.contentType = kControlContentCIconHandle;
1631 info.u.cIconHandle = bx_cicn[bmap_id];
1633 SetControlData(bx_tool_pixmap[hbar_id].control,
1634 kControlEntireControl, kControlIconContentTag, sizeof(ControlButtonContentInfo), &info);
1635 show_headerbar();
1639 // ::EXIT()
1641 // Called before bochs terminates, to allow for a graceful
1642 // exit from the native GUI mechanism.
1644 void bx_carbon_gui_c::exit(void)
1646 if (!menubarVisible)
1647 ShowMenubar(); // Make the menubar visible again
1648 InitCursor();
1650 // Make the clipboard all happy before we go
1651 CallInScrapPromises();
1654 #if 0
1655 void bx_carbon_gui_c::snapshot_handler(void)
1657 PicHandle ScreenShot;
1658 long val;
1660 SetPortWindowPort(win);
1662 ScreenShot = OpenPicture(&win->portRect);
1664 CopyBits(&win->portBits, &win->portBits, &win->portRect, &win->portRect, srcCopy, NULL);
1666 ClosePicture();
1668 val = ZeroScrap();
1670 HLock((Handle)ScreenShot);
1671 PutScrap(GetHandleSize((Handle)ScreenShot), 'PICT', *ScreenShot);
1672 HUnlock((Handle)ScreenShot);
1674 KillPicture(ScreenShot);
1676 #endif
1678 // HidePointer()
1680 // Hides the Mac mouse pointer
1682 void HidePointer()
1684 HiliteMenu(0);
1685 HideCursor();
1686 SetPortWindowPort(win);
1687 SetPt(&scrCenter, 300, 240);
1688 LocalToGlobal(&scrCenter);
1689 ResetPointer();
1690 GetMouse(&prevPt);
1691 cursorVisible = false;
1692 CheckMenuItem(GetMenuHandle(mBochs), iCursor, false);
1695 // ShowPointer()
1697 // Shows the Mac mouse pointer
1699 void ShowPointer()
1701 InitCursor();
1702 cursorVisible = true;
1703 CheckMenuItem(GetMenuHandle(mBochs), iCursor, true);
1704 //CheckItem(GetMenuHandle(mBochs), iCursor, true);
1707 // UpdateTools()
1709 // Check the state of the emulation and use it to tell which tools are available or not.
1710 void UpdateTools()
1712 ScrapRef theScrap;
1713 ScrapFlavorFlags theScrapFlags;
1715 GetCurrentScrap(&theScrap);
1717 // If keyboard mapping is on AND there is text on the clipboard enable pasting
1718 if (SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get() &&
1719 (GetScrapFlavorFlags(theScrap, kScrapFlavorTypeText, &theScrapFlags) == noErr))
1721 EnableMenuItem(GetMenuRef(mEdit), iPaste);
1722 EnableControl(bx_tool_pixmap[PASTE_TOOL_BUTTON].control);
1724 else
1726 DisableMenuItem(GetMenuRef(mEdit), iPaste);
1727 DisableControl(bx_tool_pixmap[PASTE_TOOL_BUTTON].control);
1730 // Currently copy and snapshot aren't available if we aren't in text mode
1731 if (screen_state == GRAPHIC_MODE) {
1732 DisableMenuItem(GetMenuRef(mEdit), iCopy);
1733 DisableMenuItem(GetMenuRef(mBochs), iSnapshot);
1734 DisableControl(bx_tool_pixmap[COPY_TOOL_BUTTON].control);
1735 DisableControl(bx_tool_pixmap[SNAPSHOT_TOOL_BUTTON].control);
1736 } else
1738 EnableMenuItem(GetMenuRef(mEdit), iCopy);
1739 EnableMenuItem(GetMenuRef(mBochs), iSnapshot);
1740 EnableControl(bx_tool_pixmap[COPY_TOOL_BUTTON].control);
1741 EnableControl(bx_tool_pixmap[SNAPSHOT_TOOL_BUTTON].control);
1744 // User control active if keys defined
1745 char *user_shortcut;
1746 user_shortcut = SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr();
1747 if (user_shortcut[0] && (strcmp(user_shortcut, "none"))) {
1748 EnableControl(bx_tool_pixmap[USER_TOOL_BUTTON].control);
1750 else
1752 DisableControl(bx_tool_pixmap[USER_TOOL_BUTTON].control);
1755 // Config panel only available if user has a terminal or equivalent
1756 if(isatty(STDIN_FILENO))
1758 EnableControl(bx_tool_pixmap[CONFIGURE_TOOL_BUTTON].control);
1760 else
1762 DisableControl(bx_tool_pixmap[CONFIGURE_TOOL_BUTTON].control);
1766 // HideTools()
1768 // Hides the Bochs toolbar
1770 void HideTools()
1772 HideWindow(toolwin);
1773 #if 0
1774 if (menubarVisible)
1776 MoveWindow(win, gLeft, gMinTop, false);
1778 else
1780 MoveWindow(hidden, gLeft, gMinTop, false);
1782 #endif
1783 CheckMenuItem(GetMenuHandle(mBochs), iTool, false);
1784 HiliteWindow(win, true);
1787 // ShowTools()
1789 // Shows the Bochs toolbar
1791 void ShowTools()
1793 #if 0
1794 if (menubarVisible)
1796 MoveWindow(win, gLeft, gMaxTop, false);
1798 else
1800 MoveWindow(hidden, gLeft, gMaxTop, false);
1802 #endif
1803 ShowWindow(toolwin);
1804 // theGui->show_headerbar();
1805 CheckMenuItem(GetMenuHandle(mBochs), iTool, true);
1806 HiliteWindow(win, true);
1809 // HideMenubar()
1811 // Hides the menubar (obviously)
1813 void HideMenubar()
1815 HideMenuBar();
1817 HideWindow(win);
1818 ShowWindow(backdrop);
1819 hidden = win;
1820 win = fullwin;
1821 ShowWindow(win);
1823 SelectWindow(win);
1824 menubarVisible = false;
1825 CheckMenuItem(GetMenuHandle(mBochs), iMenuBar, false);
1828 // ShowMenubar()
1830 // Makes the menubar visible again so other programs will display correctly.
1832 void ShowMenubar()
1834 HideWindow(backdrop);
1835 win = hidden;
1836 hidden = fullwin;
1837 HideWindow(hidden);
1838 ShowWindow(win);
1839 HiliteWindow(win, true);
1841 ShowMenuBar();
1843 menubarVisible = true;
1844 CheckMenuItem(GetMenuHandle(mBochs), iMenuBar, true);
1847 void HideConsole()
1849 // HideWindow(SouixWin);
1850 CheckMenuItem(GetMenuHandle(mBochs), iConsole, false);
1853 void ShowConsole()
1855 // ShowWindow(SouixWin);
1856 // SelectWindow(SouixWin);
1857 CheckMenuItem(GetMenuHandle(mBochs), iConsole, true);
1860 // CreateKeyMap()
1862 // Create a KCHR data structure to map Mac virtual key codes to Bochs key codes
1864 void CreateKeyMap(void)
1866 const unsigned char KCHRHeader [258] = {
1871 const unsigned char KCHRTable [130] = {
1874 BX_KEY_A,
1875 BX_KEY_S,
1876 BX_KEY_D,
1877 BX_KEY_F,
1878 BX_KEY_H,
1879 BX_KEY_G,
1880 BX_KEY_Z,
1881 BX_KEY_X,
1882 BX_KEY_C,
1883 BX_KEY_V,
1884 BX_KEY_LEFT_BACKSLASH,
1885 BX_KEY_B,
1886 BX_KEY_Q,
1887 BX_KEY_W,
1888 BX_KEY_E,
1889 BX_KEY_R,
1890 BX_KEY_Y,
1891 BX_KEY_T,
1892 BX_KEY_1,
1893 BX_KEY_2,
1894 BX_KEY_3,
1895 BX_KEY_4,
1896 BX_KEY_6,
1897 BX_KEY_5,
1898 BX_KEY_EQUALS,
1899 BX_KEY_9,
1900 BX_KEY_7,
1901 BX_KEY_MINUS,
1902 BX_KEY_8,
1903 BX_KEY_0,
1904 BX_KEY_RIGHT_BRACKET,
1905 BX_KEY_O,
1906 BX_KEY_U,
1907 BX_KEY_LEFT_BRACKET,
1908 BX_KEY_I,
1909 BX_KEY_P,
1910 BX_KEY_ENTER,
1911 BX_KEY_L,
1912 BX_KEY_J,
1913 BX_KEY_SINGLE_QUOTE,
1914 BX_KEY_K,
1915 BX_KEY_SEMICOLON,
1916 BX_KEY_BACKSLASH,
1917 BX_KEY_COMMA,
1918 BX_KEY_SLASH,
1919 BX_KEY_N,
1920 BX_KEY_M,
1921 BX_KEY_PERIOD,
1922 BX_KEY_TAB,
1923 BX_KEY_SPACE,
1924 BX_KEY_GRAVE,
1925 BX_KEY_BACKSPACE,
1926 BX_KEY_KP_ENTER,
1927 BX_KEY_ESC,
1928 0, // 0x36 (record button)
1929 0, // 0x37 (cmd key)
1930 0, // 0x38 (left shift)
1931 0, // 0x39 (caps lock)
1932 0, // 0x3A (left option/alt)
1933 0, // 0x3B (left ctrl)
1934 0, // 0x3C (right shift)
1935 0, // 0x3D (right option/alt)
1936 0, // 0x3E (right ctrl)
1937 0, // 0x3F (fn key -- laptops)
1938 0, // 0x40
1939 BX_KEY_KP_DELETE, // KP_PERIOD
1940 0, // 0x42 (move right/multiply)
1941 BX_KEY_KP_MULTIPLY,
1942 0, // 0x44
1943 BX_KEY_KP_ADD,
1944 0, // 0x46 (move left/add)
1945 BX_KEY_NUM_LOCK,
1946 0, // 0x48 (move down/equals)
1947 0, // 0x49
1948 0, // 0x4A
1949 BX_KEY_KP_DIVIDE,
1950 BX_KEY_KP_ENTER,
1951 0, // 0x4D (move up/divide)
1952 BX_KEY_KP_SUBTRACT,
1953 0, // 0x4F
1954 0, // 0x50
1955 BX_KEY_EQUALS, // 0x51 (kp equals)
1956 BX_KEY_KP_INSERT, // 0x52 (kp 0)
1957 BX_KEY_KP_END, // 0x53 (kp 1)
1958 BX_KEY_KP_DOWN, // 0x54 (kp 2)
1959 BX_KEY_KP_PAGE_DOWN, // 0x55 (kp 3)
1960 BX_KEY_KP_LEFT, // 0x56 (kp 4)
1961 BX_KEY_KP_5,
1962 BX_KEY_KP_RIGHT, // 0x58 (kp 6)
1963 BX_KEY_KP_HOME, // 0x59 (kp 7)
1964 0, // 0x5A
1965 BX_KEY_KP_UP, // 0x5B (kp 8)
1966 BX_KEY_KP_PAGE_UP, // 0x5C (kp 9)
1967 0, // 0x5D
1968 0, // 0x5E
1969 0, // 0x5F
1970 BX_KEY_F5,
1971 BX_KEY_F6,
1972 BX_KEY_F7,
1973 BX_KEY_F3,
1974 BX_KEY_F8,
1975 BX_KEY_F9,
1976 0, // 0x66
1977 BX_KEY_F11,
1978 0, // 0x68
1979 BX_KEY_PRINT, // 0x69 (print screen)
1980 0, // 0x6A
1981 BX_KEY_SCRL_LOCK, // 0x6B (scroll lock)
1982 0, // 0x6C
1983 BX_KEY_F10,
1984 BX_KEY_MENU, // 0x6E
1985 BX_KEY_F12,
1986 0, // 0x70
1987 BX_KEY_PAUSE, // 0x71 (pause)
1988 BX_KEY_INSERT,
1989 BX_KEY_HOME,
1990 BX_KEY_PAGE_UP,
1991 BX_KEY_DELETE,
1992 BX_KEY_F4,
1993 BX_KEY_END,
1994 BX_KEY_F2,
1995 BX_KEY_PAGE_DOWN,
1996 BX_KEY_F1,
1997 BX_KEY_LEFT,
1998 BX_KEY_RIGHT,
1999 BX_KEY_DOWN,
2000 BX_KEY_UP
2003 KCHR = NewPtrClear(390);
2004 if (KCHR == NULL)
2005 BX_PANIC(("mac: can't allocate memory for key map"));
2007 BlockMove(KCHRHeader, KCHR, sizeof(KCHRHeader));
2008 BlockMove(KCHRTable, Ptr(KCHR + sizeof(KCHRHeader)), sizeof(KCHRTable));
2011 // CreateVGAFont()
2013 // Create an array of PixMaps for the PC screen font
2015 void CreateVGAFont(unsigned char *vga_charmap)
2017 int i, x;
2018 unsigned char *fontData, curPixel;
2019 long row_bytes, bytecount;
2021 SetRect(&srcTextRect, 0, 0, font_width, font_height);
2022 for (i=0; i<256; i++)
2024 if(vgafont[i] != NULL) free(vgafont[i]);
2025 vgafont[i] = CreateBitMap(font_width, font_height);
2026 row_bytes = (*(vgafont[i])).rowBytes;
2027 bytecount = row_bytes * font_height;
2028 fontData = (unsigned char *)NewPtrClear(bytecount);
2030 for (x=0; x<font_height; x++)
2032 //curPixel = ~(bx_vgafont[i].data[x]);
2033 curPixel = (vga_charmap[(i*32) + x]);
2034 fontData[x*row_bytes] = curPixel;
2035 fontData[x*row_bytes + 1] = curPixel << 7;
2037 vgafont[i]->baseAddr = Ptr(fontData);
2041 // CreateBitMap()
2042 // Allocate a new bitmap and fill in the fields with appropriate
2043 // values.
2045 BitMap *CreateBitMap(unsigned width, unsigned height)
2047 BitMap *bm;
2048 long row_bytes;
2050 row_bytes = ((width + 31) >> 5) << 2;
2051 bm = (BitMap *)calloc(1, sizeof(BitMap));
2052 if (bm == NULL)
2053 BX_PANIC(("mac: can't allocate memory for pixmap"));
2054 SetRect(&bm->bounds, 0, 0, width, height);
2055 bm->rowBytes = row_bytes;
2056 // Quickdraw allocates a new color table by default, but we want to
2057 // use one we created earlier.
2059 return bm;
2062 // CreatePixMap()
2063 // Allocate a new pixmap handle and fill in the fields with appropriate
2064 // values.
2066 PixMapHandle CreatePixMap(unsigned left, unsigned top, unsigned width,
2067 unsigned height, unsigned depth, CTabHandle clut)
2069 PixMapHandle pm;
2070 long row_bytes;
2072 row_bytes = (((long) depth * ((long) width) + 31) >> 5) << 2;
2073 pm = NewPixMap();
2074 if (pm == NULL)
2075 BX_PANIC(("mac: can't allocate memory for pixmap"));
2076 (**pm).bounds.left = left;
2077 (**pm).bounds.top = top;
2078 (**pm).bounds.right = left+width;
2079 (**pm).bounds.bottom = top+height;
2080 (**pm).pixelSize = depth;
2081 (**pm).rowBytes = row_bytes | 0x8000;
2083 DisposeCTable((**pm).pmTable);
2084 (**pm).pmTable = clut;
2085 // Quickdraw allocates a new color table by default, but we want to
2086 // use one we created earlier.
2088 return pm;
2091 unsigned char reverse_bitorder(unsigned char b)
2093 unsigned char ret=0;
2095 for (unsigned i=0; i<8; i++)
2097 ret |= (b & 0x01) << (7-i);
2098 b >>= 1;
2101 return(ret);
2104 void bx_carbon_gui_c::mouse_enabled_changed_specific (bx_bool val)
2108 void bx_carbon_gui_c::beep_on(float frequency)
2110 AlertSoundPlay();
2111 BX_INFO(("Carbon Beep ON (frequency=%.2f)",frequency));
2114 void bx_carbon_gui_c::beep_off()
2116 BX_INFO(("Carbon Beep OFF"));
2119 // we need to handle "ask" events so that PANICs are properly reported
2120 static BxEvent * CarbonSiminterfaceCallback (void *theClass, BxEvent *event)
2122 event->retcode = 0; // default return code
2124 if(event->type == BX_ASYNC_EVT_LOG_MSG || event->type == BX_SYNC_EVT_LOG_ASK)
2126 DialogRef alertDialog;
2127 CFStringRef title;
2128 CFStringRef exposition;
2129 DialogItemIndex index;
2130 AlertStdCFStringAlertParamRec alertParam = {0};
2132 if(event->u.logmsg.prefix != NULL)
2134 title = CFStringCreateWithCString(NULL, event->u.logmsg.prefix, kCFStringEncodingASCII);
2135 exposition = CFStringCreateWithCString(NULL, event->u.logmsg.msg, kCFStringEncodingASCII);
2137 else
2139 title = CFStringCreateWithCString(NULL, event->u.logmsg.msg, kCFStringEncodingASCII);
2140 exposition = NULL;
2143 alertParam.version = kStdCFStringAlertVersionOne;
2144 alertParam.defaultText = CFSTR("Continue");
2145 alertParam.cancelText = CFSTR("Quit");
2146 alertParam.position = kWindowDefaultPosition;
2147 alertParam.defaultButton = kAlertStdAlertOKButton;
2148 alertParam.cancelButton = kAlertStdAlertCancelButton;
2150 CreateStandardAlert(
2151 kAlertCautionAlert,
2152 title,
2153 exposition, /* can be NULL */
2154 &alertParam, /* can be NULL */
2155 &alertDialog);
2157 RunStandardAlert(
2158 alertDialog,
2159 NULL, /* can be NULL */
2160 &index);
2162 CFRelease(title);
2164 if(exposition != NULL)
2166 CFRelease(exposition);
2169 // continue
2170 if(index == kAlertStdAlertOKButton)
2172 event->retcode = 0;
2174 // quit
2175 else if(index == kAlertStdAlertCancelButton)
2177 event->retcode = 2;
2179 #if 0
2180 if(event->u.logmsg.prefix != NULL)
2182 BX_INFO(("Callback log: Prefix: %s", event->u.logmsg.prefix));
2184 BX_INFO(("Callback log: Message: %s", event->u.logmsg.msg));
2185 #endif
2186 return event;
2189 #if 0
2190 // Track down the message that exiting leaves...
2191 switch(event->type)
2193 case BX_SYNC_EVT_TICK:
2194 case BX_SYNC_EVT_LOG_ASK:
2195 break;
2196 default:
2197 BX_INFO(("Callback tracing: Evt: %d (%s)", event->type,
2198 ((BX_EVT_IS_ASYNC(event->type))?"async":"sync")));
2200 #endif
2201 if (old_callback != NULL) {
2202 return (*old_callback)(old_callback_arg, event);
2203 } else {
2204 return event;
2207 #endif /* if BX_WITH_CARBON */