2 * a GUI application for displaying a console
4 * Copyright 2001 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "winecon_user.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(wineconsole
);
28 WINE_DECLARE_DEBUG_CHANNEL(wc_font
);
30 /* mapping console colors to RGB values */
31 COLORREF WCUSER_ColorMap
[16] =
33 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x80), RGB(0x00, 0x80, 0x00), RGB(0x00, 0x80, 0x80),
34 RGB(0x80, 0x00, 0x00), RGB(0x80, 0x00, 0x80), RGB(0x80, 0x80, 0x00), RGB(0x80, 0x80, 0x80),
35 RGB(0xC0, 0xC0, 0xC0), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xFF),
36 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xFF),
39 static BOOL
WCUSER_SetFont(struct inner_data
* data
, const LOGFONT
* font
);
41 /******************************************************************
44 * Fills the Mem DC with current cells values
46 static void WCUSER_FillMemDC(const struct inner_data
* data
, int upd_tp
, int upd_bm
)
54 /* no font has been set up yet, don't worry about filling the bitmap,
55 * we'll do it once a font is chosen
57 if (!PRIVATE(data
)->hFont
) return;
59 /* FIXME: could set up a mechanism to reuse the line between different
60 * calls to this function
62 if (!(line
= HeapAlloc(GetProcessHeap(), 0, data
->curcfg
.sb_width
* sizeof(WCHAR
))))
63 WINECON_Fatal("OOM\n");
65 hOldFont
= SelectObject(PRIVATE(data
)->hMemDC
, PRIVATE(data
)->hFont
);
66 for (j
= upd_tp
; j
<= upd_bm
; j
++)
68 cell
= &data
->cells
[j
* data
->curcfg
.sb_width
];
69 for (i
= 0; i
< data
->curcfg
.sb_width
; i
++)
71 attr
= cell
[i
].Attributes
;
72 SetBkColor(PRIVATE(data
)->hMemDC
, WCUSER_ColorMap
[(attr
>>4)&0x0F]);
73 SetTextColor(PRIVATE(data
)->hMemDC
, WCUSER_ColorMap
[attr
&0x0F]);
74 for (k
= i
; k
< data
->curcfg
.sb_width
&& cell
[k
].Attributes
== attr
; k
++)
76 line
[k
- i
] = cell
[k
].Char
.UnicodeChar
;
78 TextOut(PRIVATE(data
)->hMemDC
, i
* data
->curcfg
.cell_width
, j
* data
->curcfg
.cell_height
,
83 SelectObject(PRIVATE(data
)->hMemDC
, hOldFont
);
84 HeapFree(GetProcessHeap(), 0, line
);
87 /******************************************************************
90 * Either the font geometry or the sb geometry has changed. we need
91 * to recreate the bitmap geometry.
93 static void WCUSER_NewBitmap(struct inner_data
* data
)
98 if (!data
->curcfg
.sb_width
|| !data
->curcfg
.sb_height
||
99 !PRIVATE(data
)->hFont
|| !(hDC
= GetDC(PRIVATE(data
)->hWnd
)))
101 hnew
= CreateCompatibleBitmap(hDC
,
102 data
->curcfg
.sb_width
* data
->curcfg
.cell_width
,
103 data
->curcfg
.sb_height
* data
->curcfg
.cell_height
);
104 ReleaseDC(PRIVATE(data
)->hWnd
, hDC
);
105 hold
= SelectObject(PRIVATE(data
)->hMemDC
, hnew
);
107 if (PRIVATE(data
)->hBitmap
)
109 if (hold
== PRIVATE(data
)->hBitmap
)
110 DeleteObject(PRIVATE(data
)->hBitmap
);
112 WINE_FIXME("leak\n");
114 PRIVATE(data
)->hBitmap
= hnew
;
115 WCUSER_FillMemDC(data
, 0, data
->curcfg
.sb_height
- 1);
118 /******************************************************************
119 * WCUSER_ResizeScreenBuffer
123 static void WCUSER_ResizeScreenBuffer(struct inner_data
* data
)
125 WCUSER_NewBitmap(data
);
128 /******************************************************************
131 * Set a new position for the cursor
133 static void WCUSER_PosCursor(const struct inner_data
* data
)
135 if (PRIVATE(data
)->hWnd
!= GetFocus() || !data
->curcfg
.cursor_visible
) return;
137 SetCaretPos((data
->cursor
.X
- data
->curcfg
.win_pos
.X
) * data
->curcfg
.cell_width
,
138 (data
->cursor
.Y
- data
->curcfg
.win_pos
.Y
) * data
->curcfg
.cell_height
);
139 ShowCaret(PRIVATE(data
)->hWnd
);
142 /******************************************************************
145 * Sets a new shape for the cursor
147 static void WCUSER_ShapeCursor(struct inner_data
* data
, int size
, int vis
, BOOL force
)
149 if (force
|| size
!= data
->curcfg
.cursor_size
)
151 if (data
->curcfg
.cursor_visible
&& PRIVATE(data
)->hWnd
== GetFocus()) DestroyCaret();
152 if (PRIVATE(data
)->cursor_bitmap
) DeleteObject(PRIVATE(data
)->cursor_bitmap
);
153 PRIVATE(data
)->cursor_bitmap
= NULL
;
156 int w16b
; /* number of bytes per row, aligned on word size */
160 w16b
= ((data
->curcfg
.cell_width
+ 15) & ~15) / 8;
161 ptr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, w16b
* data
->curcfg
.cell_height
);
162 if (!ptr
) WINECON_Fatal("OOM");
163 nbl
= max((data
->curcfg
.cell_height
* size
) / 100, 1);
164 for (j
= data
->curcfg
.cell_height
- nbl
; j
< data
->curcfg
.cell_height
; j
++)
166 for (i
= 0; i
< data
->curcfg
.cell_width
; i
++)
168 ptr
[w16b
* j
+ (i
/ 8)] |= 0x80 >> (i
& 7);
171 PRIVATE(data
)->cursor_bitmap
= CreateBitmap(data
->curcfg
.cell_width
,
172 data
->curcfg
.cell_height
, 1, 1, ptr
);
173 HeapFree(GetProcessHeap(), 0, ptr
);
175 data
->curcfg
.cursor_size
= size
;
176 data
->curcfg
.cursor_visible
= -1;
179 vis
= (vis
) ? TRUE
: FALSE
;
180 if (force
|| vis
!= data
->curcfg
.cursor_visible
)
182 data
->curcfg
.cursor_visible
= vis
;
183 if (PRIVATE(data
)->hWnd
== GetFocus())
187 CreateCaret(PRIVATE(data
)->hWnd
, PRIVATE(data
)->cursor_bitmap
,
188 data
->curcfg
.cell_width
, data
->curcfg
.cell_height
);
189 WCUSER_PosCursor(data
);
197 WINECON_DumpConfig("crsr", &data
->curcfg
);
200 /******************************************************************
201 * WCUSER_ComputePositions
203 * Recomputes all the components (mainly scroll bars) positions
205 void WCUSER_ComputePositions(struct inner_data
* data
)
210 /* compute window size from desired client size */
212 r
.right
= data
->curcfg
.win_width
* data
->curcfg
.cell_width
;
213 r
.bottom
= data
->curcfg
.win_height
* data
->curcfg
.cell_height
;
215 if (IsRectEmpty(&r
)) return;
217 AdjustWindowRect(&r
, GetWindowLong(PRIVATE(data
)->hWnd
, GWL_STYLE
), FALSE
);
220 if (data
->curcfg
.sb_width
> data
->curcfg
.win_width
)
222 dy
= GetSystemMetrics(SM_CYHSCROLL
);
223 SetScrollRange(PRIVATE(data
)->hWnd
, SB_HORZ
, 0,
224 data
->curcfg
.sb_width
- data
->curcfg
.win_width
, FALSE
);
225 SetScrollPos(PRIVATE(data
)->hWnd
, SB_HORZ
, 0, FALSE
); /* FIXME */
226 ShowScrollBar(PRIVATE(data
)->hWnd
, SB_HORZ
, TRUE
);
230 ShowScrollBar(PRIVATE(data
)->hWnd
, SB_HORZ
, FALSE
);
233 if (data
->curcfg
.sb_height
> data
->curcfg
.win_height
)
235 dx
= GetSystemMetrics(SM_CXVSCROLL
);
236 SetScrollRange(PRIVATE(data
)->hWnd
, SB_VERT
, 0,
237 data
->curcfg
.sb_height
- data
->curcfg
.win_height
, FALSE
);
238 SetScrollPos(PRIVATE(data
)->hWnd
, SB_VERT
, 0, FALSE
); /* FIXME */
239 ShowScrollBar(PRIVATE(data
)->hWnd
, SB_VERT
, TRUE
);
243 ShowScrollBar(PRIVATE(data
)->hWnd
, SB_VERT
, FALSE
);
246 SetWindowPos(PRIVATE(data
)->hWnd
, 0, 0, 0, r
.right
- r
.left
+ dx
, r
.bottom
- r
.top
+ dy
,
247 SWP_NOMOVE
|SWP_NOZORDER
);
248 WCUSER_ShapeCursor(data
, data
->curcfg
.cursor_size
, data
->curcfg
.cursor_visible
, TRUE
);
249 WCUSER_PosCursor(data
);
252 /******************************************************************
255 * Sets the title to the wine console
257 static void WCUSER_SetTitle(const struct inner_data
* data
)
261 if (WINECON_GetConsoleTitle(data
->hConIn
, buffer
, sizeof(buffer
)))
262 SetWindowText(PRIVATE(data
)->hWnd
, buffer
);
265 void WCUSER_DumpLogFont(const char* pfx
, const LOGFONT
* lf
, DWORD ft
)
267 WINE_TRACE_(wc_font
)("%s %s%s%s%s\n"
268 "\tlf.lfHeight=%ld lf.lfWidth=%ld lf.lfEscapement=%ld lf.lfOrientation=%ld\n"
269 "\tlf.lfWeight=%ld lf.lfItalic=%u lf.lfUnderline=%u lf.lfStrikeOut=%u\n"
270 "\tlf.lfCharSet=%u lf.lfOutPrecision=%u lf.lfClipPrecision=%u lf.lfQuality=%u\n"
271 "\tlf->lfPitchAndFamily=%u lf.lfFaceName=%s\n",
273 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
274 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
275 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
276 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
277 lf
->lfHeight
, lf
->lfWidth
, lf
->lfEscapement
, lf
->lfOrientation
,
278 lf
->lfWeight
, lf
->lfItalic
, lf
->lfUnderline
, lf
->lfStrikeOut
, lf
->lfCharSet
,
279 lf
->lfOutPrecision
, lf
->lfClipPrecision
, lf
->lfQuality
, lf
->lfPitchAndFamily
,
280 wine_dbgstr_w(lf
->lfFaceName
));
283 void WCUSER_DumpTextMetric(const TEXTMETRIC
* tm
, DWORD ft
)
285 WINE_TRACE_(wc_font
)("%s%s%s%s\n"
286 "\ttmHeight=%ld tmAscent=%ld tmDescent=%ld tmInternalLeading=%ld tmExternalLeading=%ld\n"
287 "\ttmAveCharWidth=%ld tmMaxCharWidth=%ld tmWeight=%ld tmOverhang=%ld\n"
288 "\ttmDigitizedAspectX=%ld tmDigitizedAspectY=%ld\n"
289 "\ttmFirstChar=%d tmLastChar=%d tmDefaultChar=%d tmBreakChar=%d\n"
290 "\ttmItalic=%u tmUnderlined=%u tmStruckOut=%u tmPitchAndFamily=%u tmCharSet=%u\n",
291 (ft
& RASTER_FONTTYPE
) ? "raster" : "",
292 (ft
& TRUETYPE_FONTTYPE
) ? "truetype" : "",
293 ((ft
& (RASTER_FONTTYPE
|TRUETYPE_FONTTYPE
)) == 0) ? "vector" : "",
294 (ft
& DEVICE_FONTTYPE
) ? "|device" : "",
295 tm
->tmHeight
, tm
->tmAscent
, tm
->tmDescent
, tm
->tmInternalLeading
, tm
->tmExternalLeading
, tm
->tmAveCharWidth
,
296 tm
->tmMaxCharWidth
, tm
->tmWeight
, tm
->tmOverhang
, tm
->tmDigitizedAspectX
, tm
->tmDigitizedAspectY
,
297 tm
->tmFirstChar
, tm
->tmLastChar
, tm
->tmDefaultChar
, tm
->tmBreakChar
, tm
->tmItalic
, tm
->tmUnderlined
, tm
->tmStruckOut
,
298 tm
->tmPitchAndFamily
, tm
->tmCharSet
);
301 /******************************************************************
302 * WCUSER_AreFontsEqual
306 BOOL
WCUSER_AreFontsEqual(const struct config_data
* config
, const LOGFONT
* lf
)
308 return lf
->lfHeight
== config
->cell_height
&&
309 lf
->lfWeight
== config
->font_weight
&&
310 !lf
->lfItalic
&& !lf
->lfUnderline
&& !lf
->lfStrikeOut
&&
311 !lstrcmp(lf
->lfFaceName
, config
->face_name
);
316 struct inner_data
* data
;
320 /******************************************************************
321 * WCUSER_ValidateFontMetric
323 * Returns true if the font described in tm is usable as a font for the renderer
325 BOOL
WCUSER_ValidateFontMetric(const struct inner_data
* data
, const TEXTMETRIC
* tm
, DWORD fontType
)
329 if (fontType
& RASTER_FONTTYPE
)
330 ret
= (tm
->tmMaxCharWidth
* data
->curcfg
.win_width
< GetSystemMetrics(SM_CXSCREEN
) &&
331 tm
->tmHeight
* data
->curcfg
.win_height
< GetSystemMetrics(SM_CYSCREEN
));
332 return ret
&& !tm
->tmItalic
&& !tm
->tmUnderlined
&& !tm
->tmStruckOut
&&
333 (tm
->tmCharSet
== DEFAULT_CHARSET
|| tm
->tmCharSet
== ANSI_CHARSET
);
336 /******************************************************************
337 * WCUSER_ValidateFont
339 * Returns true if the font family described in lf is usable as a font for the renderer
341 BOOL
WCUSER_ValidateFont(const struct inner_data
* data
, const LOGFONT
* lf
)
343 return (lf
->lfPitchAndFamily
& 3) == FIXED_PITCH
&&
344 /* (lf->lfPitchAndFamily & 0xF0) == FF_MODERN && */
345 (lf
->lfCharSet
== DEFAULT_CHARSET
|| lf
->lfCharSet
== ANSI_CHARSET
);
348 /******************************************************************
349 * get_first_font_enum_2
350 * get_first_font_enum
352 * Helper functions to get a decent font for the renderer
354 static int CALLBACK
get_first_font_enum_2(const LOGFONT
* lf
, const TEXTMETRIC
* tm
,
355 DWORD FontType
, LPARAM lParam
)
357 struct font_chooser
* fc
= (struct font_chooser
*)lParam
;
359 WCUSER_DumpTextMetric(tm
, FontType
);
360 if (WCUSER_ValidateFontMetric(fc
->data
, tm
, FontType
))
364 /* Use the default sizes for the font (this is needed, especially for
365 * TrueType fonts, so that we get a decent size, not the max size)
367 mlf
.lfWidth
= fc
->data
->curcfg
.cell_width
;
368 mlf
.lfHeight
= fc
->data
->curcfg
.cell_height
;
369 if (WCUSER_SetFont(fc
->data
, &mlf
))
371 struct config_data defcfg
;
373 WCUSER_DumpLogFont("InitChoosing: ", &mlf
, FontType
);
375 /* since we've modified the current config with new font information,
376 * set this information as the new default.
378 WINECON_RegLoad(NULL
, &defcfg
);
379 defcfg
.cell_width
= fc
->data
->curcfg
.cell_width
;
380 defcfg
.cell_height
= fc
->data
->curcfg
.cell_height
;
381 lstrcpyW(defcfg
.face_name
, fc
->data
->curcfg
.face_name
);
382 /* Force also its writing back to the registry so that we can get it
385 WINECON_RegSave(&defcfg
);
392 static int CALLBACK
get_first_font_enum(const LOGFONT
* lf
, const TEXTMETRIC
* tm
,
393 DWORD FontType
, LPARAM lParam
)
395 struct font_chooser
* fc
= (struct font_chooser
*)lParam
;
397 WCUSER_DumpLogFont("InitFamily: ", lf
, FontType
);
398 if (WCUSER_ValidateFont(fc
->data
, lf
))
400 EnumFontFamilies(PRIVATE(fc
->data
)->hMemDC
, lf
->lfFaceName
,
401 get_first_font_enum_2
, lParam
);
402 return !fc
->done
; /* we just need the first matching one... */
407 /******************************************************************
410 * get the relevant information from the font described in lf and store them
413 HFONT
WCUSER_CopyFont(struct config_data
* config
, HWND hWnd
, const LOGFONT
* lf
)
417 HFONT hFont
, hOldFont
;
420 if (!(hDC
= GetDC(hWnd
))) return NULL
;
421 if (!(hFont
= CreateFontIndirect(lf
))) goto err1
;
423 hOldFont
= SelectObject(hDC
, hFont
);
424 GetTextMetrics(hDC
, &tm
);
427 * the current freetype engine (at least 2.0.x with x <= 8) and its implementation
428 * in Wine don't return adequate values for fixed fonts
429 * In Windows, those fonts are expected to return the same value for
430 * - the average width
431 * - the largest width
432 * - the width of all characters in the font
433 * This isn't true in Wine. As a temporary workaround, we get as the width of the
434 * cell, the width of the first character in the font, after checking that all
435 * characters in the font have the same width (I hear paranoïa coming)
436 * when this gets fixed, the code should be using tm.tmAveCharWidth
437 * or tm.tmMaxCharWidth as the cell width.
439 GetCharWidth32(hDC
, tm
.tmFirstChar
, tm
.tmFirstChar
, &w
);
440 for (i
= tm
.tmFirstChar
+ 1; i
<= tm
.tmLastChar
; i
+= sizeof(buf
) / sizeof(buf
[0]))
444 l
= min(tm
.tmLastChar
- i
, sizeof(buf
) / sizeof(buf
[0]) - 1);
445 GetCharWidth32(hDC
, i
, i
+ l
, buf
);
446 for (j
= 0; j
<= l
; j
++)
450 WINE_WARN("Non uniform cell width: [%d]=%d [%d]=%d\n"
451 "This may be caused by old freetype libraries, >= 2.0.8 is recommended\n",
452 i
+ j
, buf
[j
], tm
.tmFirstChar
, w
);
457 SelectObject(hDC
, hOldFont
);
458 ReleaseDC(hWnd
, hDC
);
460 config
->cell_width
= w
;
461 config
->cell_height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
462 config
->font_weight
= tm
.tmWeight
;
463 lstrcpy(config
->face_name
, lf
->lfFaceName
);
467 if (hDC
&& hOldFont
) SelectObject(hDC
, hOldFont
);
468 if (hFont
) DeleteObject(hFont
);
470 if (hDC
) ReleaseDC(hWnd
, hDC
);
475 /******************************************************************
480 void WCUSER_FillLogFont(LOGFONT
* lf
, const WCHAR
* name
, UINT height
, UINT weight
)
482 lf
->lfHeight
= height
;
484 lf
->lfEscapement
= 0;
485 lf
->lfOrientation
= 0;
486 lf
->lfWeight
= weight
;
487 lf
->lfItalic
= FALSE
;
488 lf
->lfUnderline
= FALSE
;
489 lf
->lfStrikeOut
= FALSE
;
490 lf
->lfCharSet
= DEFAULT_CHARSET
;
491 lf
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
492 lf
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
493 lf
->lfQuality
= DEFAULT_QUALITY
;
494 lf
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
495 lstrcpy(lf
->lfFaceName
, name
);
498 /******************************************************************
501 * sets logfont as the new font for the console
503 BOOL
WCUSER_SetFont(struct inner_data
* data
, const LOGFONT
* logfont
)
507 if (PRIVATE(data
)->hFont
!= 0 && WCUSER_AreFontsEqual(&data
->curcfg
, logfont
))
510 hFont
= WCUSER_CopyFont(&data
->curcfg
, PRIVATE(data
)->hWnd
, logfont
);
511 if (!hFont
) {WINE_ERR("wrong font\n"); return FALSE
;}
513 if (PRIVATE(data
)->hFont
) DeleteObject(PRIVATE(data
)->hFont
);
514 PRIVATE(data
)->hFont
= hFont
;
516 WCUSER_ComputePositions(data
);
517 WCUSER_NewBitmap(data
);
518 InvalidateRect(PRIVATE(data
)->hWnd
, NULL
, FALSE
);
519 UpdateWindow(PRIVATE(data
)->hWnd
);
524 /******************************************************************
527 * Sets a new font for the console.
528 * In fact a wrapper for WCUSER_SetFont
530 static void WCUSER_SetFontPmt(struct inner_data
* data
, const WCHAR
* font
,
531 unsigned height
, unsigned weight
)
534 struct font_chooser fc
;
536 WINE_TRACE_(wc_font
)("=> %s h=%u w=%u\n",
537 wine_dbgstr_wn(font
, -1), height
, weight
);
539 if (font
[0] != '\0' && height
!= 0 && weight
!= 0)
541 WCUSER_FillLogFont(&lf
, font
, height
, weight
);
542 if (WCUSER_SetFont(data
, &lf
))
544 WCUSER_DumpLogFont("InitReuses: ", &lf
, 0);
549 /* try to find an acceptable font */
550 WINE_WARN("Couldn't match the font from registry... trying to find one\n");
553 EnumFontFamilies(PRIVATE(data
)->hMemDC
, NULL
, get_first_font_enum
, (LPARAM
)&fc
);
554 if (!fc
.done
) WINECON_Fatal("Couldn't find a decent font, aborting\n");
557 /******************************************************************
560 * Get a cell from a relative coordinate in window (takes into
561 * account the scrolling)
563 static COORD
WCUSER_GetCell(const struct inner_data
* data
, LPARAM lParam
)
567 c
.X
= data
->curcfg
.win_pos
.X
+ (short)LOWORD(lParam
) / data
->curcfg
.cell_width
;
568 c
.Y
= data
->curcfg
.win_pos
.Y
+ (short)HIWORD(lParam
) / data
->curcfg
.cell_height
;
573 /******************************************************************
574 * WCUSER_GetSelectionRect
576 * Get the selection rectangle
578 static void WCUSER_GetSelectionRect(const struct inner_data
* data
, LPRECT r
)
580 r
->left
= (min(PRIVATE(data
)->selectPt1
.X
, PRIVATE(data
)->selectPt2
.X
) - data
->curcfg
.win_pos
.X
) * data
->curcfg
.cell_width
;
581 r
->top
= (min(PRIVATE(data
)->selectPt1
.Y
, PRIVATE(data
)->selectPt2
.Y
) - data
->curcfg
.win_pos
.Y
) * data
->curcfg
.cell_height
;
582 r
->right
= (max(PRIVATE(data
)->selectPt1
.X
, PRIVATE(data
)->selectPt2
.X
) + 1 - data
->curcfg
.win_pos
.X
) * data
->curcfg
.cell_width
;
583 r
->bottom
= (max(PRIVATE(data
)->selectPt1
.Y
, PRIVATE(data
)->selectPt2
.Y
) + 1 - data
->curcfg
.win_pos
.Y
) * data
->curcfg
.cell_height
;
586 /******************************************************************
587 * WCUSER_SetSelection
591 static void WCUSER_SetSelection(const struct inner_data
* data
, HDC hRefDC
)
596 WCUSER_GetSelectionRect(data
, &r
);
597 hDC
= hRefDC
? hRefDC
: GetDC(PRIVATE(data
)->hWnd
);
600 if (PRIVATE(data
)->hWnd
== GetFocus() && data
->curcfg
.cursor_visible
)
601 HideCaret(PRIVATE(data
)->hWnd
);
604 ReleaseDC(PRIVATE(data
)->hWnd
, hDC
);
605 if (PRIVATE(data
)->hWnd
== GetFocus() && data
->curcfg
.cursor_visible
)
606 ShowCaret(PRIVATE(data
)->hWnd
);
610 /******************************************************************
611 * WCUSER_MoveSelection
615 static void WCUSER_MoveSelection(struct inner_data
* data
, COORD c1
, COORD c2
)
620 if (c1
.X
< 0 || c1
.X
>= data
->curcfg
.sb_width
||
621 c2
.X
< 0 || c2
.X
>= data
->curcfg
.sb_width
||
622 c1
.Y
< 0 || c1
.Y
>= data
->curcfg
.sb_height
||
623 c2
.Y
< 0 || c2
.Y
>= data
->curcfg
.sb_height
)
626 WCUSER_GetSelectionRect(data
, &r
);
627 hDC
= GetDC(PRIVATE(data
)->hWnd
);
630 if (PRIVATE(data
)->hWnd
== GetFocus() && data
->curcfg
.cursor_visible
)
631 HideCaret(PRIVATE(data
)->hWnd
);
634 PRIVATE(data
)->selectPt1
= c1
;
635 PRIVATE(data
)->selectPt2
= c2
;
638 WCUSER_GetSelectionRect(data
, &r
);
640 ReleaseDC(PRIVATE(data
)->hWnd
, hDC
);
641 if (PRIVATE(data
)->hWnd
== GetFocus() && data
->curcfg
.cursor_visible
)
642 ShowCaret(PRIVATE(data
)->hWnd
);
646 /******************************************************************
647 * WCUSER_CopySelectionToClipboard
649 * Copies the current selection into the clipboard
651 static void WCUSER_CopySelectionToClipboard(const struct inner_data
* data
)
657 w
= abs(PRIVATE(data
)->selectPt1
.X
- PRIVATE(data
)->selectPt2
.X
) + 2;
658 h
= abs(PRIVATE(data
)->selectPt1
.Y
- PRIVATE(data
)->selectPt2
.Y
) + 1;
660 if (!OpenClipboard(PRIVATE(data
)->hWnd
)) return;
663 hMem
= GlobalAlloc(GMEM_MOVEABLE
, (w
* h
) * sizeof(WCHAR
));
664 if (hMem
&& (p
= GlobalLock(hMem
)))
669 c
.X
= min(PRIVATE(data
)->selectPt1
.X
, PRIVATE(data
)->selectPt2
.X
);
670 c
.Y
= min(PRIVATE(data
)->selectPt1
.Y
, PRIVATE(data
)->selectPt2
.Y
);
672 for (y
= 0; y
< h
; y
++, c
.Y
++)
674 ReadConsoleOutputCharacter(data
->hConOut
, &p
[y
* w
], w
- 1, c
, NULL
);
675 p
[y
* w
+ w
- 1] = (y
< h
- 1) ? '\n' : '\0';
678 SetClipboardData(CF_UNICODETEXT
, hMem
);
683 /******************************************************************
684 * WCUSER_PasteFromClipboard
688 static void WCUSER_PasteFromClipboard(struct inner_data
* data
)
693 if (!OpenClipboard(PRIVATE(data
)->hWnd
)) return;
694 h
= GetClipboardData(CF_UNICODETEXT
);
695 if (h
&& (ptr
= GlobalLock(h
)))
697 int i
, len
= GlobalSize(h
) / sizeof(WCHAR
);
702 ir
[0].EventType
= KEY_EVENT
;
703 ir
[0].Event
.KeyEvent
.wRepeatCount
= 0;
704 ir
[0].Event
.KeyEvent
.dwControlKeyState
= 0;
705 ir
[0].Event
.KeyEvent
.bKeyDown
= TRUE
;
707 /* generate the corresponding input records */
708 for (i
= 0; i
< len
; i
++)
710 /* FIXME: the modifying keys are not generated (shift, ctrl...) */
711 sh
= VkKeyScan(ptr
[i
]);
712 ir
[0].Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(sh
);
713 ir
[0].Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKey(LOBYTE(sh
), 0);
714 ir
[0].Event
.KeyEvent
.uChar
.UnicodeChar
= ptr
[i
];
717 ir
[1].Event
.KeyEvent
.bKeyDown
= FALSE
;
719 WriteConsoleInput(data
->hConIn
, ir
, 2, &n
);
726 /******************************************************************
731 static void WCUSER_Refresh(const struct inner_data
* data
, int tp
, int bm
)
733 WCUSER_FillMemDC(data
, tp
, bm
);
734 if (data
->curcfg
.win_pos
.Y
<= bm
&& data
->curcfg
.win_pos
.Y
+ data
->curcfg
.win_height
>= tp
)
739 r
.right
= data
->curcfg
.win_width
* data
->curcfg
.cell_width
;
740 r
.top
= (tp
- data
->curcfg
.win_pos
.Y
) * data
->curcfg
.cell_height
;
741 r
.bottom
= (bm
- data
->curcfg
.win_pos
.Y
+ 1) * data
->curcfg
.cell_height
;
742 InvalidateRect(PRIVATE(data
)->hWnd
, &r
, FALSE
);
743 UpdateWindow(PRIVATE(data
)->hWnd
);
747 /******************************************************************
752 static void WCUSER_Paint(const struct inner_data
* data
)
756 BeginPaint(PRIVATE(data
)->hWnd
, &ps
);
758 data
->curcfg
.win_width
* data
->curcfg
.cell_width
,
759 data
->curcfg
.win_height
* data
->curcfg
.cell_height
,
760 PRIVATE(data
)->hMemDC
,
761 data
->curcfg
.win_pos
.X
* data
->curcfg
.cell_width
,
762 data
->curcfg
.win_pos
.Y
* data
->curcfg
.cell_height
,
764 if (PRIVATE(data
)->has_selection
)
765 WCUSER_SetSelection(data
, ps
.hdc
);
766 EndPaint(PRIVATE(data
)->hWnd
, &ps
);
769 /******************************************************************
774 static void WCUSER_Scroll(struct inner_data
* data
, int pos
, BOOL horz
)
778 SetScrollPos(PRIVATE(data
)->hWnd
, SB_HORZ
, pos
, TRUE
);
779 data
->curcfg
.win_pos
.X
= pos
;
783 SetScrollPos(PRIVATE(data
)->hWnd
, SB_VERT
, pos
, TRUE
);
784 data
->curcfg
.win_pos
.Y
= pos
;
786 InvalidateRect(PRIVATE(data
)->hWnd
, NULL
, FALSE
);
789 /******************************************************************
794 static BOOL
WCUSER_FillMenu(HMENU hMenu
, BOOL sep
)
797 HINSTANCE hInstance
= GetModuleHandle(NULL
);
800 if (!hMenu
) return FALSE
;
802 /* FIXME: error handling & memory cleanup */
803 hSubMenu
= CreateMenu();
804 if (!hSubMenu
) return FALSE
;
806 LoadString(hInstance
, IDS_MARK
, buff
, sizeof(buff
) / sizeof(WCHAR
));
807 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_MARK
, buff
);
808 LoadString(hInstance
, IDS_COPY
, buff
, sizeof(buff
) / sizeof(WCHAR
));
809 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_COPY
, buff
);
810 LoadString(hInstance
, IDS_PASTE
, buff
, sizeof(buff
) / sizeof(WCHAR
));
811 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PASTE
, buff
);
812 LoadString(hInstance
, IDS_SELECTALL
, buff
, sizeof(buff
) / sizeof(WCHAR
));
813 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SELECTALL
, buff
);
814 LoadString(hInstance
, IDS_SCROLL
, buff
, sizeof(buff
) / sizeof(WCHAR
));
815 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SCROLL
, buff
);
816 LoadString(hInstance
, IDS_SEARCH
, buff
, sizeof(buff
) / sizeof(WCHAR
));
817 InsertMenu(hSubMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_SEARCH
, buff
);
819 if (sep
) InsertMenu(hMenu
, -1, MF_BYPOSITION
|MF_SEPARATOR
, 0, NULL
);
820 LoadString(hInstance
, IDS_EDIT
, buff
, sizeof(buff
) / sizeof(WCHAR
));
821 InsertMenu(hMenu
, -1, MF_BYPOSITION
|MF_STRING
|MF_POPUP
, (UINT_PTR
)hSubMenu
, buff
);
822 LoadString(hInstance
, IDS_DEFAULT
, buff
, sizeof(buff
) / sizeof(WCHAR
));
823 InsertMenu(hMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_DEFAULT
, buff
);
824 LoadString(hInstance
, IDS_PROPERTIES
, buff
, sizeof(buff
) / sizeof(WCHAR
));
825 InsertMenu(hMenu
, -1, MF_BYPOSITION
|MF_STRING
, IDS_PROPERTIES
, buff
);
830 /******************************************************************
831 * WCUSER_SetMenuDetails
833 * Grays / ungrays the menu items according to their state
835 static void WCUSER_SetMenuDetails(const struct inner_data
* data
, HMENU hMenu
)
837 if (!hMenu
) {WINE_ERR("Issue in getting menu bits\n");return;}
839 EnableMenuItem(hMenu
, IDS_COPY
,
840 MF_BYCOMMAND
|(PRIVATE(data
)->has_selection
? MF_ENABLED
: MF_GRAYED
));
841 EnableMenuItem(hMenu
, IDS_PASTE
,
842 MF_BYCOMMAND
|(IsClipboardFormatAvailable(CF_UNICODETEXT
)
843 ? MF_ENABLED
: MF_GRAYED
));
844 EnableMenuItem(hMenu
, IDS_SCROLL
, MF_BYCOMMAND
|MF_GRAYED
);
845 EnableMenuItem(hMenu
, IDS_SEARCH
, MF_BYCOMMAND
|MF_GRAYED
);
848 /******************************************************************
851 * Creates the window for the rendering
853 static LRESULT
WCUSER_Create(HWND hWnd
, LPCREATESTRUCT lpcs
)
855 struct inner_data
* data
;
858 data
= lpcs
->lpCreateParams
;
859 SetWindowLong(hWnd
, 0L, (DWORD
)data
);
860 PRIVATE(data
)->hWnd
= hWnd
;
862 hSysMenu
= GetSystemMenu(hWnd
, FALSE
);
863 if (!hSysMenu
) return 0;
864 PRIVATE(data
)->hPopMenu
= CreatePopupMenu();
865 if (!PRIVATE(data
)->hPopMenu
) return 0;
867 WCUSER_FillMenu(hSysMenu
, TRUE
);
868 WCUSER_FillMenu(PRIVATE(data
)->hPopMenu
, FALSE
);
870 PRIVATE(data
)->hMemDC
= CreateCompatibleDC(0);
871 if (!PRIVATE(data
)->hMemDC
) {WINE_ERR("no mem dc\n");return 0;}
873 data
->curcfg
.quick_edit
= FALSE
;
877 /******************************************************************
878 * WCUSER_GetCtrlKeyState
880 * Get the console bit mask equivalent to the VK_ status in keyState
882 static DWORD
WCUSER_GetCtrlKeyState(BYTE
* keyState
)
886 GetKeyboardState(keyState
);
887 if (keyState
[VK_SHIFT
] & 0x80) ret
|= SHIFT_PRESSED
;
888 if (keyState
[VK_LCONTROL
] & 0x80) ret
|= LEFT_CTRL_PRESSED
;
889 if (keyState
[VK_RCONTROL
] & 0x80) ret
|= RIGHT_CTRL_PRESSED
;
890 if (keyState
[VK_LMENU
] & 0x80) ret
|= LEFT_ALT_PRESSED
;
891 if (keyState
[VK_RMENU
] & 0x80) ret
|= RIGHT_ALT_PRESSED
;
892 if (keyState
[VK_CAPITAL
] & 0x01) ret
|= CAPSLOCK_ON
;
893 if (keyState
[VK_NUMLOCK
] & 0x01) ret
|= NUMLOCK_ON
;
894 if (keyState
[VK_SCROLL
] & 0x01) ret
|= SCROLLLOCK_ON
;
899 /******************************************************************
900 * WCUSER_HandleSelectionKey
902 * Handles keys while selecting an area
904 static void WCUSER_HandleSelectionKey(struct inner_data
* data
, BOOL down
,
905 WPARAM wParam
, LPARAM lParam
)
908 DWORD state
= WCUSER_GetCtrlKeyState(keyState
) & ~(CAPSLOCK_ON
|NUMLOCK_ON
|SCROLLLOCK_ON
);
919 PRIVATE(data
)->has_selection
= FALSE
;
920 WCUSER_SetSelection(data
, 0);
921 WCUSER_CopySelectionToClipboard(data
);
924 c1
= PRIVATE(data
)->selectPt1
;
925 c2
= PRIVATE(data
)->selectPt2
;
927 WCUSER_MoveSelection(data
, c1
, c2
);
930 c1
= PRIVATE(data
)->selectPt1
;
931 c2
= PRIVATE(data
)->selectPt2
;
933 WCUSER_MoveSelection(data
, c1
, c2
);
936 c1
= PRIVATE(data
)->selectPt1
;
937 c2
= PRIVATE(data
)->selectPt2
;
939 WCUSER_MoveSelection(data
, c1
, c2
);
942 c1
= PRIVATE(data
)->selectPt1
;
943 c2
= PRIVATE(data
)->selectPt2
;
945 WCUSER_MoveSelection(data
, c1
, c2
);
953 c1
= PRIVATE(data
)->selectPt1
;
954 c2
= PRIVATE(data
)->selectPt2
;
956 WCUSER_MoveSelection(data
, c1
, c2
);
959 c1
= PRIVATE(data
)->selectPt1
;
960 c2
= PRIVATE(data
)->selectPt2
;
962 WCUSER_MoveSelection(data
, c1
, c2
);
965 c1
= PRIVATE(data
)->selectPt1
;
966 c2
= PRIVATE(data
)->selectPt2
;
968 WCUSER_MoveSelection(data
, c1
, c2
);
971 c1
= PRIVATE(data
)->selectPt1
;
972 c2
= PRIVATE(data
)->selectPt2
;
974 WCUSER_MoveSelection(data
, c1
, c2
);
981 /******************************************************************
982 * WCUSER_GenerateKeyInputRecord
984 * generates input_record from windows WM_KEYUP/WM_KEYDOWN messages
986 static void WCUSER_GenerateKeyInputRecord(struct inner_data
* data
, BOOL down
,
987 WPARAM wParam
, LPARAM lParam
, BOOL sys
)
992 static WCHAR last
; /* keep last char seen as feed for key up message */
995 ir
.EventType
= KEY_EVENT
;
996 ir
.Event
.KeyEvent
.bKeyDown
= down
;
997 ir
.Event
.KeyEvent
.wRepeatCount
= LOWORD(lParam
);
998 ir
.Event
.KeyEvent
.wVirtualKeyCode
= wParam
;
1000 ir
.Event
.KeyEvent
.wVirtualScanCode
= HIWORD(lParam
) & 0xFF;
1002 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
1003 ir
.Event
.KeyEvent
.dwControlKeyState
= WCUSER_GetCtrlKeyState(keyState
);
1004 if (lParam
& (1L << 24)) ir
.Event
.KeyEvent
.dwControlKeyState
|= ENHANCED_KEY
;
1005 if (sys
) ir
.Event
.KeyEvent
.dwControlKeyState
|= LEFT_ALT_PRESSED
; /* FIXME: gotta choose one */
1007 if (!(ir
.Event
.KeyEvent
.dwControlKeyState
& ENHANCED_KEY
))
1011 switch (ToUnicode(wParam
, HIWORD(lParam
), keyState
, buf
, 2, 0))
1014 /* FIXME... should generate two events... */
1024 ir
.Event
.KeyEvent
.uChar
.UnicodeChar
= last
; /* FIXME HACKY... and buggy 'coz it should be a stack, not a single value */
1025 if (!down
) last
= 0;
1028 WriteConsoleInput(data
->hConIn
, &ir
, 1, &n
);
1031 /******************************************************************
1032 * WCUSER_GenerateMouseInputRecord
1036 static void WCUSER_GenerateMouseInputRecord(struct inner_data
* data
, COORD c
,
1037 WPARAM wParam
, DWORD event
)
1043 /* MOUSE_EVENTs shouldn't be sent unless ENABLE_MOUSE_INPUT is active */
1044 if (!GetConsoleMode(data
->hConIn
, &mode
) || !(mode
& ENABLE_MOUSE_INPUT
))
1047 ir
.EventType
= MOUSE_EVENT
;
1048 ir
.Event
.MouseEvent
.dwMousePosition
= c
;
1049 ir
.Event
.MouseEvent
.dwButtonState
= 0;
1050 if (wParam
& MK_LBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_1ST_BUTTON_PRESSED
;
1051 if (wParam
& MK_MBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= FROM_LEFT_2ND_BUTTON_PRESSED
;
1052 if (wParam
& MK_RBUTTON
) ir
.Event
.MouseEvent
.dwButtonState
|= RIGHTMOST_BUTTON_PRESSED
;
1053 ir
.Event
.MouseEvent
.dwControlKeyState
= WCUSER_GetCtrlKeyState(keyState
);
1054 ir
.Event
.MouseEvent
.dwEventFlags
= event
;
1056 WriteConsoleInput(data
->hConIn
, &ir
, 1, &n
);
1059 /******************************************************************
1064 static LRESULT CALLBACK
WCUSER_Proc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1066 struct inner_data
* data
= (struct inner_data
*)GetWindowLong(hWnd
, 0);
1071 return WCUSER_Create(hWnd
, (LPCREATESTRUCT
)lParam
);
1073 PRIVATE(data
)->hWnd
= 0;
1081 if (PRIVATE(data
)->has_selection
)
1082 WCUSER_HandleSelectionKey(data
, uMsg
== WM_KEYDOWN
, wParam
, lParam
);
1084 WCUSER_GenerateKeyInputRecord(data
, uMsg
== WM_KEYDOWN
, wParam
, lParam
, FALSE
);
1088 WCUSER_GenerateKeyInputRecord(data
, uMsg
== WM_SYSKEYDOWN
, wParam
, lParam
, TRUE
);
1090 case WM_LBUTTONDOWN
:
1091 if (data
->curcfg
.quick_edit
)
1093 if (PRIVATE(data
)->has_selection
)
1095 PRIVATE(data
)->has_selection
= FALSE
;
1096 WCUSER_SetSelection(data
, 0);
1100 PRIVATE(data
)->selectPt1
= PRIVATE(data
)->selectPt2
= WCUSER_GetCell(data
, lParam
);
1101 SetCapture(PRIVATE(data
)->hWnd
);
1102 WCUSER_SetSelection(data
, 0);
1103 PRIVATE(data
)->has_selection
= TRUE
;
1108 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, 0);
1112 if (data
->curcfg
.quick_edit
)
1114 if (GetCapture() == PRIVATE(data
)->hWnd
&& PRIVATE(data
)->has_selection
&&
1115 (wParam
& MK_LBUTTON
))
1117 WCUSER_MoveSelection(data
, PRIVATE(data
)->selectPt1
, WCUSER_GetCell(data
, lParam
));
1122 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, MOUSE_MOVED
);
1126 if (data
->curcfg
.quick_edit
)
1128 if (GetCapture() == PRIVATE(data
)->hWnd
&& PRIVATE(data
)->has_selection
&&
1129 (wParam
& MK_LBUTTON
))
1131 WCUSER_MoveSelection(data
, PRIVATE(data
)->selectPt1
, WCUSER_GetCell(data
, lParam
));
1133 PRIVATE(data
)->has_selection
= FALSE
;
1138 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, 0);
1141 case WM_RBUTTONDOWN
:
1142 if ((wParam
& (MK_CONTROL
|MK_SHIFT
)) == data
->curcfg
.menu_mask
)
1146 GetWindowRect(hWnd
, &r
);
1147 WCUSER_SetMenuDetails(data
, PRIVATE(data
)->hPopMenu
);
1148 TrackPopupMenu(PRIVATE(data
)->hPopMenu
, TPM_LEFTALIGN
|TPM_TOPALIGN
,
1149 r
.left
+ LOWORD(lParam
), r
.top
+ HIWORD(lParam
), 0, hWnd
, NULL
);
1153 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, 0);
1157 /* no need to track for rbutton up when opening the popup... the event will be
1158 * swallowed by TrackPopupMenu */
1159 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, 0);
1162 /* FIXME: should we scroll too ? */
1163 WCUSER_GenerateMouseInputRecord(data
, WCUSER_GetCell(data
, lParam
), wParam
, MOUSE_WHEELED
);
1166 if (data
->curcfg
.cursor_visible
)
1168 CreateCaret(PRIVATE(data
)->hWnd
, PRIVATE(data
)->cursor_bitmap
,
1169 data
->curcfg
.cell_width
, data
->curcfg
.cell_height
);
1170 WCUSER_PosCursor(data
);
1174 if (data
->curcfg
.cursor_visible
)
1179 int pos
= data
->curcfg
.win_pos
.X
;
1181 switch (LOWORD(wParam
))
1183 case SB_PAGEUP
: pos
-= 8; break;
1184 case SB_PAGEDOWN
: pos
+= 8; break;
1185 case SB_LINEUP
: pos
--; break;
1186 case SB_LINEDOWN
: pos
++; break;
1187 case SB_THUMBTRACK
: pos
= HIWORD(wParam
); break;
1190 if (pos
< 0) pos
= 0;
1191 if (pos
> data
->curcfg
.sb_width
- data
->curcfg
.win_width
)
1192 pos
= data
->curcfg
.sb_width
- data
->curcfg
.win_width
;
1193 if (pos
!= data
->curcfg
.win_pos
.X
)
1195 ScrollWindow(hWnd
, (data
->curcfg
.win_pos
.X
- pos
) * data
->curcfg
.cell_width
, 0,
1197 data
->curcfg
.win_pos
.X
= pos
;
1198 SetScrollPos(hWnd
, SB_HORZ
, pos
, TRUE
);
1200 WCUSER_PosCursor(data
);
1201 WINECON_NotifyWindowChange(data
);
1207 int pos
= data
->curcfg
.win_pos
.Y
;
1209 switch (LOWORD(wParam
))
1211 case SB_PAGEUP
: pos
-= 8; break;
1212 case SB_PAGEDOWN
: pos
+= 8; break;
1213 case SB_LINEUP
: pos
--; break;
1214 case SB_LINEDOWN
: pos
++; break;
1215 case SB_THUMBTRACK
: pos
= HIWORD(wParam
); break;
1218 if (pos
< 0) pos
= 0;
1219 if (pos
> data
->curcfg
.sb_height
- data
->curcfg
.win_height
)
1220 pos
= data
->curcfg
.sb_height
- data
->curcfg
.win_height
;
1221 if (pos
!= data
->curcfg
.win_pos
.Y
)
1223 ScrollWindow(hWnd
, 0, (data
->curcfg
.win_pos
.Y
- pos
) * data
->curcfg
.cell_height
,
1225 data
->curcfg
.win_pos
.Y
= pos
;
1226 SetScrollPos(hWnd
, SB_VERT
, pos
, TRUE
);
1228 WCUSER_PosCursor(data
);
1229 WINECON_NotifyWindowChange(data
);
1237 WCUSER_GetProperties(data
, FALSE
);
1239 case IDS_PROPERTIES
:
1240 WCUSER_GetProperties(data
, TRUE
);
1243 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
1250 WCUSER_GetProperties(data
, FALSE
);
1252 case IDS_PROPERTIES
:
1253 WCUSER_GetProperties(data
, TRUE
);
1256 PRIVATE(data
)->selectPt1
.X
= PRIVATE(data
)->selectPt1
.Y
= 0;
1257 PRIVATE(data
)->selectPt2
.X
= PRIVATE(data
)->selectPt2
.Y
= 0;
1258 WCUSER_SetSelection(data
, 0);
1259 PRIVATE(data
)->has_selection
= TRUE
;
1262 if (PRIVATE(data
)->has_selection
)
1264 PRIVATE(data
)->has_selection
= FALSE
;
1265 WCUSER_SetSelection(data
, 0);
1266 WCUSER_CopySelectionToClipboard(data
);
1270 WCUSER_PasteFromClipboard(data
);
1273 PRIVATE(data
)->selectPt1
.X
= PRIVATE(data
)->selectPt1
.Y
= 0;
1274 PRIVATE(data
)->selectPt2
.X
= (data
->curcfg
.sb_width
- 1) * data
->curcfg
.cell_width
;
1275 PRIVATE(data
)->selectPt2
.Y
= (data
->curcfg
.sb_height
- 1) * data
->curcfg
.cell_height
;
1276 WCUSER_SetSelection(data
, 0);
1277 PRIVATE(data
)->has_selection
= TRUE
;
1281 WINE_FIXME("Unhandled yet command: %x\n", wParam
);
1284 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
1287 case WM_INITMENUPOPUP
:
1288 if (!HIWORD(lParam
)) return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
1289 WCUSER_SetMenuDetails(data
, GetSystemMenu(PRIVATE(data
)->hWnd
, FALSE
));
1292 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
1297 /******************************************************************
1298 * WCUSER_DeleteBackend
1302 void WCUSER_DeleteBackend(struct inner_data
* data
)
1304 if (!PRIVATE(data
)) return;
1305 if (PRIVATE(data
)->hMemDC
) DeleteDC(PRIVATE(data
)->hMemDC
);
1306 if (PRIVATE(data
)->hWnd
) DestroyWindow(PRIVATE(data
)->hWnd
);
1307 if (PRIVATE(data
)->hFont
) DeleteObject(PRIVATE(data
)->hFont
);
1308 if (PRIVATE(data
)->cursor_bitmap
) DeleteObject(PRIVATE(data
)->cursor_bitmap
);
1309 if (PRIVATE(data
)->hBitmap
) DeleteObject(PRIVATE(data
)->hBitmap
);
1310 HeapFree(GetProcessHeap(), 0, PRIVATE(data
));
1313 /******************************************************************
1318 static int WCUSER_MainLoop(struct inner_data
* data
)
1322 ShowWindow(PRIVATE(data
)->hWnd
, SW_SHOW
);
1325 switch (MsgWaitForMultipleObjects(1, &data
->hSynchro
, FALSE
, INFINITE
, QS_ALLINPUT
))
1328 if (!WINECON_GrabChanges(data
) && data
->curcfg
.exit_on_die
)
1331 case WAIT_OBJECT_0
+1:
1332 /* need to use PeekMessage loop instead of simple GetMessage:
1333 * multiple messages might have arrived in between,
1334 * so GetMessage would lead to delayed processing */
1335 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
1337 if (msg
.message
== WM_QUIT
) return 0;
1338 WINE_TRACE("dispatching msg %04x\n", msg
.message
);
1339 DispatchMessage(&msg
);
1343 WINE_ERR("got pb\n");
1350 /******************************************************************
1351 * WCUSER_InitBackend
1353 * Initialisation part II: creation of window.
1356 enum init_return
WCUSER_InitBackend(struct inner_data
* data
)
1358 static WCHAR wClassName
[] = {'W','i','n','e','C','o','n','s','o','l','e','C','l','a','s','s',0};
1362 data
->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct inner_data_user
));
1363 if (!data
->private) return init_failed
;
1365 data
->fnMainLoop
= WCUSER_MainLoop
;
1366 data
->fnPosCursor
= WCUSER_PosCursor
;
1367 data
->fnShapeCursor
= WCUSER_ShapeCursor
;
1368 data
->fnComputePositions
= WCUSER_ComputePositions
;
1369 data
->fnRefresh
= WCUSER_Refresh
;
1370 data
->fnResizeScreenBuffer
= WCUSER_ResizeScreenBuffer
;
1371 data
->fnSetTitle
= WCUSER_SetTitle
;
1372 data
->fnSetFont
= WCUSER_SetFontPmt
;
1373 data
->fnScroll
= WCUSER_Scroll
;
1374 data
->fnDeleteBackend
= WCUSER_DeleteBackend
;
1377 wndclass
.lpfnWndProc
= WCUSER_Proc
;
1378 wndclass
.cbClsExtra
= 0;
1379 wndclass
.cbWndExtra
= sizeof(DWORD
);
1380 wndclass
.hInstance
= GetModuleHandle(NULL
);
1381 wndclass
.hIcon
= LoadIcon(0, IDI_WINLOGO
);
1382 wndclass
.hCursor
= LoadCursor(0, IDC_ARROW
);
1383 wndclass
.hbrBackground
= GetStockObject(BLACK_BRUSH
);
1384 wndclass
.lpszMenuName
= NULL
;
1385 wndclass
.lpszClassName
= wClassName
;
1387 RegisterClass(&wndclass
);
1389 CreateWindow(wndclass
.lpszClassName
, NULL
,
1390 WS_OVERLAPPED
|WS_CAPTION
|WS_SYSMENU
|WS_THICKFRAME
|WS_MINIMIZEBOX
|WS_HSCROLL
|WS_VSCROLL
,
1391 CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0, 0, 0, wndclass
.hInstance
, data
);
1392 if (!PRIVATE(data
)->hWnd
) return init_failed
;
1394 return init_success
;