1 /////////////////////////////////////////////////////////////////////////
2 // $Id: win32.cc,v 1.121 2008/10/06 22:00:11 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 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 // Much of this file was written by:
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.
38 #include "iodev/iodev.h"
42 #include "win32dialog.h"
44 #include "font/vga.bitmap.h"
45 // windows.h is included by bochs.h
49 class bx_win32_gui_c
: public bx_gui_c
{
51 bx_win32_gui_c (void) {}
52 DECLARE_GUI_VIRTUAL_METHODS();
53 virtual void statusbar_setitem(int element
, bx_bool active
, bx_bool w
=0);
54 virtual void get_capabilities(Bit16u
*xres
, Bit16u
*yres
, Bit16u
*bpp
);
55 virtual void set_tooltip(unsigned hbar_id
, const char *tip
);
57 virtual void show_ips(Bit32u ips_count
);
61 // declare one instance of the gui object and call macro to insert the
63 static bx_win32_gui_c
*theGui
= NULL
;
64 IMPLEMENT_GUI_PLUGIN_CODE(win32
)
66 #define LOG_THIS theGui->
68 #define EXIT_GUI_SHUTDOWN 1
69 #define EXIT_GMH_FAILURE 2
70 #define EXIT_FONT_BITMAP_ERROR 3
72 #define EXIT_HEADER_BITMAP_ERROR 5
75 #define TBSTYLE_FLAT 0x0800
78 /* FIXME: Should we add a bochsrc option to control the font usage? */
79 #define BX_USE_WINDOWS_FONTS 0
81 // Keyboard/mouse stuff
82 #define SCANCODE_BUFSIZE 20
83 #define MOUSE_PRESSED 0x20000000
84 #define HEADERBAR_CLICKED 0x08000000
85 #define MOUSE_MOTION 0x22000000
86 #define BX_SYSKEY (KF_UP|KF_REPEAT|KF_ALTDOWN)
87 void enq_key_event(Bit32u
, Bit32u
);
88 void enq_mouse_event(void);
95 int mouse_button_state
;
97 QueueEvent
* deq_key_event(void);
99 static QueueEvent keyevents
[SCANCODE_BUFSIZE
];
100 static unsigned head
=0, tail
=0;
101 static int mouse_button_state
= 0;
102 static int ms_xdelta
=0, ms_ydelta
=0, ms_zdelta
=0;
103 static int ms_lastx
=0, ms_lasty
=0;
104 static int ms_savedx
=0, ms_savedy
=0;
105 static BOOL mouseCaptureMode
, mouseCaptureNew
, mouseToggleReq
;
106 static unsigned long workerThread
= 0;
107 static DWORD workerThreadID
= 0;
108 static int mouse_buttons
= 3;
110 // Graphics screen stuff
111 static unsigned x_tilesize
= 0, y_tilesize
= 0;
112 static BITMAPINFO
* bitmap_info
=(BITMAPINFO
*)0;
113 static RGBQUAD
* cmap_index
; // indeces into system colormap
114 static HBITMAP MemoryBitmap
= NULL
;
115 static HDC MemoryDC
= NULL
;
116 static RECT updated_area
;
117 static BOOL updated_area_valid
= FALSE
;
118 static HWND desktopWindow
;
120 static BOOL queryFullScreen
= FALSE
;
121 static int desktop_x
, desktop_y
;
122 static BOOL toolbarVisible
, statusVisible
;
124 // Text mode screen stuff
125 static unsigned prev_cursor_x
= 0;
126 static unsigned prev_cursor_y
= 0;
127 static HBITMAP vgafont
[256];
128 static int xChar
= 8, yChar
= 16;
129 static unsigned int text_rows
=25, text_cols
=80;
130 static Bit8u text_pal_idx
[16];
131 #if !BX_USE_WINDOWS_FONTS
132 static Bit8u h_panning
= 0, v_panning
= 0;
133 static Bit16u line_compare
= 1023;
135 static HFONT hFont
[3];
136 static int FontId
= 2;
141 unsigned bx_bitmap_entries
;
146 } bx_bitmaps
[BX_MAX_PIXMAPS
];
152 } bx_headerbar_entry
[BX_MAX_HEADERBAR_ENTRIES
];
154 static int bx_headerbar_entries
;
155 static unsigned bx_hb_separator
;
159 static BOOL ipsUpdate
= FALSE
;
160 static char ipsText
[20];
161 #define BX_SB_TEXT_ELEMENTS 2
163 #define BX_SB_TEXT_ELEMENTS 1
165 #define SIZE_OF_SB_ELEMENT 40
166 #define SIZE_OF_SB_MOUSE_MESSAGE 170
167 #define SIZE_OF_SB_IPS_MESSAGE 90
168 long SB_Edges
[BX_MAX_STATUSITEMS
+BX_SB_TEXT_ELEMENTS
+1];
169 char SB_Text
[BX_MAX_STATUSITEMS
][10];
170 bx_bool SB_Active
[BX_MAX_STATUSITEMS
];
171 bx_bool SB_ActiveW
[BX_MAX_STATUSITEMS
];
174 static unsigned dimension_x
, dimension_y
, current_bpp
;
175 static unsigned stretched_x
, stretched_y
;
176 static unsigned stretch_factor
=1;
177 static BOOL BxTextMode
= TRUE
;
178 static BOOL legacyF12
= FALSE
;
179 static BOOL fix_size
= FALSE
;
181 static BOOL windebug
= FALSE
;
183 static HWND hotKeyReceiver
= NULL
;
184 static HWND saveParent
= NULL
;
186 static char *szMouseEnable
= "CTRL + 3rd button enables mouse ";
187 static char *szMouseDisable
= "CTRL + 3rd button disables mouse";
188 static char *szMouseTooltip
= "Enable mouse capture\nUse CTRL + 3rd button to release";
190 static char szAppName
[] = "Bochs for Windows";
191 static char szWindowName
[] = "Bochs for Windows - Display";
196 CRITICAL_SECTION drawCS
;
197 CRITICAL_SECTION keyCS
;
198 CRITICAL_SECTION mouseCS
;
200 int kill
; // reason for terminateEmul(int)
206 sharedThreadInfo stInfo
;
208 LRESULT CALLBACK
mainWndProc (HWND
, UINT
, WPARAM
, LPARAM
);
209 LRESULT CALLBACK
simWndProc (HWND
, UINT
, WPARAM
, LPARAM
);
210 VOID CDECL
UIThread(PVOID
);
211 void SetStatusText(int Num
, const char *Text
, bx_bool active
, bx_bool w
=0);
212 void terminateEmul(int);
213 void create_vga_font(void);
214 static unsigned char reverse_bitorder(unsigned char);
215 void DrawBitmap (HDC
, HBITMAP
, int, int, int, int, int, int, DWORD
, unsigned char);
216 void DrawChar (HDC
, unsigned char, int, int, unsigned char cColor
, int, int);
217 void updateUpdated(int,int,int,int);
218 static void headerbar_click(int x
);
219 #if BX_USE_WINDOWS_FONTS
221 void DestroyFont(void);
225 Bit32u win32_to_bx_key
[2][0x100] =
257 BX_KEY_RIGHT_BRACKET
,
320 BX_KEY_LEFT_BACKSLASH
,
348 0, /* Todo: "Katakana" key (ibm 133) for Japanese 106 keyboard */
351 0, /* Todo: "Ro" key (ibm 56) for Japanese 106 keyboard */
357 0, /* Todo: "convert" key (ibm 132) for Japanese 106 keyboard */
359 0, /* Todo: "non-convert" key (ibm 131) for Japanese 106 keyboard */
361 0, /* Todo: "Yen" key (ibm 14) for Japanese 106 keyboard */
365 { /* extended-keys */
488 /* Macro to convert WM_ button state to BX button state */
490 #if defined(__MINGW32__) || defined(_MSC_VER)
491 VOID CALLBACK
MyTimer(HWND
,UINT
,UINT
,DWORD
);
495 static void processMouseXY(int x
, int y
, int z
, int windows_state
, int implied_state_change
)
499 EnterCriticalSection(&stInfo
.mouseCS
);
500 bx_state
=((windows_state
& MK_LBUTTON
) ? 1 : 0) + ((windows_state
& MK_RBUTTON
) ? 2 : 0) +
501 ((windows_state
& MK_MBUTTON
) ? 4 : 0);
502 old_bx_state
=bx_state
^ implied_state_change
;
503 if (old_bx_state
!=mouse_button_state
)
505 /* Make up for missing message */
506 BX_INFO(("&&&missing mouse state change"));
507 EnterCriticalSection(&stInfo
.keyCS
);
509 mouse_button_state
=old_bx_state
;
510 enq_key_event(mouse_button_state
, MOUSE_PRESSED
);
511 LeaveCriticalSection(&stInfo
.keyCS
);
513 ms_ydelta
=ms_savedy
-y
;
514 ms_xdelta
=x
-ms_savedx
;
518 if (bx_state
!=mouse_button_state
)
520 EnterCriticalSection(&stInfo
.keyCS
);
522 mouse_button_state
=bx_state
;
523 enq_key_event(mouse_button_state
, MOUSE_PRESSED
);
524 LeaveCriticalSection(&stInfo
.keyCS
);
526 LeaveCriticalSection(&stInfo
.mouseCS
);
529 static void resetDelta()
531 EnterCriticalSection(&stInfo
.mouseCS
);
534 ms_ydelta
=ms_xdelta
=ms_zdelta
=0;
535 LeaveCriticalSection(&stInfo
.mouseCS
);
538 static void cursorWarped()
540 EnterCriticalSection(&stInfo
.mouseCS
);
541 EnterCriticalSection(&stInfo
.keyCS
);
543 LeaveCriticalSection(&stInfo
.keyCS
);
544 ms_lastx
=stretched_x
/2;
545 ms_lasty
=stretched_y
/2;
548 LeaveCriticalSection(&stInfo
.mouseCS
);
551 // GUI thread must be dead/done in order to call terminateEmul
552 void terminateEmul(int reason
)
554 // We know that Critical Sections were inited when x_tilesize has been set
555 // See bx_win32_gui_c::specific_init
556 if (x_tilesize
!= 0) {
557 DeleteCriticalSection (&stInfo
.drawCS
);
558 DeleteCriticalSection (&stInfo
.keyCS
);
559 DeleteCriticalSection (&stInfo
.mouseCS
);
563 if (MemoryDC
) DeleteDC (MemoryDC
);
564 if (MemoryBitmap
) DeleteObject (MemoryBitmap
);
566 if (bitmap_info
) delete[] (char*)bitmap_info
;
568 for (unsigned b
=0; b
<bx_bitmap_entries
; b
++)
569 if (bx_bitmaps
[b
].bmap
) DeleteObject(bx_bitmaps
[b
].bmap
);
570 for (unsigned c
=0; c
<256; c
++)
571 if (vgafont
[c
]) DeleteObject(vgafont
[c
]);
573 LOG_THIS
setonoff(LOGLEV_PANIC
, ACT_FATAL
);
576 case EXIT_GUI_SHUTDOWN
:
577 BX_PANIC(("Window closed, exiting!"));
579 case EXIT_GMH_FAILURE
:
580 BX_PANIC(("GetModuleHandle failure!"));
582 case EXIT_FONT_BITMAP_ERROR
:
583 BX_PANIC(("Font bitmap creation failure!"));
585 case EXIT_HEADER_BITMAP_ERROR
:
586 BX_PANIC(("Header bitmap creation failure!"));
596 // Called from gui.cc, once upon program startup, to allow for the
597 // specific GUI code (X11, BeOS, ...) to be initialized.
599 // argc, argv: not used right now, but the intention is to pass native GUI
600 // specific options from the command line. (X11 options, BeOS options,...)
602 // tilewidth, tileheight: for optimization, graphics_tile_update() passes
603 // only updated regions of the screen to the gui code to be redrawn.
604 // These define the dimensions of a region (tile).
605 // headerbar_y: A headerbar (toolbar) is display on the top of the
606 // VGA window, showing floppy status, and other information. It
607 // always assumes the width of the current VGA mode width, but
608 // it's height is defined by this parameter.
610 void bx_win32_gui_c::specific_init(int argc
, char **argv
, unsigned
611 tilewidth
, unsigned tileheight
,
612 unsigned headerbar_y
)
618 // prepare for possible fullscreen mode
619 desktopWindow
= GetDesktopWindow();
620 GetWindowRect(desktopWindow
, &desktop
);
621 desktop_x
= desktop
.right
- desktop
.left
;
622 desktop_y
= desktop
.bottom
- desktop
.top
;
623 hotKeyReceiver
= stInfo
.simWnd
;
624 BX_INFO(("Desktop Window dimensions: %d x %d", desktop_x
, desktop_y
));
626 static RGBQUAD black_quad
={ 0, 0, 0, 0};
628 stInfo
.UIinited
= FALSE
;
629 InitializeCriticalSection(&stInfo
.drawCS
);
630 InitializeCriticalSection(&stInfo
.keyCS
);
631 InitializeCriticalSection(&stInfo
.mouseCS
);
633 x_tilesize
= tilewidth
;
634 y_tilesize
= tileheight
;
636 bx_bitmap_entries
= 0;
637 bx_headerbar_entries
= 0;
639 mouseCaptureMode
= FALSE
;
640 mouseCaptureNew
= FALSE
;
641 mouseToggleReq
= FALSE
;
643 mouse_buttons
= GetSystemMetrics(SM_CMOUSEBUTTONS
);
644 BX_INFO(("Number of Mouse Buttons = %d", mouse_buttons
));
645 if (mouse_buttons
== 2) {
646 szMouseEnable
= "CTRL + Lbutton + Rbutton enables mouse ";
647 szMouseDisable
= "CTRL + Lbutton + Rbutton disables mouse";
648 szMouseTooltip
= "Enable mouse capture\nUse CTRL + Lbutton + Rbutton to release";
651 // parse win32 specific options
653 for (i
= 1; i
< argc
; i
++) {
654 BX_INFO(("option %d: %s", i
, argv
[i
]));
655 if (!strcmp(argv
[i
], "legacyF12")) {
658 } else if (!strcmp(argv
[i
], "windebug")) {
660 SIM
->set_debug_gui(1);
663 BX_PANIC(("Unknown win32 option '%s'", argv
[i
]));
669 szMouseEnable
= "Press F12 to enable mouse ";
670 szMouseDisable
= "Press F12 to disable mouse";
671 szMouseTooltip
= "Enable mouse capture\nUse F12 to release";
674 stInfo
.hInstance
= GetModuleHandle(NULL
);
680 stretched_x
= dimension_x
;
681 stretched_y
= dimension_y
;
684 for(unsigned c
=0; c
<256; c
++) vgafont
[c
] = NULL
;
687 bitmap_info
=(BITMAPINFO
*)new char[sizeof(BITMAPINFOHEADER
)+
688 259*sizeof(RGBQUAD
)]; // 256 + 3 entries for 16 bpp mode
689 bitmap_info
->bmiHeader
.biSize
=sizeof(BITMAPINFOHEADER
);
690 bitmap_info
->bmiHeader
.biWidth
=x_tilesize
;
691 // Height is negative for top-down bitmap
692 bitmap_info
->bmiHeader
.biHeight
= -(LONG
)y_tilesize
;
693 bitmap_info
->bmiHeader
.biPlanes
=1;
694 bitmap_info
->bmiHeader
.biBitCount
=8;
695 bitmap_info
->bmiHeader
.biCompression
=BI_RGB
;
696 bitmap_info
->bmiHeader
.biSizeImage
=x_tilesize
*y_tilesize
*4;
697 // I think these next two figures don't matter; saying 45 pixels/centimeter
698 bitmap_info
->bmiHeader
.biXPelsPerMeter
=4500;
699 bitmap_info
->bmiHeader
.biYPelsPerMeter
=4500;
700 bitmap_info
->bmiHeader
.biClrUsed
=256;
701 bitmap_info
->bmiHeader
.biClrImportant
=0;
702 cmap_index
=bitmap_info
->bmiColors
;
703 // start out with all color map indeces pointing to Black
704 cmap_index
[0] = black_quad
;
705 for (i
=1; i
<259; i
++) {
706 cmap_index
[i
] = cmap_index
[0];
709 if (stInfo
.hInstance
)
710 workerThread
= _beginthread (UIThread
, 0, NULL
);
712 terminateEmul(EXIT_GMH_FAILURE
);
714 // Wait for a window before continuing
715 if ((stInfo
.kill
== 0) && (FindWindow(szAppName
, NULL
) == NULL
))
718 // Now set this thread's priority to below normal because this is where
719 // the emulated CPU runs, and it hogs the real CPU
720 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL
);
722 if (SIM
->get_param_bool(BXPN_PRIVATE_COLORMAP
)->get())
723 BX_INFO(("private_colormap option ignored."));
725 // load keymap tables
726 if (SIM
->get_param_bool(BXPN_KBD_USEMAPPING
)->get()) {
727 bx_keymap
.loadKeymap(NULL
); // I have no function to convert X windows symbols
730 win32_init_notify_callback();
731 dialog_caps
= BX_GUI_DLG_ALL
;
734 void resize_main_window()
739 unsigned long mainStyle
;
741 if (IsWindowVisible(hwndTB
)) {
742 toolbarVisible
= TRUE
;
743 GetWindowRect(hwndTB
, &R
);
744 toolbar_y
= R
.bottom
- R
.top
;
747 if (IsWindowVisible(hwndSB
)) {
748 statusVisible
= TRUE
;
749 GetWindowRect(hwndSB
, &R
);
750 statusbar_y
= R
.bottom
- R
.top
;
753 // stretched_x and stretched_y were set in dimension_update()
754 // if we need to do any additional resizing, do it now
755 if ((desktop_y
> 0) && (stretched_y
>= (unsigned)desktop_y
)) {
756 if (!queryFullScreen
) {
758 "Going into fullscreen mode -- Alt-Enter to revert",
761 queryFullScreen
= TRUE
;
763 // hide toolbar and status bars to get some additional space
764 ShowWindow(hwndTB
, SW_HIDE
);
765 ShowWindow(hwndSB
, SW_HIDE
);
767 mainStyle
= GetWindowLong(stInfo
.mainWnd
, GWL_STYLE
);
768 mainStyle
&= ~(WS_CAPTION
| WS_BORDER
);
769 SetWindowLong(stInfo
.mainWnd
, GWL_STYLE
, mainStyle
);
770 // maybe need to adjust stInfo.simWnd here also?
771 if (saveParent
= SetParent(stInfo
.mainWnd
, desktopWindow
)) {
772 BX_DEBUG(("Saved parent window"));
773 SetWindowPos(stInfo
.mainWnd
, HWND_TOPMOST
, desktop
.left
, desktop
.top
,
774 desktop
.right
, desktop
.bottom
, SWP_SHOWWINDOW
);
778 BX_DEBUG(("Restoring parent window"));
779 SetParent(stInfo
.mainWnd
, saveParent
);
782 // put back the title bar, border, etc...
783 mainStyle
= GetWindowLong(stInfo
.mainWnd
, GWL_STYLE
);
784 mainStyle
|= WS_CAPTION
| WS_BORDER
;
785 SetWindowLong(stInfo
.mainWnd
, GWL_STYLE
, mainStyle
);
786 if (toolbarVisible
) ShowWindow(hwndTB
, SW_SHOW
);
787 if (statusVisible
) ShowWindow(hwndSB
, SW_SHOW
);
788 SetRect(&R
, 0, 0, stretched_x
, stretched_y
);
789 DWORD style
= GetWindowLong(stInfo
.simWnd
, GWL_STYLE
);
790 DWORD exstyle
= GetWindowLong(stInfo
.simWnd
, GWL_EXSTYLE
);
791 AdjustWindowRectEx(&R
, style
, FALSE
, exstyle
);
792 style
= GetWindowLong(stInfo
.mainWnd
, GWL_STYLE
);
793 AdjustWindowRect(&R
, style
, FALSE
);
794 SetWindowPos(stInfo
.mainWnd
, HWND_TOP
, 0, 0, R
.right
- R
.left
,
795 R
.bottom
- R
.top
+ toolbar_y
+ statusbar_y
,
796 SWP_NOMOVE
| SWP_NOZORDER
);
801 // This thread controls the GUI window.
802 VOID CDECL
UIThread(PVOID pvoid
)
809 workerThreadID
= GetCurrentThreadId();
811 GetClassInfo(NULL
, WC_DIALOG
, &wndclass
);
812 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
813 wndclass
.lpfnWndProc
= mainWndProc
;
814 wndclass
.cbClsExtra
= 0;
815 wndclass
.cbWndExtra
= 0;
816 wndclass
.hInstance
= stInfo
.hInstance
;
817 wndclass
.hIcon
= LoadIcon (stInfo
.hInstance
, MAKEINTRESOURCE(ICON_BOCHS
));
818 wndclass
.lpszMenuName
= NULL
;
819 wndclass
.lpszClassName
= szAppName
;
821 RegisterClass (&wndclass
);
823 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
824 wndclass
.lpfnWndProc
= simWndProc
;
825 wndclass
.cbClsExtra
= 0;
826 wndclass
.cbWndExtra
= 0;
827 wndclass
.hInstance
= stInfo
.hInstance
;
828 wndclass
.hIcon
= NULL
;
829 wndclass
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
830 wndclass
.hbrBackground
= (HBRUSH
) GetStockObject (BLACK_BRUSH
);
831 wndclass
.lpszMenuName
= NULL
;
832 wndclass
.lpszClassName
= "SIMWINDOW";
834 RegisterClass (&wndclass
);
836 SetRect(&wndRect
, 0, 0, stretched_x
, stretched_y
);
837 DWORD sim_style
= WS_CHILD
;
838 DWORD sim_exstyle
= WS_EX_CLIENTEDGE
;
839 AdjustWindowRectEx(&wndRect
, sim_style
, FALSE
, sim_exstyle
);
840 DWORD main_style
= WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
;
841 AdjustWindowRect(&wndRect
, main_style
, FALSE
);
842 stInfo
.mainWnd
= CreateWindow (szAppName
,
847 wndRect
.right
- wndRect
.left
,
848 wndRect
.bottom
- wndRect
.top
,
854 if (stInfo
.mainWnd
) {
856 InitCommonControls();
857 hwndTB
= CreateWindowEx(0, TOOLBARCLASSNAME
, (LPSTR
) NULL
,
858 WS_CHILD
| TBSTYLE_TOOLTIPS
| TBSTYLE_FLAT
, 0, 0, 0, 0, stInfo
.mainWnd
,
859 (HMENU
) 100, stInfo
.hInstance
, NULL
);
860 SendMessage(hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
861 SendMessage(hwndTB
, TB_SETBITMAPSIZE
, 0, (LPARAM
)MAKELONG(32, 32));
863 hwndSB
= CreateStatusWindow(WS_CHILD
| WS_VISIBLE
, "",
864 stInfo
.mainWnd
, 0x7712);
867 SB_Edges
[0] = SIZE_OF_SB_MOUSE_MESSAGE
+ SIZE_OF_SB_ELEMENT
;
869 SB_Edges
[1] = SB_Edges
[0] + SIZE_OF_SB_IPS_MESSAGE
;
871 for (elements
= BX_SB_TEXT_ELEMENTS
; elements
< (BX_MAX_STATUSITEMS
+BX_SB_TEXT_ELEMENTS
); elements
++)
872 SB_Edges
[elements
] = SB_Edges
[elements
-1] + SIZE_OF_SB_ELEMENT
;
873 SB_Edges
[elements
] = -1;
874 SendMessage(hwndSB
, SB_SETPARTS
, BX_MAX_STATUSITEMS
+BX_SB_TEXT_ELEMENTS
+1, (long)&SB_Edges
);
876 SetStatusText(0, szMouseEnable
, TRUE
);
878 stInfo
.simWnd
= CreateWindowEx(sim_exstyle
,
891 /* needed for the Japanese versions of Windows */
894 hm
= GetModuleHandle("USER32");
896 BOOL (WINAPI
*enableime
)(HWND
, BOOL
);
897 enableime
= (BOOL (WINAPI
*)(HWND
, BOOL
))GetProcAddress(hm
, "WINNLSEnableIME");
899 enableime(stInfo
.simWnd
, FALSE
);
900 BX_INFO(("IME disabled"));
905 ShowWindow(stInfo
.simWnd
, SW_SHOW
);
906 SetFocus(stInfo
.simWnd
);
908 ShowCursor(!mouseCaptureMode
);
910 ClientToScreen(stInfo
.simWnd
, &pt
);
911 SetCursorPos(pt
.x
+ stretched_x
/2, pt
.y
+ stretched_y
/2);
914 hdc
= GetDC(stInfo
.simWnd
);
915 MemoryBitmap
= CreateCompatibleBitmap(hdc
, BX_MAX_XRES
, BX_MAX_YRES
);
916 MemoryDC
= CreateCompatibleDC(hdc
);
917 ReleaseDC(stInfo
.simWnd
, hdc
);
919 if (MemoryBitmap
&& MemoryDC
) {
920 resize_main_window();
921 ShowWindow(stInfo
.mainWnd
, SW_SHOW
);
924 InitDebugDialog(stInfo
.mainWnd
);
927 stInfo
.UIinited
= TRUE
;
929 bx_gui
->clear_screen();
931 while (GetMessage (&msg
, NULL
, 0, 0)) {
932 TranslateMessage (&msg
);
933 DispatchMessage (&msg
);
938 stInfo
.kill
= EXIT_GUI_SHUTDOWN
;
943 void SetStatusText(int Num
, const char *Text
, bx_bool active
, bx_bool w
)
945 char StatText
[MAX_PATH
];
947 if ((Num
< BX_SB_TEXT_ELEMENTS
) || (Num
> (BX_MAX_STATUSITEMS
+BX_SB_TEXT_ELEMENTS
))) {
948 StatText
[0] = ' '; // Add space to text in 1st and last items
949 lstrcpy(StatText
+1, Text
);
950 SendMessage(hwndSB
, SB_SETTEXT
, Num
, (long)StatText
);
952 StatText
[0] = 9; // Center the rest
953 lstrcpy(StatText
+1, Text
);
954 lstrcpy(SB_Text
[Num
-BX_SB_TEXT_ELEMENTS
], StatText
);
955 SB_Active
[Num
-BX_SB_TEXT_ELEMENTS
] = active
;
956 SB_ActiveW
[Num
-BX_SB_TEXT_ELEMENTS
] = w
;
957 SendMessage(hwndSB
, SB_SETTEXT
, Num
| SBT_OWNERDRAW
, (long)SB_Text
[Num
-BX_SB_TEXT_ELEMENTS
]);
959 UpdateWindow(hwndSB
);
962 void bx_win32_gui_c::statusbar_setitem(int element
, bx_bool active
, bx_bool w
)
965 for (int i
= 0; i
< (int)statusitem_count
; i
++) {
966 SetStatusText(i
+BX_SB_TEXT_ELEMENTS
, statusitem_text
[i
], active
, w
);
968 } else if (element
< (int)statusitem_count
) {
969 SetStatusText(element
+BX_SB_TEXT_ELEMENTS
, statusitem_text
[element
], active
, w
);
973 LRESULT CALLBACK
mainWndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
975 DRAWITEMSTRUCT
*lpdis
;
983 SetStatusText(0, szMouseEnable
, TRUE
);
987 if (LOWORD(wParam
) >= 101) {
988 EnterCriticalSection(&stInfo
.keyCS
);
989 enq_key_event(LOWORD(wParam
)-101, HEADERBAR_CLICKED
);
990 LeaveCriticalSection(&stInfo
.keyCS
);
995 SetFocus(stInfo
.simWnd
);
999 SendMessage(stInfo
.simWnd
, WM_CLOSE
, 0, 0);
1003 PostQuitMessage (0);
1009 SendMessage(hwndTB
, TB_AUTOSIZE
, 0, 0);
1010 SendMessage(hwndSB
, WM_SIZE
, 0, 0);
1011 // now fit simWindow to mainWindow
1012 int rect_data
[] = { 1, 0, IsWindowVisible(hwndTB
),
1013 100, IsWindowVisible(hwndSB
), 0x7712, 0, 0 };
1015 GetEffectiveClientRect(hwnd
, &R
, rect_data
);
1016 x
= R
.right
- R
.left
;
1017 y
= R
.bottom
- R
.top
;
1018 MoveWindow(stInfo
.simWnd
, R
.left
, R
.top
, x
, y
, TRUE
);
1019 GetClientRect(stInfo
.simWnd
, &R
);
1020 x
= R
.right
- R
.left
;
1021 y
= R
.bottom
- R
.top
;
1022 if ((x
!= (int)stretched_x
) || (y
!= (int)stretched_y
)) {
1023 BX_ERROR(("Sim client size(%d, %d) != stretched size(%d, %d)!",
1024 x
, y
, stretched_x
, stretched_y
));
1025 if (!saveParent
) fix_size
= TRUE
; // no fixing if fullscreen
1031 lpdis
= (DRAWITEMSTRUCT
*)lParam
;
1032 if (lpdis
->hwndItem
== hwndSB
) {
1033 sbtext
= (char *)lpdis
->itemData
;
1034 if (SB_Active
[lpdis
->itemID
-BX_SB_TEXT_ELEMENTS
]) {
1035 if (SB_ActiveW
[lpdis
->itemID
-BX_SB_TEXT_ELEMENTS
])
1036 SetBkColor(lpdis
->hDC
, 0x000040FF);
1038 SetBkColor(lpdis
->hDC
, 0x0000FF00);
1040 SetBkMode(lpdis
->hDC
, TRANSPARENT
);
1041 SetTextColor(lpdis
->hDC
, 0x00808080);
1043 DrawText(lpdis
->hDC
, sbtext
+1, lstrlen(sbtext
)-1, &lpdis
->rcItem
, DT_SINGLELINE
| DT_CENTER
| DT_VCENTER
);
1049 lpnmh
= (LPNMHDR
)lParam
;
1050 if (lpnmh
->code
== TTN_NEEDTEXT
) {
1051 lpttt
= (LPTOOLTIPTEXT
)lParam
;
1053 hbar_id
= idTT
- 101;
1054 if (SendMessage(hwndTB
, TB_GETSTATE
, idTT
, 0) && bx_headerbar_entry
[hbar_id
].tooltip
!= NULL
) {
1055 lstrcpy(lpttt
->szText
, bx_headerbar_entry
[hbar_id
].tooltip
);
1062 return DefWindowProc(hwnd
, iMsg
, wParam
, lParam
);
1065 void SetMouseCapture()
1069 if (mouseToggleReq
) {
1070 mouseCaptureMode
= mouseCaptureNew
;
1071 mouseToggleReq
= FALSE
;
1073 SIM
->get_param_bool(BXPN_MOUSE_ENABLED
)->set(mouseCaptureMode
);
1075 ShowCursor(!mouseCaptureMode
);
1076 ShowCursor(!mouseCaptureMode
); // somehow one didn't do the trick (win98)
1077 ClientToScreen(stInfo
.simWnd
, &pt
);
1078 SetCursorPos(pt
.x
+ stretched_x
/2, pt
.y
+ stretched_y
/2);
1080 if (mouseCaptureMode
)
1081 SetStatusText(0, szMouseDisable
, TRUE
);
1083 SetStatusText(0, szMouseEnable
, TRUE
);
1086 LRESULT CALLBACK
simWndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
1091 static BOOL mouseModeChange
= FALSE
;
1096 #if BX_USE_WINDOWS_FONTS
1099 SetTimer (hwnd
, 1, 330, NULL
);
1103 if (mouseToggleReq
&& (GetActiveWindow() == stInfo
.mainWnd
)) {
1106 // If mouse escaped, bring it back
1107 if (mouseCaptureMode
)
1111 ClientToScreen(hwnd
, &pt
);
1112 SetCursorPos(pt
.x
+ stretched_x
/2, pt
.y
+ stretched_y
/2);
1116 resize_main_window();
1121 EnterCriticalSection(&stInfo
.drawCS
);
1122 hdc
= BeginPaint (hwnd
, &ps
);
1124 hdcMem
= CreateCompatibleDC (hdc
);
1125 SelectObject (hdcMem
, MemoryBitmap
);
1127 if (stretch_factor
== 1) {
1128 BitBlt(hdc
, ps
.rcPaint
.left
, ps
.rcPaint
.top
,
1129 ps
.rcPaint
.right
- ps
.rcPaint
.left
+ 1,
1130 ps
.rcPaint
.bottom
- ps
.rcPaint
.top
+ 1, hdcMem
,
1131 ps
.rcPaint
.left
, ps
.rcPaint
.top
, SRCCOPY
);
1133 StretchBlt(hdc
, ps
.rcPaint
.left
, ps
.rcPaint
.top
,
1134 ps
.rcPaint
.right
- ps
.rcPaint
.left
+ 1,
1135 ps
.rcPaint
.bottom
- ps
.rcPaint
.top
+ 1, hdcMem
,
1136 ps
.rcPaint
.left
/stretch_factor
, ps
.rcPaint
.top
,
1137 (ps
.rcPaint
.right
- ps
.rcPaint
.left
+1)/stretch_factor
,
1138 (ps
.rcPaint
.bottom
- ps
.rcPaint
.top
+1), SRCCOPY
);
1141 EndPaint (hwnd
, &ps
);
1142 LeaveCriticalSection(&stInfo
.drawCS
);
1146 if (!mouseModeChange
) {
1147 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 0);
1152 if (!mouseModeChange
) {
1153 // WM_MOUSEWHEEL returns x and y relative to the main screen.
1154 // WM_MOUSEMOVE below returns x and y relative to the current view.
1156 pt
.x
= LOWORD(lParam
);
1157 pt
.y
= HIWORD(lParam
);
1158 ScreenToClient(stInfo
.simWnd
, &pt
);
1159 processMouseXY(pt
.x
, pt
.y
, (Bit16s
) HIWORD(wParam
) / 120, LOWORD(wParam
), 0);
1163 case WM_LBUTTONDOWN
:
1164 case WM_LBUTTONDBLCLK
:
1166 if (mouse_buttons
== 2) {
1167 if (wParam
== (MK_CONTROL
| MK_LBUTTON
| MK_RBUTTON
)) {
1168 mouseCaptureMode
= !mouseCaptureMode
;
1170 mouseModeChange
= TRUE
;
1171 } else if (mouseModeChange
&& (iMsg
== WM_LBUTTONUP
)) {
1172 mouseModeChange
= FALSE
;
1174 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 1);
1178 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 1);
1181 case WM_MBUTTONDOWN
:
1182 case WM_MBUTTONDBLCLK
:
1184 if (wParam
== (MK_CONTROL
| MK_MBUTTON
)) {
1185 mouseCaptureMode
= !mouseCaptureMode
;
1187 mouseModeChange
= TRUE
;
1188 } else if (mouseModeChange
&& (iMsg
== WM_MBUTTONUP
)) {
1189 mouseModeChange
= FALSE
;
1191 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 4);
1195 case WM_RBUTTONDOWN
:
1196 case WM_RBUTTONDBLCLK
:
1198 if (mouse_buttons
== 2) {
1199 if (wParam
== (MK_CONTROL
| MK_LBUTTON
| MK_RBUTTON
)) {
1200 mouseCaptureMode
= !mouseCaptureMode
;
1202 mouseModeChange
= TRUE
;
1203 } else if (mouseModeChange
&& (iMsg
== WM_RBUTTONUP
)) {
1204 mouseModeChange
= FALSE
;
1206 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 2);
1210 processMouseXY(LOWORD(lParam
), HIWORD(lParam
), 0, wParam
, 2);
1214 return DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
1217 KillTimer (hwnd
, 1);
1218 stInfo
.UIinited
= FALSE
;
1219 #if BX_USE_WINDOWS_FONTS
1226 if (legacyF12
&& (wParam
== VK_F12
)) {
1227 mouseCaptureMode
= !mouseCaptureMode
;
1231 EnterCriticalSection(&stInfo
.keyCS
);
1232 enq_key_event(HIWORD (lParam
) & 0x01FF, BX_KEY_PRESSED
);
1233 LeaveCriticalSection(&stInfo
.keyCS
);
1238 // check if it's keyup, alt key, non-repeat
1239 // see http://msdn2.microsoft.com/en-us/library/ms646267.aspx
1240 if ((wParam
== VK_RETURN
) &&
1241 ((HIWORD(lParam
) & BX_SYSKEY
) == (KF_ALTDOWN
| KF_UP
))) {
1243 BX_INFO(("entering fullscreen mode"));
1244 theGui
->dimension_update(desktop_x
, desktop_y
,
1247 BX_INFO(("leaving fullscreen mode"));
1248 theGui
->dimension_update(dimension_x
, desktop_y
- 1,
1252 EnterCriticalSection(&stInfo
.keyCS
);
1253 enq_key_event(HIWORD (lParam
) & 0x01FF, BX_KEY_RELEASED
);
1254 LeaveCriticalSection(&stInfo
.keyCS
);
1259 // check if it's keydown, alt key, non-repeat
1260 // see http://msdn2.microsoft.com/en-us/library/ms646267.aspx
1261 if (wParam
== VK_RETURN
) {
1262 if ((HIWORD(lParam
) & BX_SYSKEY
) == KF_ALTDOWN
) {
1264 BX_INFO(("entering fullscreen mode"));
1265 theGui
->dimension_update(desktop_x
, desktop_y
,
1268 BX_INFO(("leaving fullscreen mode"));
1269 theGui
->dimension_update(dimension_x
, desktop_y
- 1,
1276 case WM_SYSDEADCHAR
:
1279 return DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
1283 void enq_key_event(Bit32u key
, Bit32u press_release
)
1285 static BOOL alt_pressed_l
= FALSE
;
1286 static BOOL alt_pressed_r
= FALSE
;
1287 static BOOL ctrl_pressed_l
= FALSE
;
1288 static BOOL ctrl_pressed_r
= FALSE
;
1289 static BOOL shift_pressed_l
= FALSE
;
1290 static BOOL shift_pressed_r
= FALSE
;
1292 // Windows generates multiple keypresses when holding down these keys
1293 if (press_release
== BX_KEY_PRESSED
) {
1298 ctrl_pressed_l
= TRUE
;
1301 if (shift_pressed_l
)
1303 shift_pressed_l
= TRUE
;
1306 if (shift_pressed_r
)
1308 shift_pressed_r
= TRUE
;
1313 alt_pressed_l
= TRUE
;
1318 ctrl_pressed_r
= TRUE
;
1323 // This makes the "AltGr" key on European keyboards work
1324 if (ctrl_pressed_l
) {
1325 enq_key_event(0x1d, BX_KEY_RELEASED
);
1327 alt_pressed_r
= TRUE
;
1333 if (!ctrl_pressed_l
)
1335 ctrl_pressed_l
= FALSE
;
1338 shift_pressed_l
= FALSE
;
1341 shift_pressed_r
= FALSE
;
1344 alt_pressed_l
= FALSE
;
1347 ctrl_pressed_r
= FALSE
;
1350 alt_pressed_r
= FALSE
;
1354 if (((tail
+1) % SCANCODE_BUFSIZE
) == head
) {
1355 BX_ERROR(("enq_scancode: buffer full"));
1358 keyevents
[tail
].key_event
= key
| press_release
;
1359 tail
= (tail
+ 1) % SCANCODE_BUFSIZE
;
1362 void enq_mouse_event(void)
1364 EnterCriticalSection(&stInfo
.mouseCS
);
1365 if (ms_xdelta
|| ms_ydelta
|| ms_zdelta
)
1367 if (((tail
+1) % SCANCODE_BUFSIZE
) == head
) {
1368 BX_ERROR(("enq_scancode: buffer full"));
1371 QueueEvent
& current
=keyevents
[tail
];
1372 current
.key_event
=MOUSE_MOTION
;
1373 current
.mouse_x
=ms_xdelta
;
1374 current
.mouse_y
=ms_ydelta
;
1375 current
.mouse_z
=ms_zdelta
;
1376 current
.mouse_button_state
=mouse_button_state
;
1378 tail
= (tail
+ 1) % SCANCODE_BUFSIZE
;
1380 LeaveCriticalSection(&stInfo
.mouseCS
);
1383 QueueEvent
* deq_key_event(void)
1388 BX_ERROR(("deq_scancode: buffer empty"));
1389 return((QueueEvent
*)0);
1391 key
= &keyevents
[head
];
1392 head
= (head
+ 1) % SCANCODE_BUFSIZE
;
1398 // ::HANDLE_EVENTS()
1400 // Called periodically (vga_update_interval in .bochsrc) so the
1401 // the gui code can poll for keyboard, mouse, and other
1404 void bx_win32_gui_c::handle_events(void)
1409 if (stInfo
.kill
) terminateEmul(stInfo
.kill
);
1411 // Handle mouse moves
1414 // Handle keyboard and mouse clicks
1415 EnterCriticalSection(&stInfo
.keyCS
);
1416 while (head
!= tail
) {
1417 QueueEvent
* queue_event
=deq_key_event();
1420 key
= queue_event
->key_event
;
1421 if (key
==MOUSE_MOTION
)
1423 DEV_mouse_motion_ext(queue_event
->mouse_x
,
1424 queue_event
->mouse_y
, queue_event
->mouse_z
, queue_event
->mouse_button_state
);
1426 // Check for mouse buttons first
1427 else if (key
& MOUSE_PRESSED
) {
1428 DEV_mouse_motion_ext(0, 0, 0, LOWORD(key
));
1430 else if (key
& HEADERBAR_CLICKED
) {
1431 headerbar_click(LOWORD(key
));
1434 key_event
= win32_to_bx_key
[(key
& 0x100) ? 1 : 0][key
& 0xff];
1435 if (key
& BX_KEY_RELEASED
) key_event
|= BX_KEY_RELEASED
;
1436 DEV_kbd_gen_scancode(key_event
);
1441 SetStatusText(1, ipsText
, 1);
1445 LeaveCriticalSection(&stInfo
.keyCS
);
1451 // Called periodically, requesting that the gui code flush all pending
1452 // screen update requests.
1454 void bx_win32_gui_c::flush(void)
1456 EnterCriticalSection(&stInfo
.drawCS
);
1457 if (updated_area_valid
) {
1459 updated_area
.right
++;
1460 updated_area
.bottom
++;
1461 InvalidateRect(stInfo
.simWnd
, &updated_area
, FALSE
);
1462 updated_area_valid
= FALSE
;
1464 LeaveCriticalSection(&stInfo
.drawCS
);
1469 // Called to request that the VGA region is cleared. Don't
1470 // clear the area that defines the headerbar.
1472 void bx_win32_gui_c::clear_screen(void)
1476 if (!stInfo
.UIinited
) return;
1478 EnterCriticalSection(&stInfo
.drawCS
);
1480 oldObj
= SelectObject(MemoryDC
, MemoryBitmap
);
1481 PatBlt(MemoryDC
, 0, 0, stretched_x
, stretched_y
, BLACKNESS
);
1482 SelectObject(MemoryDC
, oldObj
);
1484 updateUpdated(0, 0, dimension_x
-1, dimension_y
-1);
1486 LeaveCriticalSection(&stInfo
.drawCS
);
1492 // Called in a VGA text mode, to update the screen with
1495 // old_text: array of character/attributes making up the contents
1496 // of the screen from the last call. See below
1497 // new_text: array of character/attributes making up the current
1498 // contents, which should now be displayed. See below
1500 // format of old_text & new_text: each is tm_info.line_offset*text_rows
1501 // bytes long. Each character consists of 2 bytes. The first by is
1502 // the character value, the second is the attribute byte.
1504 // cursor_x: new x location of cursor
1505 // cursor_y: new y location of cursor
1506 // tm_info: this structure contains information for additional
1507 // features in text mode (cursor shape, line offset,...)
1509 void bx_win32_gui_c::text_update(Bit8u
*old_text
, Bit8u
*new_text
,
1510 unsigned long cursor_x
, unsigned long cursor_y
,
1511 bx_vga_tminfo_t tm_info
)
1514 unsigned char data
[64];
1515 Bit8u
*old_line
, *new_line
;
1517 unsigned int curs
, hchars
, i
, offset
, rows
, x
, y
, xc
, yc
;
1518 BOOL forceUpdate
= FALSE
, blink_state
, blink_mode
;
1519 #if !BX_USE_WINDOWS_FONTS
1521 Bit8u cfwidth
, cfheight
, cfheight2
, font_col
, font_row
, font_row2
;
1522 Bit8u split_textrow
, split_fontrows
;
1523 unsigned int yc2
, cs_y
;
1527 if (!stInfo
.UIinited
) return;
1529 EnterCriticalSection(&stInfo
.drawCS
);
1531 blink_mode
= (tm_info
.blink_flags
& BX_TEXT_BLINK_MODE
) > 0;
1532 blink_state
= (tm_info
.blink_flags
& BX_TEXT_BLINK_STATE
) > 0;
1534 if (tm_info
.blink_flags
& BX_TEXT_BLINK_TOGGLE
)
1537 if (charmap_updated
) {
1538 for (unsigned c
= 0; c
<256; c
++) {
1539 if (char_changed
[c
]) {
1540 memset(data
, 0, sizeof(data
));
1541 BOOL gfxchar
= tm_info
.line_graphics
&& ((c
& 0xE0) == 0xC0);
1542 for (i
=0; i
<(unsigned)yChar
; i
++) {
1543 data
[i
*2] = vga_charmap
[c
*32+i
];
1545 data
[i
*2+1] = (data
[i
*2] << 7);
1548 SetBitmapBits(vgafont
[c
], 64, data
);
1549 char_changed
[c
] = 0;
1553 charmap_updated
= 0;
1555 for (i
=0; i
<16; i
++) {
1556 text_pal_idx
[i
] = DEV_vga_get_actl_pal_idx(i
);
1559 hdc
= GetDC(stInfo
.simWnd
);
1561 #if !BX_USE_WINDOWS_FONTS
1562 if((tm_info
.h_panning
!= h_panning
) || (tm_info
.v_panning
!= v_panning
)) {
1564 h_panning
= tm_info
.h_panning
;
1565 v_panning
= tm_info
.v_panning
;
1567 if(tm_info
.line_compare
!= line_compare
) {
1569 line_compare
= tm_info
.line_compare
;
1573 // first invalidate character at previous and new cursor location
1574 if((prev_cursor_y
< text_rows
) && (prev_cursor_x
< text_cols
)) {
1575 curs
= prev_cursor_y
* tm_info
.line_offset
+ prev_cursor_x
* 2;
1576 old_text
[curs
] = ~new_text
[curs
];
1578 if((tm_info
.cs_start
<= tm_info
.cs_end
) && (tm_info
.cs_start
< yChar
) &&
1579 (cursor_y
< text_rows
) && (cursor_x
< text_cols
)) {
1580 curs
= cursor_y
* tm_info
.line_offset
+ cursor_x
* 2;
1581 old_text
[curs
] = ~new_text
[curs
];
1586 #if !BX_USE_WINDOWS_FONTS
1588 if (v_panning
) rows
++;
1591 text_base
= new_text
- tm_info
.start_address
;
1592 split_textrow
= (line_compare
+ v_panning
) / yChar
;
1593 split_fontrows
= ((line_compare
+ v_panning
) % yChar
) + 1;
1597 if (h_panning
) hchars
++;
1599 yc
= line_compare
+ cs_y
* yChar
+ 1;
1602 cfheight
= (dimension_y
- line_compare
- 1) % yChar
;
1603 if (cfheight
== 0) cfheight
= yChar
;
1607 } else if (v_panning
) {
1610 font_row
= v_panning
;
1611 cfheight
= yChar
- v_panning
;
1613 yc
= y
* yChar
- v_panning
;
1616 cfheight
= v_panning
;
1626 if (!split_screen
&& (y
== split_textrow
)) {
1627 if (split_fontrows
< cfheight
) cfheight
= split_fontrows
;
1629 new_line
= new_text
;
1630 old_line
= old_text
;
1632 offset
= cs_y
* tm_info
.line_offset
;
1635 if (hchars
> text_cols
) {
1637 font_col
= h_panning
;
1638 cfwidth
= xChar
- h_panning
;
1640 xc
= x
* xChar
- h_panning
;
1643 cfwidth
= h_panning
;
1653 if (forceUpdate
|| (old_text
[0] != new_text
[0])
1654 || (old_text
[1] != new_text
[1])) {
1655 cChar
= new_text
[0];
1657 cAttr
= new_text
[1] & 0x7F;
1658 if (!blink_state
&& (new_text
[1] & 0x80))
1659 cAttr
= (cAttr
& 0x70) | (cAttr
>> 4);
1661 cAttr
= new_text
[1];
1663 DrawBitmap(hdc
, vgafont
[cChar
], xc
, yc
, cfwidth
, cfheight
, font_col
,
1664 font_row
, SRCCOPY
, cAttr
);
1665 if (offset
== curs
) {
1666 if (font_row
== 0) {
1667 yc2
= yc
+ tm_info
.cs_start
;
1668 font_row2
= tm_info
.cs_start
;
1669 cfheight2
= tm_info
.cs_end
- tm_info
.cs_start
+ 1;
1671 if (v_panning
> tm_info
.cs_start
) {
1673 font_row2
= font_row
;
1674 cfheight2
= tm_info
.cs_end
- v_panning
+ 1;
1676 yc2
= yc
+ tm_info
.cs_start
- v_panning
;
1677 font_row2
= tm_info
.cs_start
;
1678 cfheight2
= tm_info
.cs_end
- tm_info
.cs_start
+ 1;
1681 cAttr
= ((cAttr
>> 4) & 0xF) + ((cAttr
& 0xF) << 4);
1682 DrawBitmap(hdc
, vgafont
[cChar
], xc
, yc2
, cfwidth
, cfheight2
, font_col
,
1683 font_row2
, SRCCOPY
, cAttr
);
1691 if (!split_screen
&& (y
== split_textrow
)) {
1692 new_text
= text_base
;
1695 if (tm_info
.split_hpanning
) h_panning
= 0;
1696 rows
= ((dimension_y
- line_compare
+ yChar
- 2) / yChar
) + 1;
1701 new_text
= new_line
+ tm_info
.line_offset
;
1702 old_text
= old_line
+ tm_info
.line_offset
;
1706 h_panning
= tm_info
.h_panning
;
1713 new_line
= new_text
;
1714 old_line
= old_text
;
1716 offset
= y
* tm_info
.line_offset
;
1719 if (forceUpdate
|| (old_text
[0] != new_text
[0])
1720 || (old_text
[1] != new_text
[1])) {
1721 cChar
= new_text
[0];
1723 cAttr
= new_text
[1] & 0x7F;
1724 if (!blink_state
&& (new_text
[1] & 0x80))
1725 cAttr
= (cAttr
& 0x70) | (cAttr
>> 4);
1727 cAttr
= new_text
[1];
1729 DrawChar(hdc
, cChar
, xc
, yc
, cAttr
, 1, 0);
1730 if (offset
== curs
) {
1731 DrawChar(hdc
, cChar
, xc
, yc
, cAttr
, tm_info
.cs_start
, tm_info
.cs_end
);
1740 new_text
= new_line
+ tm_info
.line_offset
;
1741 old_text
= old_line
+ tm_info
.line_offset
;
1745 prev_cursor_x
= cursor_x
;
1746 prev_cursor_y
= cursor_y
;
1748 ReleaseDC(stInfo
.simWnd
, hdc
);
1750 LeaveCriticalSection(&stInfo
.drawCS
);
1753 int bx_win32_gui_c::get_clipboard_text(Bit8u
**bytes
, Bit32s
*nbytes
)
1755 if (OpenClipboard(stInfo
.simWnd
)) {
1756 HGLOBAL hg
= GetClipboardData(CF_TEXT
);
1757 char *data
= (char *)GlobalLock(hg
);
1758 *nbytes
= strlen(data
);
1759 *bytes
= new Bit8u
[1 + *nbytes
];
1760 BX_INFO (("found %d bytes on the clipboard", *nbytes
));
1761 memcpy (*bytes
, data
, *nbytes
+1);
1762 BX_INFO (("first byte is 0x%02x", *bytes
[0]));
1766 // *bytes will be freed in bx_keyb_c::paste_bytes or
1767 // bx_keyb_c::service_paste_buf, using delete [].
1769 BX_ERROR (("paste: could not open clipboard"));
1774 int bx_win32_gui_c::set_clipboard_text(char *text_snapshot
, Bit32u len
)
1776 if (OpenClipboard(stInfo
.simWnd
)) {
1777 HANDLE hMem
= GlobalAlloc(GMEM_ZEROINIT
, len
);
1779 lstrcpy((char *)hMem
, text_snapshot
);
1780 SetClipboardData(CF_TEXT
, hMem
);
1785 BX_ERROR (("copy: could not open clipboard"));
1791 // ::PALETTE_CHANGE()
1793 // Allocate a color in the native GUI, for this color, and put
1794 // it in the colormap location 'index'.
1795 // returns: 0=no screen update needed (color map change has direct effect)
1796 // 1=screen updated needed (redraw using current colormap)
1798 bx_bool
bx_win32_gui_c::palette_change(unsigned index
, unsigned red
,
1799 unsigned green
, unsigned blue
) {
1800 if ((current_bpp
== 16) && (index
< 3)) {
1801 cmap_index
[256+index
].rgbRed
= red
;
1802 cmap_index
[256+index
].rgbBlue
= blue
;
1803 cmap_index
[256+index
].rgbGreen
= green
;
1806 cmap_index
[index
].rgbRed
= red
;
1807 cmap_index
[index
].rgbBlue
= blue
;
1808 cmap_index
[index
].rgbGreen
= green
;
1814 // ::GRAPHICS_TILE_UPDATE()
1816 // Called to request that a tile of graphics be drawn to the
1817 // screen, since info in this region has changed.
1819 // tile: array of 8bit values representing a block of pixels with
1820 // dimension equal to the 'tilewidth' & 'tileheight' parameters to
1821 // ::specific_init(). Each value specifies an index into the
1822 // array of colors you allocated for ::palette_change()
1823 // x0: x origin of tile
1824 // y0: y origin of tile
1826 // note: origin of tile and of window based on (0,0) being in the upper
1827 // left of the window.
1829 void bx_win32_gui_c::graphics_tile_update(Bit8u
*tile
, unsigned x0
, unsigned y0
)
1834 EnterCriticalSection(&stInfo
.drawCS
);
1835 hdc
= GetDC(stInfo
.simWnd
);
1837 oldObj
= SelectObject(MemoryDC
, MemoryBitmap
);
1839 StretchDIBits(MemoryDC
, x0
, y0
, x_tilesize
, y_tilesize
, 0, 0,
1840 x_tilesize
, y_tilesize
, tile
, bitmap_info
, DIB_RGB_COLORS
, SRCCOPY
);
1842 SelectObject(MemoryDC
, oldObj
);
1844 updateUpdated(x0
, y0
, x0
+ x_tilesize
- 1, y0
+ y_tilesize
- 1);
1846 ReleaseDC(stInfo
.simWnd
, hdc
);
1847 LeaveCriticalSection(&stInfo
.drawCS
);
1852 // ::DIMENSION_UPDATE()
1854 // Called when the VGA mode changes it's X,Y dimensions.
1855 // Resize the window to this size, but you need to add on
1856 // the height of the headerbar to the Y value.
1858 // x: new VGA x size
1859 // y: new VGA y size (add headerbar_y parameter from ::specific_init().
1860 // fheight: new VGA character height in text mode
1861 // fwidth : new VGA character width in text mode
1862 // bpp : bits per pixel in graphics mode
1864 void bx_win32_gui_c::dimension_update(unsigned x
, unsigned y
, unsigned fheight
, unsigned fwidth
, unsigned bpp
)
1866 BxTextMode
= (fheight
> 0);
1868 text_cols
= x
/ fwidth
;
1869 text_rows
= y
/ fheight
;
1870 #if BX_USE_WINDOWS_FONTS
1871 if (fheight
>= 14) {
1875 } else if (fheight
>= 12) {
1884 if (fwidth
!= xChar
) {
1887 if (fheight
!= yChar
) {
1888 y
= y
* yChar
/ fheight
;
1896 if (x
==dimension_x
&& y
==dimension_y
&& bpp
==current_bpp
)
1900 stretched_x
= dimension_x
;
1901 stretched_y
= dimension_y
;
1903 if (BxTextMode
&& (stretched_x
<400)) {
1905 stretch_factor
*= 2;
1908 bitmap_info
->bmiHeader
.biBitCount
= bpp
;
1911 bitmap_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1912 static RGBQUAD red_mask
= {0x00, 0xF8, 0x00, 0x00};
1913 static RGBQUAD green_mask
= {0xE0, 0x07, 0x00, 0x00};
1914 static RGBQUAD blue_mask
= {0x1F, 0x00, 0x00, 0x00};
1915 bitmap_info
->bmiColors
[256] = bitmap_info
->bmiColors
[0];
1916 bitmap_info
->bmiColors
[257] = bitmap_info
->bmiColors
[1];
1917 bitmap_info
->bmiColors
[258] = bitmap_info
->bmiColors
[2];
1918 bitmap_info
->bmiColors
[0] = red_mask
;
1919 bitmap_info
->bmiColors
[1] = green_mask
;
1920 bitmap_info
->bmiColors
[2] = blue_mask
;
1924 if (current_bpp
== 16)
1926 bitmap_info
->bmiColors
[0] = bitmap_info
->bmiColors
[256];
1927 bitmap_info
->bmiColors
[1] = bitmap_info
->bmiColors
[257];
1928 bitmap_info
->bmiColors
[2] = bitmap_info
->bmiColors
[258];
1930 bitmap_info
->bmiHeader
.biCompression
= BI_RGB
;
1933 bitmap_info
->bmiHeader
.biBitCount
= 16;
1938 resize_main_window();
1940 BX_INFO(("dimension update x=%d y=%d fontheight=%d fontwidth=%d bpp=%d", x
, y
, fheight
, fwidth
, bpp
));
1948 // ::CREATE_BITMAP()
1950 // Create a monochrome bitmap of size 'xdim' by 'ydim', which will
1951 // be drawn in the headerbar. Return an integer ID to the bitmap,
1952 // with which the bitmap can be referenced later.
1954 // bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
1955 // bit0 is the left most pixel, bit7 is the right most pixel.
1956 // xdim: x dimension of bitmap
1957 // ydim: y dimension of bitmap
1959 unsigned bx_win32_gui_c::create_bitmap(const unsigned char *bmap
, unsigned xdim
,
1962 unsigned char *data
;
1965 if (bx_bitmap_entries
>= BX_MAX_PIXMAPS
)
1966 terminateEmul(EXIT_HEADER_BITMAP_ERROR
);
1968 bx_bitmaps
[bx_bitmap_entries
].bmap
= CreateBitmap(xdim
,ydim
,1,1,NULL
);
1969 if (!bx_bitmaps
[bx_bitmap_entries
].bmap
)
1970 terminateEmul(EXIT_HEADER_BITMAP_ERROR
);
1972 data
= new unsigned char[ydim
* xdim
/8];
1973 for (unsigned i
=0; i
<ydim
* xdim
/8; i
++)
1974 data
[i
] = 255 - reverse_bitorder(bmap
[i
]);
1975 SetBitmapBits(bx_bitmaps
[bx_bitmap_entries
].bmap
, ydim
* xdim
/8, data
);
1979 bx_bitmaps
[bx_bitmap_entries
].xdim
= xdim
;
1980 bx_bitmaps
[bx_bitmap_entries
].ydim
= ydim
;
1983 tbab
.nID
= (UINT
)bx_bitmaps
[bx_bitmap_entries
].bmap
;
1984 SendMessage(hwndTB
, TB_ADDBITMAP
, 1, (LPARAM
)&tbab
);
1986 bx_bitmap_entries
++;
1987 return(bx_bitmap_entries
-1); // return index as handle
1991 // ::HEADERBAR_BITMAP()
1993 // Called to install a bitmap in the bochs headerbar (toolbar).
1995 // bmap_id: will correspond to an ID returned from
1996 // ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
1997 // or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
1998 // available leftmost or rightmost space.
1999 // alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
2000 // meaning install the bitmap in the next
2001 // available leftmost or rightmost space.
2002 // f: a 'C' function pointer to callback when the mouse is clicked in
2003 // the boundaries of this bitmap.
2005 unsigned bx_win32_gui_c::headerbar_bitmap(unsigned bmap_id
, unsigned alignment
,
2011 if ((bx_headerbar_entries
+1) > BX_MAX_HEADERBAR_ENTRIES
)
2012 terminateEmul(EXIT_HEADER_BITMAP_ERROR
);
2014 bx_headerbar_entries
++;
2015 hb_index
= bx_headerbar_entries
- 1;
2017 memset(tbb
,0,sizeof(tbb
));
2018 if (bx_hb_separator
==0) {
2020 tbb
[0].idCommand
= 0;
2022 tbb
[0].fsStyle
= TBSTYLE_SEP
;
2023 SendMessage(hwndTB
, TB_ADDBUTTONS
, 1,(LPARAM
)(LPTBBUTTON
)&tbb
);
2025 tbb
[0].iBitmap
= bmap_id
;
2026 tbb
[0].idCommand
= hb_index
+ 101;
2027 tbb
[0].fsState
= TBSTATE_ENABLED
;
2028 tbb
[0].fsStyle
= TBSTYLE_BUTTON
;
2029 if (alignment
== BX_GRAVITY_LEFT
) {
2030 SendMessage(hwndTB
, TB_INSERTBUTTON
, bx_hb_separator
,(LPARAM
)(LPTBBUTTON
)&tbb
);
2032 } else { // BX_GRAVITY_RIGHT
2033 SendMessage(hwndTB
, TB_INSERTBUTTON
, bx_hb_separator
+1, (LPARAM
)(LPTBBUTTON
)&tbb
);
2036 bx_headerbar_entry
[hb_index
].bmap_id
= bmap_id
;
2037 bx_headerbar_entry
[hb_index
].f
= f
;
2038 bx_headerbar_entry
[hb_index
].tooltip
= NULL
;
2044 // ::SHOW_HEADERBAR()
2046 // Show (redraw) the current headerbar, which is composed of
2047 // currently installed bitmaps.
2049 void bx_win32_gui_c::show_headerbar(void)
2051 if (!IsWindowVisible(hwndTB
)) {
2052 SendMessage(hwndTB
, TB_AUTOSIZE
, 0, 0);
2053 ShowWindow(hwndTB
, SW_SHOW
);
2054 resize_main_window();
2055 bx_gui
->set_tooltip(bx_gui
->get_mouse_headerbar_id(), szMouseTooltip
);
2060 // ::REPLACE_BITMAP()
2062 // Replace the bitmap installed in the headerbar ID slot 'hbar_id',
2063 // with the one specified by 'bmap_id'. 'bmap_id' will have
2064 // been generated by ::create_bitmap(). The old and new bitmap
2065 // must be of the same size. This allows the bitmap the user
2066 // sees to change, when some action occurs. For example when
2067 // the user presses on the floppy icon, it then displays
2068 // the ejected status.
2070 // hbar_id: headerbar slot ID
2071 // bmap_id: bitmap ID
2073 void bx_win32_gui_c::replace_bitmap(unsigned hbar_id
, unsigned bmap_id
)
2075 if (bmap_id
!= bx_headerbar_entry
[hbar_id
].bmap_id
) {
2076 bx_headerbar_entry
[hbar_id
].bmap_id
= bmap_id
;
2077 bx_bool is_visible
= IsWindowVisible(hwndTB
);
2079 ShowWindow(hwndTB
, SW_HIDE
);
2081 SendMessage(hwndTB
, TB_CHANGEBITMAP
, (WPARAM
)hbar_id
+101, (LPARAM
)
2082 MAKELPARAM(bmap_id
, 0));
2083 SendMessage(hwndTB
, TB_AUTOSIZE
, 0, 0);
2085 ShowWindow(hwndTB
, SW_SHOW
);
2093 // Called before bochs terminates, to allow for a graceful
2094 // exit from the native GUI mechanism.
2095 void bx_win32_gui_c::exit(void)
2097 printf("# In bx_win32_gui_c::exit(void)!\n");
2099 // kill thread first...
2100 PostMessage(stInfo
.mainWnd
, WM_CLOSE
, 0, 0);
2102 // Wait until it dies
2103 while ((stInfo
.kill
== 0) && (workerThreadID
!= 0)) Sleep(500);
2105 if (!stInfo
.kill
) terminateEmul(EXIT_NORMAL
);
2109 void create_vga_font(void)
2111 unsigned char data
[64];
2113 // VGA font is 8 or 9 wide and up to 32 high
2114 for (unsigned c
= 0; c
<256; c
++) {
2115 vgafont
[c
] = CreateBitmap(9,32,1,1,NULL
);
2116 if (!vgafont
[c
]) terminateEmul(EXIT_FONT_BITMAP_ERROR
);
2117 memset(data
, 0, sizeof(data
));
2118 for (unsigned i
=0; i
<16; i
++)
2119 data
[i
*2] = reverse_bitorder(bx_vgafont
[c
].data
[i
]);
2120 SetBitmapBits(vgafont
[c
], 64, data
);
2125 unsigned char reverse_bitorder(unsigned char b
)
2127 unsigned char ret
=0;
2129 for (unsigned i
=0; i
<8; i
++) {
2130 ret
|= (b
& 0x01) << (7-i
);
2138 COLORREF
GetColorRef(unsigned char attr
)
2140 Bit8u pal_idx
= text_pal_idx
[attr
];
2141 return RGB(cmap_index
[pal_idx
].rgbRed
, cmap_index
[pal_idx
].rgbGreen
,
2142 cmap_index
[pal_idx
].rgbBlue
);
2146 void DrawBitmap(HDC hdc
, HBITMAP hBitmap
, int xStart
, int yStart
, int width
,
2147 int height
, int fcol
, int frow
, DWORD dwRop
, unsigned char cColor
)
2151 POINT ptSize
, ptOrg
;
2154 hdcMem
= CreateCompatibleDC (hdc
);
2155 SelectObject (hdcMem
, hBitmap
);
2156 SetMapMode (hdcMem
, GetMapMode (hdc
));
2158 GetObject (hBitmap
, sizeof (BITMAP
), (LPVOID
) &bm
);
2163 DPtoLP (hdc
, &ptSize
, 1);
2167 DPtoLP (hdcMem
, &ptOrg
, 1);
2169 oldObj
= SelectObject(MemoryDC
, MemoryBitmap
);
2171 COLORREF crFore
= SetTextColor(MemoryDC
, GetColorRef((cColor
>>4)&0xf));
2172 COLORREF crBack
= SetBkColor(MemoryDC
, GetColorRef(cColor
&0xf));
2173 BitBlt(MemoryDC
, xStart
, yStart
, ptSize
.x
, ptSize
.y
, hdcMem
, ptOrg
.x
,
2175 SetBkColor(MemoryDC
, crBack
);
2176 SetTextColor(MemoryDC
, crFore
);
2178 SelectObject(MemoryDC
, oldObj
);
2180 updateUpdated(xStart
, yStart
, ptSize
.x
+ xStart
- 1, ptSize
.y
+ yStart
- 1);
2186 void updateUpdated(int x1
, int y1
, int x2
, int y2
)
2190 if (!updated_area_valid
) {
2191 updated_area
.left
= x1
;
2192 updated_area
.top
= y1
;
2193 updated_area
.right
= x2
;
2194 updated_area
.bottom
= y2
;
2196 if (x1
< updated_area
.left
) updated_area
.left
= x1
;
2197 if (y1
< updated_area
.top
) updated_area
.top
= y1
;
2198 if (x2
> updated_area
.right
) updated_area
.right
= x2
;
2199 if (y2
> updated_area
.bottom
) updated_area
.bottom
= y2
;
2202 updated_area_valid
= TRUE
;
2206 void headerbar_click(int x
)
2208 if (x
< bx_headerbar_entries
) {
2209 bx_headerbar_entry
[x
].f();
2213 #if defined(__MINGW32__) || defined(_MSC_VER)
2215 VOID CALLBACK
MyTimer(HWND hwnd
,UINT uMsg
, UINT idEvent
, DWORD dwTime
)
2217 bx_signal_handler(SIGALRM
);
2220 void alarm(int time
)
2223 SetTimer(stInfo
.simWnd
,idTimer
,time
*1000,MyTimer
);
2228 void bx_win32_gui_c::mouse_enabled_changed_specific(bx_bool val
)
2230 if ((val
!= (bx_bool
)mouseCaptureMode
) && !mouseToggleReq
) {
2231 mouseToggleReq
= TRUE
;
2232 mouseCaptureNew
= val
;
2236 void bx_win32_gui_c::get_capabilities(Bit16u
*xres
, Bit16u
*yres
, Bit16u
*bpp
)
2238 if (desktop_y
> 0) {
2249 void bx_win32_gui_c::set_tooltip(unsigned hbar_id
, const char *tip
)
2251 bx_headerbar_entry
[hbar_id
].tooltip
= tip
;
2255 void bx_win32_gui_c::show_ips(Bit32u ips_count
)
2258 sprintf(ipsText
, "IPS: %9u", ips_count
);
2264 #if BX_USE_WINDOWS_FONTS
2266 void DrawChar (HDC hdc
, unsigned char c
, int xStart
, int yStart
,
2267 unsigned char cColor
, int cs_start
, int cs_end
)
2270 POINT ptSize
, ptOrg
;
2275 hdcMem
= CreateCompatibleDC (hdc
);
2276 SetMapMode (hdcMem
, GetMapMode (hdc
));
2280 DPtoLP (hdc
, &ptSize
, 1);
2285 DPtoLP (hdcMem
, &ptOrg
, 1);
2287 oldObj
= SelectObject(MemoryDC
, MemoryBitmap
);
2288 hFontOld
=(HFONT
)SelectObject(MemoryDC
, hFont
[FontId
]);
2290 COLORREF crFore
= SetTextColor(MemoryDC
, GetColorRef(cColor
&0xf));
2291 COLORREF crBack
= SetBkColor(MemoryDC
, GetColorRef((cColor
>>4)&0xf));
2295 int y
= FontId
== 2 ? 16 : 8;
2297 TextOut(MemoryDC
, xStart
, yStart
, str
, 1);
2298 if (cs_start
<= cs_end
&& cs_start
< y
)
2301 SetBkColor(MemoryDC
, GetColorRef(cColor
&0xf));
2302 SetTextColor(MemoryDC
, GetColorRef((cColor
>>4)&0xf));
2304 rc
.right
= xStart
+xChar
;
2307 rc
.top
= yStart
+cs_start
*yChar
/y
;
2308 rc
.bottom
= yStart
+(cs_end
+1)*yChar
/y
;
2309 ExtTextOut(MemoryDC
, xStart
, yStart
, ETO_CLIPPED
|ETO_OPAQUE
, &rc
, str
, 1, NULL
);
2312 SetBkColor(MemoryDC
, crBack
);
2313 SetTextColor(MemoryDC
, crFore
);
2315 SelectObject(MemoryDC
, hFontOld
);
2316 SelectObject(MemoryDC
, oldObj
);
2318 updateUpdated(xStart
, yStart
, ptSize
.x
+ xStart
- 1, ptSize
.y
+ yStart
- 1);
2328 lf
.lfEscapement
= 0;
2329 lf
.lfOrientation
= 0;
2330 lf
.lfWeight
= FW_MEDIUM
;
2331 lf
.lfItalic
= FALSE
;
2332 lf
.lfUnderline
=FALSE
;
2333 lf
.lfStrikeOut
=FALSE
;
2334 lf
.lfCharSet
=OEM_CHARSET
;
2335 lf
.lfOutPrecision
=OUT_DEFAULT_PRECIS
;
2336 lf
.lfClipPrecision
=CLIP_DEFAULT_PRECIS
;
2337 lf
.lfQuality
=DEFAULT_QUALITY
;
2338 lf
.lfPitchAndFamily
=FIXED_PITCH
| FF_DONTCARE
;
2339 wsprintf(lf
.lfFaceName
, "Lucida Console");
2341 for (int i
=0; i
< 3; i
++)
2343 lf
.lfHeight
= 12 + i
* 2;
2344 hFont
[i
]=CreateFontIndirect(&lf
);
2348 void DestroyFont(void)
2350 for(int i
= 0; i
< 3; i
++)
2352 DeleteObject(hFont
[i
]);
2356 #endif /* if BX_USE_WINDOWS_FONTS */
2358 #endif /* if BX_WITH_WIN32 */