1 /////////////////////////////////////////////////////////////////////////
2 // $Id: macintosh.cc,v 1.29 2008/02/15 22:05:40 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
26 /////////////////////////////////////////////////////////////////////////
28 // macintosh.cc -- bochs GUI file for the Macintosh
29 // written by David Batterham <drbatter@progsoc.uts.edu.au>
30 // with contributions from Tim Senecal
32 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
33 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
34 // is used to know when we are exporting symbols and when we are importing.
42 // decide whether to enable this file or not
45 #include "icon_bochs.h"
46 #include "font/vga.bitmap.h"
49 #undef ACCESSOR_CALLS_ARE_FUNCTIONS
50 #define ACCESSOR_CALLS_ARE_FUNCTIONS 1
51 #include <Quickdraw.h>
52 #include <QuickdrawText.h>
53 #include <QDOffscreen.h>
55 #include <ImageCompression.h>
60 #include <TextUtils.h>
61 #include <ToolUtils.h>
65 #include <CursorDevices.h>
89 #define SLEEP_TIME 0 // Number of ticks to surrender the processor during a WaitNextEvent()
90 // Change this to 15 or higher if you don't want Bochs to hog the processor!
93 #define FONT_HEIGHT 16
95 #define WINBITMAP(w) (((GrafPtr)(w))->portBits)
97 #define ASCII_1_MASK 0x00FF0000
98 #define ASCII_2_MASK 0x000000FF
100 const RGBColor black
= {0, 0, 0};
101 const RGBColor white
= {0xFFFF, 0xFFFF, 0xFFFF};
102 const RGBColor medGrey
= {0xCCCC, 0xCCCC, 0xCCCC};
103 const RGBColor ltGrey
= {0xEEEE, 0xEEEE, 0xEEEE};
105 class bx_macintosh_gui_c
: public bx_gui_c
{
107 bx_macintosh_gui_c (void) {}
108 DECLARE_GUI_VIRTUAL_METHODS()
111 // declare one instance of the gui object and call macro to insert the
113 static bx_macintosh_gui_c
*theGui
= NULL
;
114 IMPLEMENT_GUI_PLUGIN_CODE(macintosh
)
116 #define LOG_THIS theGui->
120 WindowPtr win
, toolwin
, fullwin
, backdrop
, hidden
, SouixWin
;
121 SInt16 gOldMBarHeight
;
122 bx_bool menubarVisible
= true, cursorVisible
= true;
123 RgnHandle mBarRgn
, cnrRgn
;
124 unsigned mouse_button_state
= 0;
127 BitMap
*vgafont
[256];
128 Rect srcTextRect
, srcTileRect
;
129 Point scrCenter
= {320, 240};
133 unsigned width
, height
, gMinTop
, gMaxTop
, gLeft
;
136 static unsigned vga_bpp
=8;
137 static EventModifiers oldMods
= 0;
138 static unsigned int text_rows
=25, text_cols
=80;
141 int numPixMaps
= 0, toolPixMaps
= 0;
142 unsigned bx_bitmap_left_xorigin
= 2; // pixels from left
143 unsigned bx_bitmap_right_xorigin
= 2; // pixels from right
144 //PixMapHandle bx_pixmap[BX_MAX_PIXMAPS];
145 CIconHandle bx_cicn
[BX_MAX_PIXMAPS
];
156 } bx_tool_pixmap
[BX_MAX_PIXMAPS
];
159 BX_CPP_INLINE
void HandleKey(EventRecord
*event
, Bit32u keyState
);
160 BX_CPP_INLINE
void HandleToolClick(Point where
);
161 void HandleMenuChoice(long menuChoice
);
162 BX_CPP_INLINE
void HandleClick(EventRecord
*event
);
165 void UpdateWindow(WindowPtr window
);
166 void UpdateRgn(RgnHandle rgn
);
168 // Show/hide UI elements
169 void HidePointer(void);
170 void ShowPointer(void);
171 void HideTools(void);
172 void ShowTools(void);
173 void HideMenubar(void);
174 void ShowMenubar(void);
175 void HideConsole(void);
176 void ShowConsole(void);
179 void FixWindow(void);
181 void InitToolbox(void);
182 void CreateTile(void);
183 void CreateMenus(void);
184 void CreateWindows(void);
185 void CreateKeyMap(void);
186 void CreateVGAFont(void);
187 BitMap
*CreateBitMap(unsigned width
, unsigned height
);
188 PixMapHandle
CreatePixMap(unsigned left
, unsigned top
, unsigned width
,
189 unsigned height
, unsigned depth
, CTabHandle clut
);
190 unsigned char reverse_bitorder(unsigned char);
192 //this routine moves the initial window position so that it is entirely onscreen
193 //it is needed for os 8.x with appearance managaer
198 CWindowRecord
*thing
;
205 thing
= (CWindowRecord
*)win
;
206 wStruct
= thing
->strucRgn
;
207 wRgn
= (Region
*)*wStruct
;
208 wRect
= wRgn
->rgnBBox
;
210 thing
= (CWindowRecord
*)toolwin
;
211 tStruct
= thing
->strucRgn
;
212 tRgn
= (Region
*)*tStruct
;
213 tRect
= tRgn
->rgnBBox
;
217 gLeft
= gLeft
+ (2 - wRect
.left
);
220 MinVal
= tRect
.bottom
+2;
221 //MinVal = MinVal + GetMBarHeight();
223 if (wRect
.top
< MinVal
)
225 // gMinTop = gMinTop + (MinVal - wRect.top);
226 gMaxTop
= gMaxTop
+ (MinVal
- wRect
.top
);
229 MoveWindow(win
, gLeft
, gMaxTop
, false);
234 StopAlert(200, NULL
);
237 void InitToolbox(void)
239 InitGraf(&qd
.thePort
);
245 // Initialise the toolbox
248 void CreateTile(void)
254 long theRowBytes
= ((((long) (vga_bpp
==24?32:(((vga_bpp
+1)>>1)<<1)) * ((long) (srcTileRect
.right
-srcTileRect
.left
)) + 31) >> 5) << 2);
256 //if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
259 GetGWorld(&savePort
, &saveDevice
);
263 p_f
= k1MonochromePixelFormat
;
266 p_f
= k2IndexedPixelFormat
;
269 p_f
= k4IndexedPixelFormat
;
272 p_f
= k8IndexedPixelFormat
;
275 p_f
= k16LE555PixelFormat
;
278 p_f
= k16LE565PixelFormat
;
281 //p_f = k24BGRPixelFormat;
284 p_f
= k32ARGBPixelFormat
;//k32BGRAPixelFormat;
288 BX_ASSERT((gMyBuffer
= (Ptr
)malloc(theRowBytes
* (srcTileRect
.bottom
- srcTileRect
.top
))) != NULL
);
289 err
= QTNewGWorldFromPtr(&gOffWorld
, p_f
,
290 &srcTileRect
, vga_bpp
>8 ? NULL
: gCTable
, NULL
, keepLocal
, gMyBuffer
, theRowBytes
);
291 if (err
!= noErr
|| gOffWorld
== NULL
)
292 BX_PANIC(("mac: can't create gOffWorld; err=%hd", err
));
294 SetGWorld(gOffWorld
, NULL
);
295 RGBForeColor(&black
);
296 RGBBackColor(&white
);
298 gTile
= GetGWorldPixMap(gOffWorld
);
302 NoPurgePixels(gTile
);
303 if (!LockPixels(gTile
))
304 BX_ERROR(("mac: can't LockPixels gTile"));
305 if ((**gTile
).pixelType
!= RGBDirect
&& (**gTile
).pmTable
!= gCTable
)
307 DisposeCTable(gCTable
);
308 gCTable
= (**gTile
).pmTable
;
311 (**gCTable
).ctFlags
|= 0x4000; //use palette manager indexes
312 CTabChanged(gCTable
);
315 BX_PANIC(("mac: can't create gTile"));
317 SetGWorld(savePort
, saveDevice
);
323 gTile = CreatePixMap(0, 0, srcTileRect.right, srcTileRect.bottom, 8, gCTable);
325 BX_PANIC(("mac: can't create gTile"));
329 void CreateMenus(void)
333 menu
= GetNewMBar(rMBarID
); // get our menus from resource
338 AppendResMenu(GetMenuHandle(mApple
), 'DRVR'); // add apple menu items
342 BX_PANIC(("can't create menu"));
345 void CreateWindows(void)
350 SetRect(&winRect
, 0, 0, qd
.screenBits
.bounds
.right
, qd
.screenBits
.bounds
.bottom
);
351 backdrop
= NewWindow(NULL
, &winRect
, "\p", false, plainDBox
, (WindowPtr
)-1, false, 0);
357 gMaxTop
= 44 + gheaderbar_y
;
359 l
= (qd
.screenBits
.bounds
.right
- width
)/2;
361 t
= (qd
.screenBits
.bounds
.bottom
- height
)/2;
364 SetRect(&winRect
, 0, 20, qd
.screenBits
.bounds
.right
, 22+gheaderbar_y
);
365 toolwin
= NewCWindow(NULL
, &winRect
, "\pMacBochs 586", true, floatProc
,
366 (WindowPtr
)-1, false, 0);
368 BX_PANIC(("mac: can't create tool window"));
369 // Create a moveable tool window for the "headerbar"
371 SetRect(&winRect
, l
, t
, r
, b
);
372 fullwin
= NewCWindow(NULL
, &winRect
, "\p", false, plainDBox
, (WindowPtr
)-1, false, 1);
374 SetRect(&winRect
, gLeft
, gMaxTop
, gLeft
+width
, gMaxTop
+height
);
375 win
= NewCWindow(NULL
, &winRect
, "\pMacBochs 586", true, documentProc
,
376 (WindowPtr
)-1, true, 1);
378 BX_PANIC(("mac: can't create emulator window"));
384 HiliteWindow(win
, true);
391 // Called from gui.cc, once upon program startup, to allow for the
392 // specific GUI code (X11, BeOS, ...) to be initialized.
394 // argc, argv: not used right now, but the intention is to pass native GUI
395 // specific options from the command line. (X11 options, BeOS options,...)
397 // tilewidth, tileheight: for optimization, graphics_tile_update() passes
398 // only updated regions of the screen to the gui code to be redrawn.
399 // These define the dimensions of a region (tile).
400 // headerbar_y: A headerbar (toolbar) is display on the top of the
401 // VGA window, showing floppy status, and other information. It
402 // always assumes the width of the current VGA mode width, but
403 // it's height is defined by this parameter.
405 void bx_macintosh_gui_c::specific_init(int argc
, char **argv
, unsigned tilewidth
, unsigned tileheight
, unsigned headerbar_y
)
410 //SouixWin = FrontWindow();
414 gheaderbar_y
= headerbar_y
;
418 gCTable
= GetCTable(128);
419 BX_ASSERT (gCTable
!= NULL
);
420 CTabChanged(gCTable
); //(*gCTable)->ctSeed = GetCTSeed();
421 SetRect(&srcTextRect
, 0, 0, FONT_WIDTH
, FONT_HEIGHT
);
422 SetRect(&srcTileRect
, 0, 0, tilewidth
, tileheight
);
430 SetEventMask(everyEvent
);
432 SIOUXSettings
.setupmenus
= false;
433 SIOUXSettings
.autocloseonquit
= true;
434 SIOUXSettings
.asktosaveonclose
= false;
435 SIOUXSettings
.standalone
= false;
440 //HideWindow(SouixWin);
445 // Handles keyboard-related events.
447 BX_CPP_INLINE
void HandleKey(EventRecord
*event
, Bit32u keyState
)
451 static UInt32 transState
= 0;
453 key
= event
->message
& charCodeMask
;
455 if (event
->modifiers
& cmdKey
)
457 HandleMenuChoice(MenuKey(key
));
459 //else if (FrontWindow() == SouixWin)
461 // SIOUXHandleOneEvent(event);
465 /* if (event->modifiers & shiftKey)
466 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | keyState);
467 if (event->modifiers & controlKey)
468 DEV_kbd_gen_scancode(BX_KEY_CTRL_L | keyState);
469 if (event->modifiers & optionKey)
470 DEV_kbd_gen_scancode(BX_KEY_ALT_L | keyState);*/
472 key
= (event
->message
& keyCodeMask
) >> 8;
474 trans
= KeyTranslate(KCHR
, key
, &transState
);
475 if ((trans
== BX_KEY_PRINT
) && ((oldMods
& optionKey
) || (oldMods
& rightOptionKey
)))
476 trans
= BX_KEY_ALT_SYSREQ
;
477 if ((trans
== BX_KEY_PAUSE
) && ((oldMods
& controlKey
) || (oldMods
& rightControlKey
)))
478 trans
= BX_KEY_CTRL_BREAK
;
480 // KeyTranslate maps Mac virtual key codes to any type of character code
481 // you like (in this case, Bochs key codes). Much nicer than a huge switch
485 DEV_kbd_gen_scancode(trans
| keyState
);
487 /* if (event->modifiers & shiftKey)
488 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L | BX_KEY_RELEASED);
489 if (event->modifiers & controlKey)
490 DEV_kbd_gen_scancode(BX_KEY_CTRL_L | BX_KEY_RELEASED);
491 if (event->modifiers & optionKey)
492 DEV_kbd_gen_scancode(BX_KEY_ALT_L | BX_KEY_RELEASED);*/
498 // Handles mouse clicks in the Bochs tool window
500 BX_CPP_INLINE
void HandleToolClick(Point where
)
507 GlobalToLocal(&where
);
508 for (i
=0; i
<toolPixMaps
; i
++)
510 if (bx_tool_pixmap
[i
].alignment
== BX_GRAVITY_LEFT
)
511 xorigin
= bx_tool_pixmap
[i
].xorigin
;
513 xorigin
= toolwin
->portRect
.right
- bx_tool_pixmap
[i
].xorigin
;
514 SetRect(&bounds
, xorigin
, 0, xorigin
+32, 32);
515 if (PtInRect(where
, &bounds
))
516 bx_tool_pixmap
[i
].f();
518 theGui
->show_headerbar();
521 BX_CPP_INLINE
void ResetPointer(void)
524 CursorDevice
*theMouse
;
528 CrsrDevNextDevice(&theMouse
);
529 CrsrDevMoveTo(theMouse
, (long)scrCenter
.h
, (long)scrCenter
.v
);
533 #define MouseCur 0x082C
534 #define MouseTemp 0x0828
535 #define MouseNew 0x08CE
536 #define MouseAttached 0x08CF
538 *(Point
*)MouseCur
= scrCenter
;
539 *(Point
*)MouseTemp
= scrCenter
;
540 *(Ptr
)MouseNew
= *(Ptr
)MouseAttached
;
541 //*(char *)CrsrNew = 0xFF;
546 // Handles mouse click events.
549 void HandleMenuChoice(long menuChoice
)
559 item
= LoWord(menuChoice
);
560 menu
= HiWord(menuChoice
);
566 theDlog
= GetNewDialog(128, NULL
, (WindowPtr
)-1);
567 ModalDialog(NULL
, &i
);
568 DisposeDialog(theDlog
);
572 GetMenuItemText(GetMenuHandle(mApple
), item
, daName
);
573 daRefNum
= OpenDeskAcc(daName
);
581 BX_PANIC(("User terminated"));
603 if (IsWindowVisible(toolwin
))
617 if (cursorVisible
|| IsWindowVisible(toolwin
) || menubarVisible
)
623 if (IsWindowVisible(toolwin
))
632 if (!IsWindowVisible(toolwin
))
638 if (IsWindowVisible(SouixWin
))
645 // the following will break if snapshot is not last bitmap button instantiated
646 bx_tool_pixmap
[toolPixMaps
-1].f();
657 BX_CPP_INLINE
void HandleClick(EventRecord
*event
)
660 WindowPtr whichWindow
;
663 part
= FindWindow(event
->where
, &whichWindow
);
668 if (whichWindow
== win
)
670 if (win
!= FrontWindow())
672 if (event
->modifiers
& cmdKey
)
673 mouse_button_state
|= 0x02;
675 mouse_button_state
|= 0x01;
677 else if (whichWindow
== toolwin
)
679 HiliteWindow(win
, true);
680 HandleToolClick(event
->where
);
682 else if (whichWindow
== backdrop
)
686 else if (whichWindow
== SouixWin
)
688 SelectWindow(SouixWin
);
693 dRect
= qd
.screenBits
.bounds
;
694 if (IsWindowVisible(toolwin
))
696 DragWindow(whichWindow
, event
->where
, &dRect
);
700 HandleMenuChoice(MenuSelect(event
->where
));
705 void UpdateWindow(WindowPtr window
)
717 box
= window
->portRect
;
718 DEV_vga_redraw_area(box
.left
, box
.top
, box
.right
, box
.bottom
);
720 else if (window
== backdrop
)
722 box
= window
->portRect
;
723 FillRect(&box
, &qd
.black
);
725 else if (window
== toolwin
)
727 theGui
->show_headerbar();
736 // Called periodically (vga_update_interval in .bochsrc) so the
737 // the gui code can poll for keyboard, mouse, and other
740 void bx_macintosh_gui_c::handle_events(void)
746 EventModifiers newMods
;
750 curstate
= mouse_button_state
; //so we can compare the old and the new mouse state
752 if (WaitNextEvent(everyEvent
, &event
, SLEEP_TIME
, NULL
))
764 if (event
.modifiers
& cmdKey
)
765 mouse_button_state
&= ~0x02;
767 mouse_button_state
&= ~0x01;
772 oldMods1
= event
.modifiers
;
773 HandleKey(&event
, BX_KEY_PRESSED
);
777 event
.modifiers
= oldMods1
;
778 HandleKey(&event
, BX_KEY_RELEASED
);
782 if ((WindowPtr
)event
.message
== SouixWin
)
783 SIOUXHandleOneEvent(&event
);
785 UpdateWindow((WindowPtr
)event
.message
);
795 else if (oldMods
!= (newMods
= (event
.modifiers
& 0xfe00)))
797 if ((newMods
^ oldMods
) & shiftKey
)
798 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L
| ((newMods
& shiftKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
799 if ((newMods
^ oldMods
) & alphaLock
)
800 DEV_kbd_gen_scancode(BX_KEY_CAPS_LOCK
| ((newMods
& alphaLock
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
801 if ((newMods
^ oldMods
) & optionKey
)
802 DEV_kbd_gen_scancode(BX_KEY_ALT_L
| ((newMods
& optionKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
803 if ((newMods
^ oldMods
) & controlKey
)
804 DEV_kbd_gen_scancode(BX_KEY_CTRL_L
| ((newMods
& controlKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
805 if ((newMods
^ oldMods
) & rightShiftKey
)
806 DEV_kbd_gen_scancode(BX_KEY_SHIFT_R
| ((newMods
& rightShiftKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
807 if ((newMods
^ oldMods
) & rightOptionKey
)
808 DEV_kbd_gen_scancode(BX_KEY_ALT_R
| ((newMods
& rightOptionKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
809 if ((newMods
^ oldMods
) & rightControlKey
)
810 DEV_kbd_gen_scancode(BX_KEY_CTRL_R
| ((newMods
& rightControlKey
)?BX_KEY_PRESSED
:BX_KEY_RELEASED
));
819 //if mouse has moved, or button has changed state
820 if ((!EqualPt(mousePt
, prevPt
)) || (curstate
!= mouse_button_state
))
822 dx
= mousePt
.h
- prevPt
.h
;
823 dy
= prevPt
.v
- mousePt
.v
;
825 DEV_mouse_motion(dx
, dy
, mouse_button_state
);
829 SetPt(&scrCenter
, 320, 240);
830 LocalToGlobal(&scrCenter
);
831 ResetPointer(); //next getmouse should be 320, 240
832 SetPt(&mousePt
, 320, 240);
843 // Called periodically, requesting that the gui code flush all pending
844 // screen update requests.
846 void bx_macintosh_gui_c::flush(void)
848 // an opportunity to make the Window Manager happy.
849 // not needed on the macintosh....
854 // Called to request that the VGA region is cleared. Don't
855 // clear the area that defines the headerbar.
857 void bx_macintosh_gui_c::clear_screen(void)
861 RGBForeColor(&black
);
862 RGBBackColor(&white
);
864 FillRect(&win
->portRect
, &qd
.black
);
869 // Called in a VGA text mode, to update the screen with
872 // old_text: array of character/attributes making up the contents
873 // of the screen from the last call. See below
874 // new_text: array of character/attributes making up the current
875 // contents, which should now be displayed. See below
877 // format of old_text & new_text: each is tm_info.line_offset*text_rows
878 // bytes long. Each character consists of 2 bytes. The first by is
879 // the character value, the second is the attribute byte.
881 // cursor_x: new x location of cursor
882 // cursor_y: new y location of cursor
883 // tm_info: this structure contains information for additional
884 // features in text mode (cursor shape, line offset,...)
886 void bx_macintosh_gui_c::text_update(Bit8u
*old_text
, Bit8u
*new_text
,
887 unsigned long cursor_x
, unsigned long cursor_y
,
888 bx_vga_tminfo_t tm_info
)
896 RGBColor fgColor
, bgColor
;
905 //current cursor position
906 cursori
= (cursor_y
* text_cols
+ cursor_x
) * 2;
908 // Number of characters on screen, variable number of rows
909 nchars
= text_cols
* text_rows
;
911 for (i
=0; i
<nchars
*2; i
+=2)
913 if (i
== cursori
|| i
== previ
|| new_text
[i
] != old_text
[i
] || new_text
[i
+1] != old_text
[i
+1])
917 // fgColor = (**gCTable).ctTable[new_text[i+1] & 0x0F].rgb;
918 // bgColor = (**gCTable).ctTable[(new_text[i+1] & 0xF0) >> 4].rgb;
920 // RGBForeColor(&fgColor);
921 // RGBBackColor(&bgColor);
923 if (SIM
->get_param_bool(BXPN_PRIVATE_COLORMAP
)->get())
925 PmForeColor(new_text
[i
+1] & 0x0F);
926 PmBackColor((new_text
[i
+1] & 0xF0) >> 4);
930 fgColor
= (**gCTable
).ctTable
[new_text
[i
+1] & 0x0F].rgb
;
931 bgColor
= (**gCTable
).ctTable
[(new_text
[i
+1] & 0xF0) >> 4].rgb
;
933 RGBForeColor(&fgColor
);
934 RGBBackColor(&bgColor
);
937 x
= ((i
/2) % text_cols
)*FONT_WIDTH
;
938 y
= ((i
/2) / text_cols
)*FONT_HEIGHT
;
940 SetRect(&destRect
, x
, y
, x
+FONT_WIDTH
, y
+FONT_HEIGHT
);
942 CopyBits(vgafont
[achar
], &WINBITMAP(win
),
943 &srcTextRect
, &destRect
, srcCopy
, NULL
);
944 if ((theError
= QDError()) != noErr
)
945 BX_ERROR(("mac: CopyBits returned %hd", theError
));
947 if (i
== cursori
) //invert the current cursor block
949 InvertRect(&destRect
);
954 //previous cursor position
960 int bx_macintosh_gui_c::get_clipboard_text(Bit8u
**bytes
, Bit32s
*nbytes
)
965 int bx_macintosh_gui_c::set_clipboard_text(char *text_snapshot
, Bit32u len
)
970 // ::PALETTE_CHANGE()
972 // Allocate a color in the native GUI, for this color, and put
973 // it in the colormap location 'index'.
974 // returns: 0=no screen update needed (color map change has direct effect)
975 // 1=screen updated needed (redraw using current colormap)
977 bx_bool
bx_macintosh_gui_c::palette_change(unsigned index
, unsigned red
, unsigned green
, unsigned blue
)
979 PaletteHandle thePal
, oldpal
;
984 /*if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
986 GetGWorld(&savePort, &saveDevice);
988 SetGWorld(gOffWorld, NULL);
991 if ((**gTile
).pixelType
!= RGBDirect
)
996 (**gCTable
).ctTable
[index
].value
= index
;
997 (**gCTable
).ctTable
[index
].rgb
.red
= (red
<< 8);
998 (**gCTable
).ctTable
[index
].rgb
.green
= (green
<< 8);
999 (**gCTable
).ctTable
[index
].rgb
.blue
= (blue
<< 8);
1001 SetEntries(index
, index
, (**gCTable
).ctTable
);
1003 CTabChanged(gCTable
);
1008 /*if (gOffWorld != NULL) //(SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
1009 SetGWorld(savePort, saveDevice);*/
1011 if (SIM
->get_param_bool(BXPN_PRIVATE_COLORMAP
)->get())
1013 thePal
= NewPalette(index
, gCTable
, pmTolerant
, 0x5000);
1014 oldpal
= GetPalette(win
);
1016 SetPalette(win
, thePal
, false);
1017 SetPalette(fullwin
, thePal
, false);
1018 SetPalette(hidden
, thePal
, false);
1023 return((**gTile
).pixelType
!= RGBDirect
);
1026 // ::GRAPHICS_TILE_UPDATE()
1028 // Called to request that a tile of graphics be drawn to the
1029 // screen, since info in this region has changed.
1031 // tile: array of 8bit values representing a block of pixels with
1032 // dimension equal to the 'tilewidth' & 'tileheight' parameters to
1033 // ::specific_init(). Each value specifies an index into the
1034 // array of colors you allocated for ::palette_change()
1035 // x0: x origin of tile
1036 // y0: y origin of tile
1038 // note: origin of tile and of window based on (0,0) being in the upper
1039 // left of the window.
1041 void bx_macintosh_gui_c::graphics_tile_update(Bit8u
*tile
, unsigned x0
, unsigned y0
)
1047 /*GDHandle saveDevice;
1050 GetGWorld(&savePort, &saveDevice);
1052 SetGWorld(gOffWorld, NULL); */
1055 destRect
= srcTileRect
;
1056 OffsetRect(&destRect
, x0
, y0
);
1058 //(**gTile).baseAddr = (Ptr)tile;
1059 if ((theBaseAddr
= GetPixBaseAddr(gTile
)) == NULL
)
1060 BX_PANIC(("mac: gTile has NULL baseAddr (offscreen buffer purged)"));
1061 else if (vga_bpp
== 24 || vga_bpp
== 32)
1063 for (unsigned iY
= 0; iY
< (srcTileRect
.bottom
-srcTileRect
.top
); iY
++)
1065 Bit8u
*iA
= ((Bit8u
*)theBaseAddr
) + iY
* GetPixRowBytes(gTile
);
1066 for (unsigned iX
= 0; iX
< (srcTileRect
.right
-srcTileRect
.left
); iX
++)
1068 iA
[iX
*4 + 3] = tile
[((srcTileRect
.right
-srcTileRect
.left
)*iY
+iX
)*(vga_bpp
>>3)];
1069 iA
[iX
*4 + 2] = tile
[((srcTileRect
.right
-srcTileRect
.left
)*iY
+iX
)*(vga_bpp
>>3) + 1];
1070 iA
[iX
*4 + 1] = tile
[((srcTileRect
.right
-srcTileRect
.left
)*iY
+iX
)*(vga_bpp
>>3) + 2];
1071 iA
[iX
*4] = vga_bpp
== 24 ? 0 : tile
[((srcTileRect
.right
-srcTileRect
.left
)*iY
+iX
)*4 + 3];
1076 BlockMoveData(tile
, theBaseAddr
, (srcTileRect
.bottom
-srcTileRect
.top
) * GetPixRowBytes(gTile
));
1077 RGBForeColor(&black
);
1078 RGBBackColor(&white
);
1079 CopyBits(GetPortBitMapForCopyBits(gOffWorld
), &WINBITMAP(win
),
1080 &srcTileRect
, &destRect
, srcCopy
, NULL
);
1081 if ((theError
= QDError()) != noErr
)
1082 BX_ERROR(("mac: CopyBits returned %hd", theError
));
1085 //SetGWorld(savePort, saveDevice);
1088 // ::DIMENSION_UPDATE()
1090 // Called when the VGA mode changes it's X,Y dimensions.
1091 // Resize the window to this size, but you need to add on
1092 // the height of the headerbar to the Y value.
1094 // x: new VGA x size
1095 // y: new VGA y size (add headerbar_y parameter from ::specific_init().
1096 // fheight: new VGA character height in text mode
1097 // fwidth : new VGA character width in text mode
1098 // bpp : bits per pixel in graphics mode
1100 void bx_macintosh_gui_c::dimension_update(unsigned x
, unsigned y
, unsigned fheight
, unsigned fwidth
, unsigned bpp
)
1102 if ((bpp
!= 1) && (bpp
!= 2) && (bpp
!= 4) && (bpp
!= 8) && (bpp
!= 15) && (bpp
!= 16) && (bpp
!= 24) && (bpp
!= 32)) {
1103 BX_PANIC(("%d bpp graphics mode not supported yet", bpp
));
1108 if ((**gTile
).pixelType
== RGBDirect
)
1109 gCTable
= GetCTable(128);
1110 DisposeGWorld(gOffWorld
);
1115 text_cols
= x
/ fwidth
;
1116 text_rows
= y
/ fheight
;
1120 if (fheight
!= 16) {
1121 y
= y
* 16 / fheight
;
1125 if (x
!= width
|| y
!= height
)
1127 SizeWindow(win
, x
, y
, false);
1128 SizeWindow(fullwin
, x
, y
, false);
1129 SizeWindow(hidden
, x
, y
, false);
1139 // ::CREATE_BITMAP()
1141 // Create a monochrome bitmap of size 'xdim' by 'ydim', which will
1142 // be drawn in the headerbar. Return an integer ID to the bitmap,
1143 // with which the bitmap can be referenced later.
1145 // bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
1146 // bit0 is the left most pixel, bit7 is the right most pixel.
1147 // xdim: x dimension of bitmap
1148 // ydim: y dimension of bitmap
1150 // rewritten by tim senecal to use the cicn (color icon) resources instead
1152 unsigned bx_macintosh_gui_c::create_bitmap(const unsigned char *bmap
, unsigned xdim
, unsigned ydim
)
1155 unsigned char *data
;
1156 long row_bytes
, bytecount
;
1158 bx_cicn
[numPixMaps
] = GetCIcon(numPixMaps
+128);
1159 BX_ASSERT(bx_cicn
[numPixMaps
]);
1163 return(numPixMaps
-1);
1166 // ::HEADERBAR_BITMAP()
1168 // Called to install a bitmap in the bochs headerbar (toolbar).
1170 // bmap_id: will correspond to an ID returned from
1171 // ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
1172 // or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
1173 // available leftmost or rightmost space.
1174 // f: a 'C' function pointer to callback when the mouse is clicked in
1175 // the boundaries of this bitmap.
1177 unsigned bx_macintosh_gui_c::headerbar_bitmap(unsigned bmap_id
, unsigned alignment
, void (*f
)(void))
1182 hb_index
= toolPixMaps
-1;
1183 //bx_tool_pixmap[hb_index].pm = bx_pixmap[bmap_id];
1184 bx_tool_pixmap
[hb_index
].cicn
= bx_cicn
[bmap_id
];
1185 bx_tool_pixmap
[hb_index
].alignment
= alignment
;
1186 bx_tool_pixmap
[hb_index
].f
= f
;
1188 if (alignment
== BX_GRAVITY_LEFT
)
1190 bx_tool_pixmap
[hb_index
].xorigin
= bx_bitmap_left_xorigin
;
1191 bx_tool_pixmap
[hb_index
].yorigin
= 0;
1192 // bx_bitmap_left_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
1193 bx_bitmap_left_xorigin
+= 34;
1197 // bx_bitmap_right_xorigin += (**bx_pixmap[bmap_id]).bounds.right;
1198 bx_bitmap_right_xorigin
+= 34;
1199 bx_tool_pixmap
[hb_index
].xorigin
= bx_bitmap_right_xorigin
;
1200 bx_tool_pixmap
[hb_index
].yorigin
= 0;
1205 // ::SHOW_HEADERBAR()
1207 // Show (redraw) the current headerbar, which is composed of
1208 // currently installed bitmaps.
1210 void bx_macintosh_gui_c::show_headerbar(void)
1216 RGBForeColor(&medGrey
);
1217 FillRect(&toolwin
->portRect
, &qd
.black
);
1218 for (i
=0; i
<toolPixMaps
; i
++)
1220 if (bx_tool_pixmap
[i
].alignment
== BX_GRAVITY_LEFT
)
1221 xorigin
= bx_tool_pixmap
[i
].xorigin
;
1223 xorigin
= toolwin
->portRect
.right
- bx_tool_pixmap
[i
].xorigin
;
1225 SetRect(&destRect
, xorigin
, 0, xorigin
+32, 32);
1227 //changed, simply plot the cicn for that button, in the prescribed rectangle
1228 PlotCIcon(&destRect
, bx_tool_pixmap
[i
].cicn
);
1230 RGBForeColor(&black
);
1234 // ::REPLACE_BITMAP()
1236 // Replace the bitmap installed in the headerbar ID slot 'hbar_id',
1237 // with the one specified by 'bmap_id'. 'bmap_id' will have
1238 // been generated by ::create_bitmap(). The old and new bitmap
1239 // must be of the same size. This allows the bitmap the user
1240 // sees to change, when some action occurs. For example when
1241 // the user presses on the floppy icon, it then displays
1242 // the ejected status.
1244 // hbar_id: headerbar slot ID
1245 // bmap_id: bitmap ID
1247 void bx_macintosh_gui_c::replace_bitmap(unsigned hbar_id
, unsigned bmap_id
)
1249 //bx_tool_pixmap[hbar_id].pm = bx_pixmap[bmap_id];
1250 bx_tool_pixmap
[hbar_id
].cicn
= bx_cicn
[bmap_id
];
1256 // Called before bochs terminates, to allow for a graceful
1257 // exit from the native GUI mechanism.
1259 void bx_macintosh_gui_c::exit(void)
1261 if (!menubarVisible
)
1262 ShowMenubar(); // Make the menubar visible again
1267 void bx_macintosh_gui_c::snapshot_handler(void)
1269 PicHandle ScreenShot
;
1274 ScreenShot
= OpenPicture(&win
->portRect
);
1276 CopyBits(&win
->portBits
, &win
->portBits
, &win
->portRect
, &win
->portRect
, srcCopy
, NULL
);
1282 HLock((Handle
)ScreenShot
);
1283 PutScrap(GetHandleSize((Handle
)ScreenShot
), 'PICT', *ScreenShot
);
1284 HUnlock((Handle
)ScreenShot
);
1286 KillPicture(ScreenShot
);
1292 // Updates the screen after the menubar and round corners have been hidden
1294 void UpdateRgn(RgnHandle rgn
)
1298 window
= FrontWindow();
1299 PaintBehind(window
, rgn
);
1300 CalcVisBehind(window
, rgn
);
1305 // Hides the Mac mouse pointer
1312 SetPt(&scrCenter
, 320, 240);
1313 LocalToGlobal(&scrCenter
);
1316 cursorVisible
= false;
1317 CheckItem(GetMenuHandle(mBochs
), iCursor
, false);
1322 // Shows the Mac mouse pointer
1327 cursorVisible
= true;
1328 CheckItem(GetMenuHandle(mBochs
), iCursor
, true);
1333 // Hides the Bochs toolbar
1337 HideWindow(toolwin
);
1340 MoveWindow(win
, gLeft
, gMinTop
, false);
1344 MoveWindow(hidden
, gLeft
, gMinTop
, false);
1346 CheckItem(GetMenuHandle(mBochs
), iTool
, false);
1347 HiliteWindow(win
, true);
1352 // Shows the Bochs toolbar
1358 MoveWindow(win
, gLeft
, gMaxTop
, false);
1362 MoveWindow(hidden
, gLeft
, gMaxTop
, false);
1364 ShowWindow(toolwin
);
1365 BringToFront(toolwin
);
1366 SelectWindow(toolwin
);
1367 HiliteWindow(win
, true);
1368 //theGui->show_headerbar();
1369 CheckItem(GetMenuHandle(mBochs
), iTool
, true);
1370 HiliteWindow(win
, true);
1375 // Hides the menubar (obviously)
1382 grayRgn
= LMGetGrayRgn();
1383 gOldMBarHeight
= GetMBarHeight();
1386 mBarRect
= qd
.screenBits
.bounds
;
1387 mBarRect
.bottom
= mBarRect
.top
+ gOldMBarHeight
;
1388 RectRgn(mBarRgn
, &mBarRect
);
1389 UnionRgn(grayRgn
, mBarRgn
, grayRgn
);
1393 RectRgn(cnrRgn
, &qd
.screenBits
.bounds
);
1394 DiffRgn(cnrRgn
, grayRgn
, cnrRgn
);
1395 UnionRgn(grayRgn
, cnrRgn
, grayRgn
);
1399 ShowWindow(backdrop
);
1400 SelectWindow(backdrop
);
1406 menubarVisible
= false;
1407 CheckItem(GetMenuHandle(mBochs
), iMenuBar
, false);
1412 // Makes the menubar visible again so other programs will display correctly.
1419 grayRgn
= LMGetGrayRgn();
1420 LMSetMBarHeight(gOldMBarHeight
);
1421 DiffRgn(grayRgn
, mBarRgn
, grayRgn
);
1422 DisposeRgn(mBarRgn
);
1426 SetPort(LMGetWMgrPort());
1428 FillRgn(cnrRgn
, &qd
.black
);
1430 DiffRgn(grayRgn
, cnrRgn
, grayRgn
);
1433 HideWindow(backdrop
);
1438 HiliteWindow(win
, true);
1440 menubarVisible
= true;
1441 CheckItem(GetMenuHandle(mBochs
), iMenuBar
, true);
1446 HideWindow(SouixWin
);
1447 CheckItem(GetMenuHandle(mBochs
), iConsole
, false);
1452 ShowWindow(SouixWin
);
1453 SelectWindow(SouixWin
);
1454 CheckItem(GetMenuHandle(mBochs
), iConsole
, true);
1459 // Create a KCHR data structure to map Mac virtual key codes to Bochs key codes
1461 void CreateKeyMap(void)
1463 const unsigned char KCHRHeader
[258] = { 0, 1 };
1465 const unsigned char KCHRTable
[130] = {
1478 BX_KEY_LEFT_BACKSLASH
,
1498 BX_KEY_RIGHT_BRACKET
,
1501 BX_KEY_LEFT_BRACKET
,
1507 BX_KEY_SINGLE_QUOTE
,
1522 0, // 0x36 (record button)
1523 0, // 0x37 (cmd key)
1524 0, // 0x38 (left shift)
1525 0, // 0x39 (caps lock)
1526 0, // 0x3A (left option/alt)
1527 0, // 0x3B (left ctrl)
1528 0, // 0x3C (right shift)
1529 0, // 0x3D (right option/alt)
1530 0, // 0x3E (right ctrl)
1531 0, // 0x3F (fn key -- laptops)
1533 BX_KEY_KP_DELETE
, // KP_PERIOD
1534 0, // 0x42 (move right/multiply)
1538 0, // 0x46 (move left/add)
1540 0, // 0x48 (move down/equals)
1545 0, // 0x4D (move up/divide)
1549 BX_KEY_EQUALS
, // 0x51 (kp equals)
1550 BX_KEY_KP_INSERT
, // 0x52 (kp 0)
1551 BX_KEY_KP_END
, // 0x53 (kp 1)
1552 BX_KEY_KP_DOWN
, // 0x54 (kp 2)
1553 BX_KEY_KP_PAGE_DOWN
, // 0x55 (kp 3)
1554 BX_KEY_KP_LEFT
, // 0x56 (kp 4)
1556 BX_KEY_KP_RIGHT
, // 0x58 (kp 6)
1557 BX_KEY_KP_HOME
, // 0x59 (kp 7)
1559 BX_KEY_KP_UP
, // 0x5B (kp 8)
1560 BX_KEY_KP_PAGE_UP
, // 0x5C (kp 9)
1573 BX_KEY_PRINT
, // 0x69 (print screen)
1575 BX_KEY_SCRL_LOCK
, // 0x6B (scroll lock)
1578 BX_KEY_MENU
, // 0x6E
1581 BX_KEY_PAUSE
, // 0x71 (pause)
1597 KCHR
= NewPtrClear(390);
1599 BX_PANIC(("mac: can't allocate memory for key map"));
1601 BlockMove(KCHRHeader
, KCHR
, sizeof(KCHRHeader
));
1602 BlockMove(KCHRTable
, Ptr(KCHR
+ sizeof(KCHRHeader
)), sizeof(KCHRTable
));
1607 // Create an array of PixMaps for the PC screen font
1609 void CreateVGAFont(void)
1612 unsigned char *fontData
, curPixel
;
1613 long row_bytes
, bytecount
;
1615 for (i
=0; i
<256; i
++)
1617 vgafont
[i
] = CreateBitMap(FONT_WIDTH
, FONT_HEIGHT
);
1618 row_bytes
= (*(vgafont
[i
])).rowBytes
;
1619 bytecount
= row_bytes
* FONT_HEIGHT
;
1620 fontData
= (unsigned char *)NewPtrClear(bytecount
);
1622 for (x
=0; x
<16; x
++)
1624 //curPixel = ~(bx_vgafont[i].data[x]);
1625 curPixel
= (bx_vgafont
[i
].data
[x
]);
1626 fontData
[x
*row_bytes
] = reverse_bitorder(curPixel
);
1629 vgafont
[i
]->baseAddr
= Ptr(fontData
);
1634 // Allocate a new bitmap and fill in the fields with appropriate
1637 BitMap
*CreateBitMap(unsigned width
, unsigned height
)
1642 row_bytes
= ((width
+ 31) >> 5) << 2;
1643 bm
= (BitMap
*)calloc(1, sizeof(BitMap
));
1645 BX_PANIC(("mac: can't allocate memory for pixmap"));
1646 SetRect(&bm
->bounds
, 0, 0, width
, height
);
1647 bm
->rowBytes
= row_bytes
;
1648 // Quickdraw allocates a new color table by default, but we want to
1649 // use one we created earlier.
1655 // Allocate a new pixmap handle and fill in the fields with appropriate
1658 PixMapHandle
CreatePixMap(unsigned left
, unsigned top
, unsigned width
,
1659 unsigned height
, unsigned depth
, CTabHandle clut
)
1664 row_bytes
= (((long) depth
* ((long) width
) + 31) >> 5) << 2;
1667 BX_PANIC(("mac: can't allocate memory for pixmap"));
1668 (**pm
).bounds
.left
= left
;
1669 (**pm
).bounds
.top
= top
;
1670 (**pm
).bounds
.right
= left
+width
;
1671 (**pm
).bounds
.bottom
= top
+height
;
1672 (**pm
).pixelSize
= depth
;
1673 (**pm
).rowBytes
= row_bytes
| 0x8000;
1675 DisposeCTable((**pm
).pmTable
);
1676 (**pm
).pmTable
= clut
;
1677 // Quickdraw allocates a new color table by default, but we want to
1678 // use one we created earlier.
1683 unsigned char reverse_bitorder(unsigned char b
)
1685 unsigned char ret
=0;
1687 for (unsigned i
=0; i
<8; i
++)
1689 ret
|= (b
& 0x01) << (7-i
);
1696 void bx_macintosh_gui_c::mouse_enabled_changed_specific (bx_bool val
)
1700 #endif /* if BX_WITH_MACOS */