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 %s registry settings.\n", wine_dbgstr_w( key_name
));
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 /* read global settings */
269 if (!RegOpenKeyW( HKEY_CURRENT_USER
, L
"Console", &key
))
271 load_registry_key( key
, config
);
272 /* if requested, load part related to console title */
273 if (key_name
&& !RegOpenKeyW( key
, key_name
, &app_key
))
275 load_registry_key( app_key
, config
);
276 RegCloseKey( app_key
);
280 TRACE( "%s\n", debugstr_config( config
));
283 static void save_registry_key( HKEY key
, const struct console_config
*config
)
285 DWORD val
, width
, height
, i
;
286 WCHAR color_name
[13];
288 TRACE( "%s\n", debugstr_config( config
));
290 for (i
= 0; i
< ARRAY_SIZE(config
->color_map
); i
++)
292 wsprintfW( color_name
, L
"ColorTable%02d", i
);
293 val
= config
->color_map
[i
];
294 RegSetValueExW( key
, color_name
, 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
297 val
= config
->cursor_size
;
298 RegSetValueExW( key
, L
"CursorSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
300 val
= config
->cursor_visible
;
301 RegSetValueExW( key
, L
"CursorVisible", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
303 val
= config
->edition_mode
;
304 RegSetValueExW( key
, L
"EditionMode", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
306 RegSetValueExW( key
, L
"FaceName", 0, REG_SZ
, (BYTE
*)&config
->face_name
,
307 (lstrlenW(config
->face_name
) + 1) * sizeof(WCHAR
) );
309 val
= config
->font_pitch_family
;
310 RegSetValueExW( key
, L
"FontPitchFamily", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
312 width
= MulDiv( config
->cell_width
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
313 height
= MulDiv( config
->cell_height
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
314 val
= MAKELONG( width
, height
);
315 RegSetValueExW( key
, L
"FontSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
317 val
= config
->font_weight
;
318 RegSetValueExW( key
, L
"FontWeight", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
320 val
= config
->history_size
;
321 RegSetValueExW( key
, L
"HistoryBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
323 val
= config
->history_mode
;
324 RegSetValueExW( key
, L
"HistoryNoDup", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
326 val
= config
->insert_mode
;
327 RegSetValueExW( key
, L
"InsertMode", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
329 val
= config
->menu_mask
;
330 RegSetValueExW( key
, L
"MenuMask", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
332 val
= config
->popup_attr
;
333 RegSetValueExW( key
, L
"PopupColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
335 val
= config
->quick_edit
;
336 RegSetValueExW( key
, L
"QuickEdit", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
338 val
= MAKELONG(config
->sb_width
, config
->sb_height
);
339 RegSetValueExW( key
, L
"ScreenBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
342 RegSetValueExW( key
, L
"ScreenColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
344 val
= MAKELONG( config
->win_width
, config
->win_height
);
345 RegSetValueExW( key
, L
"WindowSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
348 static void save_config( const WCHAR
*key_name
, const struct console_config
*config
)
352 TRACE( "%s %s\n", debugstr_w( key_name
), debugstr_config( config
));
354 if (RegCreateKeyW( HKEY_CURRENT_USER
, L
"Console", &key
))
356 ERR("Can't open registry for saving\n");
362 if (RegCreateKeyW( key
, key_name
, &app_key
))
364 ERR("Can't open registry for saving\n");
368 /* FIXME: maybe only save the values different from the default value ? */
369 save_registry_key( app_key
, config
);
370 RegCloseKey( app_key
);
373 else save_registry_key( key
, config
);
377 /* fill memory DC with current cells values */
378 static void fill_mem_dc( struct console
*console
, const RECT
*update
)
380 unsigned int i
, j
, k
;
389 if (!console
->window
->font
|| !console
->window
->bitmap
)
392 if (!(line
= malloc( (update
->right
- update
->left
+ 1) * sizeof(WCHAR
))) ) return;
393 dx
= malloc( (update
->right
- update
->left
+ 1) * sizeof(*dx
) );
395 old_font
= SelectObject( console
->window
->mem_dc
, console
->window
->font
);
396 for (j
= update
->top
; j
<= update
->bottom
; j
++)
398 cell
= &console
->active
->data
[j
* console
->active
->width
];
399 for (i
= update
->left
; i
<= update
->right
; i
++)
402 SetBkColor( console
->window
->mem_dc
, console
->active
->color_map
[(attr
>> 4) & 0x0F] );
403 SetTextColor( console
->window
->mem_dc
, console
->active
->color_map
[attr
& 0x0F] );
404 for (k
= i
; k
<= update
->right
&& cell
[k
].attr
== attr
; k
++)
406 line
[k
- i
] = cell
[k
].ch
;
407 dx
[k
- i
] = console
->active
->font
.width
;
409 ExtTextOutW( console
->window
->mem_dc
, i
* console
->active
->font
.width
,
410 j
* console
->active
->font
.height
, 0, NULL
, line
, k
- i
, dx
);
411 if (console
->window
->ext_leading
&&
412 (brush
= CreateSolidBrush( console
->active
->color_map
[(attr
>> 4) & 0x0F] )))
414 r
.left
= i
* console
->active
->font
.width
;
415 r
.top
= (j
+ 1) * console
->active
->font
.height
- console
->window
->ext_leading
;
416 r
.right
= k
* console
->active
->font
.width
;
417 r
.bottom
= (j
+ 1) * console
->active
->font
.height
;
418 FillRect( console
->window
->mem_dc
, &r
, brush
);
419 DeleteObject( brush
);
424 SelectObject( console
->window
->mem_dc
, old_font
);
429 /* set a new position for the cursor */
430 static void update_window_cursor( struct console
*console
)
432 if (!console
->active
->cursor_visible
|| console
->win
!= GetFocus()) return;
434 SetCaretPos( (get_bounded_cursor_x( console
->active
) - console
->active
->win
.left
) * console
->active
->font
.width
,
435 (console
->active
->cursor_y
- console
->active
->win
.top
) * console
->active
->font
.height
);
436 ShowCaret( console
->win
);
439 /* sets a new shape for the cursor */
440 static void shape_cursor( struct console
*console
)
442 int size
= console
->active
->cursor_size
;
444 if (console
->active
->cursor_visible
&& console
->win
== GetFocus()) DestroyCaret();
445 if (console
->window
->cursor_bitmap
) DeleteObject( console
->window
->cursor_bitmap
);
446 console
->window
->cursor_bitmap
= NULL
;
447 console
->window
->cursor_visible
= FALSE
;
451 int w16b
; /* number of bytes per row, aligned on word size */
455 w16b
= ((console
->active
->font
.width
+ 15) & ~15) / 8;
456 ptr
= calloc( w16b
, console
->active
->font
.height
);
458 nbl
= max( (console
->active
->font
.height
* size
) / 100, 1 );
459 for (j
= console
->active
->font
.height
- nbl
; j
< console
->active
->font
.height
; j
++)
461 for (i
= 0; i
< console
->active
->font
.width
; i
++)
463 ptr
[w16b
* j
+ (i
/ 8)] |= 0x80 >> (i
& 7);
466 console
->window
->cursor_bitmap
= CreateBitmap( console
->active
->font
.width
,
467 console
->active
->font
.height
, 1, 1, ptr
);
472 static void update_window( struct console
*console
)
474 unsigned int win_width
, win_height
;
475 BOOL update_all
= FALSE
;
479 console
->window
->update_state
= UPDATE_BUSY
;
481 if (console
->window
->sb_width
!= console
->active
->width
||
482 console
->window
->sb_height
!= console
->active
->height
||
483 (!console
->window
->bitmap
&& IsWindowVisible( console
->win
)))
485 console
->window
->sb_width
= console
->active
->width
;
486 console
->window
->sb_height
= console
->active
->height
;
488 if (console
->active
->width
&& console
->active
->height
&& console
->window
->font
)
494 if (!(dc
= GetDC( console
->win
))) return;
496 bitmap
= CreateCompatibleBitmap( dc
,
497 console
->active
->width
* console
->active
->font
.width
,
498 console
->active
->height
* console
->active
->font
.height
);
499 ReleaseDC( console
->win
, dc
);
500 SelectObject( console
->window
->mem_dc
, bitmap
);
502 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
503 console
->window
->bitmap
= bitmap
;
504 SetRect( &r
, 0, 0, console
->active
->width
- 1, console
->active
->height
- 1 );
505 fill_mem_dc( console
, &r
);
508 empty_update_rect( console
->active
, &console
->window
->update
);
512 /* compute window size from desired client size */
513 win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
514 win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
516 if (update_all
|| win_width
!= console
->window
->win_width
||
517 win_height
!= console
->window
->win_height
)
519 console
->window
->win_width
= win_width
;
520 console
->window
->win_height
= win_height
;
523 r
.right
= win_width
* console
->active
->font
.width
;
524 r
.bottom
= win_height
* console
->active
->font
.height
;
525 AdjustWindowRect( &r
, GetWindowLongW( console
->win
, GWL_STYLE
), FALSE
);
528 if (console
->active
->width
> win_width
)
530 dy
= GetSystemMetrics( SM_CYHSCROLL
);
531 SetScrollRange( console
->win
, SB_HORZ
, 0, console
->active
->width
- win_width
, FALSE
);
532 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
533 ShowScrollBar( console
->win
, SB_HORZ
, TRUE
);
537 ShowScrollBar( console
->win
, SB_HORZ
, FALSE
);
540 if (console
->active
->height
> win_height
)
542 dx
= GetSystemMetrics( SM_CXVSCROLL
);
543 SetScrollRange( console
->win
, SB_VERT
, 0, console
->active
->height
- win_height
, FALSE
);
544 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
545 ShowScrollBar( console
->win
, SB_VERT
, TRUE
);
548 ShowScrollBar( console
->win
, SB_VERT
, FALSE
);
550 dx
+= r
.right
- r
.left
;
551 dy
+= r
.bottom
- r
.top
;
552 SetWindowPos( console
->win
, 0, 0, 0, dx
, dy
, SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
554 SystemParametersInfoW( SPI_GETWORKAREA
, 0, &r
, 0 );
555 console
->active
->max_width
= (r
.right
- r
.left
) / console
->active
->font
.width
;
556 console
->active
->max_height
= (r
.bottom
- r
.top
- GetSystemMetrics( SM_CYCAPTION
)) /
557 console
->active
->font
.height
;
559 InvalidateRect( console
->win
, NULL
, FALSE
);
560 UpdateWindow( console
->win
);
563 else if (console
->active
->win
.left
!= console
->window
->win_pos
.X
||
564 console
->active
->win
.top
!= console
->window
->win_pos
.Y
)
566 ScrollWindow( console
->win
,
567 (console
->window
->win_pos
.X
- console
->active
->win
.left
) * console
->active
->font
.width
,
568 (console
->window
->win_pos
.Y
- console
->active
->win
.top
) * console
->active
->font
.height
,
570 SetScrollPos( console
->win
, SB_HORZ
, console
->active
->win
.left
, TRUE
);
571 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, TRUE
);
572 InvalidateRect( console
->win
, NULL
, FALSE
);
575 console
->window
->win_pos
.X
= console
->active
->win
.left
;
576 console
->window
->win_pos
.Y
= console
->active
->win
.top
;
578 if (console
->window
->update
.top
<= console
->window
->update
.bottom
&&
579 console
->window
->update
.left
<= console
->window
->update
.right
)
581 RECT
*update
= &console
->window
->update
;
582 r
.left
= (update
->left
- console
->active
->win
.left
) * console
->active
->font
.width
;
583 r
.right
= (update
->right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
;
584 r
.top
= (update
->top
- console
->active
->win
.top
) * console
->active
->font
.height
;
585 r
.bottom
= (update
->bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
;
586 fill_mem_dc( console
, update
);
587 empty_update_rect( console
->active
, &console
->window
->update
);
588 InvalidateRect( console
->win
, &r
, FALSE
);
589 UpdateWindow( console
->win
);
592 if (update_all
|| console
->active
->cursor_size
!= console
->window
->cursor_size
)
594 console
->window
->cursor_size
= console
->active
->cursor_size
;
595 shape_cursor( console
);
598 if (console
->active
->cursor_visible
!= console
->window
->cursor_visible
)
600 console
->window
->cursor_visible
= console
->active
->cursor_visible
;
601 if (console
->win
== GetFocus())
603 if (console
->window
->cursor_visible
)
604 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
605 console
->active
->font
.width
, console
->active
->font
.height
);
611 if (update_all
|| get_bounded_cursor_x( console
->active
) != console
->window
->cursor_pos
.X
||
612 console
->active
->cursor_y
!= console
->window
->cursor_pos
.Y
)
614 console
->window
->cursor_pos
.X
= get_bounded_cursor_x( console
->active
);
615 console
->window
->cursor_pos
.Y
= console
->active
->cursor_y
;
616 update_window_cursor( console
);
619 console
->window
->update_state
= UPDATE_NONE
;
622 /* get the relevant information from the font described in lf and store them in config */
623 static HFONT
select_font_config( struct console_config
*config
, unsigned int cp
, HWND hwnd
,
626 HFONT font
, old_font
;
631 if (!(dc
= GetDC( hwnd
))) return NULL
;
632 if (!(font
= CreateFontIndirectW( lf
)))
634 ReleaseDC( hwnd
, dc
);
638 old_font
= SelectObject( dc
, font
);
639 GetTextMetricsW( dc
, &tm
);
640 SelectObject( dc
, old_font
);
641 ReleaseDC( hwnd
, dc
);
643 config
->cell_width
= tm
.tmAveCharWidth
;
644 config
->cell_height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
645 config
->font_weight
= tm
.tmWeight
;
646 lstrcpyW( config
->face_name
, lf
->lfFaceName
);
648 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
649 if (GetCPInfo( cp
, &cpinfo
) && cpinfo
.MaxCharSize
== 2)
650 config
->cell_width
= tm
.tmMaxCharWidth
;
655 static void fill_logfont( LOGFONTW
*lf
, const WCHAR
*face_name
, size_t face_name_size
,
656 unsigned int height
, unsigned int weight
)
658 lf
->lfHeight
= height
;
660 lf
->lfEscapement
= 0;
661 lf
->lfOrientation
= 0;
662 lf
->lfWeight
= weight
;
663 lf
->lfItalic
= FALSE
;
664 lf
->lfUnderline
= FALSE
;
665 lf
->lfStrikeOut
= FALSE
;
666 lf
->lfCharSet
= DEFAULT_CHARSET
;
667 lf
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
668 lf
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
669 lf
->lfQuality
= DEFAULT_QUALITY
;
670 lf
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
671 face_name_size
= min( face_name_size
, sizeof(lf
->lfFaceName
) - sizeof(WCHAR
) );
672 memcpy( lf
->lfFaceName
, face_name
, face_name_size
);
673 lf
->lfFaceName
[face_name_size
/ sizeof(WCHAR
)] = 0;
676 static BOOL
set_console_font( struct console
*console
, const LOGFONTW
*logfont
)
678 struct font_info
*font_info
= &console
->active
->font
;
679 HFONT font
, old_font
;
684 TRACE( "%s\n", debugstr_logfont( logfont
, 0 ));
686 if (console
->window
->font
&& logfont
->lfHeight
== console
->active
->font
.height
&&
687 logfont
->lfWeight
== console
->active
->font
.weight
&&
688 !logfont
->lfItalic
&& !logfont
->lfUnderline
&& !logfont
->lfStrikeOut
&&
689 console
->active
->font
.face_len
== wcslen( logfont
->lfFaceName
) &&
690 !memcmp( logfont
->lfFaceName
, console
->active
->font
.face_name
,
691 console
->active
->font
.face_len
* sizeof(WCHAR
) ))
693 TRACE( "equal to current\n" );
697 if (!(dc
= GetDC( console
->win
))) return FALSE
;
698 if (!(font
= CreateFontIndirectW( logfont
)))
700 ReleaseDC( console
->win
, dc
);
704 old_font
= SelectObject( dc
, font
);
705 GetTextMetricsW( dc
, &tm
);
706 SelectObject( dc
, old_font
);
707 ReleaseDC( console
->win
, dc
);
709 font_info
->width
= tm
.tmAveCharWidth
;
710 font_info
->height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
711 font_info
->pitch_family
= tm
.tmPitchAndFamily
;
712 font_info
->weight
= tm
.tmWeight
;
714 free( font_info
->face_name
);
715 font_info
->face_len
= wcslen( logfont
->lfFaceName
);
716 font_info
->face_name
= malloc( font_info
->face_len
* sizeof(WCHAR
) );
717 memcpy( font_info
->face_name
, logfont
->lfFaceName
, font_info
->face_len
* sizeof(WCHAR
) );
719 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
720 if (GetCPInfo( console
->output_cp
, &cpinfo
) && cpinfo
.MaxCharSize
== 2)
721 font_info
->width
= tm
.tmMaxCharWidth
;
723 if (console
->window
->font
) DeleteObject( console
->window
->font
);
724 console
->window
->font
= font
;
725 console
->window
->ext_leading
= tm
.tmExternalLeading
;
727 if (console
->window
->bitmap
)
729 DeleteObject(console
->window
->bitmap
);
730 console
->window
->bitmap
= NULL
;
737 struct console
*console
;
742 /* check if the font described in tm is usable as a font for the renderer */
743 static BOOL
validate_font_metric( struct console
*console
, const TEXTMETRICW
*tm
,
744 DWORD type
, int pass
)
746 switch (pass
) /* we get increasingly lenient in later passes */
749 if (type
& RASTER_FONTTYPE
) return FALSE
;
752 if (type
& RASTER_FONTTYPE
)
754 if (tm
->tmMaxCharWidth
* (console
->active
->win
.right
- console
->active
->win
.left
+ 1)
755 >= GetSystemMetrics(SM_CXSCREEN
))
757 if (tm
->tmHeight
* (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
758 >= GetSystemMetrics(SM_CYSCREEN
))
763 if (tm
->tmCharSet
!= DEFAULT_CHARSET
&& tm
->tmCharSet
!= console
->window
->ui_charset
)
767 if (tm
->tmItalic
|| tm
->tmUnderlined
|| tm
->tmStruckOut
) return FALSE
;
773 /* check if the font family described in lf is usable as a font for the renderer */
774 static BOOL
validate_font( struct console
*console
, const LOGFONTW
*lf
, int pass
)
776 switch (pass
) /* we get increasingly lenient in later passes */
781 if (lf
->lfCharSet
!= DEFAULT_CHARSET
&& lf
->lfCharSet
!= console
->window
->ui_charset
)
785 if ((lf
->lfPitchAndFamily
& 3) != FIXED_PITCH
) return FALSE
;
788 if (lf
->lfFaceName
[0] == '@') return FALSE
;
794 /* helper functions to get a decent font for the renderer */
795 static int WINAPI
get_first_font_sub_enum( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
796 DWORD font_type
, LPARAM lparam
)
798 struct font_chooser
*fc
= (struct font_chooser
*)lparam
;
800 TRACE( "%s\n", debugstr_textmetric( tm
, font_type
));
802 if (validate_font_metric( fc
->console
, tm
, font_type
, fc
->pass
))
806 /* Use the default sizes for the font (this is needed, especially for
807 * TrueType fonts, so that we get a decent size, not the max size)
809 mlf
.lfWidth
= fc
->console
->active
->font
.width
;
810 mlf
.lfHeight
= fc
->console
->active
->font
.height
;
812 mlf
.lfHeight
= MulDiv( 16, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
814 if (set_console_font( fc
->console
, &mlf
))
816 struct console_config config
;
820 /* since we've modified the current config with new font information,
821 * set this information as the new default.
823 load_config( fc
->console
->window
->config_key
, &config
);
824 config
.cell_width
= fc
->console
->active
->font
.width
;
825 config
.cell_height
= fc
->console
->active
->font
.height
;
826 memcpy( config
.face_name
, fc
->console
->active
->font
.face_name
,
827 fc
->console
->active
->font
.face_len
* sizeof(WCHAR
) );
828 config
.face_name
[fc
->console
->active
->font
.face_len
] = 0;
830 /* Force also its writing back to the registry so that we can get it
833 save_config( fc
->console
->window
->config_key
, &config
);
840 static int WINAPI
get_first_font_enum( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
841 DWORD font_type
, LPARAM lparam
)
843 struct font_chooser
*fc
= (struct font_chooser
*)lparam
;
845 TRACE("%s\n", debugstr_logfont( lf
, font_type
));
847 if (validate_font( fc
->console
, lf
, fc
->pass
))
849 EnumFontFamiliesW( fc
->console
->window
->mem_dc
, lf
->lfFaceName
,
850 get_first_font_sub_enum
, lparam
);
851 return !fc
->done
; /* we just need the first matching one... */
857 /* sets logfont as the new font for the console */
858 void update_console_font( struct console
*console
, const WCHAR
*face_name
, size_t face_name_size
,
859 unsigned int height
, unsigned int weight
)
861 struct font_chooser fc
;
864 if (face_name
[0] && height
&& weight
)
866 fill_logfont( &lf
, face_name
, face_name_size
, height
, weight
);
867 if (set_console_font( console
, &lf
)) return;
870 /* try to find an acceptable font */
871 WARN( "Couldn't match the font from registry, trying to find one\n" );
872 fc
.console
= console
;
874 for (fc
.pass
= 0; fc
.pass
<= 5; fc
.pass
++)
876 EnumFontFamiliesW( console
->window
->mem_dc
, NULL
, get_first_font_enum
, (LPARAM
)&fc
);
879 ERR( "Couldn't find a decent font\n" );
882 /* get a cell from a relative coordinate in window (takes into account the scrolling) */
883 static COORD
get_cell( struct console
*console
, LPARAM lparam
)
886 c
.X
= console
->active
->win
.left
+ (short)LOWORD(lparam
) / console
->active
->font
.width
;
887 c
.Y
= console
->active
->win
.top
+ (short)HIWORD(lparam
) / console
->active
->font
.height
;
891 /* get the console bit mask equivalent to the VK_ status in key state */
892 static DWORD
get_ctrl_state( BYTE
*key_state
)
894 unsigned int ret
= 0;
896 GetKeyboardState(key_state
);
897 if (key_state
[VK_SHIFT
] & 0x80) ret
|= SHIFT_PRESSED
;
898 if (key_state
[VK_LCONTROL
] & 0x80) ret
|= LEFT_CTRL_PRESSED
;
899 if (key_state
[VK_RCONTROL
] & 0x80) ret
|= RIGHT_CTRL_PRESSED
;
900 if (key_state
[VK_LMENU
] & 0x80) ret
|= LEFT_ALT_PRESSED
;
901 if (key_state
[VK_RMENU
] & 0x80) ret
|= RIGHT_ALT_PRESSED
;
902 if (key_state
[VK_CAPITAL
] & 0x01) ret
|= CAPSLOCK_ON
;
903 if (key_state
[VK_NUMLOCK
] & 0x01) ret
|= NUMLOCK_ON
;
904 if (key_state
[VK_SCROLL
] & 0x01) ret
|= SCROLLLOCK_ON
;
909 /* get the selection rectangle */
910 static void get_selection_rect( struct console
*console
, RECT
*r
)
912 r
->left
= (min(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) -
913 console
->active
->win
.left
) * console
->active
->font
.width
;
914 r
->top
= (min(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) -
915 console
->active
->win
.top
) * console
->active
->font
.height
;
916 r
->right
= (max(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) + 1 -
917 console
->active
->win
.left
) * console
->active
->font
.width
;
918 r
->bottom
= (max(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) + 1 -
919 console
->active
->win
.top
) * console
->active
->font
.height
;
922 static void update_selection( struct console
*console
, HDC ref_dc
)
927 get_selection_rect( console
, &r
);
928 dc
= ref_dc
? ref_dc
: GetDC( console
->win
);
931 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
932 HideCaret( console
->win
);
933 InvertRect( dc
, &r
);
935 ReleaseDC( console
->win
, dc
);
936 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
937 ShowCaret( console
->win
);
940 static void move_selection( struct console
*console
, COORD c1
, COORD c2
)
945 if (c1
.X
< 0 || c1
.X
>= console
->active
->width
||
946 c2
.X
< 0 || c2
.X
>= console
->active
->width
||
947 c1
.Y
< 0 || c1
.Y
>= console
->active
->height
||
948 c2
.Y
< 0 || c2
.Y
>= console
->active
->height
)
951 get_selection_rect( console
, &r
);
952 dc
= GetDC( console
->win
);
955 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
956 HideCaret( console
->win
);
957 InvertRect( dc
, &r
);
959 console
->window
->selection_start
= c1
;
960 console
->window
->selection_end
= c2
;
963 get_selection_rect( console
, &r
);
964 InvertRect( dc
, &r
);
965 ReleaseDC( console
->win
, dc
);
966 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
967 ShowCaret( console
->win
);
971 /* copies the current selection into the clipboard */
972 static void copy_selection( struct console
*console
)
978 w
= abs( console
->window
->selection_start
.X
- console
->window
->selection_end
.X
) + 1;
979 h
= abs( console
->window
->selection_start
.Y
- console
->window
->selection_end
.Y
) + 1;
981 if (!OpenClipboard( console
->win
)) return;
984 mem
= GlobalAlloc( GMEM_MOVEABLE
, (w
+ 1) * h
* sizeof(WCHAR
) );
985 if (mem
&& (p
= buf
= GlobalLock( mem
)))
990 c
.X
= min( console
->window
->selection_start
.X
, console
->window
->selection_end
.X
);
991 c
.Y
= min( console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
);
993 for (y
= c
.Y
; y
< c
.Y
+ h
; y
++)
997 for (x
= c
.X
; x
< c
.X
+ w
; x
++)
998 p
[x
- c
.X
] = console
->active
->data
[y
* console
->active
->width
+ x
].ch
;
1000 /* strip spaces from the end of the line */
1002 while (end
> p
&& *(end
- 1) == ' ')
1004 *end
= (y
< c
.Y
+ h
- 1) ? '\n' : '\0';
1008 TRACE( "%s\n", debugstr_w( buf
));
1009 if (p
- buf
!= (w
+ 1) * h
)
1012 new_mem
= GlobalReAlloc( mem
, (p
- buf
) * sizeof(WCHAR
), GMEM_MOVEABLE
);
1013 if (new_mem
) mem
= new_mem
;
1015 GlobalUnlock( mem
);
1016 SetClipboardData( CF_UNICODETEXT
, mem
);
1021 static void paste_clipboard( struct console
*console
)
1026 if (!OpenClipboard( console
->win
)) return;
1027 h
= GetClipboardData( CF_UNICODETEXT
);
1028 if (h
&& (ptr
= GlobalLock( h
)))
1030 unsigned int i
, len
= GlobalSize(h
) / sizeof(WCHAR
);
1034 ir
[0].EventType
= KEY_EVENT
;
1035 ir
[0].Event
.KeyEvent
.wRepeatCount
= 0;
1036 ir
[0].Event
.KeyEvent
.dwControlKeyState
= 0;
1037 ir
[0].Event
.KeyEvent
.bKeyDown
= TRUE
;
1039 /* generate the corresponding input records */
1040 for (i
= 0; i
< len
; i
++)
1042 /* FIXME: the modifying keys are not generated (shift, ctrl...) */
1043 sh
= VkKeyScanW( ptr
[i
] );
1044 ir
[0].Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(sh
);
1045 ir
[0].Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKeyW( LOBYTE(sh
), 0 );
1046 ir
[0].Event
.KeyEvent
.uChar
.UnicodeChar
= ptr
[i
];
1049 ir
[1].Event
.KeyEvent
.bKeyDown
= FALSE
;
1051 write_console_input( console
, ir
, 2, i
== len
- 1 );
1059 /* handle keys while selecting an area */
1060 static void handle_selection_key( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1062 BYTE key_state
[256];
1067 state
= get_ctrl_state( key_state
) & ~(CAPSLOCK_ON
|NUMLOCK_ON
|SCROLLLOCK_ON
);
1075 console
->window
->in_selection
= FALSE
;
1076 update_selection( console
, 0 );
1077 copy_selection( console
);
1080 c1
= console
->window
->selection_start
;
1081 c2
= console
->window
->selection_end
;
1083 move_selection( console
, c1
, c2
);
1086 c1
= console
->window
->selection_start
;
1087 c2
= console
->window
->selection_end
;
1089 move_selection( console
, c1
, c2
);
1092 c1
= console
->window
->selection_start
;
1093 c2
= console
->window
->selection_end
;
1095 move_selection( console
, c1
, c2
);
1098 c1
= console
->window
->selection_start
;
1099 c2
= console
->window
->selection_end
;
1101 move_selection( console
, c1
, c2
);
1109 c1
= console
->window
->selection_start
;
1110 c2
= console
->window
->selection_end
;
1112 move_selection( console
, c1
, c2
);
1115 c1
= console
->window
->selection_start
;
1116 c2
= console
->window
->selection_end
;
1118 move_selection( console
, c1
, c2
);
1121 c1
= console
->window
->selection_start
;
1122 c2
= console
->window
->selection_end
;
1124 move_selection( console
, c1
, c2
);
1127 c1
= console
->window
->selection_start
;
1128 c2
= console
->window
->selection_end
;
1130 move_selection( console
, c1
, c2
);
1136 if (wparam
< VK_SPACE
) /* Shift, Alt, Ctrl, Num Lock etc. */
1139 update_selection( console
, 0 );
1140 console
->window
->in_selection
= FALSE
;
1143 /* generate input_record from windows WM_KEYUP/WM_KEYDOWN messages */
1144 static void record_key_input( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1146 static WCHAR last
; /* keep last char seen as feed for key up message */
1147 BYTE key_state
[256];
1151 ir
.EventType
= KEY_EVENT
;
1152 ir
.Event
.KeyEvent
.bKeyDown
= down
;
1153 ir
.Event
.KeyEvent
.wRepeatCount
= LOWORD(lparam
);
1154 ir
.Event
.KeyEvent
.wVirtualKeyCode
= wparam
;
1155 ir
.Event
.KeyEvent
.wVirtualScanCode
= HIWORD(lparam
) & 0xFF;
1156 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
1157 ir
.Event
.KeyEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1158 if (lparam
& (1u << 24)) ir
.Event
.KeyEvent
.dwControlKeyState
|= ENHANCED_KEY
;
1162 switch (ToUnicode(wparam
, HIWORD(lparam
), key_state
, buf
, 2, 0))
1165 /* FIXME: should generate two events */
1175 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= last
;
1176 if (!down
) last
= 0; /* FIXME: buggy HACK */
1178 write_console_input( console
, &ir
, 1, TRUE
);
1181 static void record_mouse_input( struct console
*console
, COORD c
, WPARAM wparam
, DWORD event
)
1183 BYTE key_state
[256];
1186 /* MOUSE_EVENTs shouldn't be sent unless ENABLE_MOUSE_INPUT is active */
1187 if (!(console
->mode
& ENABLE_MOUSE_INPUT
)) return;
1189 ir
.EventType
= MOUSE_EVENT
;
1190 ir
.Event
.MouseEvent
.dwMousePosition
= c
;
1191 ir
.Event
.MouseEvent
.dwButtonState
= 0;
1192 if (wparam
& MK_LBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1193 if (wparam
& MK_MBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1194 if (wparam
& MK_RBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1195 if (wparam
& MK_CONTROL
) ir
.Event
.MouseEvent
.dwButtonState
|= LEFT_CTRL_PRESSED
;
1196 if (wparam
& MK_SHIFT
) ir
.Event
.MouseEvent
.dwButtonState
|= SHIFT_PRESSED
;
1197 if (event
== MOUSE_WHEELED
) ir
.Event
.MouseEvent
.dwButtonState
|= wparam
& 0xFFFF0000;
1198 ir
.Event
.MouseEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1199 ir
.Event
.MouseEvent
.dwEventFlags
= event
;
1201 write_console_input( console
, &ir
, 1, TRUE
);
1206 struct console
*console
;
1207 struct console_config config
;
1208 HWND dialog
; /* handle to active propsheet */
1211 /* dialog proc for the option property sheet */
1212 static INT_PTR WINAPI
option_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1214 struct dialog_info
*di
;
1220 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1221 di
->dialog
= dialog
;
1222 SetWindowLongPtrW( dialog
, DWLP_USER
, (LONG_PTR
)di
);
1224 SendMessageW( GetDlgItem( dialog
, IDC_OPT_HIST_SIZE_UD
), UDM_SETRANGE
, 0, MAKELPARAM(500, 0) );
1226 if (di
->config
.cursor_size
<= 25) idc
= IDC_OPT_CURSOR_SMALL
;
1227 else if (di
->config
.cursor_size
<= 50) idc
= IDC_OPT_CURSOR_MEDIUM
;
1228 else idc
= IDC_OPT_CURSOR_LARGE
;
1230 SendDlgItemMessageW( dialog
, idc
, BM_SETCHECK
, BST_CHECKED
, 0 );
1231 SetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, di
->config
.history_size
, FALSE
);
1232 SendDlgItemMessageW( dialog
, IDC_OPT_HIST_NODOUBLE
, BM_SETCHECK
,
1233 (di
->config
.history_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1234 SendDlgItemMessageW( dialog
, IDC_OPT_INSERT_MODE
, BM_SETCHECK
,
1235 (di
->config
.insert_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1236 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_CTRL
, BM_SETCHECK
,
1237 (di
->config
.menu_mask
& MK_CONTROL
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1238 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_SHIFT
, BM_SETCHECK
,
1239 (di
->config
.menu_mask
& MK_SHIFT
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1240 SendDlgItemMessageW( dialog
, IDC_OPT_QUICK_EDIT
, BM_SETCHECK
,
1241 (di
->config
.quick_edit
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1242 return FALSE
; /* because we set the focus */
1249 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1253 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1255 switch (nmhdr
->code
)
1258 /* needed in propsheet to keep properly the selected radio button
1259 * otherwise, the focus would be set to the first tab stop in the
1260 * propsheet, which would always activate the first radio button
1262 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
)
1263 idc
= IDC_OPT_CURSOR_SMALL
;
1264 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
)
1265 idc
= IDC_OPT_CURSOR_MEDIUM
;
1267 idc
= IDC_OPT_CURSOR_LARGE
;
1268 PostMessageW( dialog
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem( dialog
, idc
), TRUE
);
1269 di
->dialog
= dialog
;
1272 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
) val
= 25;
1273 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
) val
= 50;
1275 di
->config
.cursor_size
= val
;
1277 val
= GetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, &done
, FALSE
);
1278 if (done
) di
->config
.history_size
= val
;
1280 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_HIST_NODOUBLE
) & BST_CHECKED
) != 0;
1281 di
->config
.history_mode
= val
;
1283 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_INSERT_MODE
) & BST_CHECKED
) != 0;
1284 di
->config
.insert_mode
= val
;
1287 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_CTRL
) & BST_CHECKED
) val
|= MK_CONTROL
;
1288 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_SHIFT
) & BST_CHECKED
) val
|= MK_SHIFT
;
1289 di
->config
.menu_mask
= val
;
1291 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_QUICK_EDIT
) & BST_CHECKED
) != 0;
1292 di
->config
.quick_edit
= val
;
1294 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1307 static COLORREF
get_color( struct dialog_info
*di
, unsigned int idc
)
1311 index
= GetWindowLongPtrW(GetDlgItem( di
->dialog
, idc
), 0);
1312 return di
->config
.color_map
[index
];
1315 /* window proc for font previewer in font property sheet */
1316 static LRESULT WINAPI
font_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1321 SetWindowLongPtrW( hwnd
, 0, 0 );
1325 return GetWindowLongPtrW( hwnd
, 0 );
1328 SetWindowLongPtrW( hwnd
, 0, wparam
);
1331 InvalidateRect( hwnd
, NULL
, TRUE
);
1332 UpdateWindow( hwnd
);
1338 HFONT font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1339 if (font
) DeleteObject( font
);
1345 struct dialog_info
*di
;
1346 HFONT font
, old_font
;
1349 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent( hwnd
), DWLP_USER
);
1350 BeginPaint( hwnd
, &ps
);
1352 font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1355 static const WCHAR ascii
[] = L
"ASCII: abcXYZ";
1360 old_font
= SelectObject( ps
.hdc
, font
);
1361 bkcolor
= get_color( di
, IDC_FNT_COLOR_BK
);
1362 FillRect( ps
.hdc
, &ps
.rcPaint
, CreateSolidBrush( bkcolor
));
1363 SetBkColor( ps
.hdc
, bkcolor
);
1364 SetTextColor( ps
.hdc
, get_color( di
, IDC_FNT_COLOR_FG
));
1365 len
= LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_PREVIEW
, buf
, ARRAY_SIZE(buf
) );
1366 if (len
) TextOutW( ps
.hdc
, 0, 0, buf
, len
);
1367 TextOutW( ps
.hdc
, 0, di
->config
.cell_height
, ascii
, ARRAY_SIZE(ascii
) - 1 );
1368 SelectObject( ps
.hdc
, old_font
);
1370 EndPaint( hwnd
, &ps
);
1375 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1380 /* window proc for color previewer */
1381 static LRESULT WINAPI
color_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1387 struct dialog_info
*di
;
1393 BeginPaint( hwnd
, &ps
);
1394 GetClientRect( hwnd
, &client
);
1395 step
= client
.right
/ 8;
1397 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent(hwnd
), DWLP_USER
);
1399 for (i
= 0; i
< 16; i
++)
1401 r
.top
= (i
/ 8) * (client
.bottom
/ 2);
1402 r
.bottom
= r
.top
+ client
.bottom
/ 2;
1403 r
.left
= (i
& 7) * step
;
1404 r
.right
= r
.left
+ step
;
1405 brush
= CreateSolidBrush( di
->config
.color_map
[i
] );
1406 FillRect( ps
.hdc
, &r
, brush
);
1407 DeleteObject( brush
);
1408 if (GetWindowLongW( hwnd
, 0 ) == i
)
1413 old_pen
= SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1414 r
.right
--; r
.bottom
--;
1417 MoveToEx( ps
.hdc
, r
.left
, r
.bottom
, NULL
);
1418 LineTo( ps
.hdc
, r
.left
, r
.top
);
1419 LineTo( ps
.hdc
, r
.right
, r
.top
);
1420 SelectObject( ps
.hdc
, GetStockObject( BLACK_PEN
));
1421 LineTo( ps
.hdc
, r
.right
, r
.bottom
);
1422 LineTo( ps
.hdc
, r
.left
, r
.bottom
);
1423 if (--i
== 0) break;
1424 r
.left
++; r
.top
++; r
.right
--; r
.bottom
--;
1425 SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1427 SelectObject( ps
.hdc
, old_pen
);
1430 EndPaint( hwnd
, &ps
);
1434 case WM_LBUTTONDOWN
:
1439 GetClientRect( hwnd
, &client
);
1440 step
= client
.right
/ 8;
1441 i
= (HIWORD(lparam
) >= client
.bottom
/ 2) ? 8 : 0;
1442 i
+= LOWORD(lparam
) / step
;
1443 SetWindowLongW( hwnd
, 0, i
);
1444 InvalidateRect( GetDlgItem( GetParent( hwnd
), IDC_FNT_PREVIEW
), NULL
, FALSE
);
1445 InvalidateRect( hwnd
, NULL
, FALSE
);
1450 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1455 static BOOL
select_font( struct dialog_info
*di
)
1457 int font_idx
, size_idx
;
1458 WCHAR face_name
[LF_FACESIZE
], height_buf
[4];
1460 unsigned int font_height
;
1462 HFONT font
, old_font
;
1467 font_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETCURSEL
, 0, 0 );
1468 size_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1470 if (font_idx
< 0 || size_idx
< 0)
1473 len
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETTEXT
, font_idx
, (LPARAM
)&face_name
);
1474 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETTEXT
, size_idx
, (LPARAM
)&height_buf
);
1475 font_height
= _wtoi( height_buf
);
1477 fill_logfont( &lf
, face_name
, len
* sizeof(WCHAR
), font_height
, FW_NORMAL
);
1478 font
= select_font_config( &di
->config
, di
->console
->output_cp
, di
->console
->win
, &lf
);
1479 if (!font
) return FALSE
;
1481 if (di
->config
.cell_height
!= font_height
)
1482 TRACE( "mismatched heights (%u<>%u)\n", di
->config
.cell_height
, font_height
);
1484 old_font
= (HFONT
)SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_GETFONT
, 0, 0 );
1485 SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1486 if (old_font
) DeleteObject( old_font
);
1488 LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_DISPLAY
, fmt
, ARRAY_SIZE(fmt
) );
1489 args
[0] = di
->config
.cell_width
;
1490 args
[1] = di
->config
.cell_height
;
1491 FormatMessageW( FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
1492 fmt
, 0, 0, buf
, ARRAY_SIZE(buf
), (__ms_va_list
*)args
);
1494 SendDlgItemMessageW( di
->dialog
, IDC_FNT_FONT_INFO
, WM_SETTEXT
, 0, (LPARAM
)buf
);
1498 static BOOL
fill_list_size( struct dialog_info
*di
, BOOL init
)
1502 static const int sizes
[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
1503 unsigned int i
, idx
= 4;
1506 for (i
= 0; i
< ARRAY_SIZE(sizes
); i
++)
1508 wsprintfW( buf
, L
"%u", sizes
[i
] );
1509 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_INSERTSTRING
, -1, (LPARAM
)buf
);
1511 if (di
->config
.cell_height
== sizes
[i
]) idx
= i
;
1514 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_SETCURSEL
, idx
, 0 );
1522 static int CALLBACK
enum_list_font_proc( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1523 DWORD font_type
, LPARAM lparam
)
1525 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1527 if (font_type
!= TRUETYPE_FONTTYPE
) return 1;
1529 TRACE( "%s\n", debugstr_logfont( lf
, font_type
));
1531 if (validate_font( di
->console
, lf
, 0 ))
1532 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_ADDSTRING
, 0, (LPARAM
)lf
->lfFaceName
);
1537 static BOOL
fill_list_font( struct dialog_info
*di
)
1541 memset( &lf
, 0, sizeof(lf
) );
1542 lf
.lfCharSet
= DEFAULT_CHARSET
;
1543 lf
.lfFaceName
[0] = 0;
1544 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
1546 EnumFontFamiliesExW( di
->console
->window
->mem_dc
, &lf
, enum_list_font_proc
, (LPARAM
)di
, 0 );
1548 if (SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SELECTSTRING
,
1549 -1, (LPARAM
)di
->config
.face_name
) == LB_ERR
)
1550 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SETCURSEL
, 0, 0 );
1552 fill_list_size( di
, TRUE
);
1557 /* dialog proc for the font property sheet */
1558 static INT_PTR WINAPI
font_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1560 struct dialog_info
*di
;
1565 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1566 di
->dialog
= dialog
;
1567 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1568 /* use default system font until user-selected font is applied */
1569 SendDlgItemMessageW( dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, 0, 0 );
1570 fill_list_font( di
);
1571 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0, (di
->config
.attr
>> 4) & 0x0F );
1572 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0, di
->config
.attr
& 0x0F );
1576 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1577 switch (LOWORD(wparam
))
1579 case IDC_FNT_LIST_FONT
:
1580 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1581 fill_list_size( di
, FALSE
);
1583 case IDC_FNT_LIST_SIZE
:
1584 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1592 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1595 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1596 switch (nmhdr
->code
)
1599 di
->dialog
= dialog
;
1602 val
= (GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0 ) << 4) |
1603 GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0 );
1604 di
->config
.attr
= val
;
1605 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1618 /* dialog proc for the config property sheet */
1619 static INT_PTR WINAPI
config_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1621 struct dialog_info
*di
;
1627 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1628 di
->dialog
= dialog
;
1630 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1631 SetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, di
->config
.sb_width
, FALSE
);
1632 SetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, di
->config
.sb_height
, FALSE
);
1633 SetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, di
->config
.win_width
, FALSE
);
1634 SetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, di
->config
.win_height
, FALSE
);
1636 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1637 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1638 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1639 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1641 SendDlgItemMessageW( dialog
, IDC_CNF_CLOSE_EXIT
, BM_SETCHECK
, BST_CHECKED
, 0 );
1643 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Win32" );
1644 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Emacs" );
1645 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_SETCURSEL
, di
->config
.edition_mode
, 0 );
1650 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1651 int win_w
, win_h
, sb_w
, sb_h
;
1654 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1655 switch (nmhdr
->code
)
1658 di
->dialog
= dialog
;
1661 sb_w
= GetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, &st1
, FALSE
);
1662 sb_h
= GetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, &st2
, FALSE
);
1665 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1668 win_w
= GetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, &st1
, FALSE
);
1669 win_h
= GetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, &st2
, FALSE
);
1672 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1675 if (win_w
> sb_w
|| win_h
> sb_h
)
1680 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_TIT_ERROR
, cap
, ARRAY_SIZE(cap
) );
1681 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_ERR_SBWINSIZE
, txt
, ARRAY_SIZE(txt
) );
1683 MessageBoxW( dialog
, txt
, cap
, MB_OK
);
1684 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1687 di
->config
.win_width
= win_w
;
1688 di
->config
.win_height
= win_h
;
1689 di
->config
.sb_width
= sb_w
;
1690 di
->config
.sb_height
= sb_h
;
1692 di
->config
.edition_mode
= SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
,
1693 CB_GETCURSEL
, 0, 0 );
1694 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1707 /* dialog proc for choosing how to handle modification to the console settings */
1708 static INT_PTR WINAPI
save_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1713 SendMessageW( dialog
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem( dialog
, IDC_SAV_SESSION
), TRUE
);
1714 SendDlgItemMessageW( dialog
, IDC_SAV_SESSION
, BM_SETCHECK
, BST_CHECKED
, 0 );
1718 switch (LOWORD(wparam
))
1722 (IsDlgButtonChecked(dialog
, IDC_SAV_SAVE
) == BST_CHECKED
) ?
1723 IDC_SAV_SAVE
: IDC_SAV_SESSION
);
1726 EndDialog( dialog
, IDCANCEL
); break;
1735 static void apply_config( struct console
*console
, const struct console_config
*config
)
1737 if (console
->active
->width
!= config
->sb_width
|| console
->active
->height
!= config
->sb_height
)
1738 change_screen_buffer_size( console
->active
, config
->sb_width
, config
->sb_height
);
1740 console
->window
->menu_mask
= config
->menu_mask
;
1741 console
->window
->quick_edit
= config
->quick_edit
;
1743 console
->edition_mode
= config
->edition_mode
;
1744 console
->history_mode
= config
->history_mode
;
1746 if (console
->history_size
!= config
->history_size
)
1748 struct history_line
**mem
= NULL
;
1751 if (config
->history_size
&& (mem
= malloc( config
->history_size
* sizeof(*mem
) )))
1753 memset( mem
, 0, config
->history_size
* sizeof(*mem
) );
1755 delta
= (console
->history_index
> config
->history_size
)
1756 ? (console
->history_index
- config
->history_size
) : 0;
1758 for (i
= delta
; i
< console
->history_index
; i
++)
1760 mem
[i
- delta
] = console
->history
[i
];
1761 console
->history
[i
] = NULL
;
1763 console
->history_index
-= delta
;
1765 for (i
= 0; i
< console
->history_size
; i
++)
1766 free( console
->history
[i
] );
1767 free( console
->history
);
1768 console
->history
= mem
;
1769 console
->history_size
= config
->history_size
;
1773 if (config
->insert_mode
)
1774 console
->mode
|= ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
;
1776 console
->mode
&= ~ENABLE_INSERT_MODE
;
1778 console
->active
->cursor_size
= config
->cursor_size
;
1779 console
->active
->cursor_visible
= config
->cursor_visible
;
1780 console
->active
->attr
= config
->attr
;
1781 console
->active
->popup_attr
= config
->popup_attr
;
1782 console
->active
->win
.left
= config
->win_pos
.X
;
1783 console
->active
->win
.top
= config
->win_pos
.Y
;
1784 console
->active
->win
.right
= config
->win_pos
.X
+ config
->win_width
- 1;
1785 console
->active
->win
.bottom
= config
->win_pos
.Y
+ config
->win_height
- 1;
1786 memcpy( console
->active
->color_map
, config
->color_map
, sizeof(config
->color_map
) );
1788 if (console
->active
->font
.width
!= config
->cell_width
||
1789 console
->active
->font
.height
!= config
->cell_height
||
1790 console
->active
->font
.weight
!= config
->font_weight
||
1791 console
->active
->font
.pitch_family
!= config
->font_pitch_family
||
1792 console
->active
->font
.face_len
!= wcslen( config
->face_name
) ||
1793 memcmp( console
->active
->font
.face_name
, config
->face_name
,
1794 console
->active
->font
.face_len
* sizeof(WCHAR
) ))
1796 update_console_font( console
, config
->face_name
, wcslen(config
->face_name
) * sizeof(WCHAR
),
1797 config
->cell_height
, config
->font_weight
);
1800 update_window( console
);
1802 notify_screen_buffer_size( console
->active
);
1805 static void current_config( struct console
*console
, struct console_config
*config
)
1809 config
->menu_mask
= console
->window
->menu_mask
;
1810 config
->quick_edit
= console
->window
->quick_edit
;
1812 config
->edition_mode
= console
->edition_mode
;
1813 config
->history_mode
= console
->history_mode
;
1814 config
->history_size
= console
->history_size
;
1816 config
->insert_mode
= (console
->mode
& (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
)) ==
1817 (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
);
1819 config
->cursor_size
= console
->active
->cursor_size
;
1820 config
->cursor_visible
= console
->active
->cursor_visible
;
1821 config
->attr
= console
->active
->attr
;
1822 config
->popup_attr
= console
->active
->popup_attr
;
1823 memcpy( config
->color_map
, console
->active
->color_map
, sizeof(config
->color_map
) );
1825 config
->cell_width
= console
->active
->font
.width
;
1826 config
->cell_height
= console
->active
->font
.height
;
1827 config
->font_weight
= console
->active
->font
.weight
;
1828 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
1829 len
= min( ARRAY_SIZE(config
->face_name
) - 1, console
->active
->font
.face_len
);
1830 if (len
) memcpy( config
->face_name
, console
->active
->font
.face_name
, len
* sizeof(WCHAR
) );
1831 config
->face_name
[len
] = 0;
1833 config
->sb_width
= console
->active
->width
;
1834 config
->sb_height
= console
->active
->height
;
1836 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1837 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1838 config
->win_pos
.X
= console
->active
->win
.left
;
1839 config
->win_pos
.Y
= console
->active
->win
.top
;
1842 /* run the dialog box to set up the console options */
1843 static BOOL
config_dialog( struct console
*console
, BOOL current
)
1845 struct console_config prev_config
;
1846 struct dialog_info di
;
1847 PROPSHEETHEADERW header
;
1848 HPROPSHEETPAGE pages
[3];
1852 BOOL modify_session
= FALSE
;
1855 InitCommonControls();
1857 memset( &di
, 0, sizeof(di
) );
1858 di
.console
= console
;
1861 load_config( NULL
, &di
.config
);
1864 else current_config( console
, &di
.config
);
1865 prev_config
= di
.config
;
1868 wndclass
.lpfnWndProc
= font_preview_proc
;
1869 wndclass
.cbClsExtra
= 0;
1870 wndclass
.cbWndExtra
= sizeof(HFONT
);
1871 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1873 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1874 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1875 wndclass
.lpszMenuName
= NULL
;
1876 wndclass
.lpszClassName
= L
"WineConFontPreview";
1877 RegisterClassW( &wndclass
);
1880 wndclass
.lpfnWndProc
= color_preview_proc
;
1881 wndclass
.cbClsExtra
= 0;
1882 wndclass
.cbWndExtra
= sizeof(DWORD
);
1883 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1885 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1886 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1887 wndclass
.lpszMenuName
= NULL
;
1888 wndclass
.lpszClassName
= L
"WineConColorPreview";
1889 RegisterClassW( &wndclass
);
1891 memset( &psp
, 0, sizeof(psp
) );
1892 psp
.dwSize
= sizeof(psp
);
1894 psp
.hInstance
= wndclass
.hInstance
;
1895 psp
.lParam
= (LPARAM
)&di
;
1897 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_OPTION
);
1898 psp
.pfnDlgProc
= option_dialog_proc
;
1899 pages
[0] = CreatePropertySheetPageW( &psp
);
1901 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_FONT
);
1902 psp
.pfnDlgProc
= font_dialog_proc
;
1903 pages
[1] = CreatePropertySheetPageW( &psp
);
1905 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CONFIG
);
1906 psp
.pfnDlgProc
= config_dialog_proc
;
1907 pages
[2] = CreatePropertySheetPageW( &psp
);
1909 memset( &header
, 0, sizeof(header
) );
1910 header
.dwSize
= sizeof(header
);
1912 if (!LoadStringW( GetModuleHandleW( NULL
),
1913 current
? IDS_DLG_TIT_CURRENT
: IDS_DLG_TIT_DEFAULT
,
1914 buff
, ARRAY_SIZE(buff
) ))
1915 wcscpy( buff
, L
"Setup" );
1917 header
.pszCaption
= buff
;
1919 header
.hwndParent
= console
->win
;
1920 header
.u3
.phpage
= pages
;
1921 header
.dwFlags
= PSH_NOAPPLYNOW
;
1922 if (PropertySheetW( &header
) < 1)
1925 if (!memcmp( &prev_config
, &di
.config
, sizeof(prev_config
) ))
1928 TRACE( "%s\n", debugstr_config(&di
.config
) );
1932 switch (DialogBoxW( GetModuleHandleW( NULL
), MAKEINTRESOURCEW(IDD_SAVE_SETTINGS
),
1933 console
->win
, save_dialog_proc
))
1937 modify_session
= TRUE
;
1939 case IDC_SAV_SESSION
:
1940 modify_session
= TRUE
;
1943 ERR( "dialog failed\n" );
1946 modify_session
= FALSE
;
1954 apply_config( console
, &di
.config
);
1955 update_window( di
.console
);
1958 save_config( current
? console
->window
->config_key
: NULL
, &di
.config
);
1962 static void resize_window( struct console
*console
, int width
, int height
)
1964 struct console_config config
;
1966 current_config( console
, &config
);
1967 config
.win_width
= width
;
1968 config
.win_height
= height
;
1970 /* auto size screen-buffer if it's now smaller than window */
1971 if (config
.sb_width
< config
.win_width
)
1972 config
.sb_width
= config
.win_width
;
1973 if (config
.sb_height
< config
.win_height
)
1974 config
.sb_height
= config
.win_height
;
1976 /* and reset window pos so that we don't display outside of the screen-buffer */
1977 if (config
.win_pos
.X
+ config
.win_width
> config
.sb_width
)
1978 config
.win_pos
.X
= config
.sb_width
- config
.win_width
;
1979 if (config
.win_pos
.Y
+ config
.win_height
> config
.sb_height
)
1980 config
.win_pos
.Y
= config
.sb_height
- config
.win_height
;
1982 apply_config( console
, &config
);
1985 /* grays / ungrays the menu items according to their state */
1986 static void set_menu_details( struct console
*console
, HMENU menu
)
1988 EnableMenuItem( menu
, IDS_COPY
, MF_BYCOMMAND
|
1989 (console
->window
->in_selection
? MF_ENABLED
: MF_GRAYED
) );
1990 EnableMenuItem( menu
, IDS_PASTE
, MF_BYCOMMAND
|
1991 (IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
) );
1992 EnableMenuItem( menu
, IDS_SCROLL
, MF_BYCOMMAND
| MF_GRAYED
);
1993 EnableMenuItem( menu
, IDS_SEARCH
, MF_BYCOMMAND
| MF_GRAYED
);
1996 static BOOL
fill_menu( HMENU menu
, BOOL sep
)
1998 HINSTANCE module
= GetModuleHandleW( NULL
);
2002 if (!menu
) return FALSE
;
2004 sub_menu
= CreateMenu();
2005 if (!sub_menu
) return FALSE
;
2007 LoadStringW( module
, IDS_MARK
, buff
, ARRAY_SIZE(buff
) );
2008 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
2009 LoadStringW( module
, IDS_COPY
, buff
, ARRAY_SIZE(buff
) );
2010 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
2011 LoadStringW( module
, IDS_PASTE
, buff
, ARRAY_SIZE(buff
) );
2012 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
2013 LoadStringW( module
, IDS_SELECTALL
, buff
, ARRAY_SIZE(buff
) );
2014 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
2015 LoadStringW( module
, IDS_SCROLL
, buff
, ARRAY_SIZE(buff
) );
2016 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
2017 LoadStringW( module
, IDS_SEARCH
, buff
, ARRAY_SIZE(buff
) );
2018 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
2020 if (sep
) InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
2021 LoadStringW( module
, IDS_EDIT
, buff
, ARRAY_SIZE(buff
) );
2022 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)sub_menu
, buff
);
2023 LoadStringW( module
, IDS_DEFAULT
, buff
, ARRAY_SIZE(buff
) );
2024 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
2025 LoadStringW( module
, IDS_PROPERTIES
, buff
, ARRAY_SIZE(buff
) );
2026 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
2031 static LRESULT
window_create( HWND hwnd
, const CREATESTRUCTW
*create
)
2033 struct console
*console
= create
->lpCreateParams
;
2036 TRACE( "%p\n", hwnd
);
2038 SetWindowLongPtrW( hwnd
, 0, (DWORD_PTR
)console
);
2039 console
->win
= hwnd
;
2041 if (console
->window
)
2043 sys_menu
= GetSystemMenu( hwnd
, FALSE
);
2044 if (!sys_menu
) return 0;
2045 console
->window
->popup_menu
= CreatePopupMenu();
2046 if (!console
->window
->popup_menu
) return 0;
2048 fill_menu( sys_menu
, TRUE
);
2049 fill_menu( console
->window
->popup_menu
, FALSE
);
2051 console
->window
->mem_dc
= CreateCompatibleDC( 0 );
2056 static LRESULT WINAPI
window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2058 struct console
*console
= (struct console
*)GetWindowLongPtrW( hwnd
, 0 );
2063 return window_create( hwnd
, (const CREATESTRUCTW
*)lparam
);
2066 console
->win
= NULL
;
2067 PostQuitMessage( 0 );
2071 case WM_UPDATE_CONFIG
:
2072 if (console
->window
&& console
->window
->update_state
== UPDATE_PENDING
)
2073 update_window( console
);
2080 if (!console
->window
) break;
2082 BeginPaint( console
->win
, &ps
);
2083 BitBlt( ps
.hdc
, 0, 0,
2084 (console
->active
->win
.right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
,
2085 (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
,
2086 console
->window
->mem_dc
,
2087 console
->active
->win
.left
* console
->active
->font
.width
,
2088 console
->active
->win
.top
* console
->active
->font
.height
,
2090 if (console
->window
->in_selection
) update_selection( console
, ps
.hdc
);
2091 EndPaint( console
->win
, &ps
);
2096 if (!console
->window
) break;
2098 update_window( console
);
2101 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
2102 console
->window
->bitmap
= NULL
;
2108 if (console
->window
&& console
->window
->in_selection
)
2109 handle_selection_key( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2111 record_key_input( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2116 record_key_input( console
, msg
== WM_SYSKEYDOWN
, wparam
, lparam
);
2119 case WM_LBUTTONDOWN
:
2120 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2122 if (console
->window
->in_selection
)
2123 update_selection( console
, 0 );
2125 if (console
->window
->quick_edit
&& console
->window
->in_selection
)
2127 console
->window
->in_selection
= FALSE
;
2131 console
->window
->selection_end
= get_cell( console
, lparam
);
2132 console
->window
->selection_start
= console
->window
->selection_end
;
2133 SetCapture( console
->win
);
2134 update_selection( console
, 0 );
2135 console
->window
->in_selection
= TRUE
;
2140 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2145 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2147 if (GetCapture() == console
->win
&& console
->window
->in_selection
&&
2148 (wparam
& MK_LBUTTON
))
2150 move_selection( console
, console
->window
->selection_start
,
2151 get_cell(console
, lparam
) );
2156 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, MOUSE_MOVED
);
2161 if (console
->window
&& (console
->window
->quick_edit
|| console
->window
->in_selection
))
2163 if (GetCapture() == console
->win
&& console
->window
->in_selection
)
2165 move_selection( console
, console
->window
->selection_start
,
2166 get_cell(console
, lparam
) );
2172 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2176 case WM_RBUTTONDOWN
:
2177 if (console
->window
&& (wparam
& (MK_CONTROL
|MK_SHIFT
)) == console
->window
->menu_mask
)
2180 pt
.x
= (short)LOWORD(lparam
);
2181 pt
.y
= (short)HIWORD(lparam
);
2182 ClientToScreen( hwnd
, &pt
);
2183 set_menu_details( console
, console
->window
->popup_menu
);
2184 TrackPopupMenu( console
->window
->popup_menu
, TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RIGHTBUTTON
,
2185 pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2189 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2194 /* no need to track for rbutton up when opening the popup... the event will be
2195 * swallowed by TrackPopupMenu */
2196 case WM_MBUTTONDOWN
:
2198 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2201 case WM_LBUTTONDBLCLK
:
2202 case WM_MBUTTONDBLCLK
:
2203 case WM_RBUTTONDBLCLK
:
2204 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, DOUBLE_CLICK
);
2208 if (console
->window
&& console
->active
->cursor_visible
)
2210 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
2211 console
->active
->font
.width
, console
->active
->font
.height
);
2212 update_window_cursor( console
);
2217 if (console
->window
&& console
->active
->cursor_visible
)
2222 if (console
->window
&& console
->window
->update_state
!= UPDATE_BUSY
)
2223 resize_window( console
,
2224 max( LOWORD(lparam
) / console
->active
->font
.width
, 20 ),
2225 max( HIWORD(lparam
) / console
->active
->font
.height
, 20 ));
2230 int win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
2231 int x
= console
->active
->win
.left
;
2233 if (!console
->window
) break;
2234 switch (LOWORD(wparam
))
2236 case SB_PAGEUP
: x
-= 8; break;
2237 case SB_PAGEDOWN
: x
+= 8; break;
2238 case SB_LINEUP
: x
--; break;
2239 case SB_LINEDOWN
: x
++; break;
2240 case SB_THUMBTRACK
: x
= HIWORD(wparam
); break;
2243 x
= min( max( x
, 0 ), console
->active
->width
- win_width
);
2244 if (x
!= console
->active
->win
.left
)
2246 console
->active
->win
.left
= x
;
2247 console
->active
->win
.right
= x
+ win_width
- 1;
2248 update_window( console
);
2254 if (console
->active
->height
<= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
2256 record_mouse_input(console
, get_cell(console
, lparam
), wparam
, MOUSE_WHEELED
);
2259 /* else fallthrough */
2262 int win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
2263 int y
= console
->active
->win
.top
;
2265 if (!console
->window
) break;
2267 if (msg
== WM_MOUSEWHEEL
)
2269 UINT scroll_lines
= 3;
2270 SystemParametersInfoW( SPI_GETWHEELSCROLLLINES
, 0, &scroll_lines
, 0 );
2271 scroll_lines
*= -GET_WHEEL_DELTA_WPARAM(wparam
) / WHEEL_DELTA
;
2276 switch (LOWORD(wparam
))
2278 case SB_PAGEUP
: y
-= 8; break;
2279 case SB_PAGEDOWN
: y
+= 8; break;
2280 case SB_LINEUP
: y
--; break;
2281 case SB_LINEDOWN
: y
++; break;
2282 case SB_THUMBTRACK
: y
= HIWORD(wparam
); break;
2287 y
= min( max( y
, 0 ), console
->active
->height
- win_height
);
2288 if (y
!= console
->active
->win
.top
)
2290 console
->active
->win
.top
= y
;
2291 console
->active
->win
.bottom
= y
+ win_height
- 1;
2292 update_window( console
);
2298 if (!console
->window
) break;
2302 config_dialog( console
, FALSE
);
2304 case IDS_PROPERTIES
:
2305 config_dialog( console
, TRUE
);
2308 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2313 if (!console
->window
) break;
2317 config_dialog( console
, FALSE
);
2319 case IDS_PROPERTIES
:
2320 config_dialog( console
, TRUE
);
2323 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2324 console
->window
->selection_end
.X
= console
->window
->selection_end
.Y
= 0;
2325 update_selection( console
, 0 );
2326 console
->window
->in_selection
= TRUE
;
2329 if (console
->window
->in_selection
)
2331 console
->window
->in_selection
= FALSE
;
2332 update_selection( console
, 0 );
2333 copy_selection( console
);
2337 paste_clipboard( console
);
2340 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2341 console
->window
->selection_end
.X
= console
->active
->width
- 1;
2342 console
->window
->selection_end
.Y
= console
->active
->height
- 1;
2343 update_selection( console
, 0 );
2344 console
->window
->in_selection
= TRUE
;
2348 FIXME( "Unhandled yet command: %Ix\n", wparam
);
2351 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2355 case WM_INITMENUPOPUP
:
2356 if (!console
->window
|| !HIWORD(lparam
)) return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2357 set_menu_details( console
, GetSystemMenu(console
->win
, FALSE
) );
2361 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2367 void update_window_config( struct console
*console
, BOOL delay
)
2369 const int delay_timeout
= 50;
2371 if (!console
->window
|| console
->window
->update_state
!= UPDATE_NONE
) return;
2372 console
->window
->update_state
= UPDATE_PENDING
;
2374 SetTimer( console
->win
, 1, delay_timeout
, NULL
);
2376 PostMessageW( console
->win
, WM_UPDATE_CONFIG
, 0, 0 );
2379 void update_window_region( struct console
*console
, const RECT
*update
)
2381 RECT
*window_rect
= &console
->window
->update
;
2382 window_rect
->left
= min( window_rect
->left
, update
->left
);
2383 window_rect
->top
= min( window_rect
->top
, update
->top
);
2384 window_rect
->right
= max( window_rect
->right
, update
->right
);
2385 window_rect
->bottom
= max( window_rect
->bottom
, update
->bottom
);
2386 update_window_config( console
, TRUE
);
2389 BOOL
init_window( struct console
*console
)
2391 struct console_config config
;
2396 static struct console_window console_window
;
2398 console
->window
= &console_window
;
2399 if (!TranslateCharsetInfo( (DWORD
*)(INT_PTR
)GetACP(), &ci
, TCI_SRCCODEPAGE
))
2402 console
->window
->ui_charset
= ci
.ciCharset
;
2404 GetStartupInfoW(&si
);
2407 size_t i
, title_len
= wcslen( si
.lpTitle
);
2408 if (!(console
->window
->config_key
= malloc( (title_len
+ 1) * sizeof(WCHAR
) )))
2410 for (i
= 0; i
< title_len
; i
++)
2411 console
->window
->config_key
[i
] = si
.lpTitle
[i
] == '\\' ? '_' : si
.lpTitle
[i
];
2412 console
->window
->config_key
[title_len
] = 0;
2415 load_config( console
->window
->config_key
, &config
);
2416 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
2418 config
.sb_width
= si
.dwXCountChars
;
2419 config
.sb_height
= si
.dwYCountChars
;
2421 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
2422 config
.attr
= si
.dwFillAttribute
;
2424 wndclass
.style
= CS_DBLCLKS
;
2425 wndclass
.lpfnWndProc
= window_proc
;
2426 wndclass
.cbClsExtra
= 0;
2427 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2428 wndclass
.hInstance
= GetModuleHandleW(NULL
);
2429 wndclass
.hIcon
= LoadIconW( 0, (const WCHAR
*)IDI_WINLOGO
);
2430 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
2431 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2432 wndclass
.lpszMenuName
= NULL
;
2433 wndclass
.lpszClassName
= L
"WineConsoleClass";
2434 RegisterClassW(&wndclass
);
2436 if (!CreateWindowW( wndclass
.lpszClassName
, NULL
,
2437 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2438 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2439 0, 0, 0, 0, wndclass
.hInstance
, console
))
2442 apply_config( console
, &config
);
2446 void init_message_window( struct console
*console
)
2450 wndclass
.style
= CS_DBLCLKS
;
2451 wndclass
.lpfnWndProc
= window_proc
;
2452 wndclass
.cbClsExtra
= 0;
2453 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2454 wndclass
.hInstance
= GetModuleHandleW( NULL
);
2456 wndclass
.hCursor
= 0;
2457 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2458 wndclass
.lpszMenuName
= NULL
;
2459 wndclass
.lpszClassName
= L
"WineConsoleClass";
2460 RegisterClassW(&wndclass
);
2462 CreateWindowW( wndclass
.lpszClassName
, NULL
,
2463 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2464 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2465 0, 0, HWND_MESSAGE
, 0, wndclass
.hInstance
, console
);