b211b638ed619adb2b59023dd78878a8c923edeb
[reactos.git] / reactos / 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/win32/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 const WCHAR szPreviewText[] =
16 L"C:\\ReactOS> dir \n" \
17 L"SYSTEM <DIR> 13-04-15 5:00a\n" \
18 L"SYSTEM32 <DIR> 13-04-15 5:00a\n" \
19 L"readme txt 1739 13-04-15 5:00a\n" \
20 L"explorer exe 3329536 13-04-15 5:00a\n" \
21 L"vgafonts cab 18736 13-04-15 5:00a\n" \
22 L"setuplog txt 313 13-04-15 5:00a\n" \
23 L"win ini 7005 13-04-15 5:00a\n" ;
24
25
26 VOID
27 PaintConsole(LPDRAWITEMSTRUCT drawItem,
28 PCONSOLE_STATE_INFO pConInfo)
29 {
30 HBRUSH hBrush;
31 RECT cRect, fRect;
32 DWORD startx, starty;
33 DWORD endx, endy;
34 DWORD sizex, sizey;
35
36 FillRect(drawItem->hDC, &drawItem->rcItem, GetSysColorBrush(COLOR_BACKGROUND));
37
38 // FIXME: Use: SM_CXSIZE, SM_CYSIZE, SM_CXVSCROLL, SM_CYHSCROLL, SM_CXMIN, SM_CYMIN, SM_CXFRAME, SM_CYFRAME
39 /* Use it for scaling */
40 sizex = drawItem->rcItem.right - drawItem->rcItem.left;
41 sizey = drawItem->rcItem.bottom - drawItem->rcItem.top ;
42
43 if ( pConInfo->WindowPosition.x == MAXDWORD &&
44 pConInfo->WindowPosition.y == MAXDWORD )
45 {
46 startx = sizex / 3;
47 starty = sizey / 3;
48 }
49 else
50 {
51 // TODO:
52 // Calculate pos correctly when console centered
53 startx = pConInfo->WindowPosition.x;
54 starty = pConInfo->WindowPosition.y;
55 }
56
57 // TODO:
58 // Stretch console when bold fonts are selected
59 endx = startx + pConInfo->WindowSize.X; // drawItem->rcItem.right - startx + 15;
60 endy = starty + pConInfo->WindowSize.Y; // starty + sizey / 3;
61
62 /* Draw console size */
63 SetRect(&cRect, startx, starty, endx, endy);
64 FillRect(drawItem->hDC, &cRect, GetSysColorBrush(COLOR_WINDOWFRAME));
65
66 /* Draw console border */
67 SetRect(&fRect, startx + 1, starty + 1, cRect.right - 1, cRect.bottom - 1);
68 FrameRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_ACTIVEBORDER));
69
70 /* Draw left box */
71 SetRect(&fRect, startx + 3, starty + 3, startx + 5, starty + 5);
72 FillRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_ACTIVEBORDER));
73
74 /* Draw window title */
75 SetRect(&fRect, startx + 7, starty + 3, cRect.right - 9, starty + 5);
76 FillRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_ACTIVECAPTION));
77
78 /* Draw first right box */
79 SetRect(&fRect, fRect.right + 1, starty + 3, fRect.right + 3, starty + 5);
80 FillRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_ACTIVEBORDER));
81
82 /* Draw second right box */
83 SetRect(&fRect, fRect.right + 1, starty + 3, fRect.right + 3, starty + 5);
84 FillRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_ACTIVEBORDER));
85
86 /* Draw scrollbar */
87 SetRect(&fRect, cRect.right - 5, fRect.bottom + 1, cRect.right - 3, cRect.bottom - 3);
88 FillRect(drawItem->hDC, &fRect, GetSysColorBrush(COLOR_SCROLLBAR));
89
90 /* Draw console background */
91 hBrush = CreateSolidBrush(pConInfo->ColorTable[BkgdAttribFromAttrib(pConInfo->ScreenAttributes)]);
92 SetRect(&fRect, startx + 3, starty + 6, cRect.right - 6, cRect.bottom - 3);
93 FillRect(drawItem->hDC, &fRect, hBrush);
94 DeleteObject((HGDIOBJ)hBrush);
95 }
96
97 BOOL
98 PaintText(LPDRAWITEMSTRUCT drawItem,
99 PCONSOLE_STATE_INFO pConInfo,
100 TEXT_TYPE TextMode)
101 {
102 USHORT CurrentAttrib;
103 COLORREF pbkColor, ptColor;
104 COLORREF nbkColor, ntColor;
105 HBRUSH hBrush;
106 HFONT Font, OldFont;
107
108 COORD FontSize = pConInfo->FontSize;
109
110 if (TextMode == Screen)
111 CurrentAttrib = pConInfo->ScreenAttributes;
112 else if (TextMode == Popup)
113 CurrentAttrib = pConInfo->PopupAttributes;
114 else
115 return FALSE;
116
117 nbkColor = pConInfo->ColorTable[BkgdAttribFromAttrib(CurrentAttrib)];
118 ntColor = pConInfo->ColorTable[TextAttribFromAttrib(CurrentAttrib)];
119
120 hBrush = CreateSolidBrush(nbkColor);
121 if (!hBrush) return FALSE;
122
123 FontSize.Y = FontSize.Y > 0 ? -MulDiv(FontSize.Y, GetDeviceCaps(drawItem->hDC, LOGPIXELSY), 72)
124 : FontSize.Y;
125
126 Font = CreateFontW(FontSize.Y,
127 FontSize.X,
128 0,
129 TA_BASELINE,
130 pConInfo->FontWeight,
131 FALSE,
132 FALSE,
133 FALSE,
134 OEM_CHARSET,
135 OUT_DEFAULT_PRECIS,
136 CLIP_DEFAULT_PRECIS,
137 DEFAULT_QUALITY,
138 FIXED_PITCH | pConInfo->FontFamily,
139 pConInfo->FaceName);
140 if (Font == NULL)
141 {
142 DPRINT1("PaintText: CreateFont failed\n");
143 return FALSE;
144 }
145
146 OldFont = SelectObject(drawItem->hDC, Font);
147 if (OldFont == NULL)
148 {
149 DeleteObject(Font);
150 return FALSE;
151 }
152
153 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
154
155 ptColor = SetTextColor(drawItem->hDC, ntColor);
156 pbkColor = SetBkColor(drawItem->hDC, nbkColor);
157 DrawTextW(drawItem->hDC, szPreviewText, wcslen(szPreviewText), &drawItem->rcItem, 0);
158 SetTextColor(drawItem->hDC, ptColor);
159 SetBkColor(drawItem->hDC, pbkColor);
160 DeleteObject(hBrush);
161
162 SelectObject(drawItem->hDC, OldFont);
163 DeleteObject(Font);
164
165 return TRUE;
166 }
167
168 INT_PTR
169 CALLBACK
170 LayoutProc(HWND hwndDlg,
171 UINT uMsg,
172 WPARAM wParam,
173 LPARAM lParam)
174 {
175 UNREFERENCED_PARAMETER(hwndDlg);
176 UNREFERENCED_PARAMETER(wParam);
177
178 switch (uMsg)
179 {
180 case WM_INITDIALOG:
181 {
182 /* Multi-monitor support */
183 LONG xVirtScr, yVirtScr; // Coordinates of the top-left virtual screen
184 LONG cxVirtScr, cyVirtScr; // Width and Height of the virtual screen
185 LONG cxFrame , cyFrame ; // Thickness of the window frame
186
187 /* Multi-monitor support */
188 xVirtScr = GetSystemMetrics(SM_XVIRTUALSCREEN);
189 yVirtScr = GetSystemMetrics(SM_YVIRTUALSCREEN);
190 cxVirtScr = GetSystemMetrics(SM_CXVIRTUALSCREEN);
191 cyVirtScr = GetSystemMetrics(SM_CYVIRTUALSCREEN);
192 cxFrame = GetSystemMetrics(SM_CXFRAME);
193 cyFrame = GetSystemMetrics(SM_CYFRAME);
194
195 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_SCREEN_BUFFER_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
196 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_SCREEN_BUFFER_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
197 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_SIZE_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
198 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_SIZE_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
199
200 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, ConInfo->ScreenBufferSize.Y, FALSE);
201 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH , ConInfo->ScreenBufferSize.X, FALSE);
202 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, ConInfo->WindowSize.Y, FALSE);
203 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , ConInfo->WindowSize.X, FALSE);
204
205 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, UDM_SETRANGE, 0,
206 (LPARAM)MAKELONG(xVirtScr + cxVirtScr - cxFrame, xVirtScr - cxFrame));
207 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , UDM_SETRANGE, 0,
208 (LPARAM)MAKELONG(yVirtScr + cyVirtScr - cyFrame, yVirtScr - cyFrame));
209
210 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, ConInfo->WindowPosition.x, TRUE);
211 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , ConInfo->WindowPosition.y, TRUE);
212
213 if (ConInfo->AutoPosition)
214 {
215 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
216 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
217 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
218 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
219 }
220 CheckDlgButton(hwndDlg, IDC_CHECK_SYSTEM_POS_WINDOW,
221 ConInfo->AutoPosition ? BST_CHECKED : BST_UNCHECKED);
222
223 return TRUE;
224 }
225
226 case WM_DRAWITEM:
227 {
228 PaintConsole((LPDRAWITEMSTRUCT)lParam, ConInfo);
229 return TRUE;
230 }
231
232 case WM_NOTIFY:
233 {
234 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lParam;
235 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
236
237 if (lppsn->hdr.code == UDN_DELTAPOS)
238 {
239 DWORD wheight, wwidth;
240 DWORD sheight, swidth;
241 DWORD left, top;
242
243 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH)
244 {
245 wwidth = lpnmud->iPos + lpnmud->iDelta;
246 }
247 else
248 {
249 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
250 }
251
252 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
253 {
254 wheight = lpnmud->iPos + lpnmud->iDelta;
255 }
256 else
257 {
258 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, NULL, FALSE);
259 }
260
261 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH)
262 {
263 swidth = lpnmud->iPos + lpnmud->iDelta;
264 }
265 else
266 {
267 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
268 }
269
270 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
271 {
272 sheight = lpnmud->iPos + lpnmud->iDelta;
273 }
274 else
275 {
276 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
277 }
278
279 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_LEFT)
280 {
281 left = lpnmud->iPos + lpnmud->iDelta;
282 }
283 else
284 {
285 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
286 }
287
288 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_TOP)
289 {
290 top = lpnmud->iPos + lpnmud->iDelta;
291 }
292 else
293 {
294 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, TRUE);
295 }
296
297 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
298 {
299 /* Automatically adjust screen buffer size when window size enlarges */
300 if (wwidth >= swidth)
301 {
302 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, wwidth, TRUE);
303 swidth = wwidth;
304 }
305 if (wheight >= sheight)
306 {
307 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, wheight, TRUE);
308 sheight = wheight;
309 }
310 }
311
312 /* Be sure that the (new) screen buffer sizes are in the correct range */
313 swidth = min(max(swidth , 1), 0xFFFF);
314 sheight = min(max(sheight, 1), 0xFFFF);
315
316 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
317 {
318 /* Automatically adjust window size when screen buffer decreases */
319 if (wwidth > swidth)
320 {
321 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, swidth, TRUE);
322 wwidth = swidth;
323 }
324 if (wheight > sheight)
325 {
326 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, sheight, TRUE);
327 wheight = sheight;
328 }
329 }
330
331 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
332 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
333 ConInfo->WindowSize.X = (SHORT)wwidth;
334 ConInfo->WindowSize.Y = (SHORT)wheight;
335 ConInfo->WindowPosition.x = left;
336 ConInfo->WindowPosition.y = top;
337 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
338 }
339 break;
340 }
341
342 case WM_COMMAND:
343 {
344 switch (LOWORD(wParam))
345 {
346 case IDC_EDIT_SCREEN_BUFFER_WIDTH:
347 {
348 if (HIWORD(wParam) == EN_KILLFOCUS)
349 {
350 DWORD swidth, wwidth;
351
352 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
353 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
354
355 /* Be sure that the (new) screen buffer width is in the correct range */
356 swidth = min(max(swidth, 1), 0xFFFF);
357
358 /* Automatically adjust window size when screen buffer decreases */
359 if (wwidth > swidth)
360 {
361 wwidth = swidth;
362 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, wwidth, TRUE);
363 }
364
365 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
366 ConInfo->WindowSize.X = (SHORT)wwidth;
367 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
368 }
369 break;
370 }
371
372 case IDC_EDIT_WINDOW_SIZE_WIDTH:
373 {
374 if (HIWORD(wParam) == EN_KILLFOCUS)
375 {
376 DWORD swidth, wwidth;
377
378 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
379 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
380
381 /* Automatically adjust screen buffer size when window size enlarges */
382 if (wwidth >= swidth)
383 {
384 swidth = wwidth;
385
386 /* Be sure that the (new) screen buffer width is in the correct range */
387 swidth = min(max(swidth, 1), 0xFFFF);
388
389 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, swidth, TRUE);
390 }
391
392 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
393 ConInfo->WindowSize.X = (SHORT)wwidth;
394 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
395 }
396 break;
397 }
398
399 case IDC_EDIT_SCREEN_BUFFER_HEIGHT:
400 {
401 if (HIWORD(wParam) == EN_KILLFOCUS)
402 {
403 DWORD sheight, wheight;
404
405 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
406 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
407
408 /* Be sure that the (new) screen buffer width is in the correct range */
409 sheight = min(max(sheight, 1), 0xFFFF);
410
411 /* Automatically adjust window size when screen buffer decreases */
412 if (wheight > sheight)
413 {
414 wheight = sheight;
415 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, wheight, TRUE);
416 }
417
418 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
419 ConInfo->WindowSize.Y = (SHORT)wheight;
420 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
421 }
422 break;
423 }
424
425 case IDC_EDIT_WINDOW_SIZE_HEIGHT:
426 {
427 if (HIWORD(wParam) == EN_KILLFOCUS)
428 {
429 DWORD sheight, wheight;
430
431 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
432 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
433
434 /* Automatically adjust screen buffer size when window size enlarges */
435 if (wheight >= sheight)
436 {
437 sheight = wheight;
438
439 /* Be sure that the (new) screen buffer width is in the correct range */
440 sheight = min(max(sheight, 1), 0xFFFF);
441
442 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, sheight, TRUE);
443 }
444
445 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
446 ConInfo->WindowSize.Y = (SHORT)wheight;
447 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
448 }
449 break;
450 }
451
452 case IDC_EDIT_WINDOW_POS_LEFT:
453 case IDC_EDIT_WINDOW_POS_TOP:
454 {
455 if (HIWORD(wParam) == EN_KILLFOCUS)
456 {
457 DWORD left, top;
458
459 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
460 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
461
462 ConInfo->WindowPosition.x = left;
463 ConInfo->WindowPosition.y = top;
464 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
465 }
466 break;
467 }
468
469 case IDC_CHECK_SYSTEM_POS_WINDOW:
470 {
471 LONG res = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0);
472 if (res == BST_CHECKED)
473 {
474 ULONG left, top;
475
476 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
477 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
478
479 ConInfo->AutoPosition = FALSE;
480 ConInfo->WindowPosition.x = left;
481 ConInfo->WindowPosition.y = top;
482 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
483
484 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
485 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, TRUE);
486 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , TRUE);
487 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, TRUE);
488 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , TRUE);
489 }
490 else if (res == BST_UNCHECKED)
491 {
492 ConInfo->AutoPosition = TRUE;
493 // Do not touch ConInfo->WindowPosition !!
494 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
495
496 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
497 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
498 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
499 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
500 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
501 }
502 }
503 }
504 }
505
506 default:
507 break;
508 }
509
510 return FALSE;
511 }