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=%d lfWidth=%d lfEscapement=%d "
114 "lfOrientation=%d lfWeight=%d 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=%d tmAscent=%d tmDescent=%d "
128 "tmAveCharWidth=%d tmMaxCharWidth=%d tmWeight=%d "
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
= 25;
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", 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
, sizeof(config
->face_name
) );
308 val
= config
->font_pitch_family
;
309 RegSetValueExW( key
, L
"FontPitchFamily", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
311 width
= MulDiv( config
->cell_width
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
312 height
= MulDiv( config
->cell_height
, USER_DEFAULT_SCREEN_DPI
, GetDpiForSystem() );
313 val
= MAKELONG( width
, height
);
314 RegSetValueExW( key
, L
"FontSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
316 val
= config
->font_weight
;
317 RegSetValueExW( key
, L
"FontWeight", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
319 val
= config
->history_size
;
320 RegSetValueExW( key
, L
"HistoryBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
322 val
= config
->history_mode
;
323 RegSetValueExW( key
, L
"HistoryNoDup", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
325 val
= config
->insert_mode
;
326 RegSetValueExW( key
, L
"InsertMode", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
328 val
= config
->menu_mask
;
329 RegSetValueExW( key
, L
"MenuMask", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
331 val
= config
->popup_attr
;
332 RegSetValueExW( key
, L
"PopupColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
334 val
= config
->quick_edit
;
335 RegSetValueExW( key
, L
"QuickEdit", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
337 val
= MAKELONG(config
->sb_width
, config
->sb_height
);
338 RegSetValueExW( key
, L
"ScreenBufferSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
341 RegSetValueExW( key
, L
"ScreenColors", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
343 val
= MAKELONG( config
->win_width
, config
->win_height
);
344 RegSetValueExW( key
, L
"WindowSize", 0, REG_DWORD
, (BYTE
*)&val
, sizeof(val
) );
347 static void save_config( const WCHAR
*key_name
, const struct console_config
*config
)
351 TRACE( "%s %s\n", debugstr_w( key_name
), debugstr_config( config
));
353 if (RegCreateKeyW( HKEY_CURRENT_USER
, L
"Console", &key
))
355 ERR("Can't open registry for saving\n");
361 if (RegCreateKeyW( key
, key_name
, &app_key
))
363 ERR("Can't open registry for saving\n");
367 /* FIXME: maybe only save the values different from the default value ? */
368 save_registry_key( app_key
, config
);
369 RegCloseKey( app_key
);
372 else save_registry_key( key
, config
);
376 /* fill memory DC with current cells values */
377 static void fill_mem_dc( struct console
*console
, const RECT
*update
)
379 unsigned int i
, j
, k
;
388 if (!console
->window
->font
|| !console
->window
->bitmap
)
391 if (!(line
= malloc( (update
->right
- update
->left
+ 1) * sizeof(WCHAR
))) ) return;
392 dx
= malloc( (update
->right
- update
->left
+ 1) * sizeof(*dx
) );
394 old_font
= SelectObject( console
->window
->mem_dc
, console
->window
->font
);
395 for (j
= update
->top
; j
<= update
->bottom
; j
++)
397 cell
= &console
->active
->data
[j
* console
->active
->width
];
398 for (i
= update
->left
; i
<= update
->right
; i
++)
401 SetBkColor( console
->window
->mem_dc
, console
->active
->color_map
[(attr
>> 4) & 0x0F] );
402 SetTextColor( console
->window
->mem_dc
, console
->active
->color_map
[attr
& 0x0F] );
403 for (k
= i
; k
<= update
->right
&& cell
[k
].attr
== attr
; k
++)
405 line
[k
- i
] = cell
[k
].ch
;
406 dx
[k
- i
] = console
->active
->font
.width
;
408 ExtTextOutW( console
->window
->mem_dc
, i
* console
->active
->font
.width
,
409 j
* console
->active
->font
.height
, 0, NULL
, line
, k
- i
, dx
);
410 if (console
->window
->ext_leading
&&
411 (brush
= CreateSolidBrush( console
->active
->color_map
[(attr
>> 4) & 0x0F] )))
413 r
.left
= i
* console
->active
->font
.width
;
414 r
.top
= (j
+ 1) * console
->active
->font
.height
- console
->window
->ext_leading
;
415 r
.right
= k
* console
->active
->font
.width
;
416 r
.bottom
= (j
+ 1) * console
->active
->font
.height
;
417 FillRect( console
->window
->mem_dc
, &r
, brush
);
418 DeleteObject( brush
);
423 SelectObject( console
->window
->mem_dc
, old_font
);
428 /* set a new position for the cursor */
429 static void update_window_cursor( struct console
*console
)
431 if (console
->win
!= GetFocus() || !console
->active
->cursor_visible
) return;
433 SetCaretPos( (console
->active
->cursor_x
- console
->active
->win
.left
) * console
->active
->font
.width
,
434 (console
->active
->cursor_y
- console
->active
->win
.top
) * console
->active
->font
.height
);
435 ShowCaret( console
->win
);
438 /* sets a new shape for the cursor */
439 static void shape_cursor( struct console
*console
)
441 int size
= console
->active
->cursor_size
;
443 if (console
->active
->cursor_visible
&& console
->win
== GetFocus()) DestroyCaret();
444 if (console
->window
->cursor_bitmap
) DeleteObject( console
->window
->cursor_bitmap
);
445 console
->window
->cursor_bitmap
= NULL
;
446 console
->window
->cursor_visible
= FALSE
;
450 int w16b
; /* number of bytes per row, aligned on word size */
454 w16b
= ((console
->active
->font
.width
+ 15) & ~15) / 8;
455 ptr
= calloc( w16b
, console
->active
->font
.height
);
457 nbl
= max( (console
->active
->font
.height
* size
) / 100, 1 );
458 for (j
= console
->active
->font
.height
- nbl
; j
< console
->active
->font
.height
; j
++)
460 for (i
= 0; i
< console
->active
->font
.width
; i
++)
462 ptr
[w16b
* j
+ (i
/ 8)] |= 0x80 >> (i
& 7);
465 console
->window
->cursor_bitmap
= CreateBitmap( console
->active
->font
.width
,
466 console
->active
->font
.height
, 1, 1, ptr
);
471 static void update_window( struct console
*console
)
473 unsigned int win_width
, win_height
;
474 BOOL update_all
= FALSE
;
478 console
->window
->update_state
= UPDATE_BUSY
;
480 if (console
->window
->sb_width
!= console
->active
->width
||
481 console
->window
->sb_height
!= console
->active
->height
||
482 (!console
->window
->bitmap
&& IsWindowVisible( console
->win
)))
484 console
->window
->sb_width
= console
->active
->width
;
485 console
->window
->sb_height
= console
->active
->height
;
487 if (console
->active
->width
&& console
->active
->height
&& console
->window
->font
)
493 if (!(dc
= GetDC( console
->win
))) return;
495 bitmap
= CreateCompatibleBitmap( dc
,
496 console
->active
->width
* console
->active
->font
.width
,
497 console
->active
->height
* console
->active
->font
.height
);
498 ReleaseDC( console
->win
, dc
);
499 SelectObject( console
->window
->mem_dc
, bitmap
);
501 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
502 console
->window
->bitmap
= bitmap
;
503 SetRect( &r
, 0, 0, console
->active
->width
- 1, console
->active
->height
- 1 );
504 fill_mem_dc( console
, &r
);
507 empty_update_rect( console
->active
, &console
->window
->update
);
511 /* compute window size from desired client size */
512 win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
513 win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
515 if (update_all
|| win_width
!= console
->window
->win_width
||
516 win_height
!= console
->window
->win_height
)
518 console
->window
->win_width
= win_width
;
519 console
->window
->win_height
= win_height
;
522 r
.right
= win_width
* console
->active
->font
.width
;
523 r
.bottom
= win_height
* console
->active
->font
.height
;
524 AdjustWindowRect( &r
, GetWindowLongW( console
->win
, GWL_STYLE
), FALSE
);
527 if (console
->active
->width
> win_width
)
529 dy
= GetSystemMetrics( SM_CYHSCROLL
);
530 SetScrollRange( console
->win
, SB_HORZ
, 0, console
->active
->width
- win_width
, FALSE
);
531 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
532 ShowScrollBar( console
->win
, SB_HORZ
, TRUE
);
536 ShowScrollBar( console
->win
, SB_HORZ
, FALSE
);
539 if (console
->active
->height
> win_height
)
541 dx
= GetSystemMetrics( SM_CXVSCROLL
);
542 SetScrollRange( console
->win
, SB_VERT
, 0, console
->active
->height
- win_height
, FALSE
);
543 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, FALSE
);
544 ShowScrollBar( console
->win
, SB_VERT
, TRUE
);
547 ShowScrollBar( console
->win
, SB_VERT
, FALSE
);
549 dx
+= r
.right
- r
.left
;
550 dy
+= r
.bottom
- r
.top
;
551 SetWindowPos( console
->win
, 0, 0, 0, dx
, dy
, SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
553 SystemParametersInfoW( SPI_GETWORKAREA
, 0, &r
, 0 );
554 console
->active
->max_width
= (r
.right
- r
.left
) / console
->active
->font
.width
;
555 console
->active
->max_height
= (r
.bottom
- r
.top
- GetSystemMetrics( SM_CYCAPTION
)) /
556 console
->active
->font
.height
;
558 InvalidateRect( console
->win
, NULL
, FALSE
);
559 UpdateWindow( console
->win
);
562 else if (console
->active
->win
.left
!= console
->window
->win_pos
.X
||
563 console
->active
->win
.top
!= console
->window
->win_pos
.Y
)
565 ScrollWindow( console
->win
,
566 (console
->window
->win_pos
.X
- console
->active
->win
.left
) * console
->active
->font
.width
,
567 (console
->window
->win_pos
.Y
- console
->active
->win
.top
) * console
->active
->font
.height
,
569 SetScrollPos( console
->win
, SB_HORZ
, console
->active
->win
.left
, TRUE
);
570 SetScrollPos( console
->win
, SB_VERT
, console
->active
->win
.top
, TRUE
);
571 InvalidateRect( console
->win
, NULL
, FALSE
);
574 console
->window
->win_pos
.X
= console
->active
->win
.left
;
575 console
->window
->win_pos
.Y
= console
->active
->win
.top
;
577 if (console
->window
->update
.top
<= console
->window
->update
.bottom
&&
578 console
->window
->update
.left
<= console
->window
->update
.right
)
580 RECT
*update
= &console
->window
->update
;
581 r
.left
= (update
->left
- console
->active
->win
.left
) * console
->active
->font
.width
;
582 r
.right
= (update
->right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
;
583 r
.top
= (update
->top
- console
->active
->win
.top
) * console
->active
->font
.height
;
584 r
.bottom
= (update
->bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
;
585 fill_mem_dc( console
, update
);
586 empty_update_rect( console
->active
, &console
->window
->update
);
587 InvalidateRect( console
->win
, &r
, FALSE
);
588 UpdateWindow( console
->win
);
591 if (update_all
|| console
->active
->cursor_size
!= console
->window
->cursor_size
)
593 console
->window
->cursor_size
= console
->active
->cursor_size
;
594 shape_cursor( console
);
597 if (console
->active
->cursor_visible
!= console
->window
->cursor_visible
)
599 console
->window
->cursor_visible
= console
->active
->cursor_visible
;
600 if (console
->win
== GetFocus())
602 if (console
->window
->cursor_visible
)
603 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
604 console
->active
->font
.width
, console
->active
->font
.height
);
610 if (update_all
|| console
->active
->cursor_x
!= console
->window
->cursor_pos
.X
||
611 console
->active
->cursor_y
!= console
->window
->cursor_pos
.Y
)
613 console
->window
->cursor_pos
.X
= console
->active
->cursor_x
;
614 console
->window
->cursor_pos
.Y
= console
->active
->cursor_y
;
615 update_window_cursor( console
);
618 console
->window
->update_state
= UPDATE_NONE
;
621 /* get the relevant information from the font described in lf and store them in config */
622 static HFONT
select_font_config( struct console_config
*config
, unsigned int cp
, HWND hwnd
,
625 HFONT font
, old_font
;
630 if (!(dc
= GetDC( hwnd
))) return NULL
;
631 if (!(font
= CreateFontIndirectW( lf
)))
633 ReleaseDC( hwnd
, dc
);
637 old_font
= SelectObject( dc
, font
);
638 GetTextMetricsW( dc
, &tm
);
639 SelectObject( dc
, old_font
);
640 ReleaseDC( hwnd
, dc
);
642 config
->cell_width
= tm
.tmAveCharWidth
;
643 config
->cell_height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
644 config
->font_weight
= tm
.tmWeight
;
645 lstrcpyW( config
->face_name
, lf
->lfFaceName
);
647 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
648 if (GetCPInfo( cp
, &cpinfo
) && cpinfo
.MaxCharSize
> 1)
649 config
->cell_width
= tm
.tmMaxCharWidth
;
654 static void fill_logfont( LOGFONTW
*lf
, const WCHAR
*name
, unsigned int height
, unsigned int weight
)
656 lf
->lfHeight
= height
;
658 lf
->lfEscapement
= 0;
659 lf
->lfOrientation
= 0;
660 lf
->lfWeight
= weight
;
661 lf
->lfItalic
= FALSE
;
662 lf
->lfUnderline
= FALSE
;
663 lf
->lfStrikeOut
= FALSE
;
664 lf
->lfCharSet
= DEFAULT_CHARSET
;
665 lf
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
666 lf
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
667 lf
->lfQuality
= DEFAULT_QUALITY
;
668 lf
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
669 lstrcpyW( lf
->lfFaceName
, name
);
672 static BOOL
set_console_font( struct console
*console
, const LOGFONTW
*logfont
)
674 struct font_info
*font_info
= &console
->active
->font
;
675 HFONT font
, old_font
;
680 TRACE( "%s\n", debugstr_logfont( logfont
, 0 ));
682 if (console
->window
->font
&& logfont
->lfHeight
== console
->active
->font
.height
&&
683 logfont
->lfWeight
== console
->active
->font
.weight
&&
684 !logfont
->lfItalic
&& !logfont
->lfUnderline
&& !logfont
->lfStrikeOut
&&
685 console
->active
->font
.face_len
== wcslen( logfont
->lfFaceName
) * sizeof(WCHAR
) &&
686 !memcmp( logfont
->lfFaceName
, console
->active
->font
.face_name
,
687 console
->active
->font
.face_len
))
689 TRACE( "equal to current\n" );
693 if (!(dc
= GetDC( console
->win
))) return FALSE
;
694 if (!(font
= CreateFontIndirectW( logfont
)))
696 ReleaseDC( console
->win
, dc
);
700 old_font
= SelectObject( dc
, font
);
701 GetTextMetricsW( dc
, &tm
);
702 SelectObject( dc
, old_font
);
703 ReleaseDC( console
->win
, dc
);
705 font_info
->width
= tm
.tmAveCharWidth
;
706 font_info
->height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
707 font_info
->weight
= tm
.tmWeight
;
709 free( font_info
->face_name
);
710 font_info
->face_len
= wcslen( logfont
->lfFaceName
) * sizeof(WCHAR
);
711 font_info
->face_name
= malloc( font_info
->face_len
);
712 memcpy( font_info
->face_name
, logfont
->lfFaceName
, font_info
->face_len
);
714 /* FIXME: use maximum width for DBCS codepages since some chars take two cells */
715 if (GetCPInfo( console
->output_cp
, &cpinfo
) && cpinfo
.MaxCharSize
> 1)
716 font_info
->width
= tm
.tmMaxCharWidth
;
718 if (console
->window
->font
) DeleteObject( console
->window
->font
);
719 console
->window
->font
= font
;
720 console
->window
->ext_leading
= tm
.tmExternalLeading
;
722 if (console
->window
->bitmap
)
724 DeleteObject(console
->window
->bitmap
);
725 console
->window
->bitmap
= NULL
;
732 struct console
*console
;
737 /* check if the font described in tm is usable as a font for the renderer */
738 static BOOL
validate_font_metric( struct console
*console
, const TEXTMETRICW
*tm
,
739 DWORD type
, int pass
)
741 switch (pass
) /* we get increasingly lenient in later passes */
744 if (type
& RASTER_FONTTYPE
) return FALSE
;
747 if (type
& RASTER_FONTTYPE
)
749 if (tm
->tmMaxCharWidth
* (console
->active
->win
.right
- console
->active
->win
.left
+ 1)
750 >= GetSystemMetrics(SM_CXSCREEN
))
752 if (tm
->tmHeight
* (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
753 >= GetSystemMetrics(SM_CYSCREEN
))
758 if (tm
->tmCharSet
!= DEFAULT_CHARSET
&& tm
->tmCharSet
!= console
->window
->ui_charset
)
762 if (tm
->tmItalic
|| tm
->tmUnderlined
|| tm
->tmStruckOut
) return FALSE
;
768 /* check if the font family described in lf is usable as a font for the renderer */
769 static BOOL
validate_font( struct console
*console
, const LOGFONTW
*lf
, int pass
)
771 switch (pass
) /* we get increasingly lenient in later passes */
776 if (lf
->lfCharSet
!= DEFAULT_CHARSET
&& lf
->lfCharSet
!= console
->window
->ui_charset
)
780 if ((lf
->lfPitchAndFamily
& 3) != FIXED_PITCH
) return FALSE
;
783 if (lf
->lfFaceName
[0] == '@') return FALSE
;
789 /* helper functions to get a decent font for the renderer */
790 static int WINAPI
get_first_font_sub_enum( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
791 DWORD font_type
, LPARAM lparam
)
793 struct font_chooser
*fc
= (struct font_chooser
*)lparam
;
795 TRACE( "%s\n", debugstr_textmetric( tm
, font_type
));
797 if (validate_font_metric( fc
->console
, tm
, font_type
, fc
->pass
))
801 /* Use the default sizes for the font (this is needed, especially for
802 * TrueType fonts, so that we get a decent size, not the max size)
804 mlf
.lfWidth
= fc
->console
->active
->font
.width
;
805 mlf
.lfHeight
= fc
->console
->active
->font
.height
;
807 mlf
.lfHeight
= MulDiv( 16, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI
);
809 if (set_console_font( fc
->console
, &mlf
))
811 struct console_config config
;
815 /* since we've modified the current config with new font information,
816 * set this information as the new default.
818 load_config( fc
->console
->window
->config_key
, &config
);
819 config
.cell_width
= fc
->console
->active
->font
.width
;
820 config
.cell_height
= fc
->console
->active
->font
.height
;
821 fc
->console
->active
->font
.face_len
= wcslen( config
.face_name
) * sizeof(WCHAR
);
822 memcpy( fc
->console
->active
->font
.face_name
, config
.face_name
,
823 fc
->console
->active
->font
.face_len
);
824 /* Force also its writing back to the registry so that we can get it
827 save_config( fc
->console
->window
->config_key
, &config
);
834 static int WINAPI
get_first_font_enum( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
835 DWORD font_type
, LPARAM lparam
)
837 struct font_chooser
*fc
= (struct font_chooser
*)lparam
;
839 TRACE("%s\n", debugstr_logfont( lf
, font_type
));
841 if (validate_font( fc
->console
, lf
, fc
->pass
))
843 EnumFontFamiliesW( fc
->console
->window
->mem_dc
, lf
->lfFaceName
,
844 get_first_font_sub_enum
, lparam
);
845 return !fc
->done
; /* we just need the first matching one... */
851 /* sets logfont as the new font for the console */
852 static void update_console_font( struct console
*console
, const WCHAR
*font
,
853 unsigned int height
, unsigned int weight
)
855 struct font_chooser fc
;
858 if (font
[0] && height
&& weight
)
860 fill_logfont( &lf
, font
, height
, weight
);
861 if (set_console_font( console
, &lf
)) return;
864 /* try to find an acceptable font */
865 WARN( "Couldn't match the font from registry, trying to find one\n" );
866 fc
.console
= console
;
868 for (fc
.pass
= 0; fc
.pass
<= 5; fc
.pass
++)
870 EnumFontFamiliesW( console
->window
->mem_dc
, NULL
, get_first_font_enum
, (LPARAM
)&fc
);
873 ERR( "Couldn't find a decent font" );
876 /* get a cell from a relative coordinate in window (takes into account the scrolling) */
877 static COORD
get_cell( struct console
*console
, LPARAM lparam
)
880 c
.X
= console
->active
->win
.left
+ (short)LOWORD(lparam
) / console
->active
->font
.width
;
881 c
.Y
= console
->active
->win
.top
+ (short)HIWORD(lparam
) / console
->active
->font
.height
;
885 /* get the console bit mask equivalent to the VK_ status in key state */
886 static DWORD
get_ctrl_state( BYTE
*key_state
)
888 unsigned int ret
= 0;
890 GetKeyboardState(key_state
);
891 if (key_state
[VK_SHIFT
] & 0x80) ret
|= SHIFT_PRESSED
;
892 if (key_state
[VK_LCONTROL
] & 0x80) ret
|= LEFT_CTRL_PRESSED
;
893 if (key_state
[VK_RCONTROL
] & 0x80) ret
|= RIGHT_CTRL_PRESSED
;
894 if (key_state
[VK_LMENU
] & 0x80) ret
|= LEFT_ALT_PRESSED
;
895 if (key_state
[VK_RMENU
] & 0x80) ret
|= RIGHT_ALT_PRESSED
;
896 if (key_state
[VK_CAPITAL
] & 0x01) ret
|= CAPSLOCK_ON
;
897 if (key_state
[VK_NUMLOCK
] & 0x01) ret
|= NUMLOCK_ON
;
898 if (key_state
[VK_SCROLL
] & 0x01) ret
|= SCROLLLOCK_ON
;
903 /* get the selection rectangle */
904 static void get_selection_rect( struct console
*console
, RECT
*r
)
906 r
->left
= (min(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) -
907 console
->active
->win
.left
) * console
->active
->font
.width
;
908 r
->top
= (min(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) -
909 console
->active
->win
.top
) * console
->active
->font
.height
;
910 r
->right
= (max(console
->window
->selection_start
.X
, console
->window
->selection_end
.X
) + 1 -
911 console
->active
->win
.left
) * console
->active
->font
.width
;
912 r
->bottom
= (max(console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
) + 1 -
913 console
->active
->win
.top
) * console
->active
->font
.height
;
916 static void update_selection( struct console
*console
, HDC ref_dc
)
921 get_selection_rect( console
, &r
);
922 dc
= ref_dc
? ref_dc
: GetDC( console
->win
);
925 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
926 HideCaret( console
->win
);
927 InvertRect( dc
, &r
);
929 ReleaseDC( console
->win
, dc
);
930 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
931 ShowCaret( console
->win
);
934 static void move_selection( struct console
*console
, COORD c1
, COORD c2
)
939 if (c1
.X
< 0 || c1
.X
>= console
->active
->width
||
940 c2
.X
< 0 || c2
.X
>= console
->active
->width
||
941 c1
.Y
< 0 || c1
.Y
>= console
->active
->height
||
942 c2
.Y
< 0 || c2
.Y
>= console
->active
->height
)
945 get_selection_rect( console
, &r
);
946 dc
= GetDC( console
->win
);
949 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
950 HideCaret( console
->win
);
951 InvertRect( dc
, &r
);
953 console
->window
->selection_start
= c1
;
954 console
->window
->selection_end
= c2
;
957 get_selection_rect( console
, &r
);
958 InvertRect( dc
, &r
);
959 ReleaseDC( console
->win
, dc
);
960 if (console
->win
== GetFocus() && console
->active
->cursor_visible
)
961 ShowCaret( console
->win
);
965 /* copies the current selection into the clipboard */
966 static void copy_selection( struct console
*console
)
972 w
= abs( console
->window
->selection_start
.X
- console
->window
->selection_end
.X
) + 1;
973 h
= abs( console
->window
->selection_start
.Y
- console
->window
->selection_end
.Y
) + 1;
975 if (!OpenClipboard( console
->win
)) return;
978 mem
= GlobalAlloc( GMEM_MOVEABLE
, (w
+ 1) * h
* sizeof(WCHAR
) );
979 if (mem
&& (p
= buf
= GlobalLock( mem
)))
984 c
.X
= min( console
->window
->selection_start
.X
, console
->window
->selection_end
.X
);
985 c
.Y
= min( console
->window
->selection_start
.Y
, console
->window
->selection_end
.Y
);
987 for (y
= c
.Y
; y
< c
.Y
+ h
; y
++)
991 for (x
= c
.X
; x
< c
.X
+ w
; x
++)
992 p
[x
- c
.X
] = console
->active
->data
[y
* console
->active
->width
+ x
].ch
;
994 /* strip spaces from the end of the line */
996 while (end
> p
&& *(end
- 1) == ' ')
998 *end
= (y
< c
.Y
+ h
- 1) ? '\n' : '\0';
1002 TRACE( "%s\n", debugstr_w( buf
));
1003 if (p
- buf
!= (w
+ 1) * h
)
1006 new_mem
= GlobalReAlloc( mem
, (p
- buf
) * sizeof(WCHAR
), GMEM_MOVEABLE
);
1007 if (new_mem
) mem
= new_mem
;
1009 GlobalUnlock( mem
);
1010 SetClipboardData( CF_UNICODETEXT
, mem
);
1015 static void paste_clipboard( struct console
*console
)
1020 if (!OpenClipboard( console
->win
)) return;
1021 h
= GetClipboardData( CF_UNICODETEXT
);
1022 if (h
&& (ptr
= GlobalLock( h
)))
1024 unsigned int i
, len
= GlobalSize(h
) / sizeof(WCHAR
);
1028 ir
[0].EventType
= KEY_EVENT
;
1029 ir
[0].Event
.KeyEvent
.wRepeatCount
= 0;
1030 ir
[0].Event
.KeyEvent
.dwControlKeyState
= 0;
1031 ir
[0].Event
.KeyEvent
.bKeyDown
= TRUE
;
1033 /* generate the corresponding input records */
1034 for (i
= 0; i
< len
; i
++)
1036 /* FIXME: the modifying keys are not generated (shift, ctrl...) */
1037 sh
= VkKeyScanW( ptr
[i
] );
1038 ir
[0].Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(sh
);
1039 ir
[0].Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKeyW( LOBYTE(sh
), 0 );
1040 ir
[0].Event
.KeyEvent
.uChar
.UnicodeChar
= ptr
[i
];
1043 ir
[1].Event
.KeyEvent
.bKeyDown
= FALSE
;
1045 write_console_input( console
, ir
, 2, i
== len
- 1 );
1053 /* handle keys while selecting an area */
1054 static void handle_selection_key( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1056 BYTE key_state
[256];
1061 state
= get_ctrl_state( key_state
) & ~(CAPSLOCK_ON
|NUMLOCK_ON
|SCROLLLOCK_ON
);
1069 console
->window
->in_selection
= FALSE
;
1070 update_selection( console
, 0 );
1071 copy_selection( console
);
1074 c1
= console
->window
->selection_start
;
1075 c2
= console
->window
->selection_end
;
1077 move_selection( console
, c1
, c2
);
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
);
1103 c1
= console
->window
->selection_start
;
1104 c2
= console
->window
->selection_end
;
1106 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
);
1130 if (wparam
< VK_SPACE
) /* Shift, Alt, Ctrl, Num Lock etc. */
1133 update_selection( console
, 0 );
1134 console
->window
->in_selection
= FALSE
;
1137 /* generate input_record from windows WM_KEYUP/WM_KEYDOWN messages */
1138 static void record_key_input( struct console
*console
, BOOL down
, WPARAM wparam
, LPARAM lparam
)
1140 static WCHAR last
; /* keep last char seen as feed for key up message */
1141 BYTE key_state
[256];
1145 ir
.EventType
= KEY_EVENT
;
1146 ir
.Event
.KeyEvent
.bKeyDown
= down
;
1147 ir
.Event
.KeyEvent
.wRepeatCount
= LOWORD(lparam
);
1148 ir
.Event
.KeyEvent
.wVirtualKeyCode
= wparam
;
1149 ir
.Event
.KeyEvent
.wVirtualScanCode
= HIWORD(lparam
) & 0xFF;
1150 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
1151 ir
.Event
.KeyEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1152 if (lparam
& (1u << 24)) ir
.Event
.KeyEvent
.dwControlKeyState
|= ENHANCED_KEY
;
1156 switch (ToUnicode(wparam
, HIWORD(lparam
), key_state
, buf
, 2, 0))
1159 /* FIXME: should generate two events */
1169 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= last
;
1170 if (!down
) last
= 0; /* FIXME: buggy HACK */
1172 write_console_input( console
, &ir
, 1, TRUE
);
1175 static void record_mouse_input( struct console
*console
, COORD c
, WPARAM wparam
, DWORD event
)
1177 BYTE key_state
[256];
1180 /* MOUSE_EVENTs shouldn't be sent unless ENABLE_MOUSE_INPUT is active */
1181 if (!(console
->mode
& ENABLE_MOUSE_INPUT
)) return;
1183 ir
.EventType
= MOUSE_EVENT
;
1184 ir
.Event
.MouseEvent
.dwMousePosition
= c
;
1185 ir
.Event
.MouseEvent
.dwButtonState
= 0;
1186 if (wparam
& MK_LBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1187 if (wparam
& MK_MBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1188 if (wparam
& MK_RBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1189 if (wparam
& MK_CONTROL
) ir
.Event
.MouseEvent
.dwButtonState
|= LEFT_CTRL_PRESSED
;
1190 if (wparam
& MK_SHIFT
) ir
.Event
.MouseEvent
.dwButtonState
|= SHIFT_PRESSED
;
1191 if (event
== MOUSE_WHEELED
) ir
.Event
.MouseEvent
.dwButtonState
|= wparam
& 0xFFFF0000;
1192 ir
.Event
.MouseEvent
.dwControlKeyState
= get_ctrl_state( key_state
);
1193 ir
.Event
.MouseEvent
.dwEventFlags
= event
;
1195 write_console_input( console
, &ir
, 1, TRUE
);
1200 struct console
*console
;
1201 struct console_config config
;
1202 HWND dialog
; /* handle to active propsheet */
1203 int font_count
; /* number of fonts */
1204 struct dialog_font_info
1206 unsigned int height
;
1207 unsigned int weight
;
1208 WCHAR faceName
[LF_FACESIZE
];
1209 } *font
; /* array of fonts */
1212 /* dialog proc for the option property sheet */
1213 static INT_PTR WINAPI
option_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1215 struct dialog_info
*di
;
1221 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1222 di
->dialog
= dialog
;
1223 SetWindowLongPtrW( dialog
, DWLP_USER
, (LONG_PTR
)di
);
1225 SendMessageW( GetDlgItem( dialog
, IDC_OPT_HIST_SIZE_UD
), UDM_SETRANGE
, 0, MAKELPARAM(500, 0) );
1227 if (di
->config
.cursor_size
<= 25) idc
= IDC_OPT_CURSOR_SMALL
;
1228 else if (di
->config
.cursor_size
<= 50) idc
= IDC_OPT_CURSOR_MEDIUM
;
1229 else idc
= IDC_OPT_CURSOR_LARGE
;
1231 SendDlgItemMessageW( dialog
, idc
, BM_SETCHECK
, BST_CHECKED
, 0 );
1232 SetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, di
->config
.history_size
, FALSE
);
1233 SendDlgItemMessageW( dialog
, IDC_OPT_HIST_NODOUBLE
, BM_SETCHECK
,
1234 (di
->config
.history_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1235 SendDlgItemMessageW( dialog
, IDC_OPT_INSERT_MODE
, BM_SETCHECK
,
1236 (di
->config
.insert_mode
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1237 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_CTRL
, BM_SETCHECK
,
1238 (di
->config
.menu_mask
& MK_CONTROL
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1239 SendDlgItemMessageW( dialog
, IDC_OPT_CONF_SHIFT
, BM_SETCHECK
,
1240 (di
->config
.menu_mask
& MK_SHIFT
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1241 SendDlgItemMessageW( dialog
, IDC_OPT_QUICK_EDIT
, BM_SETCHECK
,
1242 (di
->config
.quick_edit
) ? BST_CHECKED
: BST_UNCHECKED
, 0 );
1243 return FALSE
; /* because we set the focus */
1250 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1254 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1256 switch (nmhdr
->code
)
1259 /* needed in propsheet to keep properly the selected radio button
1260 * otherwise, the focus would be set to the first tab stop in the
1261 * propsheet, which would always activate the first radio button
1263 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
)
1264 idc
= IDC_OPT_CURSOR_SMALL
;
1265 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
)
1266 idc
= IDC_OPT_CURSOR_MEDIUM
;
1268 idc
= IDC_OPT_CURSOR_LARGE
;
1269 PostMessageW( dialog
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem( dialog
, idc
), TRUE
);
1270 di
->dialog
= dialog
;
1273 if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_SMALL
) == BST_CHECKED
) val
= 25;
1274 else if (IsDlgButtonChecked( dialog
, IDC_OPT_CURSOR_MEDIUM
) == BST_CHECKED
) val
= 50;
1276 di
->config
.cursor_size
= val
;
1278 val
= GetDlgItemInt( dialog
, IDC_OPT_HIST_SIZE
, &done
, FALSE
);
1279 if (done
) di
->config
.history_size
= val
;
1281 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_HIST_NODOUBLE
) & BST_CHECKED
) != 0;
1282 di
->config
.history_mode
= val
;
1284 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_INSERT_MODE
) & BST_CHECKED
) != 0;
1285 di
->config
.insert_mode
= val
;
1288 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_CTRL
) & BST_CHECKED
) val
|= MK_CONTROL
;
1289 if (IsDlgButtonChecked( dialog
, IDC_OPT_CONF_SHIFT
) & BST_CHECKED
) val
|= MK_SHIFT
;
1290 di
->config
.menu_mask
= val
;
1292 val
= (IsDlgButtonChecked( dialog
, IDC_OPT_QUICK_EDIT
) & BST_CHECKED
) != 0;
1293 di
->config
.quick_edit
= val
;
1295 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1308 static COLORREF
get_color( struct dialog_info
*di
, unsigned int idc
)
1312 index
= GetWindowLongPtrW(GetDlgItem( di
->dialog
, idc
), 0);
1313 return di
->config
.color_map
[index
];
1316 /* window proc for font previewer in font property sheet */
1317 static LRESULT WINAPI
font_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1322 SetWindowLongPtrW( hwnd
, 0, 0 );
1326 return GetWindowLongPtrW( hwnd
, 0 );
1329 SetWindowLongPtrW( hwnd
, 0, wparam
);
1332 InvalidateRect( hwnd
, NULL
, TRUE
);
1333 UpdateWindow( hwnd
);
1339 HFONT font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1340 if (font
) DeleteObject( font
);
1346 struct dialog_info
*di
;
1347 HFONT font
, old_font
;
1351 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent( hwnd
), DWLP_USER
);
1352 BeginPaint( hwnd
, &ps
);
1354 size_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1355 font
= (HFONT
)GetWindowLongPtrW( hwnd
, 0 );
1358 static const WCHAR ascii
[] = L
"ASCII: abcXYZ";
1363 old_font
= SelectObject( ps
.hdc
, font
);
1364 bkcolor
= get_color( di
, IDC_FNT_COLOR_BK
);
1365 FillRect( ps
.hdc
, &ps
.rcPaint
, CreateSolidBrush( bkcolor
));
1366 SetBkColor( ps
.hdc
, bkcolor
);
1367 SetTextColor( ps
.hdc
, get_color( di
, IDC_FNT_COLOR_FG
));
1368 len
= LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_PREVIEW
, buf
, ARRAY_SIZE(buf
) );
1369 if (len
) TextOutW( ps
.hdc
, 0, 0, buf
, len
);
1370 TextOutW( ps
.hdc
, 0, di
->font
[size_idx
].height
, ascii
, ARRAY_SIZE(ascii
) - 1 );
1371 SelectObject( ps
.hdc
, old_font
);
1373 EndPaint( hwnd
, &ps
);
1378 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1383 /* window proc for color previewer */
1384 static LRESULT WINAPI
color_preview_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1390 struct dialog_info
*di
;
1396 BeginPaint( hwnd
, &ps
);
1397 GetClientRect( hwnd
, &client
);
1398 step
= client
.right
/ 8;
1400 di
= (struct dialog_info
*)GetWindowLongPtrW( GetParent(hwnd
), DWLP_USER
);
1402 for (i
= 0; i
< 16; i
++)
1404 r
.top
= (i
/ 8) * (client
.bottom
/ 2);
1405 r
.bottom
= r
.top
+ client
.bottom
/ 2;
1406 r
.left
= (i
& 7) * step
;
1407 r
.right
= r
.left
+ step
;
1408 brush
= CreateSolidBrush( di
->config
.color_map
[i
] );
1409 FillRect( ps
.hdc
, &r
, brush
);
1410 DeleteObject( brush
);
1411 if (GetWindowLongW( hwnd
, 0 ) == i
)
1416 old_pen
= SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1417 r
.right
--; r
.bottom
--;
1420 MoveToEx( ps
.hdc
, r
.left
, r
.bottom
, NULL
);
1421 LineTo( ps
.hdc
, r
.left
, r
.top
);
1422 LineTo( ps
.hdc
, r
.right
, r
.top
);
1423 SelectObject( ps
.hdc
, GetStockObject( BLACK_PEN
));
1424 LineTo( ps
.hdc
, r
.right
, r
.bottom
);
1425 LineTo( ps
.hdc
, r
.left
, r
.bottom
);
1426 if (--i
== 0) break;
1427 r
.left
++; r
.top
++; r
.right
--; r
.bottom
--;
1428 SelectObject( ps
.hdc
, GetStockObject( WHITE_PEN
));
1430 SelectObject( ps
.hdc
, old_pen
);
1433 EndPaint( hwnd
, &ps
);
1437 case WM_LBUTTONDOWN
:
1442 GetClientRect( hwnd
, &client
);
1443 step
= client
.right
/ 8;
1444 i
= (HIWORD(lparam
) >= client
.bottom
/ 2) ? 8 : 0;
1445 i
+= LOWORD(lparam
) / step
;
1446 SetWindowLongW( hwnd
, 0, i
);
1447 InvalidateRect( GetDlgItem( GetParent( hwnd
), IDC_FNT_PREVIEW
), NULL
, FALSE
);
1448 InvalidateRect( hwnd
, NULL
, FALSE
);
1453 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
1458 /* enumerates all the font names with at least one valid font */
1459 static int WINAPI
font_enum_size2( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1460 DWORD font_type
, LPARAM lparam
)
1462 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1463 TRACE( "%s\n", debugstr_textmetric( tm
, font_type
));
1464 if (validate_font_metric( di
->console
, tm
, font_type
, 0 )) di
->font_count
++;
1468 static int WINAPI
font_enum( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1469 DWORD font_type
, LPARAM lparam
)
1471 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1473 TRACE( "%s\n", debugstr_logfont( lf
, font_type
));
1475 if (validate_font( di
->console
, lf
, 0 ))
1477 if (font_type
& RASTER_FONTTYPE
)
1480 EnumFontFamiliesW( di
->console
->window
->mem_dc
, lf
->lfFaceName
,
1481 font_enum_size2
, (LPARAM
)di
);
1487 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_ADDSTRING
,
1488 0, (LPARAM
)lf
->lfFaceName
);
1493 static int WINAPI
font_enum_size( const LOGFONTW
*lf
, const TEXTMETRICW
*tm
,
1494 DWORD font_type
, LPARAM lparam
)
1496 struct dialog_info
*di
= (struct dialog_info
*)lparam
;
1499 TRACE( "%s\n", debugstr_textmetric( tm
, font_type
));
1501 if (di
->font_count
== 0 && !(font_type
& RASTER_FONTTYPE
))
1503 static const int sizes
[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
1506 di
->font_count
= ARRAY_SIZE(sizes
);
1507 di
->font
= malloc( di
->font_count
* sizeof(di
->font
[0]) );
1508 for (i
= 0; i
< di
->font_count
; i
++)
1510 /* drop sizes where window size wouldn't fit on screen */
1511 if (sizes
[i
] * di
->config
.win_height
> GetSystemMetrics( SM_CYSCREEN
))
1516 di
->font
[i
].height
= sizes
[i
];
1517 di
->font
[i
].weight
= 400;
1518 lstrcpyW( di
->font
[i
].faceName
, lf
->lfFaceName
);
1519 wsprintfW( buf
, L
"%d", sizes
[i
] );
1520 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_INSERTSTRING
, i
, (LPARAM
)buf
);
1522 /* don't need to enumerate other */
1526 if (validate_font_metric( di
->console
, tm
, font_type
, 0 ))
1530 /* we want the string to be sorted with a numeric order, not a lexicographic...
1531 * do the job by hand... get where to insert the new string
1533 while (idx
< di
->font_count
&& tm
->tmHeight
> di
->font
[idx
].height
)
1535 while (idx
< di
->font_count
&&
1536 tm
->tmHeight
== di
->font
[idx
].height
&&
1537 tm
->tmWeight
> di
->font
[idx
].weight
)
1539 if (idx
== di
->font_count
||
1540 tm
->tmHeight
!= di
->font
[idx
].height
||
1541 tm
->tmWeight
< di
->font
[idx
].weight
)
1543 /* here we need to add the new entry */
1544 wsprintfW( buf
, L
"%d", tm
->tmHeight
);
1545 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_INSERTSTRING
, idx
, (LPARAM
)buf
);
1547 /* now grow our arrays and insert the values at the same index than in the list box */
1550 di
->font
= realloc( di
->font
, sizeof(*di
->font
) * (di
->font_count
+ 1) );
1551 if (idx
!= di
->font_count
)
1552 memmove( &di
->font
[idx
+ 1], &di
->font
[idx
],
1553 (di
->font_count
- idx
) * sizeof(*di
->font
) );
1556 di
->font
= malloc( sizeof(*di
->font
) );
1557 di
->font
[idx
].height
= tm
->tmHeight
;
1558 di
->font
[idx
].weight
= tm
->tmWeight
;
1559 lstrcpyW( di
->font
[idx
].faceName
, lf
->lfFaceName
);
1566 static BOOL
select_font( struct dialog_info
*di
)
1568 struct console_config config
;
1569 int font_idx
, size_idx
;
1570 HFONT font
, old_font
;
1576 font_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETCURSEL
, 0, 0 );
1577 size_idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1579 if (font_idx
< 0 || size_idx
< 0 || size_idx
>= di
->font_count
)
1582 fill_logfont( &lf
, di
->font
[size_idx
].faceName
, di
->font
[size_idx
].height
,
1583 di
->font
[size_idx
].weight
);
1584 font
= select_font_config( &config
, di
->console
->output_cp
, di
->console
->win
, &lf
);
1585 if (!font
) return FALSE
;
1587 if (config
.cell_height
!= di
->font
[size_idx
].height
)
1588 TRACE( "mismatched heights (%u<>%u)\n", config
.cell_height
, di
->font
[size_idx
].height
);
1590 old_font
= (HFONT
)SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_GETFONT
, 0, 0 );
1591 SendDlgItemMessageW( di
->dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1592 if (old_font
) DeleteObject( old_font
);
1594 LoadStringW( GetModuleHandleW(NULL
), IDS_FNT_DISPLAY
, fmt
, ARRAY_SIZE(fmt
) );
1595 args
[0] = config
.cell_width
;
1596 args
[1] = config
.cell_height
;
1597 FormatMessageW( FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
1598 fmt
, 0, 0, buf
, ARRAY_SIZE(buf
), (__ms_va_list
*)args
);
1600 SendDlgItemMessageW( di
->dialog
, IDC_FNT_FONT_INFO
, WM_SETTEXT
, 0, (LPARAM
)buf
);
1604 /* fills the size list box according to selected family in font LB */
1605 static BOOL
fill_list_size( struct dialog_info
*di
, BOOL init
)
1607 WCHAR face_name
[LF_FACESIZE
];
1610 idx
= SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETCURSEL
, 0, 0 );
1611 if (idx
< 0) return FALSE
;
1613 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_GETTEXT
, idx
, (LPARAM
)face_name
);
1614 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_RESETCONTENT
, 0, 0 );
1619 EnumFontFamiliesW( di
->console
->window
->mem_dc
, face_name
, font_enum_size
, (LPARAM
)di
);
1624 for (idx
= 0; idx
< di
->font_count
; idx
++)
1626 if (!lstrcmpW( di
->font
[idx
].faceName
, di
->config
.face_name
) &&
1627 di
->font
[idx
].height
== di
->config
.cell_height
&&
1628 di
->font
[idx
].weight
== di
->config
.font_weight
)
1630 if (ref
== -1) ref
= idx
;
1631 else TRACE("Several matches found: ref=%d idx=%d\n", ref
, idx
);
1634 idx
= (ref
== -1) ? 0 : ref
;
1637 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_SIZE
, LB_SETCURSEL
, idx
, 0 );
1642 static BOOL
fill_list_font( struct dialog_info
*di
)
1644 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_RESETCONTENT
, 0, 0 );
1645 EnumFontFamiliesW( di
->console
->window
->mem_dc
, NULL
, font_enum
, (LPARAM
)di
);
1646 if (SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SELECTSTRING
,
1647 -1, (LPARAM
)di
->config
.face_name
) == LB_ERR
)
1648 SendDlgItemMessageW( di
->dialog
, IDC_FNT_LIST_FONT
, LB_SETCURSEL
, 0, 0 );
1649 fill_list_size( di
, TRUE
);
1653 /* dialog proc for the font property sheet */
1654 static INT_PTR WINAPI
font_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1656 struct dialog_info
*di
;
1661 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1662 di
->dialog
= dialog
;
1663 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1664 /* remove dialog from this control, font will be reset when listboxes are filled */
1665 SendDlgItemMessageW( dialog
, IDC_FNT_PREVIEW
, WM_SETFONT
, 0, 0 );
1666 fill_list_font( di
);
1667 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0, (di
->config
.attr
>> 4) & 0x0F );
1668 SetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0, di
->config
.attr
& 0x0F );
1672 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1673 switch (LOWORD(wparam
))
1675 case IDC_FNT_LIST_FONT
:
1676 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1677 fill_list_size( di
, FALSE
);
1679 case IDC_FNT_LIST_SIZE
:
1680 if (HIWORD(wparam
) == LBN_SELCHANGE
)
1688 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1691 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1692 switch (nmhdr
->code
)
1695 di
->dialog
= dialog
;
1698 val
= SendDlgItemMessageW( dialog
, IDC_FNT_LIST_SIZE
, LB_GETCURSEL
, 0, 0 );
1699 if (val
< di
->font_count
)
1703 fill_logfont( &lf
, di
->font
[val
].faceName
, di
->font
[val
].height
, di
->font
[val
].weight
);
1704 DeleteObject( select_font_config( &di
->config
, di
->console
->output_cp
,
1705 di
->console
->win
, &lf
));
1708 val
= (GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_BK
), 0 ) << 4) |
1709 GetWindowLongW( GetDlgItem( dialog
, IDC_FNT_COLOR_FG
), 0 );
1710 di
->config
.attr
= val
;
1711 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1724 /* dialog proc for the config property sheet */
1725 static INT_PTR WINAPI
config_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1727 struct dialog_info
*di
;
1733 di
= (struct dialog_info
*)((PROPSHEETPAGEA
*)lparam
)->lParam
;
1734 di
->dialog
= dialog
;
1736 SetWindowLongPtrW( dialog
, DWLP_USER
, (DWORD_PTR
)di
);
1737 SetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, di
->config
.sb_width
, FALSE
);
1738 SetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, di
->config
.sb_height
, FALSE
);
1739 SetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, di
->config
.win_width
, FALSE
);
1740 SetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, di
->config
.win_height
, FALSE
);
1742 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1743 SendMessageW( GetDlgItem(dialog
, IDC_CNF_WIN_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1744 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_HEIGHT_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1745 SendMessageW( GetDlgItem(dialog
, IDC_CNF_SB_WIDTH_UD
), UDM_SETRANGE
, 0, MAKELPARAM(max_ud
, 0));
1747 SendDlgItemMessageW( dialog
, IDC_CNF_CLOSE_EXIT
, BM_SETCHECK
, BST_CHECKED
, 0 );
1749 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Win32" );
1750 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_ADDSTRING
, 0, (LPARAM
)L
"Emacs" );
1751 SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
, CB_SETCURSEL
, di
->config
.edition_mode
, 0 );
1756 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1757 int win_w
, win_h
, sb_w
, sb_h
;
1760 di
= (struct dialog_info
*)GetWindowLongPtrW( dialog
, DWLP_USER
);
1761 switch (nmhdr
->code
)
1764 di
->dialog
= dialog
;
1767 sb_w
= GetDlgItemInt( dialog
, IDC_CNF_SB_WIDTH
, &st1
, FALSE
);
1768 sb_h
= GetDlgItemInt( dialog
, IDC_CNF_SB_HEIGHT
, &st2
, FALSE
);
1771 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1774 win_w
= GetDlgItemInt( dialog
, IDC_CNF_WIN_WIDTH
, &st1
, FALSE
);
1775 win_h
= GetDlgItemInt( dialog
, IDC_CNF_WIN_HEIGHT
, &st2
, FALSE
);
1778 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1781 if (win_w
> sb_w
|| win_h
> sb_h
)
1786 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_TIT_ERROR
, cap
, ARRAY_SIZE(cap
) );
1787 LoadStringW( GetModuleHandleW(NULL
), IDS_DLG_ERR_SBWINSIZE
, txt
, ARRAY_SIZE(txt
) );
1789 MessageBoxW( dialog
, txt
, cap
, MB_OK
);
1790 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1793 di
->config
.win_width
= win_w
;
1794 di
->config
.win_height
= win_h
;
1795 di
->config
.sb_width
= sb_w
;
1796 di
->config
.sb_height
= sb_h
;
1798 di
->config
.edition_mode
= SendDlgItemMessageW( dialog
, IDC_CNF_EDITION_MODE
,
1799 CB_GETCURSEL
, 0, 0 );
1800 SetWindowLongPtrW( dialog
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1813 /* dialog proc for choosing how to handle modification to the console settings */
1814 static INT_PTR WINAPI
save_dialog_proc( HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1819 SendDlgItemMessageW( dialog
, IDC_SAV_SESSION
, BM_SETCHECK
, BST_CHECKED
, 0 );
1823 switch (LOWORD(wparam
))
1827 (IsDlgButtonChecked(dialog
, IDC_SAV_SAVE
) == BST_CHECKED
) ?
1828 IDC_SAV_SAVE
: IDC_SAV_SESSION
);
1831 EndDialog( dialog
, IDCANCEL
); break;
1840 static void apply_config( struct console
*console
, const struct console_config
*config
)
1842 if (console
->active
->width
!= config
->sb_width
|| console
->active
->height
!= config
->sb_height
)
1843 change_screen_buffer_size( console
->active
, config
->sb_width
, config
->sb_height
);
1845 console
->window
->menu_mask
= config
->menu_mask
;
1846 console
->window
->quick_edit
= config
->quick_edit
;
1848 console
->edition_mode
= config
->edition_mode
;
1849 console
->history_mode
= config
->history_mode
;
1851 if (console
->history_size
!= config
->history_size
)
1853 struct history_line
**mem
= NULL
;
1856 if (config
->history_size
&& (mem
= malloc( config
->history_size
* sizeof(*mem
) )))
1858 memset( mem
, 0, config
->history_size
* sizeof(*mem
) );
1860 delta
= (console
->history_index
> config
->history_size
)
1861 ? (console
->history_index
- config
->history_size
) : 0;
1863 for (i
= delta
; i
< console
->history_index
; i
++)
1865 mem
[i
- delta
] = console
->history
[i
];
1866 console
->history
[i
] = NULL
;
1868 console
->history_index
-= delta
;
1870 for (i
= 0; i
< console
->history_size
; i
++)
1871 free( console
->history
[i
] );
1872 free( console
->history
);
1873 console
->history
= mem
;
1874 console
->history_size
= config
->history_size
;
1878 if (config
->insert_mode
)
1879 console
->mode
|= ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
;
1881 console
->mode
&= ~ENABLE_INSERT_MODE
;
1883 console
->active
->cursor_size
= config
->cursor_size
;
1884 console
->active
->cursor_visible
= config
->cursor_visible
;
1885 console
->active
->attr
= config
->attr
;
1886 console
->active
->popup_attr
= config
->popup_attr
;
1887 console
->active
->win
.left
= config
->win_pos
.X
;
1888 console
->active
->win
.top
= config
->win_pos
.Y
;
1889 console
->active
->win
.right
= config
->win_pos
.X
+ config
->win_width
- 1;
1890 console
->active
->win
.bottom
= config
->win_pos
.Y
+ config
->win_height
- 1;
1891 memcpy( console
->active
->color_map
, config
->color_map
, sizeof(config
->color_map
) );
1893 if (console
->active
->font
.width
!= config
->cell_width
||
1894 console
->active
->font
.height
!= config
->cell_height
||
1895 console
->active
->font
.weight
!= config
->font_weight
||
1896 console
->active
->font
.pitch_family
!= config
->font_pitch_family
||
1897 console
->active
->font
.face_len
!= wcslen( config
->face_name
) * sizeof(WCHAR
) ||
1898 memcmp( console
->active
->font
.face_name
, config
->face_name
, console
->active
->font
.face_len
))
1900 update_console_font( console
, config
->face_name
, config
->cell_height
, config
->font_weight
);
1903 update_window( console
);
1906 static void current_config( struct console
*console
, struct console_config
*config
)
1910 config
->menu_mask
= console
->window
->menu_mask
;
1911 config
->quick_edit
= console
->window
->quick_edit
;
1913 config
->edition_mode
= console
->edition_mode
;
1914 config
->history_mode
= console
->history_mode
;
1915 config
->history_size
= console
->history_size
;
1917 config
->insert_mode
= (console
->mode
& (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
)) ==
1918 (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
);
1920 config
->cursor_size
= console
->active
->cursor_size
;
1921 config
->cursor_visible
= console
->active
->cursor_visible
;
1922 config
->attr
= console
->active
->attr
;
1923 config
->popup_attr
= console
->active
->popup_attr
;
1924 memcpy( config
->color_map
, console
->active
->color_map
, sizeof(config
->color_map
) );
1926 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1927 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1928 config
->cell_width
= console
->active
->font
.width
;
1929 config
->cell_height
= console
->active
->font
.height
;
1930 config
->font_weight
= console
->active
->font
.weight
;
1931 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
1932 len
= min( ARRAY_SIZE(config
->face_name
) - 1, console
->active
->font
.face_len
/ sizeof(WCHAR
) );
1933 if (len
) memcpy( config
->face_name
, console
->active
->font
.face_name
, len
* sizeof(WCHAR
) );
1934 config
->face_name
[len
] = 0;
1936 config
->sb_width
= console
->active
->width
;
1937 config
->sb_height
= console
->active
->height
;
1939 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1940 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1941 config
->win_pos
.X
= console
->active
->win
.left
;
1942 config
->win_pos
.Y
= console
->active
->win
.top
;
1945 /* run the dialog box to set up the console options */
1946 static BOOL
config_dialog( struct console
*console
, BOOL current
)
1948 struct console_config prev_config
;
1949 struct dialog_info di
;
1950 PROPSHEETHEADERW header
;
1951 HPROPSHEETPAGE pages
[3];
1955 BOOL modify_session
= FALSE
;
1958 InitCommonControls();
1960 memset( &di
, 0, sizeof(di
) );
1961 di
.console
= console
;
1964 load_config( NULL
, &di
.config
);
1967 else current_config( console
, &di
.config
);
1968 prev_config
= di
.config
;
1973 wndclass
.lpfnWndProc
= font_preview_proc
;
1974 wndclass
.cbClsExtra
= 0;
1975 wndclass
.cbWndExtra
= sizeof(HFONT
);
1976 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1978 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1979 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1980 wndclass
.lpszMenuName
= NULL
;
1981 wndclass
.lpszClassName
= L
"WineConFontPreview";
1982 RegisterClassW( &wndclass
);
1985 wndclass
.lpfnWndProc
= color_preview_proc
;
1986 wndclass
.cbClsExtra
= 0;
1987 wndclass
.cbWndExtra
= sizeof(DWORD
);
1988 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1990 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1991 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1992 wndclass
.lpszMenuName
= NULL
;
1993 wndclass
.lpszClassName
= L
"WineConColorPreview";
1994 RegisterClassW( &wndclass
);
1996 memset( &psp
, 0, sizeof(psp
) );
1997 psp
.dwSize
= sizeof(psp
);
1999 psp
.hInstance
= wndclass
.hInstance
;
2000 psp
.lParam
= (LPARAM
)&di
;
2002 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_OPTION
);
2003 psp
.pfnDlgProc
= option_dialog_proc
;
2004 pages
[0] = CreatePropertySheetPageW( &psp
);
2006 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_FONT
);
2007 psp
.pfnDlgProc
= font_dialog_proc
;
2008 pages
[1] = CreatePropertySheetPageW( &psp
);
2010 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CONFIG
);
2011 psp
.pfnDlgProc
= config_dialog_proc
;
2012 pages
[2] = CreatePropertySheetPageW( &psp
);
2014 memset( &header
, 0, sizeof(header
) );
2015 header
.dwSize
= sizeof(header
);
2017 if (!LoadStringW( GetModuleHandleW( NULL
),
2018 current
? IDS_DLG_TIT_CURRENT
: IDS_DLG_TIT_DEFAULT
,
2019 buff
, ARRAY_SIZE(buff
) ))
2020 wcscpy( buff
, L
"Setup" );
2022 header
.pszCaption
= buff
;
2024 header
.hwndParent
= console
->win
;
2025 header
.u3
.phpage
= pages
;
2026 header
.dwFlags
= PSH_NOAPPLYNOW
;
2027 PropertySheetW( &header
);
2029 if (!memcmp( &prev_config
, &di
.config
, sizeof(prev_config
) ))
2032 TRACE( "%s\n", debugstr_config(&di
.config
) );
2036 switch (DialogBoxW( GetModuleHandleW( NULL
), MAKEINTRESOURCEW(IDD_SAVE_SETTINGS
),
2037 console
->win
, save_dialog_proc
))
2041 modify_session
= TRUE
;
2043 case IDC_SAV_SESSION
:
2044 modify_session
= TRUE
;
2047 ERR( "dialog failed\n" );
2050 modify_session
= FALSE
;
2058 apply_config( console
, &di
.config
);
2059 update_window( di
.console
);
2062 save_config( current
? console
->window
->config_key
: NULL
, &di
.config
);
2066 static void resize_window( struct console
*console
, int width
, int height
)
2068 struct console_config config
;
2070 current_config( console
, &config
);
2071 config
.win_width
= width
;
2072 config
.win_height
= height
;
2074 /* auto size screen-buffer if it's now smaller than window */
2075 if (config
.sb_width
< config
.win_width
)
2076 config
.sb_width
= config
.win_width
;
2077 if (config
.sb_height
< config
.win_height
)
2078 config
.sb_height
= config
.win_height
;
2080 /* and reset window pos so that we don't display outside of the screen-buffer */
2081 if (config
.win_pos
.X
+ config
.win_width
> config
.sb_width
)
2082 config
.win_pos
.X
= config
.sb_width
- config
.win_width
;
2083 if (config
.win_pos
.Y
+ config
.win_height
> config
.sb_height
)
2084 config
.win_pos
.Y
= config
.sb_height
- config
.win_height
;
2086 apply_config( console
, &config
);
2089 /* grays / ungrays the menu items according to their state */
2090 static void set_menu_details( struct console
*console
, HMENU menu
)
2092 EnableMenuItem( menu
, IDS_COPY
, MF_BYCOMMAND
|
2093 (console
->window
->in_selection
? MF_ENABLED
: MF_GRAYED
) );
2094 EnableMenuItem( menu
, IDS_PASTE
, MF_BYCOMMAND
|
2095 (IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
) );
2096 EnableMenuItem( menu
, IDS_SCROLL
, MF_BYCOMMAND
| MF_GRAYED
);
2097 EnableMenuItem( menu
, IDS_SEARCH
, MF_BYCOMMAND
| MF_GRAYED
);
2100 static BOOL
fill_menu( HMENU menu
, BOOL sep
)
2102 HINSTANCE module
= GetModuleHandleW( NULL
);
2106 if (!menu
) return FALSE
;
2108 sub_menu
= CreateMenu();
2109 if (!sub_menu
) return FALSE
;
2111 LoadStringW( module
, IDS_MARK
, buff
, ARRAY_SIZE(buff
) );
2112 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
2113 LoadStringW( module
, IDS_COPY
, buff
, ARRAY_SIZE(buff
) );
2114 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
2115 LoadStringW( module
, IDS_PASTE
, buff
, ARRAY_SIZE(buff
) );
2116 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
2117 LoadStringW( module
, IDS_SELECTALL
, buff
, ARRAY_SIZE(buff
) );
2118 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
2119 LoadStringW( module
, IDS_SCROLL
, buff
, ARRAY_SIZE(buff
) );
2120 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
2121 LoadStringW( module
, IDS_SEARCH
, buff
, ARRAY_SIZE(buff
) );
2122 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
2124 if (sep
) InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
2125 LoadStringW( module
, IDS_EDIT
, buff
, ARRAY_SIZE(buff
) );
2126 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)sub_menu
, buff
);
2127 LoadStringW( module
, IDS_DEFAULT
, buff
, ARRAY_SIZE(buff
) );
2128 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
2129 LoadStringW( module
, IDS_PROPERTIES
, buff
, ARRAY_SIZE(buff
) );
2130 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
2135 static LRESULT
window_create( HWND hwnd
, const CREATESTRUCTW
*create
)
2137 struct console
*console
= create
->lpCreateParams
;
2140 TRACE( "%p\n", hwnd
);
2142 SetWindowLongPtrW( hwnd
, 0, (DWORD_PTR
)console
);
2143 console
->win
= hwnd
;
2145 sys_menu
= GetSystemMenu( hwnd
, FALSE
);
2146 if (!sys_menu
) return 0;
2147 console
->window
->popup_menu
= CreatePopupMenu();
2148 if (!console
->window
->popup_menu
) return 0;
2150 fill_menu( sys_menu
, TRUE
);
2151 fill_menu( console
->window
->popup_menu
, FALSE
);
2153 console
->window
->mem_dc
= CreateCompatibleDC( 0 );
2157 static LRESULT WINAPI
window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2159 struct console
*console
= (struct console
*)GetWindowLongPtrW( hwnd
, 0 );
2164 return window_create( hwnd
, (const CREATESTRUCTW
*)lparam
);
2167 console
->win
= NULL
;
2168 PostQuitMessage( 0 );
2171 case WM_UPDATE_CONFIG
:
2172 update_window( console
);
2179 BeginPaint( console
->win
, &ps
);
2180 BitBlt( ps
.hdc
, 0, 0,
2181 (console
->active
->win
.right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
,
2182 (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
,
2183 console
->window
->mem_dc
,
2184 console
->active
->win
.left
* console
->active
->font
.width
,
2185 console
->active
->win
.top
* console
->active
->font
.height
,
2187 if (console
->window
->in_selection
) update_selection( console
, ps
.hdc
);
2188 EndPaint( console
->win
, &ps
);
2194 update_window( console
);
2197 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
2198 console
->window
->bitmap
= NULL
;
2204 if (console
->window
->in_selection
)
2205 handle_selection_key( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2207 record_key_input( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2212 record_key_input( console
, msg
== WM_SYSKEYDOWN
, wparam
, lparam
);
2215 case WM_LBUTTONDOWN
:
2216 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2218 if (console
->window
->in_selection
)
2219 update_selection( console
, 0 );
2221 if (console
->window
->quick_edit
&& console
->window
->in_selection
)
2223 console
->window
->in_selection
= FALSE
;
2227 console
->window
->selection_end
= get_cell( console
, lparam
);
2228 console
->window
->selection_start
= console
->window
->selection_end
;
2229 SetCapture( console
->win
);
2230 update_selection( console
, 0 );
2231 console
->window
->in_selection
= TRUE
;
2236 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2241 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2243 if (GetCapture() == console
->win
&& console
->window
->in_selection
&&
2244 (wparam
& MK_LBUTTON
))
2246 move_selection( console
, console
->window
->selection_start
,
2247 get_cell(console
, lparam
) );
2252 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, MOUSE_MOVED
);
2257 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2259 if (GetCapture() == console
->win
&& console
->window
->in_selection
)
2261 move_selection( console
, console
->window
->selection_start
,
2262 get_cell(console
, lparam
) );
2268 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2272 case WM_RBUTTONDOWN
:
2273 if ((wparam
& (MK_CONTROL
|MK_SHIFT
)) == console
->window
->menu_mask
)
2276 pt
.x
= (short)LOWORD(lparam
);
2277 pt
.y
= (short)HIWORD(lparam
);
2278 ClientToScreen( hwnd
, &pt
);
2279 set_menu_details( console
, console
->window
->popup_menu
);
2280 TrackPopupMenu( console
->window
->popup_menu
, TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RIGHTBUTTON
,
2281 pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2285 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2290 /* no need to track for rbutton up when opening the popup... the event will be
2291 * swallowed by TrackPopupMenu */
2292 case WM_MBUTTONDOWN
:
2294 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2297 case WM_LBUTTONDBLCLK
:
2298 case WM_MBUTTONDBLCLK
:
2299 case WM_RBUTTONDBLCLK
:
2300 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, DOUBLE_CLICK
);
2304 if (console
->active
->cursor_visible
)
2306 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
2307 console
->active
->font
.width
, console
->active
->font
.height
);
2308 update_window_cursor( console
);
2313 if (console
->active
->cursor_visible
)
2318 if (console
->window
->update_state
!= UPDATE_BUSY
)
2319 resize_window( console
,
2320 max( LOWORD(lparam
) / console
->active
->font
.width
, 20 ),
2321 max( HIWORD(lparam
) / console
->active
->font
.height
, 20 ));
2326 int win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
2327 int x
= console
->active
->win
.left
;
2329 switch (LOWORD(wparam
))
2331 case SB_PAGEUP
: x
-= 8; break;
2332 case SB_PAGEDOWN
: x
+= 8; break;
2333 case SB_LINEUP
: x
--; break;
2334 case SB_LINEDOWN
: x
++; break;
2335 case SB_THUMBTRACK
: x
= HIWORD(wparam
); break;
2338 x
= min( max( x
, 0 ), console
->active
->width
- win_width
);
2339 if (x
!= console
->active
->win
.left
)
2341 console
->active
->win
.left
= x
;
2342 console
->active
->win
.right
= x
+ win_width
- 1;
2343 update_window( console
);
2349 if (console
->active
->height
<= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
2351 record_mouse_input(console
, get_cell(console
, lparam
), wparam
, MOUSE_WHEELED
);
2354 /* else fallthrough */
2357 int win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
2358 int y
= console
->active
->win
.top
;
2360 if (msg
== WM_MOUSEWHEEL
)
2362 UINT scroll_lines
= 3;
2363 SystemParametersInfoW( SPI_GETWHEELSCROLLLINES
, 0, &scroll_lines
, 0 );
2364 scroll_lines
*= -GET_WHEEL_DELTA_WPARAM(wparam
) / WHEEL_DELTA
;
2369 switch (LOWORD(wparam
))
2371 case SB_PAGEUP
: y
-= 8; break;
2372 case SB_PAGEDOWN
: y
+= 8; break;
2373 case SB_LINEUP
: y
--; break;
2374 case SB_LINEDOWN
: y
++; break;
2375 case SB_THUMBTRACK
: y
= HIWORD(wparam
); break;
2380 y
= min( max( y
, 0 ), console
->active
->height
- win_height
);
2381 if (y
!= console
->active
->win
.top
)
2383 console
->active
->win
.top
= y
;
2384 console
->active
->win
.bottom
= y
+ win_height
- 1;
2385 update_window( console
);
2394 config_dialog( console
, FALSE
);
2396 case IDS_PROPERTIES
:
2397 config_dialog( console
, TRUE
);
2400 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2408 config_dialog( console
, FALSE
);
2410 case IDS_PROPERTIES
:
2411 config_dialog( console
, TRUE
);
2414 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2415 console
->window
->selection_end
.X
= console
->window
->selection_end
.Y
= 0;
2416 update_selection( console
, 0 );
2417 console
->window
->in_selection
= TRUE
;
2420 if (console
->window
->in_selection
)
2422 console
->window
->in_selection
= FALSE
;
2423 update_selection( console
, 0 );
2424 copy_selection( console
);
2428 paste_clipboard( console
);
2431 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2432 console
->window
->selection_end
.X
= console
->active
->width
- 1;
2433 console
->window
->selection_end
.Y
= console
->active
->height
- 1;
2434 update_selection( console
, 0 );
2435 console
->window
->in_selection
= TRUE
;
2439 FIXME( "Unhandled yet command: %lx\n", wparam
);
2442 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2446 case WM_INITMENUPOPUP
:
2447 if (!HIWORD(lparam
)) return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2448 set_menu_details( console
, GetSystemMenu(console
->win
, FALSE
) );
2452 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2458 void update_window_config( struct console
*console
)
2460 if (!console
->win
|| console
->window
->update_state
!= UPDATE_NONE
) return;
2461 console
->window
->update_state
= UPDATE_PENDING
;
2462 PostMessageW( console
->win
, WM_UPDATE_CONFIG
, 0, 0 );
2465 void update_window_region( struct console
*console
, const RECT
*update
)
2467 RECT
*window_rect
= &console
->window
->update
;
2468 window_rect
->left
= min( window_rect
->left
, update
->left
);
2469 window_rect
->top
= min( window_rect
->top
, update
->top
);
2470 window_rect
->right
= max( window_rect
->right
, update
->right
);
2471 window_rect
->bottom
= max( window_rect
->bottom
, update
->bottom
);
2472 update_window_config( console
);
2475 BOOL
init_window( struct console
*console
)
2477 struct console_config config
;
2482 static struct console_window console_window
;
2484 console
->window
= &console_window
;
2485 if (!TranslateCharsetInfo( (DWORD
*)(INT_PTR
)GetACP(), &ci
, TCI_SRCCODEPAGE
))
2488 console
->window
->ui_charset
= ci
.ciCharset
;
2490 GetStartupInfoW(&si
);
2493 size_t i
, title_len
= wcslen( si
.lpTitle
);
2494 if (!(console
->window
->config_key
= malloc( (title_len
+ 1) * sizeof(WCHAR
) )))
2496 for (i
= 0; i
< title_len
; i
++)
2497 console
->window
->config_key
[i
] = si
.lpTitle
[i
] == '\\' ? '_' : si
.lpTitle
[i
];
2498 console
->window
->config_key
[title_len
] = 0;
2501 load_config( console
->window
->config_key
, &config
);
2502 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
2504 config
.sb_width
= si
.dwXCountChars
;
2505 config
.sb_height
= si
.dwYCountChars
;
2507 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
2508 config
.attr
= si
.dwFillAttribute
;
2510 wndclass
.style
= CS_DBLCLKS
;
2511 wndclass
.lpfnWndProc
= window_proc
;
2512 wndclass
.cbClsExtra
= 0;
2513 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2514 wndclass
.hInstance
= GetModuleHandleW(NULL
);
2515 wndclass
.hIcon
= LoadIconW( 0, (const WCHAR
*)IDI_WINLOGO
);
2516 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
2517 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2518 wndclass
.lpszMenuName
= NULL
;
2519 wndclass
.lpszClassName
= L
"WineConsoleClass";
2520 RegisterClassW(&wndclass
);
2522 if (!CreateWindowW( wndclass
.lpszClassName
, NULL
,
2523 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2524 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2525 0, 0, 0, 0, wndclass
.hInstance
, console
))
2528 apply_config( console
, &config
);