[CONSOLE]
[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 DeleteObject(hBrush);
144 return FALSE;
145 }
146
147 OldFont = SelectObject(drawItem->hDC, Font);
148 if (OldFont == NULL)
149 {
150 DeleteObject(Font);
151 DeleteObject(hBrush);
152 return FALSE;
153 }
154
155 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
156
157 ptColor = SetTextColor(drawItem->hDC, ntColor);
158 pbkColor = SetBkColor(drawItem->hDC, nbkColor);
159 DrawTextW(drawItem->hDC, szPreviewText, wcslen(szPreviewText), &drawItem->rcItem, 0);
160 SetTextColor(drawItem->hDC, ptColor);
161 SetBkColor(drawItem->hDC, pbkColor);
162 DeleteObject(hBrush);
163
164 SelectObject(drawItem->hDC, OldFont);
165 DeleteObject(Font);
166
167 return TRUE;
168 }
169
170 INT_PTR
171 CALLBACK
172 LayoutProc(HWND hwndDlg,
173 UINT uMsg,
174 WPARAM wParam,
175 LPARAM lParam)
176 {
177 UNREFERENCED_PARAMETER(hwndDlg);
178 UNREFERENCED_PARAMETER(wParam);
179
180 switch (uMsg)
181 {
182 case WM_INITDIALOG:
183 {
184 /* Multi-monitor support */
185 LONG xVirtScr, yVirtScr; // Coordinates of the top-left virtual screen
186 LONG cxVirtScr, cyVirtScr; // Width and Height of the virtual screen
187 LONG cxFrame , cyFrame ; // Thickness of the window frame
188
189 /* Multi-monitor support */
190 xVirtScr = GetSystemMetrics(SM_XVIRTUALSCREEN);
191 yVirtScr = GetSystemMetrics(SM_YVIRTUALSCREEN);
192 cxVirtScr = GetSystemMetrics(SM_CXVIRTUALSCREEN);
193 cyVirtScr = GetSystemMetrics(SM_CYVIRTUALSCREEN);
194 cxFrame = GetSystemMetrics(SM_CXFRAME);
195 cyFrame = GetSystemMetrics(SM_CYFRAME);
196
197 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_SCREEN_BUFFER_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
198 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_SCREEN_BUFFER_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
199 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_SIZE_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
200 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_SIZE_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
201
202 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, ConInfo->ScreenBufferSize.Y, FALSE);
203 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH , ConInfo->ScreenBufferSize.X, FALSE);
204 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, ConInfo->WindowSize.Y, FALSE);
205 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , ConInfo->WindowSize.X, FALSE);
206
207 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, UDM_SETRANGE, 0,
208 (LPARAM)MAKELONG(xVirtScr + cxVirtScr - cxFrame, xVirtScr - cxFrame));
209 SendDlgItemMessageW(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , UDM_SETRANGE, 0,
210 (LPARAM)MAKELONG(yVirtScr + cyVirtScr - cyFrame, yVirtScr - cyFrame));
211
212 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, ConInfo->WindowPosition.x, TRUE);
213 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , ConInfo->WindowPosition.y, TRUE);
214
215 if (ConInfo->AutoPosition)
216 {
217 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
218 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
219 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
220 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
221 }
222 CheckDlgButton(hwndDlg, IDC_CHECK_SYSTEM_POS_WINDOW,
223 ConInfo->AutoPosition ? BST_CHECKED : BST_UNCHECKED);
224
225 return TRUE;
226 }
227
228 case WM_DRAWITEM:
229 {
230 PaintConsole((LPDRAWITEMSTRUCT)lParam, ConInfo);
231 return TRUE;
232 }
233
234 case WM_NOTIFY:
235 {
236 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lParam;
237 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
238
239 if (lppsn->hdr.code == UDN_DELTAPOS)
240 {
241 DWORD wheight, wwidth;
242 DWORD sheight, swidth;
243 DWORD left, top;
244
245 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH)
246 {
247 wwidth = lpnmud->iPos + lpnmud->iDelta;
248 }
249 else
250 {
251 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
252 }
253
254 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
255 {
256 wheight = lpnmud->iPos + lpnmud->iDelta;
257 }
258 else
259 {
260 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, NULL, FALSE);
261 }
262
263 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH)
264 {
265 swidth = lpnmud->iPos + lpnmud->iDelta;
266 }
267 else
268 {
269 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
270 }
271
272 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
273 {
274 sheight = lpnmud->iPos + lpnmud->iDelta;
275 }
276 else
277 {
278 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
279 }
280
281 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_LEFT)
282 {
283 left = lpnmud->iPos + lpnmud->iDelta;
284 }
285 else
286 {
287 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
288 }
289
290 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_TOP)
291 {
292 top = lpnmud->iPos + lpnmud->iDelta;
293 }
294 else
295 {
296 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, TRUE);
297 }
298
299 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
300 {
301 /* Automatically adjust screen buffer size when window size enlarges */
302 if (wwidth >= swidth)
303 {
304 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, wwidth, TRUE);
305 swidth = wwidth;
306 }
307 if (wheight >= sheight)
308 {
309 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, wheight, TRUE);
310 sheight = wheight;
311 }
312 }
313
314 /* Be sure that the (new) screen buffer sizes are in the correct range */
315 swidth = min(max(swidth , 1), 0xFFFF);
316 sheight = min(max(sheight, 1), 0xFFFF);
317
318 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
319 {
320 /* Automatically adjust window size when screen buffer decreases */
321 if (wwidth > swidth)
322 {
323 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, swidth, TRUE);
324 wwidth = swidth;
325 }
326 if (wheight > sheight)
327 {
328 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, sheight, TRUE);
329 wheight = sheight;
330 }
331 }
332
333 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
334 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
335 ConInfo->WindowSize.X = (SHORT)wwidth;
336 ConInfo->WindowSize.Y = (SHORT)wheight;
337 ConInfo->WindowPosition.x = left;
338 ConInfo->WindowPosition.y = top;
339 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
340 }
341 break;
342 }
343
344 case WM_COMMAND:
345 {
346 switch (LOWORD(wParam))
347 {
348 case IDC_EDIT_SCREEN_BUFFER_WIDTH:
349 {
350 if (HIWORD(wParam) == EN_KILLFOCUS)
351 {
352 DWORD swidth, wwidth;
353
354 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
355 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
356
357 /* Be sure that the (new) screen buffer width is in the correct range */
358 swidth = min(max(swidth, 1), 0xFFFF);
359
360 /* Automatically adjust window size when screen buffer decreases */
361 if (wwidth > swidth)
362 {
363 wwidth = swidth;
364 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, wwidth, TRUE);
365 }
366
367 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
368 ConInfo->WindowSize.X = (SHORT)wwidth;
369 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
370 }
371 break;
372 }
373
374 case IDC_EDIT_WINDOW_SIZE_WIDTH:
375 {
376 if (HIWORD(wParam) == EN_KILLFOCUS)
377 {
378 DWORD swidth, wwidth;
379
380 swidth = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
381 wwidth = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
382
383 /* Automatically adjust screen buffer size when window size enlarges */
384 if (wwidth >= swidth)
385 {
386 swidth = wwidth;
387
388 /* Be sure that the (new) screen buffer width is in the correct range */
389 swidth = min(max(swidth, 1), 0xFFFF);
390
391 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, swidth, TRUE);
392 }
393
394 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
395 ConInfo->WindowSize.X = (SHORT)wwidth;
396 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
397 }
398 break;
399 }
400
401 case IDC_EDIT_SCREEN_BUFFER_HEIGHT:
402 {
403 if (HIWORD(wParam) == EN_KILLFOCUS)
404 {
405 DWORD sheight, wheight;
406
407 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
408 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
409
410 /* Be sure that the (new) screen buffer width is in the correct range */
411 sheight = min(max(sheight, 1), 0xFFFF);
412
413 /* Automatically adjust window size when screen buffer decreases */
414 if (wheight > sheight)
415 {
416 wheight = sheight;
417 SetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, wheight, TRUE);
418 }
419
420 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
421 ConInfo->WindowSize.Y = (SHORT)wheight;
422 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
423 }
424 break;
425 }
426
427 case IDC_EDIT_WINDOW_SIZE_HEIGHT:
428 {
429 if (HIWORD(wParam) == EN_KILLFOCUS)
430 {
431 DWORD sheight, wheight;
432
433 sheight = GetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
434 wheight = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
435
436 /* Automatically adjust screen buffer size when window size enlarges */
437 if (wheight >= sheight)
438 {
439 sheight = wheight;
440
441 /* Be sure that the (new) screen buffer width is in the correct range */
442 sheight = min(max(sheight, 1), 0xFFFF);
443
444 SetDlgItemInt(hwndDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, sheight, TRUE);
445 }
446
447 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
448 ConInfo->WindowSize.Y = (SHORT)wheight;
449 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
450 }
451 break;
452 }
453
454 case IDC_EDIT_WINDOW_POS_LEFT:
455 case IDC_EDIT_WINDOW_POS_TOP:
456 {
457 if (HIWORD(wParam) == EN_KILLFOCUS)
458 {
459 DWORD left, top;
460
461 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
462 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
463
464 ConInfo->WindowPosition.x = left;
465 ConInfo->WindowPosition.y = top;
466 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
467 }
468 break;
469 }
470
471 case IDC_CHECK_SYSTEM_POS_WINDOW:
472 {
473 LONG res = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0);
474 if (res == BST_CHECKED)
475 {
476 ULONG left, top;
477
478 left = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
479 top = GetDlgItemInt(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
480
481 ConInfo->AutoPosition = FALSE;
482 ConInfo->WindowPosition.x = left;
483 ConInfo->WindowPosition.y = top;
484 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
485
486 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
487 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, TRUE);
488 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , TRUE);
489 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, TRUE);
490 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , TRUE);
491 }
492 else if (res == BST_UNCHECKED)
493 {
494 ConInfo->AutoPosition = TRUE;
495 // Do not touch ConInfo->WindowPosition !!
496 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
497
498 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
499 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
500 EnableDlgItem(hwndDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
501 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
502 EnableDlgItem(hwndDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
503 }
504 }
505 }
506 }
507
508 default:
509 break;
510 }
511
512 return FALSE;
513 }