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
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(console
);
31 #define WM_UPDATE_CONFIG (WM_USER + 1)
42 HDC mem_dc
; /* memory DC holding the bitmap below */
43 HBITMAP bitmap
; /* bitmap of display window content */
44 HFONT font
; /* font used for rendering, usually fixed */
45 HMENU popup_menu
; /* popup menu triggered by right mouse click */
46 HBITMAP cursor_bitmap
; /* bitmap used for the caret */
47 BOOL in_selection
; /* an area is being selected */
48 COORD selection_start
; /* selection coordinates */
50 unsigned int ui_charset
; /* default UI charset */
51 WCHAR
*config_key
; /* config registry key name */
52 LONG ext_leading
; /* external leading for font */
54 BOOL quick_edit
; /* whether mouse ops are sent to app or used for content selection */
55 unsigned int menu_mask
; /* MK_CONTROL MK_SHIFT mask to drive submenu opening */
56 COORD win_pos
; /* position (in cells) of visible part of screen buffer in window */
57 unsigned int win_width
; /* size (in cells) of visible part of window (width & height) */
58 unsigned int win_height
;
59 unsigned int cursor_size
; /* in % of cell height */
60 int cursor_visible
; /* cursor visibility */
61 unsigned int sb_width
; /* active screen buffer width */
62 unsigned int sb_height
; /* active screen buffer height */
63 COORD cursor_pos
; /* cursor position */
65 RECT update
; /* screen buffer update rect */
66 enum update_state update_state
; /* update state */
71 DWORD color_map
[16]; /* console color table */
72 unsigned int cell_width
; /* width in pixels of a character */
73 unsigned int cell_height
; /* height in pixels of a character */
74 unsigned int cursor_size
; /* in % of cell height */
75 int cursor_visible
; /* cursor visibility */
76 unsigned int attr
; /* default fill attributes (screen colors) */
77 unsigned int popup_attr
; /* pop-up color attributes */
78 unsigned int history_size
; /* number of commands in history buffer */
79 unsigned int history_mode
; /* flag if commands are not stored twice in buffer */
80 unsigned int insert_mode
; /* TRUE to insert text at the cursor location; FALSE to overwrite it */
81 unsigned int menu_mask
; /* MK_CONTROL MK_SHIFT mask to drive submenu opening */
82 unsigned int quick_edit
; /* whether mouse ops are sent to app or used for content selection */
83 unsigned int sb_width
; /* active screen buffer width */
84 unsigned int sb_height
; /* active screen buffer height */
85 unsigned int win_width
; /* size (in cells) of visible part of window (width & height) */
86 unsigned int win_height
;
87 COORD win_pos
; /* position (in cells) of visible part of screen buffer in window */
88 unsigned int edition_mode
; /* edition mode flavor while line editing */
89 unsigned int font_pitch_family
;
90 unsigned int font_weight
;
91 WCHAR face_name
[LF_FACESIZE
];
94 static const char *debugstr_config( const struct console_config
*config
)
96 return wine_dbg_sprintf( "cell=(%u,%u) cursor=(%d,%d) attr=%02x pop-up=%02x font=%s/%u/%u "
97 "hist=%u/%d flags=%c%c msk=%08x sb=(%u,%u) win=(%u,%u)x(%u,%u) edit=%u",
98 config
->cell_width
, config
->cell_height
, config
->cursor_size
,
99 config
->cursor_visible
, config
->attr
, config
->popup_attr
,
100 wine_dbgstr_w(config
->face_name
), config
->font_pitch_family
,
101 config
->font_weight
, config
->history_size
,
102 config
->history_mode
? 1 : 2,
103 config
->insert_mode
? 'I' : 'i',
104 config
->quick_edit
? 'Q' : 'q',
105 config
->menu_mask
, config
->sb_width
, config
->sb_height
,
106 config
->win_pos
.X
, config
->win_pos
.Y
, config
->win_width
,
107 config
->win_height
, config
->edition_mode
);
110 static const char *debugstr_logfont( const LOGFONTW
*lf
, unsigned int ft
)
112 return wine_dbg_sprintf( "%s%s%s%s lfHeight=%ld lfWidth=%ld lfEscapement=%ld "
113 "lfOrientation=%ld lfWeight=%ld lfItalic=%u lfUnderline=%u "
114 "lfStrikeOut=%u lfCharSet=%u lfPitchAndFamily=%u lfFaceName=%s",
115 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
116 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
117 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
118 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
119 lf
->lfHeight
, lf
->lfWidth
, lf
->lfEscapement
, lf
->lfOrientation
,
120 lf
->lfWeight
, lf
->lfItalic
, lf
->lfUnderline
, lf
->lfStrikeOut
,
121 lf
->lfCharSet
, lf
->lfPitchAndFamily
, wine_dbgstr_w( lf
->lfFaceName
));
124 static const char *debugstr_textmetric( const TEXTMETRICW
*tm
, unsigned int ft
)
126 return wine_dbg_sprintf( "%s%s%s%s tmHeight=%ld tmAscent=%ld tmDescent=%ld "
127 "tmAveCharWidth=%ld tmMaxCharWidth=%ld tmWeight=%ld "
128 "tmPitchAndFamily=%u tmCharSet=%u",
129 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
130 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
131 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
132 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
133 tm
->tmHeight
, tm
->tmAscent
, tm
->tmDescent
, tm
->tmAveCharWidth
,
134 tm
->tmMaxCharWidth
, tm
->tmWeight
, tm
->tmPitchAndFamily
,
138 /* read the basic configuration from any console key or subkey */
139 static void load_registry_key( HKEY key
, struct console_config
*config
)
141 DWORD type
, count
, val
, i
;
142 WCHAR color_name
[13];
144 for (i
= 0; i
< ARRAY_SIZE(config
->color_map
); i
++)
146 wsprintfW( color_name
, L
"ColorTable%02d", i
);
148 if (!RegQueryValueExW( key
, color_name
, 0, &type
, (BYTE
*)&val
, &count
))
149 config
->color_map
[i
] = val
;
153 if (!RegQueryValueExW( key
, L
"CursorSize", 0, &type
, (BYTE
*)&val
, &count
))
154 config
->cursor_size
= val
;
157 if (!RegQueryValueExW( key
, L
"CursorVisible", 0, &type
, (BYTE
*)&val
, &count
))
158 config
->cursor_visible
= val
;
161 if (!RegQueryValueExW( key
, L
"EditionMode", 0, &type
, (BYTE
*)&val
, &count
))
162 config
->edition_mode
= val
;
164 count
= sizeof(config
->face_name
);
165 RegQueryValueExW( key
, L
"FaceName", 0, &type
, (BYTE
*)&config
->face_name
, &count
);
168 if (!RegQueryValueExW( key
, L
"FontFamily", 0, &type
, (BYTE
*)&val
, &count
) ||
169 !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
"FontFamily", 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 if (!console
->window
) return;
936 fill_logfont( &lf
, face_name
, face_name_size
, height
, weight
);
938 set_console_font( console
, &lf
);
941 /* get a cell from a relative coordinate in window (takes into account the scrolling) */
942 static COORD
get_cell( struct console
*console
, LPARAM lparam
)
945 c
.X
= console
->active
->win
.left
+ (short)LOWORD(lparam
) / console
->active
->font
.width
;
946 c
.Y
= console
->active
->win
.top
+ (short)HIWORD(lparam
) / console
->active
->font
.height
;
950 /* get the console bit mask equivalent to the VK_ status in key state */
951 static DWORD
get_ctrl_state( BYTE
*key_state
)
953 unsigned int ret
= 0;
955 GetKeyboardState(key_state
);
956 if (key_state
[VK_SHIFT
] & 0x80) ret
|= SHIFT_PRESSED
;
957 if (key_state
[VK_LCONTROL
] & 0x80) ret
|= LEFT_CTRL_PRESSED
;
958 if (key_state
[VK_RCONTROL
] & 0x80) ret
|= RIGHT_CTRL_PRESSED
;
959 if (key_state
[VK_LMENU
] & 0x80) ret
|= LEFT_ALT_PRESSED
;
960 if (key_state
[VK_RMENU
] & 0x80) ret
|= RIGHT_ALT_PRESSED
;
961 if (key_state
[VK_CAPITAL
] & 0x01) ret
|= CAPSLOCK_ON
;
962 if (key_state
[VK_NUMLOCK
] & 0x01) ret
|= NUMLOCK_ON
;
963 if (key_state
[VK_SCROLL
] & 0x01) ret
|= SCROLLLOCK_ON
;
968 /* get the selection rectangle */
969 static void get_selection_rect( struct console
*console
, RECT
*r
)
971 r
->left
= (min(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) -
972 console
->active
->win
.left
) * console
->active
->font
.width
;
973 r
->top
= (min(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) -
974 console
->active
->win
.top
) * console
->active
->font
.height
;
975 r
->right
= (max(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) + 1 -
976 console
->active
->win
.left
) * console
->active
->font
.width
;
977 r
->bottom
= (max(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) + 1 -
978 console
->active
->win
.top
) * console
->active
->font
.height
;
981 static void update_selection( struct console
*console
, HDC ref_dc
)
986 get_selection_rect( console
, &r
);
987 dc
= ref_dc
? ref_dc
: GetDC( console
->win
);
990 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
991 HideCaret( console
->win
);
992 InvertRect( dc
, &r
);
994 ReleaseDC( console
->win
, dc
);
995 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
996 ShowCaret( console
->win
);
999 static void move_selection( struct console
*console
, COORD c1
, COORD c2
)
1004 if (c1
.X
< 0 || c1
.X
>= console
->active
->width
||
1005 c2
.X
< 0 || c2
.X
>= console
->active
->width
||
1006 c1
.Y
< 0 || c1
.Y
>= console
->active
->height
||
1007 c2
.Y
< 0 || c2
.Y
>= console
->active
->height
)
1010 get_selection_rect( console
, &r
);
1011 dc
= GetDC( console
->win
);
1014 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
1015 HideCaret( console
->win
);
1016 InvertRect( dc
, &r
);
1018 console
->window
->selection_start
= c1
;
1019 console
->window
->selection_end
= c2
;
1022 get_selection_rect( console
, &r
);
1023 InvertRect( dc
, &r
);
1024 ReleaseDC( console
->win
, dc
);
1025 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
1026 ShowCaret( console
->win
);
1030 /* copies the current selection into the clipboard */
1031 static void copy_selection( struct console
*console
)
1037 w
= abs( console
->window
->selection_start
.X
- console
->window
->selection_end
.X
) + 1;
1038 h
= abs( console
->window
->selection_start
.Y
- console
->window
->selection_end
.Y
) + 1;
1040 if (!OpenClipboard( console
->win
)) return;
1043 mem
= GlobalAlloc( GMEM_MOVEABLE
, (w
+ 1) * h
* sizeof(WCHAR
) );
1044 if (mem
&& (p
= buf
= GlobalLock( mem
)))
1049 c
.X
= min( console
->window
->selection_start
.X
, console
->window
->selection_end
.X
);
1050 c
.Y
= min( console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
);
1052 for (y
= c
.Y
; y
< c
.Y
+ h
; y
++)
1056 for (x
= c
.X
; x
< c
.X
+ w
; x
++)
1057 p
[x
- c
.X
] = console
->active
->data
[y
* console
->active
->width
+ x
].ch
;
1059 /* strip spaces from the end of the line */
1061 while (end
> p
&& *(end
- 1) == ' ')
1063 *end
= (y
< c
.Y
+ h
- 1) ? '\n' : '\0';
1067 TRACE( "%s\n", debugstr_w( buf
));
1068 if (p
- buf
!= (w
+ 1) * h
)
1071 new_mem
= GlobalReAlloc( mem
, (p
- buf
) * sizeof(WCHAR
), GMEM_MOVEABLE
);
1072 if (new_mem
) mem
= new_mem
;
1074 GlobalUnlock( mem
);
1075 SetClipboardData( CF_UNICODETEXT
, mem
);
1080 static void paste_clipboard( struct console
*console
)
1085 if (!OpenClipboard( console
->win
)) return;
1086 h
= GetClipboardData( CF_UNICODETEXT
);
1087 if (h
&& (ptr
= GlobalLock( h
)))
1089 unsigned int i
, len
= GlobalSize(h
) / sizeof(WCHAR
);
1093 ir
[0].EventType
= KEY_EVENT
;
1094 ir
[0].Event
.KeyEvent
.wRepeatCount
= 0;
1095 ir
[0].Event
.KeyEvent
.dwControlKeyState
= 0;
1096 ir
[0].Event
.KeyEvent
.bKeyDown
= TRUE
;
1098 /* generate the corresponding input records */
1099 for (i
= 0; i
< len
; i
++)
1101 /* FIXME: the modifying keys are not generated (shift, ctrl...) */
1102 sh
= VkKeyScanW( ptr
[i
] );
1103 ir
[0].Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(sh
);
1104 ir
[0].Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKeyW( LOBYTE(sh
), 0 );
1105 ir
[0].Event
.KeyEvent
.uChar
.UnicodeChar
= ptr
[i
];
1108 ir
[1].Event
.KeyEvent
.bKeyDown
= FALSE
;
1110 write_console_input( console
, ir
, 2, i
== len
- 1 );
1118 /* handle keys while selecting an area */
1119 static void handle_selection_key( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1121 BYTE key_state
[256];
1126 state
= get_ctrl_state( key_state
) & ~(CAPSLOCK_ON
|NUMLOCK_ON
|SCROLLLOCK_ON
);
1134 console
->window
->in_selection
= FALSE
;
1135 update_selection( console
, 0 );
1136 copy_selection( console
);
1139 c1
= console
->window
->selection_start
;
1140 c2
= console
->window
->selection_end
;
1142 move_selection( console
, c1
, c2
);
1145 c1
= console
->window
->selection_start
;
1146 c2
= console
->window
->selection_end
;
1148 move_selection( console
, c1
, c2
);
1151 c1
= console
->window
->selection_start
;
1152 c2
= console
->window
->selection_end
;
1154 move_selection( console
, c1
, c2
);
1157 c1
= console
->window
->selection_start
;
1158 c2
= console
->window
->selection_end
;
1160 move_selection( console
, c1
, c2
);
1168 c1
= console
->window
->selection_start
;
1169 c2
= console
->window
->selection_end
;
1171 move_selection( console
, c1
, c2
);
1174 c1
= console
->window
->selection_start
;
1175 c2
= console
->window
->selection_end
;
1177 move_selection( console
, c1
, c2
);
1180 c1
= console
->window
->selection_start
;
1181 c2
= console
->window
->selection_end
;
1183 move_selection( console
, c1
, c2
);
1186 c1
= console
->window
->selection_start
;
1187 c2
= console
->window
->selection_end
;
1189 move_selection( console
, c1
, c2
);
1195 if (wparam
< VK_SPACE
) /* Shift, Alt, Ctrl, Num Lock etc. */
1198 update_selection( console
, 0 );
1199 console
->window
->in_selection
= FALSE
;
1202 /* generate input_record from windows WM_KEYUP/WM_KEYDOWN messages */
1203 static void record_key_input( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1205 static WCHAR last
; /* keep last char seen as feed for key up message */
1206 BYTE key_state
[256];
1210 ir
.EventType
= KEY_EVENT
;
1211 ir
.Event
.KeyEvent
.bKeyDown
= down
;
1212 ir
.Event
.KeyEvent
.wRepeatCount
= LOWORD(lparam
);
1213 ir
.Event
.KeyEvent
.wVirtualKeyCode
= wparam
;
1214 ir
.Event
.KeyEvent
.wVirtualScanCode
= HIWORD(lparam
) & 0xFF;
1215 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
1216 ir
.Event
.KeyEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1217 if (lparam
& (1u << 24)) ir
.Event
.KeyEvent
.dwControlKeyState
|= ENHANCED_KEY
;
1221 switch (ToUnicode(wparam
, HIWORD(lparam
), key_state
, buf
, 2, 0))
1224 /* FIXME: should generate two events */
1234 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= last
;
1235 if (!down
) last
= 0; /* FIXME: buggy HACK */
1237 write_console_input( console
, &ir
, 1, TRUE
);
1240 static void record_mouse_input( struct console
*console
, COORD c
, WPARAM wparam
, DWORD event
)
1242 BYTE key_state
[256];
1245 /* MOUSE_EVENTs shouldn't be sent unless ENABLE_MOUSE_INPUT is active */
1246 if (!(console
->mode
& ENABLE_MOUSE_INPUT
)) return;
1248 ir
.EventType
= MOUSE_EVENT
;
1249 ir
.Event
.MouseEvent
.dwMousePosition
= c
;
1250 ir
.Event
.MouseEvent
.dwButtonState
= 0;
1251 if (wparam
& MK_LBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1252 if (wparam
& MK_MBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1253 if (wparam
& MK_RBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1254 if (wparam
& MK_CONTROL
) ir
.Event
.MouseEvent
.dwButtonState
|= LEFT_CTRL_PRESSED
;
1255 if (wparam
& MK_SHIFT
) ir
.Event
.MouseEvent
.dwButtonState
|= SHIFT_PRESSED
;
1256 if (event
== MOUSE_WHEELED
) ir
.Event
.MouseEvent
.dwButtonState
|= wparam
& 0xFFFF0000;
1257 ir
.Event
.MouseEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1258 ir
.Event
.MouseEvent
.dwEventFlags
= event
;
1260 write_console_input( console
, &ir
, 1, TRUE
);
1265 struct console
*console
;
1266 struct console_config config
;
1267 HWND dialog
; /* handle to active propsheet */
1270 /* dialog proc for the option property sheet */
1271 static INT_PTR WINAPI
option_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1273 struct dialog_info
*di
;
1279 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1280 di
->dialog
= dialog
;
1281 SetWindowLongPtrW( dialog
, DWLP_USER
, (LONG_PTR
)di
);
1283 SendMessageW( GetDlgItem( dialog
, IDC_OPT_HIST_SIZE_UD
), UDM_SETRANGE
, 0, MAKELPARAM(500, 0) );
1285 if (di
->config
.cursor_size
<= 25) idc
= IDC_OPT_CURSOR_SMALL
;
1286 else if (di
->config
.cursor_size
<= 50) idc
= IDC_OPT_CURSOR_MEDIUM
;
1287 else idc
= IDC_OPT_CURSOR_LARGE
;
1289 SendDlgItemMessageW( dialog
, idc
, BM_SETCHECK
, BST_CHECKED
, 0 );
1290 SetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, di
->config
.history_size
, FALSE
);
1291 SendDlgItemMessageW( dialog
, IDC_OPT_HIST_NODOUBLE
, BM_SETCHECK
,
1292 (di
->config
.history_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1293 SendDlgItemMessageW( dialog
, IDC_OPT_INSERT_MODE
, BM_SETCHECK
,
1294 (di
->config
.insert_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1295 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_CTRL
, BM_SETCHECK
,
1296 (di
->config
.menu_mask
& MK_CONTROL
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1297 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_SHIFT
, BM_SETCHECK
,
1298 (di
->config
.menu_mask
& MK_SHIFT
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1299 SendDlgItemMessageW( dialog
, IDC_OPT_QUICK_EDIT
, BM_SETCHECK
,
1300 (di
->config
.quick_edit
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1301 return FALSE
; /* because we set the focus */
1308 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1312 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1314 switch (nmhdr
->code
)
1317 /* needed in propsheet to keep properly the selected radio button
1318 * otherwise, the focus would be set to the first tab stop in the
1319 * propsheet, which would always activate the first radio button
1321 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
)
1322 idc
= IDC_OPT_CURSOR_SMALL
;
1323 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
)
1324 idc
= IDC_OPT_CURSOR_MEDIUM
;
1326 idc
= IDC_OPT_CURSOR_LARGE
;
1327 PostMessageW( dialog
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem( dialog
, idc
), TRUE
);
1328 di
->dialog
= dialog
;
1331 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
) val
= 25;
1332 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
) val
= 50;
1334 di
->config
.cursor_size
= val
;
1336 val
= GetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, &done
, FALSE
);
1337 if (done
) di
->config
.history_size
= val
;
1339 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_HIST_NODOUBLE
) & BST_CHECKED
) != 0;
1340 di
->config
.history_mode
= val
;
1342 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_INSERT_MODE
) & BST_CHECKED
) != 0;
1343 di
->config
.insert_mode
= val
;
1346 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_CTRL
) & BST_CHECKED
) val
|= MK_CONTROL
;
1347 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_SHIFT
) & BST_CHECKED
) val
|= MK_SHIFT
;
1348 di
->config
.menu_mask
= val
;
1350 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_QUICK_EDIT
) & BST_CHECKED
) != 0;
1351 di
->config
.quick_edit
= val
;
1353 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1366 static COLORREF
get_color( struct dialog_info
*di
, unsigned int idc
)
1370 index
= GetWindowLongPtrW(GetDlgItem( di
->dialog
, idc
), 0);
1371 return di
->config
.color_map
[index
];
1374 /* window proc for font previewer in font property sheet */
1375 static LRESULT WINAPI
font_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1380 SetWindowLongPtrW( hwnd
, 0, 0 );
1384 return GetWindowLongPtrW( hwnd
, 0 );
1387 SetWindowLongPtrW( hwnd
, 0, wparam
);
1390 InvalidateRect( hwnd
, NULL
, TRUE
);
1391 UpdateWindow( hwnd
);
1397 HFONT font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1398 if (font
) DeleteObject( font
);
1404 struct dialog_info
*di
;
1405 HFONT font
, old_font
;
1408 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent( hwnd
), DWLP_USER
);
1409 BeginPaint( hwnd
, &ps
);
1411 font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1414 static const WCHAR ascii
[] = L
"ASCII: abcXYZ";
1419 old_font
= SelectObject( ps
.hdc
, font
);
1420 bkcolor
= get_color( di
, IDC_FNT_COLOR_BK
);
1421 FillRect( ps
.hdc
, &ps
.rcPaint
, CreateSolidBrush( bkcolor
));
1422 SetBkColor( ps
.hdc
, bkcolor
);
1423 SetTextColor( ps
.hdc
, get_color( di
, IDC_FNT_COLOR_FG
));
1424 len
= LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_PREVIEW
, buf
, ARRAY_SIZE(buf
) );
1425 if (len
) TextOutW( ps
.hdc
, 0, 0, buf
, len
);
1426 TextOutW( ps
.hdc
, 0, di
->config
.cell_height
, ascii
, ARRAY_SIZE(ascii
) - 1 );
1427 SelectObject( ps
.hdc
, old_font
);
1429 EndPaint( hwnd
, &ps
);
1434 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1439 /* window proc for color previewer */
1440 static LRESULT WINAPI
color_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1446 struct dialog_info
*di
;
1452 BeginPaint( hwnd
, &ps
);
1453 GetClientRect( hwnd
, &client
);
1454 step
= client
.right
/ 8;
1456 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent(hwnd
), DWLP_USER
);
1458 for (i
= 0; i
< 16; i
++)
1460 r
.top
= (i
/ 8) * (client
.bottom
/ 2);
1461 r
.bottom
= r
.top
+ client
.bottom
/ 2;
1462 r
.left
= (i
& 7) * step
;
1463 r
.right
= r
.left
+ step
;
1464 brush
= CreateSolidBrush( di
->config
.color_map
[i
] );
1465 FillRect( ps
.hdc
, &r
, brush
);
1466 DeleteObject( brush
);
1467 if (GetWindowLongW( hwnd
, 0 ) == i
)
1472 old_pen
= SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1473 r
.right
--; r
.bottom
--;
1476 MoveToEx( ps
.hdc
, r
.left
, r
.bottom
, NULL
);
1477 LineTo( ps
.hdc
, r
.left
, r
.top
);
1478 LineTo( ps
.hdc
, r
.right
, r
.top
);
1479 SelectObject( ps
.hdc
, GetStockObject( BLACK_PEN
));
1480 LineTo( ps
.hdc
, r
.right
, r
.bottom
);
1481 LineTo( ps
.hdc
, r
.left
, r
.bottom
);
1482 if (--i
== 0) break;
1483 r
.left
++; r
.top
++; r
.right
--; r
.bottom
--;
1484 SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1486 SelectObject( ps
.hdc
, old_pen
);
1489 EndPaint( hwnd
, &ps
);
1493 case WM_LBUTTONDOWN
:
1498 GetClientRect( hwnd
, &client
);
1499 step
= client
.right
/ 8;
1500 i
= (HIWORD(lparam
) >= client
.bottom
/ 2) ? 8 : 0;
1501 i
+= LOWORD(lparam
) / step
;
1502 SetWindowLongW( hwnd
, 0, i
);
1503 InvalidateRect( GetDlgItem( GetParent( hwnd
), IDC_FNT_PREVIEW
), NULL
, FALSE
);
1504 InvalidateRect( hwnd
, NULL
, FALSE
);
1509 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1514 static BOOL
select_font( struct dialog_info
*di
)
1516 int font_idx
, size_idx
;
1517 WCHAR face_name
[LF_FACESIZE
], height_buf
[4];
1519 unsigned int font_height
;
1521 HFONT font
, old_font
;
1526 font_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETCURSEL
, 0, 0 );
1527 size_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1529 if (font_idx
< 0 || size_idx
< 0)
1532 len
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETTEXT
, font_idx
, (LPARAM
)&face_name
);
1533 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETTEXT
, size_idx
, (LPARAM
)&height_buf
);
1534 font_height
= _wtoi( height_buf
);
1536 fill_logfont( &lf
, face_name
, len
* sizeof(WCHAR
), font_height
, FW_NORMAL
);
1537 font
= select_font_config( &di
->config
, di
->console
->output_cp
, di
->console
->win
, &lf
);
1538 if (!font
) return FALSE
;
1540 if (di
->config
.cell_height
!= font_height
)
1541 TRACE( "mismatched heights (%u<>%u)\n", di
->config
.cell_height
, font_height
);
1543 old_font
= (HFONT
)SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_GETFONT
, 0, 0 );
1544 SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1545 if (old_font
) DeleteObject( old_font
);
1547 LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_DISPLAY
, fmt
, ARRAY_SIZE(fmt
) );
1548 args
[0] = di
->config
.cell_width
;
1549 args
[1] = di
->config
.cell_height
;
1550 FormatMessageW( FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
1551 fmt
, 0, 0, buf
, ARRAY_SIZE(buf
), (va_list *)args
);
1553 SendDlgItemMessageW( di
->dialog
, IDC_FNT_FONT_INFO
, WM_SETTEXT
, 0, (LPARAM
)buf
);
1557 static BOOL
fill_list_size( struct dialog_info
*di
, BOOL init
)
1561 static const int sizes
[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
1562 unsigned int i
, idx
= 4;
1565 for (i
= 0; i
< ARRAY_SIZE(sizes
); i
++)
1567 wsprintfW( buf
, L
"%u", sizes
[i
] );
1568 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_INSERTSTRING
, -1, (LPARAM
)buf
);
1570 if (di
->config
.cell_height
== sizes
[i
]) idx
= i
;
1573 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_SETCURSEL
, idx
, 0 );
1581 static int CALLBACK
enum_list_font_proc( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1582 DWORD font_type
, LPARAM lparam
)
1584 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1586 if (font_type
!= TRUETYPE_FONTTYPE
) return 1;
1588 TRACE( "%s\n", debugstr_logfont( lf
, font_type
));
1590 if (validate_font( di
->console
, lf
, 0 ))
1591 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_ADDSTRING
, 0, (LPARAM
)lf
->lfFaceName
);
1596 static BOOL
fill_list_font( struct dialog_info
*di
)
1600 memset( &lf
, 0, sizeof(lf
) );
1601 lf
.lfCharSet
= DEFAULT_CHARSET
;
1602 lf
.lfFaceName
[0] = 0;
1603 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
1605 EnumFontFamiliesExW( di
->console
->window
->mem_dc
, &lf
, enum_list_font_proc
, (LPARAM
)di
, 0 );
1607 if (SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SELECTSTRING
,
1608 -1, (LPARAM
)di
->config
.face_name
) == LB_ERR
)
1609 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SETCURSEL
, 0, 0 );
1611 fill_list_size( di
, TRUE
);
1616 /* dialog proc for the font property sheet */
1617 static INT_PTR WINAPI
font_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1619 struct dialog_info
*di
;
1624 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1625 di
->dialog
= dialog
;
1626 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1627 /* use default system font until user-selected font is applied */
1628 SendDlgItemMessageW( dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, 0, 0 );
1629 fill_list_font( di
);
1630 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0, (di
->config
.attr
>> 4) & 0x0F );
1631 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0, di
->config
.attr
& 0x0F );
1635 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1636 switch (LOWORD(wparam
))
1638 case IDC_FNT_LIST_FONT
:
1639 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1640 fill_list_size( di
, FALSE
);
1642 case IDC_FNT_LIST_SIZE
:
1643 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1651 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1654 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1655 switch (nmhdr
->code
)
1658 di
->dialog
= dialog
;
1661 val
= (GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0 ) << 4) |
1662 GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0 );
1663 di
->config
.attr
= val
;
1664 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1677 /* dialog proc for the config property sheet */
1678 static INT_PTR WINAPI
config_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1680 struct dialog_info
*di
;
1686 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1687 di
->dialog
= dialog
;
1689 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1690 SetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, di
->config
.sb_width
, FALSE
);
1691 SetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, di
->config
.sb_height
, FALSE
);
1692 SetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, di
->config
.win_width
, FALSE
);
1693 SetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, di
->config
.win_height
, FALSE
);
1695 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1696 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1697 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1698 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1700 SendDlgItemMessageW( dialog
, IDC_CNF_CLOSE_EXIT
, BM_SETCHECK
, BST_CHECKED
, 0 );
1702 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Win32" );
1703 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Emacs" );
1704 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_SETCURSEL
, di
->config
.edition_mode
, 0 );
1709 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1710 int win_w
, win_h
, sb_w
, sb_h
;
1713 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1714 switch (nmhdr
->code
)
1717 di
->dialog
= dialog
;
1720 sb_w
= GetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, &st1
, FALSE
);
1721 sb_h
= GetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, &st2
, FALSE
);
1724 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1727 win_w
= GetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, &st1
, FALSE
);
1728 win_h
= GetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, &st2
, FALSE
);
1731 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1734 if (win_w
> sb_w
|| win_h
> sb_h
)
1739 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_TIT_ERROR
, cap
, ARRAY_SIZE(cap
) );
1740 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_ERR_SBWINSIZE
, txt
, ARRAY_SIZE(txt
) );
1742 MessageBoxW( dialog
, txt
, cap
, MB_OK
);
1743 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1746 di
->config
.win_width
= win_w
;
1747 di
->config
.win_height
= win_h
;
1748 di
->config
.sb_width
= sb_w
;
1749 di
->config
.sb_height
= sb_h
;
1751 di
->config
.edition_mode
= SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
,
1752 CB_GETCURSEL
, 0, 0 );
1753 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1766 static void apply_config( struct console
*console
, const struct console_config
*config
)
1768 if (console
->active
->width
!= config
->sb_width
|| console
->active
->height
!= config
->sb_height
)
1769 change_screen_buffer_size( console
->active
, config
->sb_width
, config
->sb_height
);
1771 console
->window
->menu_mask
= config
->menu_mask
;
1772 console
->window
->quick_edit
= config
->quick_edit
;
1774 console
->edition_mode
= config
->edition_mode
;
1775 console
->history_mode
= config
->history_mode
;
1777 if (console
->history_size
!= config
->history_size
)
1779 struct history_line
**mem
= NULL
;
1782 if (config
->history_size
&& (mem
= malloc( config
->history_size
* sizeof(*mem
) )))
1784 memset( mem
, 0, config
->history_size
* sizeof(*mem
) );
1786 delta
= (console
->history_index
> config
->history_size
)
1787 ? (console
->history_index
- config
->history_size
) : 0;
1789 for (i
= delta
; i
< console
->history_index
; i
++)
1791 mem
[i
- delta
] = console
->history
[i
];
1792 console
->history
[i
] = NULL
;
1794 console
->history_index
-= delta
;
1796 for (i
= 0; i
< console
->history_size
; i
++)
1797 free( console
->history
[i
] );
1798 free( console
->history
);
1799 console
->history
= mem
;
1800 console
->history_size
= config
->history_size
;
1804 if (config
->insert_mode
)
1805 console
->mode
|= ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
;
1807 console
->mode
&= ~ENABLE_INSERT_MODE
;
1809 console
->active
->cursor_size
= config
->cursor_size
;
1810 console
->active
->cursor_visible
= config
->cursor_visible
;
1811 console
->active
->attr
= config
->attr
;
1812 console
->active
->popup_attr
= config
->popup_attr
;
1813 console
->active
->win
.left
= config
->win_pos
.X
;
1814 console
->active
->win
.top
= config
->win_pos
.Y
;
1815 console
->active
->win
.right
= config
->win_pos
.X
+ config
->win_width
- 1;
1816 console
->active
->win
.bottom
= config
->win_pos
.Y
+ config
->win_height
- 1;
1817 memcpy( console
->active
->color_map
, config
->color_map
, sizeof(config
->color_map
) );
1819 if (console
->active
->font
.width
!= config
->cell_width
||
1820 console
->active
->font
.height
!= config
->cell_height
||
1821 console
->active
->font
.weight
!= config
->font_weight
||
1822 console
->active
->font
.pitch_family
!= config
->font_pitch_family
||
1823 console
->active
->font
.face_len
!= wcslen( config
->face_name
) ||
1824 memcmp( console
->active
->font
.face_name
, config
->face_name
,
1825 console
->active
->font
.face_len
* sizeof(WCHAR
) ))
1827 update_console_font( console
, config
->face_name
, wcslen(config
->face_name
) * sizeof(WCHAR
),
1828 config
->cell_height
, config
->font_weight
);
1831 update_window( console
);
1833 notify_screen_buffer_size( console
->active
);
1836 static void current_config( struct console
*console
, struct console_config
*config
)
1840 config
->menu_mask
= console
->window
->menu_mask
;
1841 config
->quick_edit
= console
->window
->quick_edit
;
1843 config
->edition_mode
= console
->edition_mode
;
1844 config
->history_mode
= console
->history_mode
;
1845 config
->history_size
= console
->history_size
;
1847 config
->insert_mode
= (console
->mode
& (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
)) ==
1848 (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
);
1850 config
->cursor_size
= console
->active
->cursor_size
;
1851 config
->cursor_visible
= console
->active
->cursor_visible
;
1852 config
->attr
= console
->active
->attr
;
1853 config
->popup_attr
= console
->active
->popup_attr
;
1854 memcpy( config
->color_map
, console
->active
->color_map
, sizeof(config
->color_map
) );
1856 config
->cell_width
= console
->active
->font
.width
;
1857 config
->cell_height
= console
->active
->font
.height
;
1858 config
->font_weight
= console
->active
->font
.weight
;
1859 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
1860 len
= min( ARRAY_SIZE(config
->face_name
) - 1, console
->active
->font
.face_len
);
1861 if (len
) memcpy( config
->face_name
, console
->active
->font
.face_name
, len
* sizeof(WCHAR
) );
1862 config
->face_name
[len
] = 0;
1864 config
->sb_width
= console
->active
->width
;
1865 config
->sb_height
= console
->active
->height
;
1867 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1868 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1869 config
->win_pos
.X
= console
->active
->win
.left
;
1870 config
->win_pos
.Y
= console
->active
->win
.top
;
1873 /* run the dialog box to set up the console options */
1874 static BOOL
config_dialog( struct console
*console
, BOOL current
)
1876 struct console_config prev_config
;
1877 struct dialog_info di
;
1878 PROPSHEETHEADERW header
;
1879 HPROPSHEETPAGE pages
[3];
1884 InitCommonControls();
1886 memset( &di
, 0, sizeof(di
) );
1887 di
.console
= console
;
1890 current_config( console
, &di
.config
);
1892 load_config( NULL
, &di
.config
);
1894 prev_config
= di
.config
;
1897 wndclass
.lpfnWndProc
= font_preview_proc
;
1898 wndclass
.cbClsExtra
= 0;
1899 wndclass
.cbWndExtra
= sizeof(HFONT
);
1900 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1902 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1903 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1904 wndclass
.lpszMenuName
= NULL
;
1905 wndclass
.lpszClassName
= L
"WineConFontPreview";
1906 RegisterClassW( &wndclass
);
1909 wndclass
.lpfnWndProc
= color_preview_proc
;
1910 wndclass
.cbClsExtra
= 0;
1911 wndclass
.cbWndExtra
= sizeof(DWORD
);
1912 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1914 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1915 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1916 wndclass
.lpszMenuName
= NULL
;
1917 wndclass
.lpszClassName
= L
"WineConColorPreview";
1918 RegisterClassW( &wndclass
);
1920 memset( &psp
, 0, sizeof(psp
) );
1921 psp
.dwSize
= sizeof(psp
);
1923 psp
.hInstance
= wndclass
.hInstance
;
1924 psp
.lParam
= (LPARAM
)&di
;
1926 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_OPTION
);
1927 psp
.pfnDlgProc
= option_dialog_proc
;
1928 pages
[0] = CreatePropertySheetPageW( &psp
);
1930 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_FONT
);
1931 psp
.pfnDlgProc
= font_dialog_proc
;
1932 pages
[1] = CreatePropertySheetPageW( &psp
);
1934 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_CONFIG
);
1935 psp
.pfnDlgProc
= config_dialog_proc
;
1936 pages
[2] = CreatePropertySheetPageW( &psp
);
1938 memset( &header
, 0, sizeof(header
) );
1939 header
.dwSize
= sizeof(header
);
1941 if (!LoadStringW( GetModuleHandleW( NULL
),
1942 current
? IDS_DLG_TIT_CURRENT
: IDS_DLG_TIT_DEFAULT
,
1943 buff
, ARRAY_SIZE(buff
) ))
1944 wcscpy( buff
, L
"Setup" );
1946 header
.pszCaption
= buff
;
1948 header
.hwndParent
= console
->win
;
1949 header
.phpage
= pages
;
1950 header
.dwFlags
= PSH_NOAPPLYNOW
;
1951 if (PropertySheetW( &header
) < 1)
1954 if (!memcmp( &prev_config
, &di
.config
, sizeof(prev_config
) ))
1957 TRACE( "%s\n", debugstr_config(&di
.config
) );
1961 apply_config( console
, &di
.config
);
1962 update_window( di
.console
);
1965 save_config( current
? console
->window
->config_key
: NULL
, &di
.config
);
1970 static void resize_window( struct console
*console
, int width
, int height
)
1972 struct console_config config
;
1974 current_config( console
, &config
);
1975 config
.win_width
= width
;
1976 config
.win_height
= height
;
1978 /* auto size screen-buffer if it's now smaller than window */
1979 if (config
.sb_width
< config
.win_width
)
1980 config
.sb_width
= config
.win_width
;
1981 if (config
.sb_height
< config
.win_height
)
1982 config
.sb_height
= config
.win_height
;
1984 /* and reset window pos so that we don't display outside of the screen-buffer */
1985 if (config
.win_pos
.X
+ config
.win_width
> config
.sb_width
)
1986 config
.win_pos
.X
= config
.sb_width
- config
.win_width
;
1987 if (config
.win_pos
.Y
+ config
.win_height
> config
.sb_height
)
1988 config
.win_pos
.Y
= config
.sb_height
- config
.win_height
;
1990 apply_config( console
, &config
);
1993 /* grays / ungrays the menu items according to their state */
1994 static void set_menu_details( struct console
*console
, HMENU menu
)
1996 EnableMenuItem( menu
, IDS_COPY
, MF_BYCOMMAND
|
1997 (console
->window
->in_selection
? MF_ENABLED
: MF_GRAYED
) );
1998 EnableMenuItem( menu
, IDS_PASTE
, MF_BYCOMMAND
|
1999 (IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
) );
2000 EnableMenuItem( menu
, IDS_SCROLL
, MF_BYCOMMAND
| MF_GRAYED
);
2001 EnableMenuItem( menu
, IDS_SEARCH
, MF_BYCOMMAND
| MF_GRAYED
);
2004 static BOOL
fill_menu( HMENU menu
, BOOL sep
)
2006 HINSTANCE module
= GetModuleHandleW( NULL
);
2010 if (!menu
) return FALSE
;
2012 sub_menu
= CreateMenu();
2013 if (!sub_menu
) return FALSE
;
2015 LoadStringW( module
, IDS_MARK
, buff
, ARRAY_SIZE(buff
) );
2016 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
2017 LoadStringW( module
, IDS_COPY
, buff
, ARRAY_SIZE(buff
) );
2018 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
2019 LoadStringW( module
, IDS_PASTE
, buff
, ARRAY_SIZE(buff
) );
2020 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
2021 LoadStringW( module
, IDS_SELECTALL
, buff
, ARRAY_SIZE(buff
) );
2022 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
2023 LoadStringW( module
, IDS_SCROLL
, buff
, ARRAY_SIZE(buff
) );
2024 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
2025 LoadStringW( module
, IDS_SEARCH
, buff
, ARRAY_SIZE(buff
) );
2026 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
2028 if (sep
) InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
2029 LoadStringW( module
, IDS_EDIT
, buff
, ARRAY_SIZE(buff
) );
2030 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)sub_menu
, buff
);
2031 LoadStringW( module
, IDS_DEFAULT
, buff
, ARRAY_SIZE(buff
) );
2032 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
2033 LoadStringW( module
, IDS_PROPERTIES
, buff
, ARRAY_SIZE(buff
) );
2034 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
2039 static LRESULT
window_create( HWND hwnd
, const CREATESTRUCTW
*create
)
2041 struct console
*console
= create
->lpCreateParams
;
2044 TRACE( "%p\n", hwnd
);
2046 SetWindowLongPtrW( hwnd
, 0, (DWORD_PTR
)console
);
2047 console
->win
= hwnd
;
2049 if (console
->window
)
2051 sys_menu
= GetSystemMenu( hwnd
, FALSE
);
2052 if (!sys_menu
) return 0;
2053 console
->window
->popup_menu
= CreatePopupMenu();
2054 if (!console
->window
->popup_menu
) return 0;
2056 fill_menu( sys_menu
, TRUE
);
2057 fill_menu( console
->window
->popup_menu
, FALSE
);
2059 console
->window
->mem_dc
= CreateCompatibleDC( 0 );
2064 static LRESULT WINAPI
window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2066 struct console
*console
= (struct console
*)GetWindowLongPtrW( hwnd
, 0 );
2071 return window_create( hwnd
, (const CREATESTRUCTW
*)lparam
);
2074 console
->win
= NULL
;
2075 PostQuitMessage( 0 );
2079 case WM_UPDATE_CONFIG
:
2080 if (console
->window
&& console
->window
->update_state
== UPDATE_PENDING
)
2081 update_window( console
);
2088 if (!console
->window
) break;
2090 BeginPaint( console
->win
, &ps
);
2091 BitBlt( ps
.hdc
, 0, 0,
2092 (console
->active
->win
.right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
,
2093 (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
,
2094 console
->window
->mem_dc
,
2095 console
->active
->win
.left
* console
->active
->font
.width
,
2096 console
->active
->win
.top
* console
->active
->font
.height
,
2098 if (console
->window
->in_selection
) update_selection( console
, ps
.hdc
);
2099 EndPaint( console
->win
, &ps
);
2104 if (!console
->window
) break;
2106 update_window( console
);
2109 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
2110 console
->window
->bitmap
= NULL
;
2116 if (console
->window
&& console
->window
->in_selection
)
2117 handle_selection_key( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2119 record_key_input( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2124 record_key_input( console
, msg
== WM_SYSKEYDOWN
, wparam
, lparam
);
2127 case WM_LBUTTONDOWN
:
2128 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2130 if (console
->window
->in_selection
)
2131 update_selection( console
, 0 );
2133 if (console
->window
->quick_edit
&& console
->window
->in_selection
)
2135 console
->window
->in_selection
= FALSE
;
2139 console
->window
->selection_end
= get_cell( console
, lparam
);
2140 console
->window
->selection_start
= console
->window
->selection_end
;
2141 SetCapture( console
->win
);
2142 update_selection( console
, 0 );
2143 console
->window
->in_selection
= TRUE
;
2148 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2153 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2155 if (GetCapture() == console
->win
&& console
->window
->in_selection
&&
2156 (wparam
& MK_LBUTTON
))
2158 move_selection( console
, console
->window
->selection_start
,
2159 get_cell(console
, lparam
) );
2164 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, MOUSE_MOVED
);
2169 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2171 if (GetCapture() == console
->win
&& console
->window
->in_selection
)
2173 move_selection( console
, console
->window
->selection_start
,
2174 get_cell(console
, lparam
) );
2180 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2184 case WM_RBUTTONDOWN
:
2185 if (console
->window
&& (wparam
& (MK_CONTROL
|MK_SHIFT
)) == console
->window
->menu_mask
)
2188 pt
.x
= (short)LOWORD(lparam
);
2189 pt
.y
= (short)HIWORD(lparam
);
2190 ClientToScreen( hwnd
, &pt
);
2191 set_menu_details( console
, console
->window
->popup_menu
);
2192 TrackPopupMenu( console
->window
->popup_menu
, TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RIGHTBUTTON
,
2193 pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2197 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2202 /* no need to track for rbutton up when opening the popup... the event will be
2203 * swallowed by TrackPopupMenu */
2204 case WM_MBUTTONDOWN
:
2206 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2209 case WM_LBUTTONDBLCLK
:
2210 case WM_MBUTTONDBLCLK
:
2211 case WM_RBUTTONDBLCLK
:
2212 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, DOUBLE_CLICK
);
2216 if (console
->window
&& console
->active
->cursor_visible
)
2218 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
2219 console
->active
->font
.width
, console
->active
->font
.height
);
2220 update_window_cursor( console
);
2225 if (console
->window
&& console
->active
->cursor_visible
)
2230 if (console
->window
&& console
->window
->update_state
!= UPDATE_BUSY
)
2231 resize_window( console
,
2232 max( LOWORD(lparam
) / console
->active
->font
.width
, 20 ),
2233 max( HIWORD(lparam
) / console
->active
->font
.height
, 20 ));
2238 int win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
2239 int x
= console
->active
->win
.left
;
2241 if (!console
->window
) break;
2242 switch (LOWORD(wparam
))
2244 case SB_PAGEUP
: x
-= 8; break;
2245 case SB_PAGEDOWN
: x
+= 8; break;
2246 case SB_LINEUP
: x
--; break;
2247 case SB_LINEDOWN
: x
++; break;
2248 case SB_THUMBTRACK
: x
= HIWORD(wparam
); break;
2251 x
= min( max( x
, 0 ), console
->active
->width
- win_width
);
2252 if (x
!= console
->active
->win
.left
)
2254 console
->active
->win
.left
= x
;
2255 console
->active
->win
.right
= x
+ win_width
- 1;
2256 update_window( console
);
2262 if (console
->active
->height
<= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
2264 record_mouse_input(console
, get_cell(console
, lparam
), wparam
, MOUSE_WHEELED
);
2267 /* else fallthrough */
2270 int win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
2271 int y
= console
->active
->win
.top
;
2273 if (!console
->window
) break;
2275 if (msg
== WM_MOUSEWHEEL
)
2277 UINT scroll_lines
= 3;
2278 SystemParametersInfoW( SPI_GETWHEELSCROLLLINES
, 0, &scroll_lines
, 0 );
2279 scroll_lines
*= -GET_WHEEL_DELTA_WPARAM(wparam
) / WHEEL_DELTA
;
2284 switch (LOWORD(wparam
))
2286 case SB_PAGEUP
: y
-= 8; break;
2287 case SB_PAGEDOWN
: y
+= 8; break;
2288 case SB_LINEUP
: y
--; break;
2289 case SB_LINEDOWN
: y
++; break;
2290 case SB_THUMBTRACK
: y
= HIWORD(wparam
); break;
2295 y
= min( max( y
, 0 ), console
->active
->height
- win_height
);
2296 if (y
!= console
->active
->win
.top
)
2298 console
->active
->win
.top
= y
;
2299 console
->active
->win
.bottom
= y
+ win_height
- 1;
2300 update_window( console
);
2306 if (!console
->window
) break;
2310 config_dialog( console
, FALSE
);
2312 case IDS_PROPERTIES
:
2313 config_dialog( console
, TRUE
);
2316 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2321 if (!console
->window
) break;
2325 config_dialog( console
, FALSE
);
2327 case IDS_PROPERTIES
:
2328 config_dialog( console
, TRUE
);
2331 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2332 console
->window
->selection_end
.X
= console
->window
->selection_end
.Y
= 0;
2333 update_selection( console
, 0 );
2334 console
->window
->in_selection
= TRUE
;
2337 if (console
->window
->in_selection
)
2339 console
->window
->in_selection
= FALSE
;
2340 update_selection( console
, 0 );
2341 copy_selection( console
);
2345 paste_clipboard( console
);
2348 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2349 console
->window
->selection_end
.X
= console
->active
->width
- 1;
2350 console
->window
->selection_end
.Y
= console
->active
->height
- 1;
2351 update_selection( console
, 0 );
2352 console
->window
->in_selection
= TRUE
;
2356 FIXME( "Unhandled yet command: %Ix\n", wparam
);
2359 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2363 case WM_INITMENUPOPUP
:
2364 if (!console
->window
|| !HIWORD(lparam
)) return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2365 set_menu_details( console
, GetSystemMenu(console
->win
, FALSE
) );
2369 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2375 void update_window_config( struct console
*console
, BOOL delay
)
2377 const int delay_timeout
= 50;
2379 if (!console
->window
|| console
->window
->update_state
!= UPDATE_NONE
) return;
2380 console
->window
->update_state
= UPDATE_PENDING
;
2382 SetTimer( console
->win
, 1, delay_timeout
, NULL
);
2384 PostMessageW( console
->win
, WM_UPDATE_CONFIG
, 0, 0 );
2387 void update_window_region( struct console
*console
, const RECT
*update
)
2389 RECT
*window_rect
= &console
->window
->update
;
2390 window_rect
->left
= min( window_rect
->left
, update
->left
);
2391 window_rect
->top
= min( window_rect
->top
, update
->top
);
2392 window_rect
->right
= max( window_rect
->right
, update
->right
);
2393 window_rect
->bottom
= max( window_rect
->bottom
, update
->bottom
);
2394 update_window_config( console
, TRUE
);
2397 BOOL
init_window( struct console
*console
)
2399 struct console_config config
;
2404 static struct console_window console_window
;
2406 console
->window
= &console_window
;
2407 if (!TranslateCharsetInfo( (DWORD
*)(INT_PTR
)GetACP(), &ci
, TCI_SRCCODEPAGE
))
2410 console
->window
->ui_charset
= ci
.ciCharset
;
2412 GetStartupInfoW(&si
);
2415 size_t i
, title_len
= wcslen( si
.lpTitle
);
2416 if (!(console
->window
->config_key
= malloc( (title_len
+ 1) * sizeof(WCHAR
) )))
2418 for (i
= 0; i
< title_len
; i
++)
2419 console
->window
->config_key
[i
] = si
.lpTitle
[i
] == '\\' ? '_' : si
.lpTitle
[i
];
2420 console
->window
->config_key
[title_len
] = 0;
2423 load_config( console
->window
->config_key
, &config
);
2424 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
2426 config
.sb_width
= si
.dwXCountChars
;
2427 config
.sb_height
= si
.dwYCountChars
;
2429 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
2430 config
.attr
= si
.dwFillAttribute
;
2432 wndclass
.style
= CS_DBLCLKS
;
2433 wndclass
.lpfnWndProc
= window_proc
;
2434 wndclass
.cbClsExtra
= 0;
2435 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2436 wndclass
.hInstance
= GetModuleHandleW(NULL
);
2437 wndclass
.hIcon
= LoadIconW( 0, (const WCHAR
*)IDI_WINLOGO
);
2438 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
2439 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2440 wndclass
.lpszMenuName
= NULL
;
2441 wndclass
.lpszClassName
= L
"WineConsoleClass";
2442 RegisterClassW(&wndclass
);
2444 if (!CreateWindowW( wndclass
.lpszClassName
, NULL
,
2445 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2446 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2447 0, 0, 0, 0, wndclass
.hInstance
, console
))
2450 if (!config
.face_name
[0])
2451 set_first_font( console
, &config
);
2453 apply_config( console
, &config
);
2457 void init_message_window( struct console
*console
)
2461 wndclass
.style
= CS_DBLCLKS
;
2462 wndclass
.lpfnWndProc
= window_proc
;
2463 wndclass
.cbClsExtra
= 0;
2464 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2465 wndclass
.hInstance
= GetModuleHandleW( NULL
);
2467 wndclass
.hCursor
= 0;
2468 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2469 wndclass
.lpszMenuName
= NULL
;
2470 wndclass
.lpszClassName
= L
"WineConsoleClass";
2471 RegisterClassW(&wndclass
);
2473 CreateWindowW( wndclass
.lpszClassName
, NULL
,
2474 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2475 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2476 0, 0, HWND_MESSAGE
, 0, wndclass
.hInstance
, console
);