2 * Copyright 2001 Eric Pouech
3 * Copyright 2020 Jacek Caban for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define NONAMELESSUNION
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(console
);
32 #define WM_UPDATE_CONFIG (WM_USER + 1)
43 HDC mem_dc
; /* memory DC holding the bitmap below */
44 HBITMAP bitmap
; /* bitmap of display window content */
45 HFONT font
; /* font used for rendering, usually fixed */
46 HMENU popup_menu
; /* popup menu triggered by right mouse click */
47 HBITMAP cursor_bitmap
; /* bitmap used for the caret */
48 BOOL in_selection
; /* an area is being selected */
49 COORD selection_start
; /* selection coordinates */
51 unsigned int ui_charset
; /* default UI charset */
52 WCHAR
*config_key
; /* config registry key name */
53 LONG ext_leading
; /* external leading for font */
55 BOOL quick_edit
; /* whether mouse ops are sent to app or used for content selection */
56 unsigned int menu_mask
; /* MK_CONTROL MK_SHIFT mask to drive submenu opening */
57 COORD win_pos
; /* position (in cells) of visible part of screen buffer in window */
58 unsigned int win_width
; /* size (in cells) of visible part of window (width & height) */
59 unsigned int win_height
;
60 unsigned int cursor_size
; /* in % of cell height */
61 int cursor_visible
; /* cursor visibility */
62 unsigned int sb_width
; /* active screen buffer width */
63 unsigned int sb_height
; /* active screen buffer height */
64 COORD cursor_pos
; /* cursor position */
66 RECT update
; /* screen buffer update rect */
67 enum update_state update_state
; /* update state */
72 DWORD color_map
[16]; /* console color table */
73 unsigned int cell_width
; /* width in pixels of a character */
74 unsigned int cell_height
; /* height in pixels of a character */
75 unsigned int cursor_size
; /* in % of cell height */
76 int cursor_visible
; /* cursor visibility */
77 unsigned int attr
; /* default fill attributes (screen colors) */
78 unsigned int popup_attr
; /* pop-up color attributes */
79 unsigned int history_size
; /* number of commands in history buffer */
80 unsigned int history_mode
; /* flag if commands are not stored twice in buffer */
81 unsigned int insert_mode
; /* TRUE to insert text at the cursor location; FALSE to overwrite it */
82 unsigned int menu_mask
; /* MK_CONTROL MK_SHIFT mask to drive submenu opening */
83 unsigned int quick_edit
; /* whether mouse ops are sent to app or used for content selection */
84 unsigned int sb_width
; /* active screen buffer width */
85 unsigned int sb_height
; /* active screen buffer height */
86 unsigned int win_width
; /* size (in cells) of visible part of window (width & height) */
87 unsigned int win_height
;
88 COORD win_pos
; /* position (in cells) of visible part of screen buffer in window */
89 unsigned int edition_mode
; /* edition mode flavor while line editing */
90 unsigned int font_pitch_family
;
91 unsigned int font_weight
;
92 WCHAR face_name
[LF_FACESIZE
];
95 static const char *debugstr_config( const struct console_config
*config
)
97 return wine_dbg_sprintf( "cell=(%u,%u) cursor=(%d,%d) attr=%02x pop-up=%02x font=%s/%u/%u "
98 "hist=%u/%d flags=%c%c msk=%08x sb=(%u,%u) win=(%u,%u)x(%u,%u) edit=%u",
99 config
->cell_width
, config
->cell_height
, config
->cursor_size
,
100 config
->cursor_visible
, config
->attr
, config
->popup_attr
,
101 wine_dbgstr_w(config
->face_name
), config
->font_pitch_family
,
102 config
->font_weight
, config
->history_size
,
103 config
->history_mode
? 1 : 2,
104 config
->insert_mode
? 'I' : 'i',
105 config
->quick_edit
? 'Q' : 'q',
106 config
->menu_mask
, config
->sb_width
, config
->sb_height
,
107 config
->win_pos
.X
, config
->win_pos
.Y
, config
->win_width
,
108 config
->win_height
, config
->edition_mode
);
111 static const char *debugstr_logfont( const LOGFONTW
*lf
, unsigned int ft
)
113 return wine_dbg_sprintf( "%s%s%s%s lfHeight=%ld lfWidth=%ld lfEscapement=%ld "
114 "lfOrientation=%ld lfWeight=%ld lfItalic=%u lfUnderline=%u "
115 "lfStrikeOut=%u lfCharSet=%u lfPitchAndFamily=%u lfFaceName=%s",
116 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
117 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
118 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
119 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
120 lf
->lfHeight
, lf
->lfWidth
, lf
->lfEscapement
, lf
->lfOrientation
,
121 lf
->lfWeight
, lf
->lfItalic
, lf
->lfUnderline
, lf
->lfStrikeOut
,
122 lf
->lfCharSet
, lf
->lfPitchAndFamily
, wine_dbgstr_w( lf
->lfFaceName
));
125 static const char *debugstr_textmetric( const TEXTMETRICW
*tm
, unsigned int ft
)
127 return wine_dbg_sprintf( "%s%s%s%s tmHeight=%ld tmAscent=%ld tmDescent=%ld "
128 "tmAveCharWidth=%ld tmMaxCharWidth=%ld tmWeight=%ld "
129 "tmPitchAndFamily=%u tmCharSet=%u",
130 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
131 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
132 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
133 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
134 tm
->tmHeight
, tm
->tmAscent
, tm
->tmDescent
, tm
->tmAveCharWidth
,
135 tm
->tmMaxCharWidth
, tm
->tmWeight
, tm
->tmPitchAndFamily
,
139 /* read the basic configuration from any console key or subkey */
140 static void load_registry_key( HKEY key
, struct console_config
*config
)
142 DWORD type
, count
, val
, i
;
143 WCHAR color_name
[13];
145 for (i
= 0; i
< ARRAY_SIZE(config
->color_map
); i
++)
147 wsprintfW( color_name
, L
"ColorTable%02d", i
);
149 if (!RegQueryValueExW( key
, color_name
, 0, &type
, (BYTE
*)&val
, &count
))
150 config
->color_map
[i
] = val
;
154 if (!RegQueryValueExW( key
, L
"CursorSize", 0, &type
, (BYTE
*)&val
, &count
))
155 config
->cursor_size
= val
;
158 if (!RegQueryValueExW( key
, L
"CursorVisible", 0, &type
, (BYTE
*)&val
, &count
))
159 config
->cursor_visible
= val
;
162 if (!RegQueryValueExW( key
, L
"EditionMode", 0, &type
, (BYTE
*)&val
, &count
))
163 config
->edition_mode
= val
;
165 count
= sizeof(config
->face_name
);
166 RegQueryValueExW( key
, L
"FaceName", 0, &type
, (BYTE
*)&config
->face_name
, &count
);
169 if (!RegQueryValueExW( key
, L
"FontPitchFamily", 0, &type
, (BYTE
*)&val
, &count
))
170 config
->font_pitch_family
= val
;
173 if (!RegQueryValueExW( key
, L
"FontSize", 0, &type
, (BYTE
*)&val
, &count
))
175 int height
= HIWORD(val
);
176 int width
= LOWORD(val
);
177 /* A value of zero reflects the default settings */
178 if (height
) config
->cell_height
= MulDiv( height
, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
179 if (width
) config
->cell_width
= MulDiv( width
, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
183 if (!RegQueryValueExW( key
, L
"FontWeight", 0, &type
, (BYTE
*)&val
, &count
))
184 config
->font_weight
= val
;
187 if (!RegQueryValueExW( key
, L
"HistoryBufferSize", 0, &type
, (BYTE
*)&val
, &count
))
188 config
->history_size
= val
;
191 if (!RegQueryValueExW( key
, L
"HistoryNoDup", 0, &type
, (BYTE
*)&val
, &count
))
192 config
->history_mode
= val
;
195 if (!RegQueryValueExW( key
, L
"wszInsertMode", 0, &type
, (BYTE
*)&val
, &count
))
196 config
->insert_mode
= val
;
199 if (!RegQueryValueExW( key
, L
"MenuMask", 0, &type
, (BYTE
*)&val
, &count
))
200 config
->menu_mask
= val
;
203 if (!RegQueryValueExW( key
, L
"PopupColors", 0, &type
, (BYTE
*)&val
, &count
))
204 config
->popup_attr
= val
;
207 if (!RegQueryValueExW( key
, L
"QuickEdit", 0, &type
, (BYTE
*)&val
, &count
))
208 config
->quick_edit
= val
;
211 if (!RegQueryValueExW( key
, L
"ScreenBufferSize", 0, &type
, (BYTE
*)&val
, &count
))
213 config
->sb_height
= HIWORD(val
);
214 config
->sb_width
= LOWORD(val
);
218 if (!RegQueryValueExW( key
, L
"ScreenColors", 0, &type
, (BYTE
*)&val
, &count
))
222 if (!RegQueryValueExW( key
, L
"WindowSize", 0, &type
, (BYTE
*)&val
, &count
))
224 config
->win_height
= HIWORD(val
);
225 config
->win_width
= LOWORD(val
);
229 /* load config from registry */
230 static void load_config( const WCHAR
*key_name
, struct console_config
*config
)
232 static const COLORREF color_map
[] =
234 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x80), RGB(0x00, 0x80, 0x00), RGB(0x00, 0x80, 0x80),
235 RGB(0x80, 0x00, 0x00), RGB(0x80, 0x00, 0x80), RGB(0x80, 0x80, 0x00), RGB(0xC0, 0xC0, 0xC0),
236 RGB(0x80, 0x80, 0x80), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xFF),
237 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xFF)
242 TRACE( "Loading default console settings\n" );
244 memcpy( config
->color_map
, color_map
, sizeof(color_map
) );
245 memset( config
->face_name
, 0, sizeof(config
->face_name
) );
246 config
->cursor_size
= 25;
247 config
->cursor_visible
= 1;
248 config
->font_pitch_family
= FIXED_PITCH
| FF_DONTCARE
;
249 config
->cell_height
= MulDiv( 16, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
250 config
->cell_width
= MulDiv( 8, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
251 config
->font_weight
= FW_NORMAL
;
253 config
->history_size
= 50;
254 config
->history_mode
= 0;
255 config
->insert_mode
= 1;
256 config
->menu_mask
= 0;
257 config
->popup_attr
= 0xF5;
258 config
->quick_edit
= 0;
259 config
->sb_height
= 150;
260 config
->sb_width
= 80;
261 config
->attr
= 0x000F;
262 config
->win_height
= 25;
263 config
->win_width
= 80;
264 config
->win_pos
.X
= 0;
265 config
->win_pos
.Y
= 0;
266 config
->edition_mode
= 0;
268 /* Load default console settings */
269 if (!RegOpenKeyW( HKEY_CURRENT_USER
, L
"Console", &key
))
271 load_registry_key( key
, config
);
273 /* Load app-specific console settings (if any) */
274 if (key_name
&& !RegOpenKeyW( key
, key_name
, &app_key
))
276 TRACE( "Loading %s console settings\n", wine_dbgstr_w(key_name
) );
277 load_registry_key( app_key
, config
);
278 RegCloseKey( app_key
);
282 TRACE( "%s\n", debugstr_config( config
));
285 static void save_registry_key( HKEY key
, const struct console_config
*config
, BOOL save_all
)
287 struct console_config default_config
;
288 DWORD val
, width
, height
, i
;
289 WCHAR color_name
[13];
291 TRACE( "%s\n", debugstr_config( config
));
294 load_config( NULL
, &default_config
);
296 for (i
= 0; i
< ARRAY_SIZE(config
->color_map
); i
++)
298 if (save_all
|| config
->color_map
[i
] != default_config
.color_map
[i
])
300 wsprintfW( color_name
, L
"ColorTable%02d", i
);
301 val
= config
->color_map
[i
];
302 RegSetValueExW( key
, color_name
, 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
306 if (save_all
|| config
->cursor_size
!= default_config
.cursor_size
)
308 val
= config
->cursor_size
;
309 RegSetValueExW( key
, L
"CursorSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
312 if (save_all
|| config
->cursor_visible
!= default_config
.cursor_visible
)
314 val
= config
->cursor_visible
;
315 RegSetValueExW( key
, L
"CursorVisible", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
318 if (save_all
|| config
->edition_mode
!= default_config
.edition_mode
)
320 val
= config
->edition_mode
;
321 RegSetValueExW( key
, L
"EditionMode", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
324 if (save_all
|| lstrcmpW( config
->face_name
, default_config
.face_name
))
326 RegSetValueExW( key
, L
"FaceName", 0, REG_SZ
, (BYTE
*)&config
->face_name
,
327 (lstrlenW(config
->face_name
) + 1) * sizeof(WCHAR
) );
330 if (save_all
|| config
->font_pitch_family
!= default_config
.font_pitch_family
)
332 val
= config
->font_pitch_family
;
333 RegSetValueExW( key
, L
"FontPitchFamily", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
336 if (save_all
|| config
->cell_height
!= default_config
.cell_height
||
337 config
->cell_width
!= default_config
.cell_width
)
339 width
= MulDiv( config
->cell_width
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
340 height
= MulDiv( config
->cell_height
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
341 val
= MAKELONG( width
, height
);
343 RegSetValueExW( key
, L
"FontSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
346 if (save_all
|| config
->font_weight
!= default_config
.font_weight
)
348 val
= config
->font_weight
;
349 RegSetValueExW( key
, L
"FontWeight", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
352 if (save_all
|| config
->history_size
!= default_config
.history_size
)
354 val
= config
->history_size
;
355 RegSetValueExW( key
, L
"HistoryBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
358 if (save_all
|| config
->history_mode
!= default_config
.history_mode
)
360 val
= config
->history_mode
;
361 RegSetValueExW( key
, L
"HistoryNoDup", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
364 if (save_all
|| config
->insert_mode
!= default_config
.insert_mode
)
366 val
= config
->insert_mode
;
367 RegSetValueExW( key
, L
"InsertMode", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
370 if (save_all
|| config
->menu_mask
!= default_config
.menu_mask
)
372 val
= config
->menu_mask
;
373 RegSetValueExW( key
, L
"MenuMask", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
376 if (save_all
|| config
->popup_attr
!= default_config
.popup_attr
)
378 val
= config
->popup_attr
;
379 RegSetValueExW( key
, L
"PopupColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
382 if (save_all
|| config
->quick_edit
!= default_config
.quick_edit
)
384 val
= config
->quick_edit
;
385 RegSetValueExW( key
, L
"QuickEdit", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
388 if (save_all
|| config
->sb_width
!= default_config
.sb_width
||
389 config
->sb_height
!= default_config
.sb_height
)
391 val
= MAKELONG(config
->sb_width
, config
->sb_height
);
392 RegSetValueExW( key
, L
"ScreenBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
395 if (save_all
|| config
->attr
!= default_config
.attr
)
398 RegSetValueExW( key
, L
"ScreenColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
401 if (save_all
|| config
->win_width
!= default_config
.win_width
||
402 config
->win_height
!= default_config
.win_height
)
404 val
= MAKELONG( config
->win_width
, config
->win_height
);
405 RegSetValueExW( key
, L
"WindowSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
409 static void save_config( const WCHAR
*key_name
, const struct console_config
*config
)
413 TRACE( "Saving %s console settings\n", key_name
? debugstr_w( key_name
) : "default" );
415 if (RegCreateKeyW( HKEY_CURRENT_USER
, L
"Console", &key
))
417 ERR("Can't open registry for saving\n");
423 if (RegCreateKeyW( key
, key_name
, &app_key
))
425 ERR("Can't open registry for saving\n");
429 save_registry_key( app_key
, config
, FALSE
);
430 RegCloseKey( app_key
);
433 else save_registry_key( key
, config
, TRUE
);
437 /* fill memory DC with current cells values */
438 static void fill_mem_dc( struct console
*console
, const RECT
*update
)
440 unsigned int i
, j
, k
;
449 if (!console
->window
->font
|| !console
->window
->bitmap
)
452 if (!(line
= malloc( (update
->right
- update
->left
+ 1) * sizeof(WCHAR
))) ) return;
453 dx
= malloc( (update
->right
- update
->left
+ 1) * sizeof(*dx
) );
455 old_font
= SelectObject( console
->window
->mem_dc
, console
->window
->font
);
456 for (j
= update
->top
; j
<= update
->bottom
; j
++)
458 cell
= &console
->active
->data
[j
* console
->active
->width
];
459 for (i
= update
->left
; i
<= update
->right
; i
++)
462 SetBkColor( console
->window
->mem_dc
, console
->active
->color_map
[(attr
>> 4) & 0x0F] );
463 SetTextColor( console
->window
->mem_dc
, console
->active
->color_map
[attr
& 0x0F] );
464 for (k
= i
; k
<= update
->right
&& cell
[k
].attr
== attr
; k
++)
466 line
[k
- i
] = cell
[k
].ch
;
467 dx
[k
- i
] = console
->active
->font
.width
;
469 ExtTextOutW( console
->window
->mem_dc
, i
* console
->active
->font
.width
,
470 j
* console
->active
->font
.height
, 0, NULL
, line
, k
- i
, dx
);
471 if (console
->window
->ext_leading
&&
472 (brush
= CreateSolidBrush( console
->active
->color_map
[(attr
>> 4) & 0x0F] )))
474 r
.left
= i
* console
->active
->font
.width
;
475 r
.top
= (j
+ 1) * console
->active
->font
.height
- console
->window
->ext_leading
;
476 r
.right
= k
* console
->active
->font
.width
;
477 r
.bottom
= (j
+ 1) * console
->active
->font
.height
;
478 FillRect( console
->window
->mem_dc
, &r
, brush
);
479 DeleteObject( brush
);
484 SelectObject( console
->window
->mem_dc
, old_font
);
489 /* set a new position for the cursor */
490 static void update_window_cursor( struct console
*console
)
492 if (!console
->active
->cursor_visible
|| console
->win
!= GetFocus()) return;
494 SetCaretPos( (get_bounded_cursor_x( console
->active
) - console
->active
->win
.left
) * console
->active
->font
.width
,
495 (console
->active
->cursor_y
- console
->active
->win
.top
) * console
->active
->font
.height
);
496 ShowCaret( console
->win
);
499 /* sets a new shape for the cursor */
500 static void shape_cursor( struct console
*console
)
502 int size
= console
->active
->cursor_size
;
504 if (console
->active
->cursor_visible
&& console
->win
== GetFocus()) DestroyCaret();
505 if (console
->window
->cursor_bitmap
) DeleteObject( console
->window
->cursor_bitmap
);
506 console
->window
->cursor_bitmap
= NULL
;
507 console
->window
->cursor_visible
= FALSE
;
511 int w16b
; /* number of bytes per row, aligned on word size */
515 w16b
= ((console
->active
->font
.width
+ 15) & ~15) / 8;
516 ptr
= calloc( w16b
, console
->active
->font
.height
);
518 nbl
= max( (console
->active
->font
.height
* size
) / 100, 1 );
519 for (j
= console
->active
->font
.height
- nbl
; j
< console
->active
->font
.height
; j
++)
521 for (i
= 0; i
< console
->active
->font
.width
; i
++)
523 ptr
[w16b
* j
+ (i
/ 8)] |= 0x80 >> (i
& 7);
526 console
->window
->cursor_bitmap
= CreateBitmap( console
->active
->font
.width
,
527 console
->active
->font
.height
, 1, 1, ptr
);
532 static void update_window( struct console
*console
)
534 unsigned int win_width
, win_height
;
535 BOOL update_all
= FALSE
;
539 console
->window
->update_state
= UPDATE_BUSY
;
541 if (console
->window
->sb_width
!= console
->active
->width
||
542 console
->window
->sb_height
!= console
->active
->height
||
543 (!console
->window
->bitmap
&& IsWindowVisible( console
->win
)))
545 console
->window
->sb_width
= console
->active
->width
;
546 console
->window
->sb_height
= console
->active
->height
;
548 if (console
->active
->width
&& console
->active
->height
&& console
->window
->font
)
554 if (!(dc
= GetDC( console
->win
))) return;
556 bitmap
= CreateCompatibleBitmap( dc
,
557 console
->active
->width
* console
->active
->font
.width
,
558 console
->active
->height
* console
->active
->font
.height
);
559 ReleaseDC( console
->win
, dc
);
560 SelectObject( console
->window
->mem_dc
, bitmap
);
562 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
563 console
->window
->bitmap
= bitmap
;
564 SetRect( &r
, 0, 0, console
->active
->width
- 1, console
->active
->height
- 1 );
565 fill_mem_dc( console
, &r
);
568 empty_update_rect( console
->active
, &console
->window
->update
);
572 /* compute window size from desired client size */
573 win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
574 win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
576 if (update_all
|| win_width
!= console
->window
->win_width
||
577 win_height
!= console
->window
->win_height
)
579 console
->window
->win_width
= win_width
;
580 console
->window
->win_height
= win_height
;
583 r
.right
= win_width
* console
->active
->font
.width
;
584 r
.bottom
= win_height
* console
->active
->font
.height
;
585 AdjustWindowRect( &r
, GetWindowLongW( console
->win
, GWL_STYLE
), FALSE
);
588 if (console
->active
->width
> win_width
)
590 dy
= GetSystemMetrics( SM_CYHSCROLL
);
591 SetScrollRange( console
->win
, SB_HORZ
, 0, console
->active
->width
- win_width
, FALSE
);
592 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
593 ShowScrollBar( console
->win
, SB_HORZ
, TRUE
);
597 ShowScrollBar( console
->win
, SB_HORZ
, FALSE
);
600 if (console
->active
->height
> win_height
)
602 dx
= GetSystemMetrics( SM_CXVSCROLL
);
603 SetScrollRange( console
->win
, SB_VERT
, 0, console
->active
->height
- win_height
, FALSE
);
604 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
605 ShowScrollBar( console
->win
, SB_VERT
, TRUE
);
608 ShowScrollBar( console
->win
, SB_VERT
, FALSE
);
610 dx
+= r
.right
- r
.left
;
611 dy
+= r
.bottom
- r
.top
;
612 SetWindowPos( console
->win
, 0, 0, 0, dx
, dy
, SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
614 SystemParametersInfoW( SPI_GETWORKAREA
, 0, &r
, 0 );
615 console
->active
->max_width
= (r
.right
- r
.left
) / console
->active
->font
.width
;
616 console
->active
->max_height
= (r
.bottom
- r
.top
- GetSystemMetrics( SM_CYCAPTION
)) /
617 console
->active
->font
.height
;
619 InvalidateRect( console
->win
, NULL
, FALSE
);
620 UpdateWindow( console
->win
);
623 else if (console
->active
->win
.left
!= console
->window
->win_pos
.X
||
624 console
->active
->win
.top
!= console
->window
->win_pos
.Y
)
626 ScrollWindow( console
->win
,
627 (console
->window
->win_pos
.X
- console
->active
->win
.left
) * console
->active
->font
.width
,
628 (console
->window
->win_pos
.Y
- console
->active
->win
.top
) * console
->active
->font
.height
,
630 SetScrollPos( console
->win
, SB_HORZ
, console
->active
->win
.left
, TRUE
);
631 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, TRUE
);
632 InvalidateRect( console
->win
, NULL
, FALSE
);
635 console
->window
->win_pos
.X
= console
->active
->win
.left
;
636 console
->window
->win_pos
.Y
= console
->active
->win
.top
;
638 if (console
->window
->update
.top
<= console
->window
->update
.bottom
&&
639 console
->window
->update
.left
<= console
->window
->update
.right
)
641 RECT
*update
= &console
->window
->update
;
642 r
.left
= (update
->left
- console
->active
->win
.left
) * console
->active
->font
.width
;
643 r
.right
= (update
->right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
;
644 r
.top
= (update
->top
- console
->active
->win
.top
) * console
->active
->font
.height
;
645 r
.bottom
= (update
->bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
;
646 fill_mem_dc( console
, update
);
647 empty_update_rect( console
->active
, &console
->window
->update
);
648 InvalidateRect( console
->win
, &r
, FALSE
);
649 UpdateWindow( console
->win
);
652 if (update_all
|| console
->active
->cursor_size
!= console
->window
->cursor_size
)
654 console
->window
->cursor_size
= console
->active
->cursor_size
;
655 shape_cursor( console
);
658 if (console
->active
->cursor_visible
!= console
->window
->cursor_visible
)
660 console
->window
->cursor_visible
= console
->active
->cursor_visible
;
661 if (console
->win
== GetFocus())
663 if (console
->window
->cursor_visible
)
665 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
666 console
->active
->font
.width
, console
->active
->font
.height
);
667 update_window_cursor( console
);
674 if (update_all
|| get_bounded_cursor_x( console
->active
) != console
->window
->cursor_pos
.X
||
675 console
->active
->cursor_y
!= console
->window
->cursor_pos
.Y
)
677 console
->window
->cursor_pos
.X
= get_bounded_cursor_x( console
->active
);
678 console
->window
->cursor_pos
.Y
= console
->active
->cursor_y
;
679 update_window_cursor( console
);
682 console
->window
->update_state
= UPDATE_NONE
;
685 /* get the relevant information from the font described in lf and store them in config */
686 static HFONT
select_font_config( struct console_config
*config
, unsigned int cp
, HWND hwnd
,
689 HFONT font
, old_font
;
694 if (!(dc
= GetDC( hwnd
))) return NULL
;
695 if (!(font
= CreateFontIndirectW( lf
)))
697 ReleaseDC( hwnd
, dc
);
701 old_font
= SelectObject( dc
, font
);
702 GetTextMetricsW( dc
, &tm
);
703 SelectObject( dc
, old_font
);
704 ReleaseDC( hwnd
, dc
);
706 config
->cell_width
= tm
.tmAveCharWidth
;
707 config
->cell_height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
708 config
->font_weight
= tm
.tmWeight
;
709 lstrcpyW( config
->face_name
, lf
->lfFaceName
);
711 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
712 if (GetCPInfo( cp
, &cpinfo
) && cpinfo
.MaxCharSize
== 2)
713 config
->cell_width
= tm
.tmMaxCharWidth
;
718 static void fill_logfont( LOGFONTW
*lf
, const WCHAR
*face_name
, size_t face_name_size
,
719 unsigned int height
, unsigned int weight
)
721 lf
->lfHeight
= height
;
723 lf
->lfEscapement
= 0;
724 lf
->lfOrientation
= 0;
725 lf
->lfWeight
= weight
;
726 lf
->lfItalic
= FALSE
;
727 lf
->lfUnderline
= FALSE
;
728 lf
->lfStrikeOut
= FALSE
;
729 lf
->lfCharSet
= DEFAULT_CHARSET
;
730 lf
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
731 lf
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
732 lf
->lfQuality
= DEFAULT_QUALITY
;
733 lf
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
734 face_name_size
= min( face_name_size
, sizeof(lf
->lfFaceName
) - sizeof(WCHAR
) );
735 memcpy( lf
->lfFaceName
, face_name
, face_name_size
);
736 lf
->lfFaceName
[face_name_size
/ sizeof(WCHAR
)] = 0;
739 static BOOL
set_console_font( struct console
*console
, const LOGFONTW
*logfont
)
741 struct font_info
*font_info
= &console
->active
->font
;
742 HFONT font
, old_font
;
744 WCHAR face_name
[LF_FACESIZE
];
748 TRACE( "%s\n", debugstr_logfont( logfont
, 0 ));
750 if (console
->window
->font
&& logfont
->lfHeight
== console
->active
->font
.height
&&
751 logfont
->lfWeight
== console
->active
->font
.weight
&&
752 !logfont
->lfItalic
&& !logfont
->lfUnderline
&& !logfont
->lfStrikeOut
&&
753 console
->active
->font
.face_len
== wcslen( logfont
->lfFaceName
) &&
754 !memcmp( logfont
->lfFaceName
, console
->active
->font
.face_name
,
755 console
->active
->font
.face_len
* sizeof(WCHAR
) ))
757 TRACE( "equal to current\n" );
761 if (!(dc
= GetDC( console
->win
))) return FALSE
;
762 if (!(font
= CreateFontIndirectW( logfont
)))
764 ReleaseDC( console
->win
, dc
);
768 old_font
= SelectObject( dc
, font
);
769 GetTextMetricsW( dc
, &tm
);
770 font_info
->face_len
= GetTextFaceW( dc
, ARRAY_SIZE(face_name
), face_name
) - 1;
771 SelectObject( dc
, old_font
);
772 ReleaseDC( console
->win
, dc
);
774 font_info
->width
= tm
.tmAveCharWidth
;
775 font_info
->height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
776 font_info
->pitch_family
= tm
.tmPitchAndFamily
;
777 font_info
->weight
= tm
.tmWeight
;
779 free( font_info
->face_name
);
780 font_info
->face_name
= malloc( font_info
->face_len
* sizeof(WCHAR
) );
781 memcpy( font_info
->face_name
, face_name
, font_info
->face_len
* sizeof(WCHAR
) );
783 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
784 if (GetCPInfo( console
->output_cp
, &cpinfo
) && cpinfo
.MaxCharSize
== 2)
785 font_info
->width
= tm
.tmMaxCharWidth
;
787 if (console
->window
->font
) DeleteObject( console
->window
->font
);
788 console
->window
->font
= font
;
789 console
->window
->ext_leading
= tm
.tmExternalLeading
;
791 if (console
->window
->bitmap
)
793 DeleteObject(console
->window
->bitmap
);
794 console
->window
->bitmap
= NULL
;
801 struct console
*console
;
803 unsigned int font_height
;
804 unsigned int font_width
;
808 /* check if the font described in tm is usable as a font for the renderer */
809 static BOOL
validate_font_metric( struct console
*console
, const TEXTMETRICW
*tm
,
810 DWORD type
, int pass
)
812 switch (pass
) /* we get increasingly lenient in later passes */
815 if (type
& RASTER_FONTTYPE
) return FALSE
;
818 if (type
& RASTER_FONTTYPE
)
820 if (tm
->tmMaxCharWidth
* (console
->active
->win
.right
- console
->active
->win
.left
+ 1)
821 >= GetSystemMetrics(SM_CXSCREEN
))
823 if (tm
->tmHeight
* (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
824 >= GetSystemMetrics(SM_CYSCREEN
))
829 if (tm
->tmCharSet
!= DEFAULT_CHARSET
&& tm
->tmCharSet
!= console
->window
->ui_charset
)
833 if (tm
->tmItalic
|| tm
->tmUnderlined
|| tm
->tmStruckOut
) return FALSE
;
839 /* check if the font family described in lf is usable as a font for the renderer */
840 static BOOL
validate_font( struct console
*console
, const LOGFONTW
*lf
, int pass
)
842 switch (pass
) /* we get increasingly lenient in later passes */
847 if (lf
->lfCharSet
!= DEFAULT_CHARSET
&& lf
->lfCharSet
!= console
->window
->ui_charset
)
851 if ((lf
->lfPitchAndFamily
& 3) != FIXED_PITCH
) return FALSE
;
854 if (lf
->lfFaceName
[0] == '@') return FALSE
;
860 static int CALLBACK
enum_first_font_proc( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
861 DWORD font_type
, LPARAM lparam
)
863 struct font_chooser
*fc
= (struct font_chooser
*)lparam
;
866 if (font_type
!= TRUETYPE_FONTTYPE
) return 1;
868 TRACE( "%s\n", debugstr_logfont( lf
, font_type
));
870 if (!validate_font( fc
->console
, lf
, fc
->pass
))
873 TRACE( "%s\n", debugstr_textmetric( tm
, font_type
));
875 if (!validate_font_metric( fc
->console
, tm
, font_type
, fc
->pass
))
878 /* set default font size */
880 mlf
.lfHeight
= fc
->font_height
;
881 mlf
.lfWidth
= fc
->font_width
;
883 if (!set_console_font( fc
->console
, &mlf
))
891 static void set_first_font( struct console
*console
, struct console_config
*config
)
894 struct font_chooser fc
;
896 TRACE("Looking for a suitable console font\n");
898 memset( &lf
, 0, sizeof(lf
) );
899 lf
.lfCharSet
= DEFAULT_CHARSET
;
900 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
902 fc
.console
= console
;
903 fc
.font_height
= config
->cell_height
;
904 fc
.font_width
= config
->cell_width
;
907 for (fc
.pass
= 0; fc
.pass
<= 5; fc
.pass
++)
909 EnumFontFamiliesExW( console
->window
->mem_dc
, &lf
, enum_first_font_proc
, (LPARAM
)&fc
, 0);
914 ERR("Unable to find a valid console font\n");
916 /* Update active configuration */
917 config
->cell_width
= console
->active
->font
.width
;
918 config
->cell_height
= console
->active
->font
.height
;
919 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
920 memcpy( config
->face_name
, console
->active
->font
.face_name
,
921 console
->active
->font
.face_len
* sizeof(WCHAR
) );
922 config
->face_name
[console
->active
->font
.face_len
] = 0;
924 /* Save default console configuration to the registry */
925 save_config( NULL
, config
);
928 /* Sets the font specified in the LOGFONT as the new console font */
929 void update_console_font( struct console
*console
, const WCHAR
*face_name
, size_t face_name_size
,
930 unsigned int height
, unsigned int weight
)
934 fill_logfont( &lf
, face_name
, face_name_size
, height
, weight
);
936 set_console_font( console
, &lf
);
939 /* get a cell from a relative coordinate in window (takes into account the scrolling) */
940 static COORD
get_cell( struct console
*console
, LPARAM lparam
)
943 c
.X
= console
->active
->win
.left
+ (short)LOWORD(lparam
) / console
->active
->font
.width
;
944 c
.Y
= console
->active
->win
.top
+ (short)HIWORD(lparam
) / console
->active
->font
.height
;
948 /* get the console bit mask equivalent to the VK_ status in key state */
949 static DWORD
get_ctrl_state( BYTE
*key_state
)
951 unsigned int ret
= 0;
953 GetKeyboardState(key_state
);
954 if (key_state
[VK_SHIFT
] & 0x80) ret
|= SHIFT_PRESSED
;
955 if (key_state
[VK_LCONTROL
] & 0x80) ret
|= LEFT_CTRL_PRESSED
;
956 if (key_state
[VK_RCONTROL
] & 0x80) ret
|= RIGHT_CTRL_PRESSED
;
957 if (key_state
[VK_LMENU
] & 0x80) ret
|= LEFT_ALT_PRESSED
;
958 if (key_state
[VK_RMENU
] & 0x80) ret
|= RIGHT_ALT_PRESSED
;
959 if (key_state
[VK_CAPITAL
] & 0x01) ret
|= CAPSLOCK_ON
;
960 if (key_state
[VK_NUMLOCK
] & 0x01) ret
|= NUMLOCK_ON
;
961 if (key_state
[VK_SCROLL
] & 0x01) ret
|= SCROLLLOCK_ON
;
966 /* get the selection rectangle */
967 static void get_selection_rect( struct console
*console
, RECT
*r
)
969 r
->left
= (min(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) -
970 console
->active
->win
.left
) * console
->active
->font
.width
;
971 r
->top
= (min(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) -
972 console
->active
->win
.top
) * console
->active
->font
.height
;
973 r
->right
= (max(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) + 1 -
974 console
->active
->win
.left
) * console
->active
->font
.width
;
975 r
->bottom
= (max(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) + 1 -
976 console
->active
->win
.top
) * console
->active
->font
.height
;
979 static void update_selection( struct console
*console
, HDC ref_dc
)
984 get_selection_rect( console
, &r
);
985 dc
= ref_dc
? ref_dc
: GetDC( console
->win
);
988 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
989 HideCaret( console
->win
);
990 InvertRect( dc
, &r
);
992 ReleaseDC( console
->win
, dc
);
993 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
994 ShowCaret( console
->win
);
997 static void move_selection( struct console
*console
, COORD c1
, COORD c2
)
1002 if (c1
.X
< 0 || c1
.X
>= console
->active
->width
||
1003 c2
.X
< 0 || c2
.X
>= console
->active
->width
||
1004 c1
.Y
< 0 || c1
.Y
>= console
->active
->height
||
1005 c2
.Y
< 0 || c2
.Y
>= console
->active
->height
)
1008 get_selection_rect( console
, &r
);
1009 dc
= GetDC( console
->win
);
1012 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
1013 HideCaret( console
->win
);
1014 InvertRect( dc
, &r
);
1016 console
->window
->selection_start
= c1
;
1017 console
->window
->selection_end
= c2
;
1020 get_selection_rect( console
, &r
);
1021 InvertRect( dc
, &r
);
1022 ReleaseDC( console
->win
, dc
);
1023 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
1024 ShowCaret( console
->win
);
1028 /* copies the current selection into the clipboard */
1029 static void copy_selection( struct console
*console
)
1035 w
= abs( console
->window
->selection_start
.X
- console
->window
->selection_end
.X
) + 1;
1036 h
= abs( console
->window
->selection_start
.Y
- console
->window
->selection_end
.Y
) + 1;
1038 if (!OpenClipboard( console
->win
)) return;
1041 mem
= GlobalAlloc( GMEM_MOVEABLE
, (w
+ 1) * h
* sizeof(WCHAR
) );
1042 if (mem
&& (p
= buf
= GlobalLock( mem
)))
1047 c
.X
= min( console
->window
->selection_start
.X
, console
->window
->selection_end
.X
);
1048 c
.Y
= min( console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
);
1050 for (y
= c
.Y
; y
< c
.Y
+ h
; y
++)
1054 for (x
= c
.X
; x
< c
.X
+ w
; x
++)
1055 p
[x
- c
.X
] = console
->active
->data
[y
* console
->active
->width
+ x
].ch
;
1057 /* strip spaces from the end of the line */
1059 while (end
> p
&& *(end
- 1) == ' ')
1061 *end
= (y
< c
.Y
+ h
- 1) ? '\n' : '\0';
1065 TRACE( "%s\n", debugstr_w( buf
));
1066 if (p
- buf
!= (w
+ 1) * h
)
1069 new_mem
= GlobalReAlloc( mem
, (p
- buf
) * sizeof(WCHAR
), GMEM_MOVEABLE
);
1070 if (new_mem
) mem
= new_mem
;
1072 GlobalUnlock( mem
);
1073 SetClipboardData( CF_UNICODETEXT
, mem
);
1078 static void paste_clipboard( struct console
*console
)
1083 if (!OpenClipboard( console
->win
)) return;
1084 h
= GetClipboardData( CF_UNICODETEXT
);
1085 if (h
&& (ptr
= GlobalLock( h
)))
1087 unsigned int i
, len
= GlobalSize(h
) / sizeof(WCHAR
);
1091 ir
[0].EventType
= KEY_EVENT
;
1092 ir
[0].Event
.KeyEvent
.wRepeatCount
= 0;
1093 ir
[0].Event
.KeyEvent
.dwControlKeyState
= 0;
1094 ir
[0].Event
.KeyEvent
.bKeyDown
= TRUE
;
1096 /* generate the corresponding input records */
1097 for (i
= 0; i
< len
; i
++)
1099 /* FIXME: the modifying keys are not generated (shift, ctrl...) */
1100 sh
= VkKeyScanW( ptr
[i
] );
1101 ir
[0].Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(sh
);
1102 ir
[0].Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKeyW( LOBYTE(sh
), 0 );
1103 ir
[0].Event
.KeyEvent
.uChar
.UnicodeChar
= ptr
[i
];
1106 ir
[1].Event
.KeyEvent
.bKeyDown
= FALSE
;
1108 write_console_input( console
, ir
, 2, i
== len
- 1 );
1116 /* handle keys while selecting an area */
1117 static void handle_selection_key( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1119 BYTE key_state
[256];
1124 state
= get_ctrl_state( key_state
) & ~(CAPSLOCK_ON
|NUMLOCK_ON
|SCROLLLOCK_ON
);
1132 console
->window
->in_selection
= FALSE
;
1133 update_selection( console
, 0 );
1134 copy_selection( console
);
1137 c1
= console
->window
->selection_start
;
1138 c2
= console
->window
->selection_end
;
1140 move_selection( console
, c1
, c2
);
1143 c1
= console
->window
->selection_start
;
1144 c2
= console
->window
->selection_end
;
1146 move_selection( console
, c1
, c2
);
1149 c1
= console
->window
->selection_start
;
1150 c2
= console
->window
->selection_end
;
1152 move_selection( console
, c1
, c2
);
1155 c1
= console
->window
->selection_start
;
1156 c2
= console
->window
->selection_end
;
1158 move_selection( console
, c1
, c2
);
1166 c1
= console
->window
->selection_start
;
1167 c2
= console
->window
->selection_end
;
1169 move_selection( console
, c1
, c2
);
1172 c1
= console
->window
->selection_start
;
1173 c2
= console
->window
->selection_end
;
1175 move_selection( console
, c1
, c2
);
1178 c1
= console
->window
->selection_start
;
1179 c2
= console
->window
->selection_end
;
1181 move_selection( console
, c1
, c2
);
1184 c1
= console
->window
->selection_start
;
1185 c2
= console
->window
->selection_end
;
1187 move_selection( console
, c1
, c2
);
1193 if (wparam
< VK_SPACE
) /* Shift, Alt, Ctrl, Num Lock etc. */
1196 update_selection( console
, 0 );
1197 console
->window
->in_selection
= FALSE
;
1200 /* generate input_record from windows WM_KEYUP/WM_KEYDOWN messages */
1201 static void record_key_input( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1203 static WCHAR last
; /* keep last char seen as feed for key up message */
1204 BYTE key_state
[256];
1208 ir
.EventType
= KEY_EVENT
;
1209 ir
.Event
.KeyEvent
.bKeyDown
= down
;
1210 ir
.Event
.KeyEvent
.wRepeatCount
= LOWORD(lparam
);
1211 ir
.Event
.KeyEvent
.wVirtualKeyCode
= wparam
;
1212 ir
.Event
.KeyEvent
.wVirtualScanCode
= HIWORD(lparam
) & 0xFF;
1213 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
1214 ir
.Event
.KeyEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1215 if (lparam
& (1u << 24)) ir
.Event
.KeyEvent
.dwControlKeyState
|= ENHANCED_KEY
;
1219 switch (ToUnicode(wparam
, HIWORD(lparam
), key_state
, buf
, 2, 0))
1222 /* FIXME: should generate two events */
1232 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= last
;
1233 if (!down
) last
= 0; /* FIXME: buggy HACK */
1235 write_console_input( console
, &ir
, 1, TRUE
);
1238 static void record_mouse_input( struct console
*console
, COORD c
, WPARAM wparam
, DWORD event
)
1240 BYTE key_state
[256];
1243 /* MOUSE_EVENTs shouldn't be sent unless ENABLE_MOUSE_INPUT is active */
1244 if (!(console
->mode
& ENABLE_MOUSE_INPUT
)) return;
1246 ir
.EventType
= MOUSE_EVENT
;
1247 ir
.Event
.MouseEvent
.dwMousePosition
= c
;
1248 ir
.Event
.MouseEvent
.dwButtonState
= 0;
1249 if (wparam
& MK_LBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1250 if (wparam
& MK_MBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1251 if (wparam
& MK_RBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1252 if (wparam
& MK_CONTROL
) ir
.Event
.MouseEvent
.dwButtonState
|= LEFT_CTRL_PRESSED
;
1253 if (wparam
& MK_SHIFT
) ir
.Event
.MouseEvent
.dwButtonState
|= SHIFT_PRESSED
;
1254 if (event
== MOUSE_WHEELED
) ir
.Event
.MouseEvent
.dwButtonState
|= wparam
& 0xFFFF0000;
1255 ir
.Event
.MouseEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1256 ir
.Event
.MouseEvent
.dwEventFlags
= event
;
1258 write_console_input( console
, &ir
, 1, TRUE
);
1263 struct console
*console
;
1264 struct console_config config
;
1265 HWND dialog
; /* handle to active propsheet */
1268 /* dialog proc for the option property sheet */
1269 static INT_PTR WINAPI
option_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1271 struct dialog_info
*di
;
1277 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1278 di
->dialog
= dialog
;
1279 SetWindowLongPtrW( dialog
, DWLP_USER
, (LONG_PTR
)di
);
1281 SendMessageW( GetDlgItem( dialog
, IDC_OPT_HIST_SIZE_UD
), UDM_SETRANGE
, 0, MAKELPARAM(500, 0) );
1283 if (di
->config
.cursor_size
<= 25) idc
= IDC_OPT_CURSOR_SMALL
;
1284 else if (di
->config
.cursor_size
<= 50) idc
= IDC_OPT_CURSOR_MEDIUM
;
1285 else idc
= IDC_OPT_CURSOR_LARGE
;
1287 SendDlgItemMessageW( dialog
, idc
, BM_SETCHECK
, BST_CHECKED
, 0 );
1288 SetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, di
->config
.history_size
, FALSE
);
1289 SendDlgItemMessageW( dialog
, IDC_OPT_HIST_NODOUBLE
, BM_SETCHECK
,
1290 (di
->config
.history_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1291 SendDlgItemMessageW( dialog
, IDC_OPT_INSERT_MODE
, BM_SETCHECK
,
1292 (di
->config
.insert_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1293 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_CTRL
, BM_SETCHECK
,
1294 (di
->config
.menu_mask
& MK_CONTROL
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1295 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_SHIFT
, BM_SETCHECK
,
1296 (di
->config
.menu_mask
& MK_SHIFT
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1297 SendDlgItemMessageW( dialog
, IDC_OPT_QUICK_EDIT
, BM_SETCHECK
,
1298 (di
->config
.quick_edit
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1299 return FALSE
; /* because we set the focus */
1306 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1310 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1312 switch (nmhdr
->code
)
1315 /* needed in propsheet to keep properly the selected radio button
1316 * otherwise, the focus would be set to the first tab stop in the
1317 * propsheet, which would always activate the first radio button
1319 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
)
1320 idc
= IDC_OPT_CURSOR_SMALL
;
1321 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
)
1322 idc
= IDC_OPT_CURSOR_MEDIUM
;
1324 idc
= IDC_OPT_CURSOR_LARGE
;
1325 PostMessageW( dialog
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem( dialog
, idc
), TRUE
);
1326 di
->dialog
= dialog
;
1329 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
) val
= 25;
1330 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
) val
= 50;
1332 di
->config
.cursor_size
= val
;
1334 val
= GetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, &done
, FALSE
);
1335 if (done
) di
->config
.history_size
= val
;
1337 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_HIST_NODOUBLE
) & BST_CHECKED
) != 0;
1338 di
->config
.history_mode
= val
;
1340 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_INSERT_MODE
) & BST_CHECKED
) != 0;
1341 di
->config
.insert_mode
= val
;
1344 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_CTRL
) & BST_CHECKED
) val
|= MK_CONTROL
;
1345 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_SHIFT
) & BST_CHECKED
) val
|= MK_SHIFT
;
1346 di
->config
.menu_mask
= val
;
1348 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_QUICK_EDIT
) & BST_CHECKED
) != 0;
1349 di
->config
.quick_edit
= val
;
1351 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1364 static COLORREF
get_color( struct dialog_info
*di
, unsigned int idc
)
1368 index
= GetWindowLongPtrW(GetDlgItem( di
->dialog
, idc
), 0);
1369 return di
->config
.color_map
[index
];
1372 /* window proc for font previewer in font property sheet */
1373 static LRESULT WINAPI
font_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1378 SetWindowLongPtrW( hwnd
, 0, 0 );
1382 return GetWindowLongPtrW( hwnd
, 0 );
1385 SetWindowLongPtrW( hwnd
, 0, wparam
);
1388 InvalidateRect( hwnd
, NULL
, TRUE
);
1389 UpdateWindow( hwnd
);
1395 HFONT font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1396 if (font
) DeleteObject( font
);
1402 struct dialog_info
*di
;
1403 HFONT font
, old_font
;
1406 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent( hwnd
), DWLP_USER
);
1407 BeginPaint( hwnd
, &ps
);
1409 font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1412 static const WCHAR ascii
[] = L
"ASCII: abcXYZ";
1417 old_font
= SelectObject( ps
.hdc
, font
);
1418 bkcolor
= get_color( di
, IDC_FNT_COLOR_BK
);
1419 FillRect( ps
.hdc
, &ps
.rcPaint
, CreateSolidBrush( bkcolor
));
1420 SetBkColor( ps
.hdc
, bkcolor
);
1421 SetTextColor( ps
.hdc
, get_color( di
, IDC_FNT_COLOR_FG
));
1422 len
= LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_PREVIEW
, buf
, ARRAY_SIZE(buf
) );
1423 if (len
) TextOutW( ps
.hdc
, 0, 0, buf
, len
);
1424 TextOutW( ps
.hdc
, 0, di
->config
.cell_height
, ascii
, ARRAY_SIZE(ascii
) - 1 );
1425 SelectObject( ps
.hdc
, old_font
);
1427 EndPaint( hwnd
, &ps
);
1432 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1437 /* window proc for color previewer */
1438 static LRESULT WINAPI
color_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1444 struct dialog_info
*di
;
1450 BeginPaint( hwnd
, &ps
);
1451 GetClientRect( hwnd
, &client
);
1452 step
= client
.right
/ 8;
1454 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent(hwnd
), DWLP_USER
);
1456 for (i
= 0; i
< 16; i
++)
1458 r
.top
= (i
/ 8) * (client
.bottom
/ 2);
1459 r
.bottom
= r
.top
+ client
.bottom
/ 2;
1460 r
.left
= (i
& 7) * step
;
1461 r
.right
= r
.left
+ step
;
1462 brush
= CreateSolidBrush( di
->config
.color_map
[i
] );
1463 FillRect( ps
.hdc
, &r
, brush
);
1464 DeleteObject( brush
);
1465 if (GetWindowLongW( hwnd
, 0 ) == i
)
1470 old_pen
= SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1471 r
.right
--; r
.bottom
--;
1474 MoveToEx( ps
.hdc
, r
.left
, r
.bottom
, NULL
);
1475 LineTo( ps
.hdc
, r
.left
, r
.top
);
1476 LineTo( ps
.hdc
, r
.right
, r
.top
);
1477 SelectObject( ps
.hdc
, GetStockObject( BLACK_PEN
));
1478 LineTo( ps
.hdc
, r
.right
, r
.bottom
);
1479 LineTo( ps
.hdc
, r
.left
, r
.bottom
);
1480 if (--i
== 0) break;
1481 r
.left
++; r
.top
++; r
.right
--; r
.bottom
--;
1482 SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1484 SelectObject( ps
.hdc
, old_pen
);
1487 EndPaint( hwnd
, &ps
);
1491 case WM_LBUTTONDOWN
:
1496 GetClientRect( hwnd
, &client
);
1497 step
= client
.right
/ 8;
1498 i
= (HIWORD(lparam
) >= client
.bottom
/ 2) ? 8 : 0;
1499 i
+= LOWORD(lparam
) / step
;
1500 SetWindowLongW( hwnd
, 0, i
);
1501 InvalidateRect( GetDlgItem( GetParent( hwnd
), IDC_FNT_PREVIEW
), NULL
, FALSE
);
1502 InvalidateRect( hwnd
, NULL
, FALSE
);
1507 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1512 static BOOL
select_font( struct dialog_info
*di
)
1514 int font_idx
, size_idx
;
1515 WCHAR face_name
[LF_FACESIZE
], height_buf
[4];
1517 unsigned int font_height
;
1519 HFONT font
, old_font
;
1524 font_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETCURSEL
, 0, 0 );
1525 size_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1527 if (font_idx
< 0 || size_idx
< 0)
1530 len
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETTEXT
, font_idx
, (LPARAM
)&face_name
);
1531 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETTEXT
, size_idx
, (LPARAM
)&height_buf
);
1532 font_height
= _wtoi( height_buf
);
1534 fill_logfont( &lf
, face_name
, len
* sizeof(WCHAR
), font_height
, FW_NORMAL
);
1535 font
= select_font_config( &di
->config
, di
->console
->output_cp
, di
->console
->win
, &lf
);
1536 if (!font
) return FALSE
;
1538 if (di
->config
.cell_height
!= font_height
)
1539 TRACE( "mismatched heights (%u<>%u)\n", di
->config
.cell_height
, font_height
);
1541 old_font
= (HFONT
)SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_GETFONT
, 0, 0 );
1542 SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1543 if (old_font
) DeleteObject( old_font
);
1545 LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_DISPLAY
, fmt
, ARRAY_SIZE(fmt
) );
1546 args
[0] = di
->config
.cell_width
;
1547 args
[1] = di
->config
.cell_height
;
1548 FormatMessageW( FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
1549 fmt
, 0, 0, buf
, ARRAY_SIZE(buf
), (__ms_va_list
*)args
);
1551 SendDlgItemMessageW( di
->dialog
, IDC_FNT_FONT_INFO
, WM_SETTEXT
, 0, (LPARAM
)buf
);
1555 static BOOL
fill_list_size( struct dialog_info
*di
, BOOL init
)
1559 static const int sizes
[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
1560 unsigned int i
, idx
= 4;
1563 for (i
= 0; i
< ARRAY_SIZE(sizes
); i
++)
1565 wsprintfW( buf
, L
"%u", sizes
[i
] );
1566 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_INSERTSTRING
, -1, (LPARAM
)buf
);
1568 if (di
->config
.cell_height
== sizes
[i
]) idx
= i
;
1571 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_SETCURSEL
, idx
, 0 );
1579 static int CALLBACK
enum_list_font_proc( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1580 DWORD font_type
, LPARAM lparam
)
1582 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1584 if (font_type
!= TRUETYPE_FONTTYPE
) return 1;
1586 TRACE( "%s\n", debugstr_logfont( lf
, font_type
));
1588 if (validate_font( di
->console
, lf
, 0 ))
1589 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_ADDSTRING
, 0, (LPARAM
)lf
->lfFaceName
);
1594 static BOOL
fill_list_font( struct dialog_info
*di
)
1598 memset( &lf
, 0, sizeof(lf
) );
1599 lf
.lfCharSet
= DEFAULT_CHARSET
;
1600 lf
.lfFaceName
[0] = 0;
1601 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
1603 EnumFontFamiliesExW( di
->console
->window
->mem_dc
, &lf
, enum_list_font_proc
, (LPARAM
)di
, 0 );
1605 if (SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SELECTSTRING
,
1606 -1, (LPARAM
)di
->config
.face_name
) == LB_ERR
)
1607 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SETCURSEL
, 0, 0 );
1609 fill_list_size( di
, TRUE
);
1614 /* dialog proc for the font property sheet */
1615 static INT_PTR WINAPI
font_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1617 struct dialog_info
*di
;
1622 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1623 di
->dialog
= dialog
;
1624 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1625 /* use default system font until user-selected font is applied */
1626 SendDlgItemMessageW( dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, 0, 0 );
1627 fill_list_font( di
);
1628 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0, (di
->config
.attr
>> 4) & 0x0F );
1629 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0, di
->config
.attr
& 0x0F );
1633 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1634 switch (LOWORD(wparam
))
1636 case IDC_FNT_LIST_FONT
:
1637 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1638 fill_list_size( di
, FALSE
);
1640 case IDC_FNT_LIST_SIZE
:
1641 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1649 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1652 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1653 switch (nmhdr
->code
)
1656 di
->dialog
= dialog
;
1659 val
= (GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0 ) << 4) |
1660 GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0 );
1661 di
->config
.attr
= val
;
1662 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1675 /* dialog proc for the config property sheet */
1676 static INT_PTR WINAPI
config_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1678 struct dialog_info
*di
;
1684 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1685 di
->dialog
= dialog
;
1687 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1688 SetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, di
->config
.sb_width
, FALSE
);
1689 SetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, di
->config
.sb_height
, FALSE
);
1690 SetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, di
->config
.win_width
, FALSE
);
1691 SetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, di
->config
.win_height
, FALSE
);
1693 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1694 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1695 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1696 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1698 SendDlgItemMessageW( dialog
, IDC_CNF_CLOSE_EXIT
, BM_SETCHECK
, BST_CHECKED
, 0 );
1700 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Win32" );
1701 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Emacs" );
1702 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_SETCURSEL
, di
->config
.edition_mode
, 0 );
1707 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1708 int win_w
, win_h
, sb_w
, sb_h
;
1711 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1712 switch (nmhdr
->code
)
1715 di
->dialog
= dialog
;
1718 sb_w
= GetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, &st1
, FALSE
);
1719 sb_h
= GetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, &st2
, FALSE
);
1722 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1725 win_w
= GetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, &st1
, FALSE
);
1726 win_h
= GetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, &st2
, FALSE
);
1729 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1732 if (win_w
> sb_w
|| win_h
> sb_h
)
1737 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_TIT_ERROR
, cap
, ARRAY_SIZE(cap
) );
1738 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_ERR_SBWINSIZE
, txt
, ARRAY_SIZE(txt
) );
1740 MessageBoxW( dialog
, txt
, cap
, MB_OK
);
1741 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1744 di
->config
.win_width
= win_w
;
1745 di
->config
.win_height
= win_h
;
1746 di
->config
.sb_width
= sb_w
;
1747 di
->config
.sb_height
= sb_h
;
1749 di
->config
.edition_mode
= SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
,
1750 CB_GETCURSEL
, 0, 0 );
1751 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1764 static void apply_config( struct console
*console
, const struct console_config
*config
)
1766 if (console
->active
->width
!= config
->sb_width
|| console
->active
->height
!= config
->sb_height
)
1767 change_screen_buffer_size( console
->active
, config
->sb_width
, config
->sb_height
);
1769 console
->window
->menu_mask
= config
->menu_mask
;
1770 console
->window
->quick_edit
= config
->quick_edit
;
1772 console
->edition_mode
= config
->edition_mode
;
1773 console
->history_mode
= config
->history_mode
;
1775 if (console
->history_size
!= config
->history_size
)
1777 struct history_line
**mem
= NULL
;
1780 if (config
->history_size
&& (mem
= malloc( config
->history_size
* sizeof(*mem
) )))
1782 memset( mem
, 0, config
->history_size
* sizeof(*mem
) );
1784 delta
= (console
->history_index
> config
->history_size
)
1785 ? (console
->history_index
- config
->history_size
) : 0;
1787 for (i
= delta
; i
< console
->history_index
; i
++)
1789 mem
[i
- delta
] = console
->history
[i
];
1790 console
->history
[i
] = NULL
;
1792 console
->history_index
-= delta
;
1794 for (i
= 0; i
< console
->history_size
; i
++)
1795 free( console
->history
[i
] );
1796 free( console
->history
);
1797 console
->history
= mem
;
1798 console
->history_size
= config
->history_size
;
1802 if (config
->insert_mode
)
1803 console
->mode
|= ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
;
1805 console
->mode
&= ~ENABLE_INSERT_MODE
;
1807 console
->active
->cursor_size
= config
->cursor_size
;
1808 console
->active
->cursor_visible
= config
->cursor_visible
;
1809 console
->active
->attr
= config
->attr
;
1810 console
->active
->popup_attr
= config
->popup_attr
;
1811 console
->active
->win
.left
= config
->win_pos
.X
;
1812 console
->active
->win
.top
= config
->win_pos
.Y
;
1813 console
->active
->win
.right
= config
->win_pos
.X
+ config
->win_width
- 1;
1814 console
->active
->win
.bottom
= config
->win_pos
.Y
+ config
->win_height
- 1;
1815 memcpy( console
->active
->color_map
, config
->color_map
, sizeof(config
->color_map
) );
1817 if (console
->active
->font
.width
!= config
->cell_width
||
1818 console
->active
->font
.height
!= config
->cell_height
||
1819 console
->active
->font
.weight
!= config
->font_weight
||
1820 console
->active
->font
.pitch_family
!= config
->font_pitch_family
||
1821 console
->active
->font
.face_len
!= wcslen( config
->face_name
) ||
1822 memcmp( console
->active
->font
.face_name
, config
->face_name
,
1823 console
->active
->font
.face_len
* sizeof(WCHAR
) ))
1825 update_console_font( console
, config
->face_name
, wcslen(config
->face_name
) * sizeof(WCHAR
),
1826 config
->cell_height
, config
->font_weight
);
1829 update_window( console
);
1831 notify_screen_buffer_size( console
->active
);
1834 static void current_config( struct console
*console
, struct console_config
*config
)
1838 config
->menu_mask
= console
->window
->menu_mask
;
1839 config
->quick_edit
= console
->window
->quick_edit
;
1841 config
->edition_mode
= console
->edition_mode
;
1842 config
->history_mode
= console
->history_mode
;
1843 config
->history_size
= console
->history_size
;
1845 config
->insert_mode
= (console
->mode
& (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
)) ==
1846 (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
);
1848 config
->cursor_size
= console
->active
->cursor_size
;
1849 config
->cursor_visible
= console
->active
->cursor_visible
;
1850 config
->attr
= console
->active
->attr
;
1851 config
->popup_attr
= console
->active
->popup_attr
;
1852 memcpy( config
->color_map
, console
->active
->color_map
, sizeof(config
->color_map
) );
1854 config
->cell_width
= console
->active
->font
.width
;
1855 config
->cell_height
= console
->active
->font
.height
;
1856 config
->font_weight
= console
->active
->font
.weight
;
1857 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
1858 len
= min( ARRAY_SIZE(config
->face_name
) - 1, console
->active
->font
.face_len
);
1859 if (len
) memcpy( config
->face_name
, console
->active
->font
.face_name
, len
* sizeof(WCHAR
) );
1860 config
->face_name
[len
] = 0;
1862 config
->sb_width
= console
->active
->width
;
1863 config
->sb_height
= console
->active
->height
;
1865 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1866 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1867 config
->win_pos
.X
= console
->active
->win
.left
;
1868 config
->win_pos
.Y
= console
->active
->win
.top
;
1871 /* run the dialog box to set up the console options */
1872 static BOOL
config_dialog( struct console
*console
, BOOL current
)
1874 struct console_config prev_config
;
1875 struct dialog_info di
;
1876 PROPSHEETHEADERW header
;
1877 HPROPSHEETPAGE pages
[3];
1882 InitCommonControls();
1884 memset( &di
, 0, sizeof(di
) );
1885 di
.console
= console
;
1888 current_config( console
, &di
.config
);
1890 load_config( NULL
, &di
.config
);
1892 prev_config
= di
.config
;
1895 wndclass
.lpfnWndProc
= font_preview_proc
;
1896 wndclass
.cbClsExtra
= 0;
1897 wndclass
.cbWndExtra
= sizeof(HFONT
);
1898 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1900 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1901 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1902 wndclass
.lpszMenuName
= NULL
;
1903 wndclass
.lpszClassName
= L
"WineConFontPreview";
1904 RegisterClassW( &wndclass
);
1907 wndclass
.lpfnWndProc
= color_preview_proc
;
1908 wndclass
.cbClsExtra
= 0;
1909 wndclass
.cbWndExtra
= sizeof(DWORD
);
1910 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1912 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1913 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1914 wndclass
.lpszMenuName
= NULL
;
1915 wndclass
.lpszClassName
= L
"WineConColorPreview";
1916 RegisterClassW( &wndclass
);
1918 memset( &psp
, 0, sizeof(psp
) );
1919 psp
.dwSize
= sizeof(psp
);
1921 psp
.hInstance
= wndclass
.hInstance
;
1922 psp
.lParam
= (LPARAM
)&di
;
1924 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_OPTION
);
1925 psp
.pfnDlgProc
= option_dialog_proc
;
1926 pages
[0] = CreatePropertySheetPageW( &psp
);
1928 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_FONT
);
1929 psp
.pfnDlgProc
= font_dialog_proc
;
1930 pages
[1] = CreatePropertySheetPageW( &psp
);
1932 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CONFIG
);
1933 psp
.pfnDlgProc
= config_dialog_proc
;
1934 pages
[2] = CreatePropertySheetPageW( &psp
);
1936 memset( &header
, 0, sizeof(header
) );
1937 header
.dwSize
= sizeof(header
);
1939 if (!LoadStringW( GetModuleHandleW( NULL
),
1940 current
? IDS_DLG_TIT_CURRENT
: IDS_DLG_TIT_DEFAULT
,
1941 buff
, ARRAY_SIZE(buff
) ))
1942 wcscpy( buff
, L
"Setup" );
1944 header
.pszCaption
= buff
;
1946 header
.hwndParent
= console
->win
;
1947 header
.u3
.phpage
= pages
;
1948 header
.dwFlags
= PSH_NOAPPLYNOW
;
1949 if (PropertySheetW( &header
) < 1)
1952 if (!memcmp( &prev_config
, &di
.config
, sizeof(prev_config
) ))
1955 TRACE( "%s\n", debugstr_config(&di
.config
) );
1959 apply_config( console
, &di
.config
);
1960 update_window( di
.console
);
1963 save_config( current
? console
->window
->config_key
: NULL
, &di
.config
);
1968 static void resize_window( struct console
*console
, int width
, int height
)
1970 struct console_config config
;
1972 current_config( console
, &config
);
1973 config
.win_width
= width
;
1974 config
.win_height
= height
;
1976 /* auto size screen-buffer if it's now smaller than window */
1977 if (config
.sb_width
< config
.win_width
)
1978 config
.sb_width
= config
.win_width
;
1979 if (config
.sb_height
< config
.win_height
)
1980 config
.sb_height
= config
.win_height
;
1982 /* and reset window pos so that we don't display outside of the screen-buffer */
1983 if (config
.win_pos
.X
+ config
.win_width
> config
.sb_width
)
1984 config
.win_pos
.X
= config
.sb_width
- config
.win_width
;
1985 if (config
.win_pos
.Y
+ config
.win_height
> config
.sb_height
)
1986 config
.win_pos
.Y
= config
.sb_height
- config
.win_height
;
1988 apply_config( console
, &config
);
1991 /* grays / ungrays the menu items according to their state */
1992 static void set_menu_details( struct console
*console
, HMENU menu
)
1994 EnableMenuItem( menu
, IDS_COPY
, MF_BYCOMMAND
|
1995 (console
->window
->in_selection
? MF_ENABLED
: MF_GRAYED
) );
1996 EnableMenuItem( menu
, IDS_PASTE
, MF_BYCOMMAND
|
1997 (IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
) );
1998 EnableMenuItem( menu
, IDS_SCROLL
, MF_BYCOMMAND
| MF_GRAYED
);
1999 EnableMenuItem( menu
, IDS_SEARCH
, MF_BYCOMMAND
| MF_GRAYED
);
2002 static BOOL
fill_menu( HMENU menu
, BOOL sep
)
2004 HINSTANCE module
= GetModuleHandleW( NULL
);
2008 if (!menu
) return FALSE
;
2010 sub_menu
= CreateMenu();
2011 if (!sub_menu
) return FALSE
;
2013 LoadStringW( module
, IDS_MARK
, buff
, ARRAY_SIZE(buff
) );
2014 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
2015 LoadStringW( module
, IDS_COPY
, buff
, ARRAY_SIZE(buff
) );
2016 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
2017 LoadStringW( module
, IDS_PASTE
, buff
, ARRAY_SIZE(buff
) );
2018 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
2019 LoadStringW( module
, IDS_SELECTALL
, buff
, ARRAY_SIZE(buff
) );
2020 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
2021 LoadStringW( module
, IDS_SCROLL
, buff
, ARRAY_SIZE(buff
) );
2022 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
2023 LoadStringW( module
, IDS_SEARCH
, buff
, ARRAY_SIZE(buff
) );
2024 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
2026 if (sep
) InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
2027 LoadStringW( module
, IDS_EDIT
, buff
, ARRAY_SIZE(buff
) );
2028 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)sub_menu
, buff
);
2029 LoadStringW( module
, IDS_DEFAULT
, buff
, ARRAY_SIZE(buff
) );
2030 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
2031 LoadStringW( module
, IDS_PROPERTIES
, buff
, ARRAY_SIZE(buff
) );
2032 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
2037 static LRESULT
window_create( HWND hwnd
, const CREATESTRUCTW
*create
)
2039 struct console
*console
= create
->lpCreateParams
;
2042 TRACE( "%p\n", hwnd
);
2044 SetWindowLongPtrW( hwnd
, 0, (DWORD_PTR
)console
);
2045 console
->win
= hwnd
;
2047 if (console
->window
)
2049 sys_menu
= GetSystemMenu( hwnd
, FALSE
);
2050 if (!sys_menu
) return 0;
2051 console
->window
->popup_menu
= CreatePopupMenu();
2052 if (!console
->window
->popup_menu
) return 0;
2054 fill_menu( sys_menu
, TRUE
);
2055 fill_menu( console
->window
->popup_menu
, FALSE
);
2057 console
->window
->mem_dc
= CreateCompatibleDC( 0 );
2062 static LRESULT WINAPI
window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2064 struct console
*console
= (struct console
*)GetWindowLongPtrW( hwnd
, 0 );
2069 return window_create( hwnd
, (const CREATESTRUCTW
*)lparam
);
2072 console
->win
= NULL
;
2073 PostQuitMessage( 0 );
2077 case WM_UPDATE_CONFIG
:
2078 if (console
->window
&& console
->window
->update_state
== UPDATE_PENDING
)
2079 update_window( console
);
2086 if (!console
->window
) break;
2088 BeginPaint( console
->win
, &ps
);
2089 BitBlt( ps
.hdc
, 0, 0,
2090 (console
->active
->win
.right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
,
2091 (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
,
2092 console
->window
->mem_dc
,
2093 console
->active
->win
.left
* console
->active
->font
.width
,
2094 console
->active
->win
.top
* console
->active
->font
.height
,
2096 if (console
->window
->in_selection
) update_selection( console
, ps
.hdc
);
2097 EndPaint( console
->win
, &ps
);
2102 if (!console
->window
) break;
2104 update_window( console
);
2107 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
2108 console
->window
->bitmap
= NULL
;
2114 if (console
->window
&& console
->window
->in_selection
)
2115 handle_selection_key( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2117 record_key_input( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2122 record_key_input( console
, msg
== WM_SYSKEYDOWN
, wparam
, lparam
);
2125 case WM_LBUTTONDOWN
:
2126 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2128 if (console
->window
->in_selection
)
2129 update_selection( console
, 0 );
2131 if (console
->window
->quick_edit
&& console
->window
->in_selection
)
2133 console
->window
->in_selection
= FALSE
;
2137 console
->window
->selection_end
= get_cell( console
, lparam
);
2138 console
->window
->selection_start
= console
->window
->selection_end
;
2139 SetCapture( console
->win
);
2140 update_selection( console
, 0 );
2141 console
->window
->in_selection
= TRUE
;
2146 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2151 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2153 if (GetCapture() == console
->win
&& console
->window
->in_selection
&&
2154 (wparam
& MK_LBUTTON
))
2156 move_selection( console
, console
->window
->selection_start
,
2157 get_cell(console
, lparam
) );
2162 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, MOUSE_MOVED
);
2167 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2169 if (GetCapture() == console
->win
&& console
->window
->in_selection
)
2171 move_selection( console
, console
->window
->selection_start
,
2172 get_cell(console
, lparam
) );
2178 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2182 case WM_RBUTTONDOWN
:
2183 if (console
->window
&& (wparam
& (MK_CONTROL
|MK_SHIFT
)) == console
->window
->menu_mask
)
2186 pt
.x
= (short)LOWORD(lparam
);
2187 pt
.y
= (short)HIWORD(lparam
);
2188 ClientToScreen( hwnd
, &pt
);
2189 set_menu_details( console
, console
->window
->popup_menu
);
2190 TrackPopupMenu( console
->window
->popup_menu
, TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RIGHTBUTTON
,
2191 pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2195 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2200 /* no need to track for rbutton up when opening the popup... the event will be
2201 * swallowed by TrackPopupMenu */
2202 case WM_MBUTTONDOWN
:
2204 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2207 case WM_LBUTTONDBLCLK
:
2208 case WM_MBUTTONDBLCLK
:
2209 case WM_RBUTTONDBLCLK
:
2210 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, DOUBLE_CLICK
);
2214 if (console
->window
&& console
->active
->cursor_visible
)
2216 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
2217 console
->active
->font
.width
, console
->active
->font
.height
);
2218 update_window_cursor( console
);
2223 if (console
->window
&& console
->active
->cursor_visible
)
2228 if (console
->window
&& console
->window
->update_state
!= UPDATE_BUSY
)
2229 resize_window( console
,
2230 max( LOWORD(lparam
) / console
->active
->font
.width
, 20 ),
2231 max( HIWORD(lparam
) / console
->active
->font
.height
, 20 ));
2236 int win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
2237 int x
= console
->active
->win
.left
;
2239 if (!console
->window
) break;
2240 switch (LOWORD(wparam
))
2242 case SB_PAGEUP
: x
-= 8; break;
2243 case SB_PAGEDOWN
: x
+= 8; break;
2244 case SB_LINEUP
: x
--; break;
2245 case SB_LINEDOWN
: x
++; break;
2246 case SB_THUMBTRACK
: x
= HIWORD(wparam
); break;
2249 x
= min( max( x
, 0 ), console
->active
->width
- win_width
);
2250 if (x
!= console
->active
->win
.left
)
2252 console
->active
->win
.left
= x
;
2253 console
->active
->win
.right
= x
+ win_width
- 1;
2254 update_window( console
);
2260 if (console
->active
->height
<= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
2262 record_mouse_input(console
, get_cell(console
, lparam
), wparam
, MOUSE_WHEELED
);
2265 /* else fallthrough */
2268 int win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
2269 int y
= console
->active
->win
.top
;
2271 if (!console
->window
) break;
2273 if (msg
== WM_MOUSEWHEEL
)
2275 UINT scroll_lines
= 3;
2276 SystemParametersInfoW( SPI_GETWHEELSCROLLLINES
, 0, &scroll_lines
, 0 );
2277 scroll_lines
*= -GET_WHEEL_DELTA_WPARAM(wparam
) / WHEEL_DELTA
;
2282 switch (LOWORD(wparam
))
2284 case SB_PAGEUP
: y
-= 8; break;
2285 case SB_PAGEDOWN
: y
+= 8; break;
2286 case SB_LINEUP
: y
--; break;
2287 case SB_LINEDOWN
: y
++; break;
2288 case SB_THUMBTRACK
: y
= HIWORD(wparam
); break;
2293 y
= min( max( y
, 0 ), console
->active
->height
- win_height
);
2294 if (y
!= console
->active
->win
.top
)
2296 console
->active
->win
.top
= y
;
2297 console
->active
->win
.bottom
= y
+ win_height
- 1;
2298 update_window( console
);
2304 if (!console
->window
) break;
2308 config_dialog( console
, FALSE
);
2310 case IDS_PROPERTIES
:
2311 config_dialog( console
, TRUE
);
2314 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2319 if (!console
->window
) break;
2323 config_dialog( console
, FALSE
);
2325 case IDS_PROPERTIES
:
2326 config_dialog( console
, TRUE
);
2329 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2330 console
->window
->selection_end
.X
= console
->window
->selection_end
.Y
= 0;
2331 update_selection( console
, 0 );
2332 console
->window
->in_selection
= TRUE
;
2335 if (console
->window
->in_selection
)
2337 console
->window
->in_selection
= FALSE
;
2338 update_selection( console
, 0 );
2339 copy_selection( console
);
2343 paste_clipboard( console
);
2346 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2347 console
->window
->selection_end
.X
= console
->active
->width
- 1;
2348 console
->window
->selection_end
.Y
= console
->active
->height
- 1;
2349 update_selection( console
, 0 );
2350 console
->window
->in_selection
= TRUE
;
2354 FIXME( "Unhandled yet command: %Ix\n", wparam
);
2357 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2361 case WM_INITMENUPOPUP
:
2362 if (!console
->window
|| !HIWORD(lparam
)) return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2363 set_menu_details( console
, GetSystemMenu(console
->win
, FALSE
) );
2367 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2373 void update_window_config( struct console
*console
, BOOL delay
)
2375 const int delay_timeout
= 50;
2377 if (!console
->window
|| console
->window
->update_state
!= UPDATE_NONE
) return;
2378 console
->window
->update_state
= UPDATE_PENDING
;
2380 SetTimer( console
->win
, 1, delay_timeout
, NULL
);
2382 PostMessageW( console
->win
, WM_UPDATE_CONFIG
, 0, 0 );
2385 void update_window_region( struct console
*console
, const RECT
*update
)
2387 RECT
*window_rect
= &console
->window
->update
;
2388 window_rect
->left
= min( window_rect
->left
, update
->left
);
2389 window_rect
->top
= min( window_rect
->top
, update
->top
);
2390 window_rect
->right
= max( window_rect
->right
, update
->right
);
2391 window_rect
->bottom
= max( window_rect
->bottom
, update
->bottom
);
2392 update_window_config( console
, TRUE
);
2395 BOOL
init_window( struct console
*console
)
2397 struct console_config config
;
2402 static struct console_window console_window
;
2404 console
->window
= &console_window
;
2405 if (!TranslateCharsetInfo( (DWORD
*)(INT_PTR
)GetACP(), &ci
, TCI_SRCCODEPAGE
))
2408 console
->window
->ui_charset
= ci
.ciCharset
;
2410 GetStartupInfoW(&si
);
2413 size_t i
, title_len
= wcslen( si
.lpTitle
);
2414 if (!(console
->window
->config_key
= malloc( (title_len
+ 1) * sizeof(WCHAR
) )))
2416 for (i
= 0; i
< title_len
; i
++)
2417 console
->window
->config_key
[i
] = si
.lpTitle
[i
] == '\\' ? '_' : si
.lpTitle
[i
];
2418 console
->window
->config_key
[title_len
] = 0;
2421 load_config( console
->window
->config_key
, &config
);
2422 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
2424 config
.sb_width
= si
.dwXCountChars
;
2425 config
.sb_height
= si
.dwYCountChars
;
2427 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
2428 config
.attr
= si
.dwFillAttribute
;
2430 wndclass
.style
= CS_DBLCLKS
;
2431 wndclass
.lpfnWndProc
= window_proc
;
2432 wndclass
.cbClsExtra
= 0;
2433 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2434 wndclass
.hInstance
= GetModuleHandleW(NULL
);
2435 wndclass
.hIcon
= LoadIconW( 0, (const WCHAR
*)IDI_WINLOGO
);
2436 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
2437 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2438 wndclass
.lpszMenuName
= NULL
;
2439 wndclass
.lpszClassName
= L
"WineConsoleClass";
2440 RegisterClassW(&wndclass
);
2442 if (!CreateWindowW( wndclass
.lpszClassName
, NULL
,
2443 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2444 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2445 0, 0, 0, 0, wndclass
.hInstance
, console
))
2448 if (!config
.face_name
[0])
2449 set_first_font( console
, &config
);
2451 apply_config( console
, &config
);
2455 void init_message_window( struct console
*console
)
2459 wndclass
.style
= CS_DBLCLKS
;
2460 wndclass
.lpfnWndProc
= window_proc
;
2461 wndclass
.cbClsExtra
= 0;
2462 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2463 wndclass
.hInstance
= GetModuleHandleW( NULL
);
2465 wndclass
.hCursor
= 0;
2466 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2467 wndclass
.lpszMenuName
= NULL
;
2468 wndclass
.lpszClassName
= L
"WineConsoleClass";
2469 RegisterClassW(&wndclass
);
2471 CreateWindowW( wndclass
.lpszClassName
, NULL
,
2472 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2473 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2474 0, 0, HWND_MESSAGE
, 0, wndclass
.hInstance
, console
);