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
);
1905 notify_screen_buffer_size( console
->active
);
1908 static void current_config( struct console
*console
, struct console_config
*config
)
1912 config
->menu_mask
= console
->window
->menu_mask
;
1913 config
->quick_edit
= console
->window
->quick_edit
;
1915 config
->edition_mode
= console
->edition_mode
;
1916 config
->history_mode
= console
->history_mode
;
1917 config
->history_size
= console
->history_size
;
1919 config
->insert_mode
= (console
->mode
& (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
)) ==
1920 (ENABLE_INSERT_MODE
|ENABLE_EXTENDED_FLAGS
);
1922 config
->cursor_size
= console
->active
->cursor_size
;
1923 config
->cursor_visible
= console
->active
->cursor_visible
;
1924 config
->attr
= console
->active
->attr
;
1925 config
->popup_attr
= console
->active
->popup_attr
;
1926 memcpy( config
->color_map
, console
->active
->color_map
, sizeof(config
->color_map
) );
1928 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1929 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1930 config
->cell_width
= console
->active
->font
.width
;
1931 config
->cell_height
= console
->active
->font
.height
;
1932 config
->font_weight
= console
->active
->font
.weight
;
1933 config
->font_pitch_family
= console
->active
->font
.pitch_family
;
1934 len
= min( ARRAY_SIZE(config
->face_name
) - 1, console
->active
->font
.face_len
/ sizeof(WCHAR
) );
1935 if (len
) memcpy( config
->face_name
, console
->active
->font
.face_name
, len
* sizeof(WCHAR
) );
1936 config
->face_name
[len
] = 0;
1938 config
->sb_width
= console
->active
->width
;
1939 config
->sb_height
= console
->active
->height
;
1941 config
->win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
1942 config
->win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
1943 config
->win_pos
.X
= console
->active
->win
.left
;
1944 config
->win_pos
.Y
= console
->active
->win
.top
;
1947 /* run the dialog box to set up the console options */
1948 static BOOL
config_dialog( struct console
*console
, BOOL current
)
1950 struct console_config prev_config
;
1951 struct dialog_info di
;
1952 PROPSHEETHEADERW header
;
1953 HPROPSHEETPAGE pages
[3];
1957 BOOL modify_session
= FALSE
;
1960 InitCommonControls();
1962 memset( &di
, 0, sizeof(di
) );
1963 di
.console
= console
;
1966 load_config( NULL
, &di
.config
);
1969 else current_config( console
, &di
.config
);
1970 prev_config
= di
.config
;
1975 wndclass
.lpfnWndProc
= font_preview_proc
;
1976 wndclass
.cbClsExtra
= 0;
1977 wndclass
.cbWndExtra
= sizeof(HFONT
);
1978 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1980 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1981 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1982 wndclass
.lpszMenuName
= NULL
;
1983 wndclass
.lpszClassName
= L
"WineConFontPreview";
1984 RegisterClassW( &wndclass
);
1987 wndclass
.lpfnWndProc
= color_preview_proc
;
1988 wndclass
.cbClsExtra
= 0;
1989 wndclass
.cbWndExtra
= sizeof(DWORD
);
1990 wndclass
.hInstance
= GetModuleHandleW( NULL
);
1992 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
1993 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1994 wndclass
.lpszMenuName
= NULL
;
1995 wndclass
.lpszClassName
= L
"WineConColorPreview";
1996 RegisterClassW( &wndclass
);
1998 memset( &psp
, 0, sizeof(psp
) );
1999 psp
.dwSize
= sizeof(psp
);
2001 psp
.hInstance
= wndclass
.hInstance
;
2002 psp
.lParam
= (LPARAM
)&di
;
2004 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_OPTION
);
2005 psp
.pfnDlgProc
= option_dialog_proc
;
2006 pages
[0] = CreatePropertySheetPageW( &psp
);
2008 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_FONT
);
2009 psp
.pfnDlgProc
= font_dialog_proc
;
2010 pages
[1] = CreatePropertySheetPageW( &psp
);
2012 psp
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CONFIG
);
2013 psp
.pfnDlgProc
= config_dialog_proc
;
2014 pages
[2] = CreatePropertySheetPageW( &psp
);
2016 memset( &header
, 0, sizeof(header
) );
2017 header
.dwSize
= sizeof(header
);
2019 if (!LoadStringW( GetModuleHandleW( NULL
),
2020 current
? IDS_DLG_TIT_CURRENT
: IDS_DLG_TIT_DEFAULT
,
2021 buff
, ARRAY_SIZE(buff
) ))
2022 wcscpy( buff
, L
"Setup" );
2024 header
.pszCaption
= buff
;
2026 header
.hwndParent
= console
->win
;
2027 header
.u3
.phpage
= pages
;
2028 header
.dwFlags
= PSH_NOAPPLYNOW
;
2029 PropertySheetW( &header
);
2031 if (!memcmp( &prev_config
, &di
.config
, sizeof(prev_config
) ))
2034 TRACE( "%s\n", debugstr_config(&di
.config
) );
2038 switch (DialogBoxW( GetModuleHandleW( NULL
), MAKEINTRESOURCEW(IDD_SAVE_SETTINGS
),
2039 console
->win
, save_dialog_proc
))
2043 modify_session
= TRUE
;
2045 case IDC_SAV_SESSION
:
2046 modify_session
= TRUE
;
2049 ERR( "dialog failed\n" );
2052 modify_session
= FALSE
;
2060 apply_config( console
, &di
.config
);
2061 update_window( di
.console
);
2064 save_config( current
? console
->window
->config_key
: NULL
, &di
.config
);
2068 static void resize_window( struct console
*console
, int width
, int height
)
2070 struct console_config config
;
2072 current_config( console
, &config
);
2073 config
.win_width
= width
;
2074 config
.win_height
= height
;
2076 /* auto size screen-buffer if it's now smaller than window */
2077 if (config
.sb_width
< config
.win_width
)
2078 config
.sb_width
= config
.win_width
;
2079 if (config
.sb_height
< config
.win_height
)
2080 config
.sb_height
= config
.win_height
;
2082 /* and reset window pos so that we don't display outside of the screen-buffer */
2083 if (config
.win_pos
.X
+ config
.win_width
> config
.sb_width
)
2084 config
.win_pos
.X
= config
.sb_width
- config
.win_width
;
2085 if (config
.win_pos
.Y
+ config
.win_height
> config
.sb_height
)
2086 config
.win_pos
.Y
= config
.sb_height
- config
.win_height
;
2088 apply_config( console
, &config
);
2091 /* grays / ungrays the menu items according to their state */
2092 static void set_menu_details( struct console
*console
, HMENU menu
)
2094 EnableMenuItem( menu
, IDS_COPY
, MF_BYCOMMAND
|
2095 (console
->window
->in_selection
? MF_ENABLED
: MF_GRAYED
) );
2096 EnableMenuItem( menu
, IDS_PASTE
, MF_BYCOMMAND
|
2097 (IsClipboardFormatAvailable(CF_UNICODETEXT
) ? MF_ENABLED
: MF_GRAYED
) );
2098 EnableMenuItem( menu
, IDS_SCROLL
, MF_BYCOMMAND
| MF_GRAYED
);
2099 EnableMenuItem( menu
, IDS_SEARCH
, MF_BYCOMMAND
| MF_GRAYED
);
2102 static BOOL
fill_menu( HMENU menu
, BOOL sep
)
2104 HINSTANCE module
= GetModuleHandleW( NULL
);
2108 if (!menu
) return FALSE
;
2110 sub_menu
= CreateMenu();
2111 if (!sub_menu
) return FALSE
;
2113 LoadStringW( module
, IDS_MARK
, buff
, ARRAY_SIZE(buff
) );
2114 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
2115 LoadStringW( module
, IDS_COPY
, buff
, ARRAY_SIZE(buff
) );
2116 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
2117 LoadStringW( module
, IDS_PASTE
, buff
, ARRAY_SIZE(buff
) );
2118 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
2119 LoadStringW( module
, IDS_SELECTALL
, buff
, ARRAY_SIZE(buff
) );
2120 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
2121 LoadStringW( module
, IDS_SCROLL
, buff
, ARRAY_SIZE(buff
) );
2122 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
2123 LoadStringW( module
, IDS_SEARCH
, buff
, ARRAY_SIZE(buff
) );
2124 InsertMenuW( sub_menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
2126 if (sep
) InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
2127 LoadStringW( module
, IDS_EDIT
, buff
, ARRAY_SIZE(buff
) );
2128 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)sub_menu
, buff
);
2129 LoadStringW( module
, IDS_DEFAULT
, buff
, ARRAY_SIZE(buff
) );
2130 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
2131 LoadStringW( module
, IDS_PROPERTIES
, buff
, ARRAY_SIZE(buff
) );
2132 InsertMenuW( menu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
2137 static LRESULT
window_create( HWND hwnd
, const CREATESTRUCTW
*create
)
2139 struct console
*console
= create
->lpCreateParams
;
2142 TRACE( "%p\n", hwnd
);
2144 SetWindowLongPtrW( hwnd
, 0, (DWORD_PTR
)console
);
2145 console
->win
= hwnd
;
2147 sys_menu
= GetSystemMenu( hwnd
, FALSE
);
2148 if (!sys_menu
) return 0;
2149 console
->window
->popup_menu
= CreatePopupMenu();
2150 if (!console
->window
->popup_menu
) return 0;
2152 fill_menu( sys_menu
, TRUE
);
2153 fill_menu( console
->window
->popup_menu
, FALSE
);
2155 console
->window
->mem_dc
= CreateCompatibleDC( 0 );
2159 static LRESULT WINAPI
window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2161 struct console
*console
= (struct console
*)GetWindowLongPtrW( hwnd
, 0 );
2166 return window_create( hwnd
, (const CREATESTRUCTW
*)lparam
);
2169 console
->win
= NULL
;
2170 PostQuitMessage( 0 );
2173 case WM_UPDATE_CONFIG
:
2174 update_window( console
);
2181 BeginPaint( console
->win
, &ps
);
2182 BitBlt( ps
.hdc
, 0, 0,
2183 (console
->active
->win
.right
- console
->active
->win
.left
+ 1) * console
->active
->font
.width
,
2184 (console
->active
->win
.bottom
- console
->active
->win
.top
+ 1) * console
->active
->font
.height
,
2185 console
->window
->mem_dc
,
2186 console
->active
->win
.left
* console
->active
->font
.width
,
2187 console
->active
->win
.top
* console
->active
->font
.height
,
2189 if (console
->window
->in_selection
) update_selection( console
, ps
.hdc
);
2190 EndPaint( console
->win
, &ps
);
2196 update_window( console
);
2199 if (console
->window
->bitmap
) DeleteObject( console
->window
->bitmap
);
2200 console
->window
->bitmap
= NULL
;
2206 if (console
->window
->in_selection
)
2207 handle_selection_key( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2209 record_key_input( console
, msg
== WM_KEYDOWN
, wparam
, lparam
);
2214 record_key_input( console
, msg
== WM_SYSKEYDOWN
, wparam
, lparam
);
2217 case WM_LBUTTONDOWN
:
2218 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2220 if (console
->window
->in_selection
)
2221 update_selection( console
, 0 );
2223 if (console
->window
->quick_edit
&& console
->window
->in_selection
)
2225 console
->window
->in_selection
= FALSE
;
2229 console
->window
->selection_end
= get_cell( console
, lparam
);
2230 console
->window
->selection_start
= console
->window
->selection_end
;
2231 SetCapture( console
->win
);
2232 update_selection( console
, 0 );
2233 console
->window
->in_selection
= TRUE
;
2238 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2243 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2245 if (GetCapture() == console
->win
&& console
->window
->in_selection
&&
2246 (wparam
& MK_LBUTTON
))
2248 move_selection( console
, console
->window
->selection_start
,
2249 get_cell(console
, lparam
) );
2254 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, MOUSE_MOVED
);
2259 if (console
->window
->quick_edit
|| console
->window
->in_selection
)
2261 if (GetCapture() == console
->win
&& console
->window
->in_selection
)
2263 move_selection( console
, console
->window
->selection_start
,
2264 get_cell(console
, lparam
) );
2270 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2274 case WM_RBUTTONDOWN
:
2275 if ((wparam
& (MK_CONTROL
|MK_SHIFT
)) == console
->window
->menu_mask
)
2278 pt
.x
= (short)LOWORD(lparam
);
2279 pt
.y
= (short)HIWORD(lparam
);
2280 ClientToScreen( hwnd
, &pt
);
2281 set_menu_details( console
, console
->window
->popup_menu
);
2282 TrackPopupMenu( console
->window
->popup_menu
, TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RIGHTBUTTON
,
2283 pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2287 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2292 /* no need to track for rbutton up when opening the popup... the event will be
2293 * swallowed by TrackPopupMenu */
2294 case WM_MBUTTONDOWN
:
2296 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, 0 );
2299 case WM_LBUTTONDBLCLK
:
2300 case WM_MBUTTONDBLCLK
:
2301 case WM_RBUTTONDBLCLK
:
2302 record_mouse_input( console
, get_cell(console
, lparam
), wparam
, DOUBLE_CLICK
);
2306 if (console
->active
->cursor_visible
)
2308 CreateCaret( console
->win
, console
->window
->cursor_bitmap
,
2309 console
->active
->font
.width
, console
->active
->font
.height
);
2310 update_window_cursor( console
);
2315 if (console
->active
->cursor_visible
)
2320 if (console
->window
->update_state
!= UPDATE_BUSY
)
2321 resize_window( console
,
2322 max( LOWORD(lparam
) / console
->active
->font
.width
, 20 ),
2323 max( HIWORD(lparam
) / console
->active
->font
.height
, 20 ));
2328 int win_width
= console
->active
->win
.right
- console
->active
->win
.left
+ 1;
2329 int x
= console
->active
->win
.left
;
2331 switch (LOWORD(wparam
))
2333 case SB_PAGEUP
: x
-= 8; break;
2334 case SB_PAGEDOWN
: x
+= 8; break;
2335 case SB_LINEUP
: x
--; break;
2336 case SB_LINEDOWN
: x
++; break;
2337 case SB_THUMBTRACK
: x
= HIWORD(wparam
); break;
2340 x
= min( max( x
, 0 ), console
->active
->width
- win_width
);
2341 if (x
!= console
->active
->win
.left
)
2343 console
->active
->win
.left
= x
;
2344 console
->active
->win
.right
= x
+ win_width
- 1;
2345 update_window( console
);
2351 if (console
->active
->height
<= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1)
2353 record_mouse_input(console
, get_cell(console
, lparam
), wparam
, MOUSE_WHEELED
);
2356 /* else fallthrough */
2359 int win_height
= console
->active
->win
.bottom
- console
->active
->win
.top
+ 1;
2360 int y
= console
->active
->win
.top
;
2362 if (msg
== WM_MOUSEWHEEL
)
2364 UINT scroll_lines
= 3;
2365 SystemParametersInfoW( SPI_GETWHEELSCROLLLINES
, 0, &scroll_lines
, 0 );
2366 scroll_lines
*= -GET_WHEEL_DELTA_WPARAM(wparam
) / WHEEL_DELTA
;
2371 switch (LOWORD(wparam
))
2373 case SB_PAGEUP
: y
-= 8; break;
2374 case SB_PAGEDOWN
: y
+= 8; break;
2375 case SB_LINEUP
: y
--; break;
2376 case SB_LINEDOWN
: y
++; break;
2377 case SB_THUMBTRACK
: y
= HIWORD(wparam
); break;
2382 y
= min( max( y
, 0 ), console
->active
->height
- win_height
);
2383 if (y
!= console
->active
->win
.top
)
2385 console
->active
->win
.top
= y
;
2386 console
->active
->win
.bottom
= y
+ win_height
- 1;
2387 update_window( console
);
2396 config_dialog( console
, FALSE
);
2398 case IDS_PROPERTIES
:
2399 config_dialog( console
, TRUE
);
2402 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2410 config_dialog( console
, FALSE
);
2412 case IDS_PROPERTIES
:
2413 config_dialog( console
, TRUE
);
2416 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2417 console
->window
->selection_end
.X
= console
->window
->selection_end
.Y
= 0;
2418 update_selection( console
, 0 );
2419 console
->window
->in_selection
= TRUE
;
2422 if (console
->window
->in_selection
)
2424 console
->window
->in_selection
= FALSE
;
2425 update_selection( console
, 0 );
2426 copy_selection( console
);
2430 paste_clipboard( console
);
2433 console
->window
->selection_start
.X
= console
->window
->selection_start
.Y
= 0;
2434 console
->window
->selection_end
.X
= console
->active
->width
- 1;
2435 console
->window
->selection_end
.Y
= console
->active
->height
- 1;
2436 update_selection( console
, 0 );
2437 console
->window
->in_selection
= TRUE
;
2441 FIXME( "Unhandled yet command: %lx\n", wparam
);
2444 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2448 case WM_INITMENUPOPUP
:
2449 if (!HIWORD(lparam
)) return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2450 set_menu_details( console
, GetSystemMenu(console
->win
, FALSE
) );
2454 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
2460 void update_window_config( struct console
*console
)
2462 if (!console
->win
|| console
->window
->update_state
!= UPDATE_NONE
) return;
2463 console
->window
->update_state
= UPDATE_PENDING
;
2464 PostMessageW( console
->win
, WM_UPDATE_CONFIG
, 0, 0 );
2467 void update_window_region( struct console
*console
, const RECT
*update
)
2469 RECT
*window_rect
= &console
->window
->update
;
2470 window_rect
->left
= min( window_rect
->left
, update
->left
);
2471 window_rect
->top
= min( window_rect
->top
, update
->top
);
2472 window_rect
->right
= max( window_rect
->right
, update
->right
);
2473 window_rect
->bottom
= max( window_rect
->bottom
, update
->bottom
);
2474 update_window_config( console
);
2477 BOOL
init_window( struct console
*console
)
2479 struct console_config config
;
2484 static struct console_window console_window
;
2486 console
->window
= &console_window
;
2487 if (!TranslateCharsetInfo( (DWORD
*)(INT_PTR
)GetACP(), &ci
, TCI_SRCCODEPAGE
))
2490 console
->window
->ui_charset
= ci
.ciCharset
;
2492 GetStartupInfoW(&si
);
2495 size_t i
, title_len
= wcslen( si
.lpTitle
);
2496 if (!(console
->window
->config_key
= malloc( (title_len
+ 1) * sizeof(WCHAR
) )))
2498 for (i
= 0; i
< title_len
; i
++)
2499 console
->window
->config_key
[i
] = si
.lpTitle
[i
] == '\\' ? '_' : si
.lpTitle
[i
];
2500 console
->window
->config_key
[title_len
] = 0;
2503 load_config( console
->window
->config_key
, &config
);
2504 if (si
.dwFlags
& STARTF_USECOUNTCHARS
)
2506 config
.sb_width
= si
.dwXCountChars
;
2507 config
.sb_height
= si
.dwYCountChars
;
2509 if (si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
2510 config
.attr
= si
.dwFillAttribute
;
2512 wndclass
.style
= CS_DBLCLKS
;
2513 wndclass
.lpfnWndProc
= window_proc
;
2514 wndclass
.cbClsExtra
= 0;
2515 wndclass
.cbWndExtra
= sizeof(DWORD_PTR
);
2516 wndclass
.hInstance
= GetModuleHandleW(NULL
);
2517 wndclass
.hIcon
= LoadIconW( 0, (const WCHAR
*)IDI_WINLOGO
);
2518 wndclass
.hCursor
= LoadCursorW( 0, (const WCHAR
*)IDC_ARROW
);
2519 wndclass
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
2520 wndclass
.lpszMenuName
= NULL
;
2521 wndclass
.lpszClassName
= L
"WineConsoleClass";
2522 RegisterClassW(&wndclass
);
2524 if (!CreateWindowW( wndclass
.lpszClassName
, NULL
,
2525 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|
2526 WS_MAXIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
, CW_USEDEFAULT
, CW_USEDEFAULT
,
2527 0, 0, 0, 0, wndclass
.hInstance
, console
))
2530 apply_config( console
, &config
);