[CONSOLE.CPL] Fix the console screen preview when selecting TrueType fonts.
[reactos.git] / dll / cpl / console / layout.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/console/layout.c
5 * PURPOSE: Layout dialog
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 #include "console.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* CONSOLE WINDOW PREVIEW Control *********************************************/
16
17 #define WIN_PREVIEW_CLASS L"WinPreview"
18
19 typedef struct _WINPREV_DATA
20 {
21 HWND hWnd; // The window which this structure refers to
22 RECT rcMaxArea; // Maximum rectangle in which the preview window can be sized
23 SIZE siPreview; // Actual size of the preview window
24 SIZE siVirtScr; // Width and Height of the virtual screen
25 PVOID pData; // Private data
26 } WINPREV_DATA, *PWINPREV_DATA;
27
28 static LRESULT CALLBACK
29 WinPrevProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
30
31 BOOL
32 RegisterWinPrevClass(
33 IN HINSTANCE hInstance)
34 {
35 WNDCLASSW WndClass;
36
37 WndClass.lpszClassName = WIN_PREVIEW_CLASS;
38 WndClass.lpfnWndProc = WinPrevProc;
39 WndClass.style = 0;
40 WndClass.hInstance = hInstance;
41 WndClass.hIcon = NULL;
42 WndClass.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_ARROW));
43 WndClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
44 WndClass.lpszMenuName = NULL;
45 WndClass.cbClsExtra = 0;
46 WndClass.cbWndExtra = 0; // sizeof(PWINPREV_DATA);
47
48 return (RegisterClassW(&WndClass) != 0);
49 }
50
51 BOOL
52 UnRegisterWinPrevClass(
53 IN HINSTANCE hInstance)
54 {
55 return UnregisterClassW(WIN_PREVIEW_CLASS, hInstance);
56 }
57
58 static VOID
59 WinPrev_OnDisplayChange(
60 IN PWINPREV_DATA pData)
61 {
62 // RECT rcNew;
63
64 pData->siVirtScr.cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
65 pData->siVirtScr.cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
66
67 /*
68 * The rescaling factor "siPreview / siVirtScr" should be the minimum of the ratios
69 * pData->rcMaxArea.right / pData->siVirtScr.cx , and
70 * pData->rcMaxArea.bottom / pData->siVirtScr.cy ,
71 * or equivalently, the maximum of the inverse of these ratios.
72 * This condition is equivalent to the following inequality being tested.
73 */
74 // if (pData->siVirtScr.cx / pData->rcMaxArea.right >= pData->siVirtScr.cy / pData->rcMaxArea.bottom)
75 if (pData->siVirtScr.cx * pData->rcMaxArea.bottom >= pData->siVirtScr.cy * pData->rcMaxArea.right)
76 {
77 pData->siPreview.cx = MulDiv(pData->siVirtScr.cx, pData->rcMaxArea.right, pData->siVirtScr.cx);
78 pData->siPreview.cy = MulDiv(pData->siVirtScr.cy, pData->rcMaxArea.right, pData->siVirtScr.cx);
79 }
80 else
81 {
82 pData->siPreview.cx = MulDiv(pData->siVirtScr.cx, pData->rcMaxArea.bottom, pData->siVirtScr.cy);
83 pData->siPreview.cy = MulDiv(pData->siVirtScr.cy, pData->rcMaxArea.bottom, pData->siVirtScr.cy);
84 }
85
86 /*
87 * Now, the lengths in screen-units can be rescaled into preview-units with:
88 * MulDiv(cx, pData->siPreview.cx, pData->siVirtScr.cx);
89 * and:
90 * MulDiv(cy, pData->siPreview.cy, pData->siVirtScr.cy);
91 */
92
93 #if 0 // TODO: Investigate!
94 /*
95 * Since both rcMaxArea and siPreview are client window area sizes,
96 * transform them into window sizes.
97 */
98 SetRect(&rcNew, 0, 0, pData->siPreview.cx, pData->siPreview.cy);
99 AdjustWindowRect(&rcNew,
100 WS_BORDER,
101 // GetWindowLongPtrW(pData->hWnd, GWL_STYLE) & ~WS_OVERLAPPED,
102 FALSE);
103 OffsetRect(&rcNew, -rcNew.left, -rcNew.top);
104 rcNew.right += 2;
105 rcNew.bottom += 2;
106 #endif
107
108 SetWindowPos(pData->hWnd,
109 0 /* HWND_TOP */,
110 0, 0,
111 pData->siPreview.cx, pData->siPreview.cy,
112 // rcNew.right, rcNew.bottom,
113 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
114 }
115
116 #define RescaleCX(pData, len) \
117 MulDiv((len), (pData)->siPreview.cx, (pData)->siVirtScr.cx)
118
119 #define RescaleCY(pData, len) \
120 MulDiv((len), (pData)->siPreview.cy, (pData)->siVirtScr.cy)
121
122 #define RescaleRect(pData, rect) \
123 do { \
124 (rect).left = RescaleCX((pData), (rect).left); \
125 (rect).right = RescaleCX((pData), (rect).right); \
126 (rect).top = RescaleCY((pData), (rect).top); \
127 (rect).bottom = RescaleCY((pData), (rect).bottom); \
128 } while (0)
129
130 #if 0
131 static VOID
132 WinPrev_OnSize(VOID)
133 {
134 }
135 #endif
136
137 static VOID
138 WinPrev_OnDraw(
139 IN HDC hDC,
140 IN PWINPREV_DATA pData)
141 {
142 PCONSOLE_STATE_INFO pConInfo = (PCONSOLE_STATE_INFO)pData->pData;
143 HBRUSH hBrush;
144 RECT rcWin, fRect;
145 SIZE /*siBorder,*/ siFrame, siButton, siScroll;
146 SIZE resize;
147
148 RECT rcItem;
149
150 GetClientRect(pData->hWnd, &rcItem);
151
152 /*
153 * Retrieve some system metrics and rescale them.
154 * They will be added separately, so that to always round the sizes up.
155 */
156
157 /* Don't care about border as it is almost always 1 and <= frame size */
158 /* Example: Frame = 4, or 13 ... while Border = 1 */
159 // siBorder.cx = GetSystemMetrics(SM_CXBORDER);
160 // siBorder.cy = GetSystemMetrics(SM_CYBORDER);
161
162 /* Window frame size */
163 siFrame.cx = GetSystemMetrics(SM_CXFRAME);
164 if (siFrame.cx > 0)
165 {
166 siFrame.cx = RescaleCX(pData, siFrame.cx);
167 siFrame.cx = max(1, siFrame.cx);
168 }
169 siFrame.cy = GetSystemMetrics(SM_CYFRAME);
170 if (siFrame.cy > 0)
171 {
172 siFrame.cy = RescaleCY(pData, siFrame.cy);
173 siFrame.cy = max(1, siFrame.cy);
174 }
175
176 /* Window caption buttons */
177 siButton.cx = GetSystemMetrics(SM_CXSIZE);
178 siButton.cx = RescaleCX(pData, siButton.cx);
179 siButton.cx = max(1, siButton.cx);
180
181 siButton.cy = GetSystemMetrics(SM_CYSIZE);
182 siButton.cy = RescaleCY(pData, siButton.cy);
183 siButton.cy = max(1, siButton.cy);
184
185 /* Enlarge them for improving their appearance */
186 // siButton.cx *= 2;
187 siButton.cy *= 2;
188
189 /* Dimensions of the scrollbars */
190 siScroll.cx = GetSystemMetrics(SM_CXVSCROLL);
191 siScroll.cx = RescaleCX(pData, siScroll.cx);
192 siScroll.cx = max(1, siScroll.cx);
193
194 siScroll.cy = GetSystemMetrics(SM_CYHSCROLL);
195 siScroll.cy = RescaleCY(pData, siScroll.cy);
196 siScroll.cy = max(1, siScroll.cy);
197
198
199 // FIXME: Use SM_CXMIN, SM_CYMIN ??
200
201
202 /*
203 * Compute the console window layout
204 */
205
206 /* We start with the console client area, rescaled for the preview */
207 SetRect(&rcWin, 0, 0,
208 pConInfo->WindowSize.X * FontPreview.CharWidth,
209 pConInfo->WindowSize.Y * FontPreview.CharHeight);
210 RescaleRect(pData, rcWin);
211
212 /* Add the scrollbars if needed (does not account for any frame) */
213 if (pConInfo->WindowSize.X < pConInfo->ScreenBufferSize.X)
214 {
215 /* Horizontal scrollbar */
216 rcWin.bottom += siScroll.cy;
217 // NOTE: If an additional exterior frame is needed, add +1
218 }
219 else
220 {
221 /* No scrollbar */
222 siScroll.cy = 0;
223 }
224 if (pConInfo->WindowSize.Y < pConInfo->ScreenBufferSize.Y)
225 {
226 /* Vertical scrollbar */
227 rcWin.right += siScroll.cx;
228 // NOTE: If an additional exterior frame is needed, add +1
229 }
230 else
231 {
232 /* No scrollbar */
233 siScroll.cx = 0;
234 }
235
236 /* Add the title bar, taking into account the frames */
237 rcWin.top -= siButton.cy - 1;
238
239 /* If we have a non-zero window frame size, add an interior border and the frame */
240 resize.cx = (siFrame.cx > 0 ? 1 + siFrame.cx : 0);
241 resize.cy = (siFrame.cy > 0 ? 1 + siFrame.cy : 0);
242
243 /* Add the outer border */
244 ++resize.cx, ++resize.cy;
245
246 InflateRect(&rcWin, resize.cx, resize.cy);
247
248 /* Finally, move the window rectangle back to its correct origin */
249 OffsetRect(&rcWin, -rcWin.left, -rcWin.top);
250
251 if ( pConInfo->WindowPosition.x == MAXDWORD &&
252 pConInfo->WindowPosition.y == MAXDWORD )
253 {
254 // OffsetRect(&rcWin, (rcItem.right - rcItem.left) / 3, (rcItem.bottom - rcItem.top) / 3);
255 OffsetRect(&rcWin, 0, 0);
256 }
257 else
258 {
259 OffsetRect(&rcWin,
260 RescaleCX(pData, pConInfo->WindowPosition.x),
261 RescaleCY(pData, pConInfo->WindowPosition.y));
262 }
263
264
265 /*
266 * Paint the preview window
267 */
268
269 /* Fill the background with desktop colour */
270 FillRect(hDC, &rcItem, GetSysColorBrush(COLOR_BACKGROUND));
271
272 /*
273 * Draw the exterior frame. Use 'FillRect' instead of 'FrameRect'
274 * so that, when we want to draw frames around other elements,
275 * we can just instead separate them with space instead of redrawing
276 * a frame with 'FrameRect'.
277 */
278 FillRect(hDC, &rcWin, GetSysColorBrush(COLOR_WINDOWFRAME));
279 InflateRect(&rcWin, -1, -1);
280
281 /* Draw the border */
282 hBrush = GetSysColorBrush(COLOR_ACTIVEBORDER);
283 if (siFrame.cx > 0)
284 {
285 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.left + siFrame.cx, rcWin.bottom);
286 FillRect(hDC, &fRect, hBrush);
287 SetRect(&fRect, rcWin.right - siFrame.cx, rcWin.top, rcWin.right, rcWin.bottom);
288 FillRect(hDC, &fRect, hBrush);
289
290 InflateRect(&rcWin, -siFrame.cx, 0);
291 }
292 if (siFrame.cy > 0)
293 {
294 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.right, rcWin.top + siFrame.cy);
295 FillRect(hDC, &fRect, hBrush);
296 SetRect(&fRect, rcWin.left, rcWin.bottom - siFrame.cy, rcWin.right, rcWin.bottom);
297 FillRect(hDC, &fRect, hBrush);
298
299 InflateRect(&rcWin, 0, -siFrame.cy);
300 }
301
302 /* Draw the interior frame if we had a border */
303 if (siFrame.cx > 0 || siFrame.cy > 0)
304 {
305 #if 0 // See the remark above
306 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);
307 FrameRect(hDC, &fRect, GetSysColorBrush(COLOR_WINDOWFRAME));
308 #endif
309 InflateRect(&rcWin, (siFrame.cx > 0 ? -1 : 0), (siFrame.cy > 0 ? -1 : 0));
310 }
311
312 /* Draw the console window title bar */
313 hBrush = GetSysColorBrush(COLOR_BTNFACE);
314
315 /* Draw the system menu (left button) */
316 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.left + siButton.cx, rcWin.top + siButton.cy - 2);
317 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONCLOSE);
318 FillRect(hDC, &fRect, hBrush);
319 fRect.right++; // Separation
320
321 /* Draw the caption bar */
322 SetRect(&fRect, fRect.right, fRect.top, rcWin.right - 2 * (siButton.cx + 1), fRect.bottom);
323 FillRect(hDC, &fRect, GetSysColorBrush(COLOR_ACTIVECAPTION));
324 fRect.right++; // Separation
325
326 /* Draw the minimize menu (first right button) */
327 SetRect(&fRect, fRect.right, fRect.top, fRect.right + siButton.cx, fRect.bottom);
328 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONMIN);
329 FillRect(hDC, &fRect, hBrush);
330 fRect.right++; // Separation
331
332 /* Draw the maximize menu (second right button) */
333 SetRect(&fRect, fRect.right, fRect.top, fRect.right + siButton.cx, fRect.bottom);
334 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONMAX);
335 FillRect(hDC, &fRect, hBrush);
336
337 rcWin.top += siButton.cy - 1;
338
339 /* Add the scrollbars if needed */
340 if (siScroll.cy > 0 || siScroll.cx > 0)
341 {
342 LONG right, bottom;
343
344 right = rcWin.right;
345 bottom = rcWin.bottom;
346
347 /*
348 * If both the horizontal and vertical scrollbars are present,
349 * reserve some space for the "dead square" at the bottom right.
350 */
351 if (siScroll.cy > 0 && siScroll.cx > 0)
352 {
353 right -= (1 + siScroll.cx);
354 bottom -= (1 + siScroll.cy);
355 }
356
357 hBrush = GetSysColorBrush(COLOR_SCROLLBAR);
358
359 /* Horizontal scrollbar */
360 if (siScroll.cy > 0)
361 {
362 SetRect(&fRect, rcWin.left, rcWin.bottom - siScroll.cy, right, rcWin.bottom);
363 FillRect(hDC, &fRect, hBrush);
364 }
365
366 /* Vertical scrollbar */
367 if (siScroll.cx > 0)
368 {
369 SetRect(&fRect, rcWin.right - siScroll.cx, rcWin.top, rcWin.right, bottom);
370 FillRect(hDC, &fRect, hBrush);
371 }
372
373 /*
374 * If both the horizontal and vertical scrollbars are present,
375 * draw the "dead square" at the bottom right.
376 */
377 if (siScroll.cy > 0 && siScroll.cx > 0)
378 {
379 SetRect(&fRect, rcWin.right - siScroll.cx, rcWin.bottom - siScroll.cy, rcWin.right, rcWin.bottom);
380 FillRect(hDC, &fRect, hBrush);
381 }
382
383 // NOTE: If an additional exterior frame is needed, remove +1 for each direction
384 rcWin.right -= siScroll.cx;
385 rcWin.bottom -= siScroll.cy;
386 }
387
388 /* Draw the console background */
389 hBrush = CreateSolidBrush(pConInfo->ColorTable[BkgdAttribFromAttrib(pConInfo->ScreenAttributes)]);
390 FillRect(hDC, &rcWin, hBrush);
391 DeleteObject(hBrush);
392 }
393
394 static LRESULT CALLBACK
395 WinPrevProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
396 {
397 PWINPREV_DATA pData;
398
399 pData = (PWINPREV_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
400
401 switch (msg)
402 {
403 case WM_CREATE:
404 {
405 pData = (PWINPREV_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pData));
406 if (!pData)
407 {
408 /* We failed to allocate our private data, halt the window creation */
409 return (LRESULT)-1;
410 }
411 pData->hWnd = hWnd;
412 pData->pData = ConInfo;
413 GetClientRect(pData->hWnd, &pData->rcMaxArea);
414 // LPCREATESTRUCT::cx and cy give window (not client) size
415 WinPrev_OnDisplayChange(pData);
416 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pData);
417 break;
418 }
419
420 case WM_DESTROY:
421 {
422 if (pData)
423 HeapFree(GetProcessHeap(), 0, pData);
424 break;
425 }
426
427 case WM_DISPLAYCHANGE:
428 {
429 WinPrev_OnDisplayChange(pData);
430 UpdateWindow(hWnd);
431 // InvalidateRect(hWnd, NULL, FALSE);
432 break;
433 }
434
435 case WM_SIZE:
436 break;
437
438 case WM_ERASEBKGND:
439 return 1;
440
441 case WM_PAINT:
442 {
443 PAINTSTRUCT ps;
444 BeginPaint(hWnd, &ps);
445 WinPrev_OnDraw(ps.hdc, pData);
446 EndPaint(hWnd, &ps);
447 return 0;
448 }
449 }
450
451 return DefWindowProcW(hWnd, msg, wParam, lParam);
452 }
453
454
455 /* CONSOLE TEXT PREVIEW *******************************************************/
456
457 const WCHAR szPreviewText[] =
458 L"C:\\ReactOS> dir \n" \
459 L"SYSTEM <DIR> 13-04-15 5:00a\n" \
460 L"SYSTEM32 <DIR> 13-04-15 5:00a\n" \
461 L"readme txt 1739 13-04-15 5:00a\n" \
462 L"explorer exe 3329536 13-04-15 5:00a\n" \
463 L"vgafonts cab 18736 13-04-15 5:00a\n" \
464 L"setuplog txt 313 13-04-15 5:00a\n" \
465 L"win ini 7005 13-04-15 5:00a\n" ;
466
467 VOID
468 PaintText(
469 IN LPDRAWITEMSTRUCT drawItem,
470 IN PCONSOLE_STATE_INFO pConInfo,
471 IN TEXT_TYPE TextMode)
472 {
473 USHORT CurrentAttrib;
474 COLORREF pbkColor, ptColor;
475 COLORREF nbkColor, ntColor;
476 HBRUSH hBrush;
477 HFONT hOldFont;
478
479 if (TextMode == Screen)
480 CurrentAttrib = pConInfo->ScreenAttributes;
481 else if (TextMode == Popup)
482 CurrentAttrib = pConInfo->PopupAttributes;
483 else
484 return;
485
486 nbkColor = pConInfo->ColorTable[BkgdAttribFromAttrib(CurrentAttrib)];
487 ntColor = pConInfo->ColorTable[TextAttribFromAttrib(CurrentAttrib)];
488
489 hBrush = CreateSolidBrush(nbkColor);
490 if (!hBrush) return;
491
492 hOldFont = SelectObject(drawItem->hDC, FontPreview.hFont);
493 //if (hOldFont == NULL)
494 //{
495 // DeleteObject(hBrush);
496 // return;
497 //}
498
499 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
500
501 /* Add a few space between the preview window border and the text sample */
502 InflateRect(&drawItem->rcItem, -2, -2);
503
504 ptColor = SetTextColor(drawItem->hDC, ntColor);
505 pbkColor = SetBkColor(drawItem->hDC, nbkColor);
506 DrawTextW(drawItem->hDC, szPreviewText, (INT)wcslen(szPreviewText), &drawItem->rcItem, 0);
507 SetTextColor(drawItem->hDC, ptColor);
508 SetBkColor(drawItem->hDC, pbkColor);
509
510 SelectObject(drawItem->hDC, hOldFont);
511 DeleteObject(hBrush);
512 }
513
514
515 /* LAYOUT DIALOG **************************************************************/
516
517 INT_PTR
518 CALLBACK
519 LayoutProc(HWND hDlg,
520 UINT uMsg,
521 WPARAM wParam,
522 LPARAM lParam)
523 {
524 switch (uMsg)
525 {
526 case WM_INITDIALOG:
527 {
528 /* Multi-monitor support */
529 LONG xVirtScr, yVirtScr; // Coordinates of the top-left virtual screen
530 LONG cxVirtScr, cyVirtScr; // Width and Height of the virtual screen
531 LONG cxFrame , cyFrame ; // Thickness of the window frame
532
533 xVirtScr = GetSystemMetrics(SM_XVIRTUALSCREEN);
534 yVirtScr = GetSystemMetrics(SM_YVIRTUALSCREEN);
535 cxVirtScr = GetSystemMetrics(SM_CXVIRTUALSCREEN);
536 cyVirtScr = GetSystemMetrics(SM_CYVIRTUALSCREEN);
537 cxFrame = GetSystemMetrics(SM_CXFRAME);
538 cyFrame = GetSystemMetrics(SM_CYFRAME);
539
540 SendDlgItemMessageW(hDlg, IDC_UPDOWN_SCREEN_BUFFER_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
541 SendDlgItemMessageW(hDlg, IDC_UPDOWN_SCREEN_BUFFER_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
542 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_SIZE_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
543 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_SIZE_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
544
545 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, ConInfo->ScreenBufferSize.Y, FALSE);
546 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH , ConInfo->ScreenBufferSize.X, FALSE);
547 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, ConInfo->WindowSize.Y, FALSE);
548 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , ConInfo->WindowSize.X, FALSE);
549
550 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, UDM_SETRANGE, 0,
551 (LPARAM)MAKELONG(xVirtScr + cxVirtScr - cxFrame, xVirtScr - cxFrame));
552 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , UDM_SETRANGE, 0,
553 (LPARAM)MAKELONG(yVirtScr + cyVirtScr - cyFrame, yVirtScr - cyFrame));
554
555 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, ConInfo->WindowPosition.x, TRUE);
556 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , ConInfo->WindowPosition.y, TRUE);
557
558 if (ConInfo->AutoPosition)
559 {
560 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
561 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
562 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
563 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
564 }
565 CheckDlgButton(hDlg, IDC_CHECK_SYSTEM_POS_WINDOW,
566 ConInfo->AutoPosition ? BST_CHECKED : BST_UNCHECKED);
567
568 return TRUE;
569 }
570
571 case WM_DISPLAYCHANGE:
572 {
573 /* Retransmit to the preview window */
574 SendDlgItemMessageW(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW,
575 WM_DISPLAYCHANGE, wParam, lParam);
576 break;
577 }
578
579 case WM_NOTIFY:
580 {
581 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
582
583 if (lppsn->hdr.code == UDN_DELTAPOS)
584 {
585 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lParam;
586 DWORD wheight, wwidth;
587 DWORD sheight, swidth;
588 DWORD left, top;
589
590 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH)
591 {
592 wwidth = lpnmud->iPos + lpnmud->iDelta;
593 }
594 else
595 {
596 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
597 }
598
599 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
600 {
601 wheight = lpnmud->iPos + lpnmud->iDelta;
602 }
603 else
604 {
605 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, NULL, FALSE);
606 }
607
608 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH)
609 {
610 swidth = lpnmud->iPos + lpnmud->iDelta;
611 }
612 else
613 {
614 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
615 }
616
617 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
618 {
619 sheight = lpnmud->iPos + lpnmud->iDelta;
620 }
621 else
622 {
623 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
624 }
625
626 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_LEFT)
627 {
628 left = lpnmud->iPos + lpnmud->iDelta;
629 }
630 else
631 {
632 left = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
633 }
634
635 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_TOP)
636 {
637 top = lpnmud->iPos + lpnmud->iDelta;
638 }
639 else
640 {
641 top = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, TRUE);
642 }
643
644 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
645 {
646 /* Automatically adjust screen buffer size when window size enlarges */
647 if (wwidth >= swidth)
648 {
649 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, wwidth, TRUE);
650 swidth = wwidth;
651 }
652 if (wheight >= sheight)
653 {
654 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, wheight, TRUE);
655 sheight = wheight;
656 }
657 }
658
659 /* Be sure that the (new) screen buffer sizes are in the correct range */
660 swidth = min(max(swidth , 1), 0xFFFF);
661 sheight = min(max(sheight, 1), 0xFFFF);
662
663 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
664 {
665 /* Automatically adjust window size when screen buffer decreases */
666 if (wwidth > swidth)
667 {
668 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, swidth, TRUE);
669 wwidth = swidth;
670 }
671 if (wheight > sheight)
672 {
673 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, sheight, TRUE);
674 wheight = sheight;
675 }
676 }
677
678 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
679 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
680 ConInfo->WindowSize.X = (SHORT)wwidth;
681 ConInfo->WindowSize.Y = (SHORT)wheight;
682 ConInfo->WindowPosition.x = left;
683 ConInfo->WindowPosition.y = top;
684
685 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
686 PropSheet_Changed(GetParent(hDlg), hDlg);
687 }
688 break;
689 }
690
691 case WM_COMMAND:
692 {
693 if (HIWORD(wParam) == EN_KILLFOCUS)
694 {
695 switch (LOWORD(wParam))
696 {
697 case IDC_EDIT_SCREEN_BUFFER_WIDTH:
698 {
699 DWORD swidth, wwidth;
700
701 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
702 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
703
704 /* Be sure that the (new) screen buffer width is in the correct range */
705 swidth = min(max(swidth, 1), 0xFFFF);
706
707 /* Automatically adjust window size when screen buffer decreases */
708 if (wwidth > swidth)
709 {
710 wwidth = swidth;
711 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, wwidth, TRUE);
712 }
713
714 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
715 ConInfo->WindowSize.X = (SHORT)wwidth;
716
717 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
718 PropSheet_Changed(GetParent(hDlg), hDlg);
719 break;
720 }
721
722 case IDC_EDIT_WINDOW_SIZE_WIDTH:
723 {
724 DWORD swidth, wwidth;
725
726 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
727 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
728
729 /* Automatically adjust screen buffer size when window size enlarges */
730 if (wwidth >= swidth)
731 {
732 swidth = wwidth;
733
734 /* Be sure that the (new) screen buffer width is in the correct range */
735 swidth = min(max(swidth, 1), 0xFFFF);
736
737 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, swidth, TRUE);
738 }
739
740 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
741 ConInfo->WindowSize.X = (SHORT)wwidth;
742
743 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
744 PropSheet_Changed(GetParent(hDlg), hDlg);
745 break;
746 }
747
748 case IDC_EDIT_SCREEN_BUFFER_HEIGHT:
749 {
750 DWORD sheight, wheight;
751
752 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
753 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
754
755 /* Be sure that the (new) screen buffer width is in the correct range */
756 sheight = min(max(sheight, 1), 0xFFFF);
757
758 /* Automatically adjust window size when screen buffer decreases */
759 if (wheight > sheight)
760 {
761 wheight = sheight;
762 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, wheight, TRUE);
763 }
764
765 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
766 ConInfo->WindowSize.Y = (SHORT)wheight;
767
768 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
769 PropSheet_Changed(GetParent(hDlg), hDlg);
770 break;
771 }
772
773 case IDC_EDIT_WINDOW_SIZE_HEIGHT:
774 {
775 DWORD sheight, wheight;
776
777 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
778 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
779
780 /* Automatically adjust screen buffer size when window size enlarges */
781 if (wheight >= sheight)
782 {
783 sheight = wheight;
784
785 /* Be sure that the (new) screen buffer width is in the correct range */
786 sheight = min(max(sheight, 1), 0xFFFF);
787
788 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, sheight, TRUE);
789 }
790
791 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
792 ConInfo->WindowSize.Y = (SHORT)wheight;
793
794 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
795 PropSheet_Changed(GetParent(hDlg), hDlg);
796 break;
797 }
798
799 case IDC_EDIT_WINDOW_POS_LEFT:
800 case IDC_EDIT_WINDOW_POS_TOP:
801 {
802 ConInfo->WindowPosition.x = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
803 ConInfo->WindowPosition.y = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
804
805 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
806 PropSheet_Changed(GetParent(hDlg), hDlg);
807 break;
808 }
809 }
810 }
811 else
812 if (HIWORD(wParam) == BN_CLICKED &&
813 LOWORD(wParam) == IDC_CHECK_SYSTEM_POS_WINDOW)
814 {
815 if (IsDlgButtonChecked(hDlg, IDC_CHECK_SYSTEM_POS_WINDOW) == BST_CHECKED)
816 {
817 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
818 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
819 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
820 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
821
822 ConInfo->AutoPosition = TRUE;
823 // Do not touch ConInfo->WindowPosition !!
824
825 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
826 PropSheet_Changed(GetParent(hDlg), hDlg);
827 }
828 else
829 {
830 ULONG left, top;
831
832 left = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
833 top = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
834
835 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, TRUE);
836 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , TRUE);
837 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, TRUE);
838 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , TRUE);
839
840 ConInfo->AutoPosition = FALSE;
841 ConInfo->WindowPosition.x = left;
842 ConInfo->WindowPosition.y = top;
843
844 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
845 PropSheet_Changed(GetParent(hDlg), hDlg);
846 }
847 }
848
849 break;
850 }
851
852 default:
853 break;
854 }
855
856 return FALSE;
857 }