3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: subsys/csrss/win32csr/guiconsole.c
6 * PURPOSE: Implementation of gui-mode consoles
9 /* INCLUDES ******************************************************************/
16 /* Not defined in any header file */
17 extern VOID STDCALL
PrivateCsrssManualGuiCheck(LONG Check
);
19 /* GLOBALS *******************************************************************/
21 typedef struct GUI_CONSOLE_DATA_TAG
29 CRITICAL_SECTION Lock
;
35 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
40 #define PM_CREATE_CONSOLE (WM_APP + 1)
41 #define PM_DESTROY_CONSOLE (WM_APP + 2)
43 #define CURSOR_BLINK_TIME 500
45 static BOOL ConsInitialized
= FALSE
;
46 static HWND NotifyWnd
;
48 /* FUNCTIONS *****************************************************************/
51 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
53 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
54 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
58 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
61 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
62 PGUI_CONSOLE_DATA GuiData
;
67 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
68 sizeof(GUI_CONSOLE_DATA
) +
69 (Console
->Size
.X
+ 1) * sizeof(WCHAR
));
72 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
76 InitializeCriticalSection(&GuiData
->Lock
);
78 GuiData
->LineBuffer
= (PWCHAR
)(GuiData
+ 1);
80 GuiData
->Font
= CreateFontW(12, 0, 0, TA_BASELINE
, FW_NORMAL
,
81 FALSE
, FALSE
, FALSE
, OEM_CHARSET
,
82 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
83 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
84 L
"Bitstream Vera Sans Mono");
85 if (NULL
== GuiData
->Font
)
87 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
88 DeleteCriticalSection(&GuiData
->Lock
);
89 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
95 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
96 DeleteObject(GuiData
->Font
);
97 DeleteCriticalSection(&GuiData
->Lock
);
98 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
101 OldFont
= SelectObject(Dc
, GuiData
->Font
);
104 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
106 DeleteObject(GuiData
->Font
);
107 DeleteCriticalSection(&GuiData
->Lock
);
108 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
111 if (! GetTextMetricsW(Dc
, &Metrics
))
113 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
114 SelectObject(Dc
, OldFont
);
116 DeleteObject(GuiData
->Font
);
117 DeleteCriticalSection(&GuiData
->Lock
);
118 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
121 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
122 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
123 SelectObject(Dc
, OldFont
);
125 GuiData
->MemoryDC
= CreateCompatibleDC(Dc
);
126 GuiData
->MemoryBitmap
= CreateCompatibleBitmap(Dc
,
127 Console
->Size
.X
* GuiData
->CharWidth
,
128 Console
->Size
.Y
* GuiData
->CharHeight
);
129 /* NOTE: Don't delete the "first bitmap", it's done in DeleteDC. */
130 SelectObject(GuiData
->MemoryDC
, GuiData
->MemoryBitmap
);
131 /* NOTE: Don't delete stock font. */
132 SelectObject(GuiData
->MemoryDC
, GuiData
->Font
);
135 GuiData
->CursorBlinkOn
= TRUE
;
136 GuiData
->ForceCursorOff
= FALSE
;
138 GuiData
->Selection
.left
= -1;
140 Console
->PrivateData
= GuiData
;
141 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
143 GetWindowRect(hWnd
, &Rect
);
144 Rect
.right
= Rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+
145 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
146 Rect
.bottom
= Rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+
147 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
148 MoveWindow(hWnd
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
149 Rect
.bottom
- Rect
.top
, FALSE
);
151 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
153 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
156 static COLORREF FASTCALL
157 GuiConsoleRGBFromAttribute(BYTE Attribute
)
159 int Red
= (Attribute
& 0x04 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
160 int Green
= (Attribute
& 0x02 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
161 int Blue
= (Attribute
& 0x01 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
163 return RGB(Red
, Green
, Blue
);
167 GuiConsoleSetTextColors(HDC Dc
, BYTE Attribute
)
169 SetTextColor(Dc
, GuiConsoleRGBFromAttribute(Attribute
& 0x0f));
170 SetBkColor(Dc
, GuiConsoleRGBFromAttribute((Attribute
& 0xf0) >> 4));
174 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff
, ULONG
*CursorX
, ULONG
*CursorY
)
176 *CursorX
= Buff
->CurrentX
;
177 if (Buff
->CurrentY
< Buff
->ShowY
)
179 *CursorY
= Buff
->MaxY
- Buff
->ShowY
+ Buff
->CurrentY
;
183 *CursorY
= Buff
->CurrentY
- Buff
->ShowY
;
189 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
191 RECT oldRect
= GuiData
->Selection
;
195 RECT changeRect
= *rc
;
197 GuiData
->Selection
= *rc
;
199 changeRect
.left
*= GuiData
->CharWidth
;
200 changeRect
.top
*= GuiData
->CharHeight
;
201 changeRect
.right
*= GuiData
->CharWidth
;
202 changeRect
.bottom
*= GuiData
->CharHeight
;
204 if(rc
->left
!= oldRect
.left
||
205 rc
->top
!= oldRect
.top
||
206 rc
->right
!= oldRect
.right
||
207 rc
->bottom
!= oldRect
.bottom
)
209 if(oldRect
.left
!= -1)
213 oldRect
.left
*= GuiData
->CharWidth
;
214 oldRect
.top
*= GuiData
->CharHeight
;
215 oldRect
.right
*= GuiData
->CharWidth
;
216 oldRect
.bottom
*= GuiData
->CharHeight
;
218 /* calculate the region that needs to be updated */
219 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
221 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
223 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
225 InvalidateRgn(hWnd
, rgn1
, FALSE
);
235 InvalidateRect(hWnd
, &changeRect
, FALSE
);
239 else if(oldRect
.left
!= -1)
241 /* clear the selection */
242 GuiData
->Selection
.left
= -1;
243 oldRect
.left
*= GuiData
->CharWidth
;
244 oldRect
.top
*= GuiData
->CharHeight
;
245 oldRect
.right
*= GuiData
->CharWidth
;
246 oldRect
.bottom
*= GuiData
->CharHeight
;
247 InvalidateRect(hWnd
, &oldRect
, FALSE
);
253 GuiConsoleUpdateBitmap(HWND hWnd
, RECT rc
)
255 PCSRSS_CONSOLE Console
;
256 PGUI_CONSOLE_DATA GuiData
;
257 PCSRSS_SCREEN_BUFFER Buff
;
259 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
260 ULONG Line
, Char
, Start
;
263 BYTE LastAttribute
, Attribute
;
264 ULONG CursorX
, CursorY
, CursorHeight
;
265 HBRUSH CursorBrush
, OldBrush
;
267 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
268 if (NULL
!= Console
&& NULL
!= GuiData
&& NULL
!= Console
->ActiveBuffer
)
270 Buff
= Console
->ActiveBuffer
;
271 EnterCriticalSection(&Buff
->Header
.Lock
);
273 if (rc
.right
<= rc
.left
|| rc
.bottom
<= rc
.top
)
276 LeaveCriticalSection(&Buff
->Header
.Lock
);
280 EnterCriticalSection(&GuiData
->Lock
);
282 TopLine
= rc
.top
/ GuiData
->CharHeight
;
283 BottomLine
= (rc
.bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1;
284 LeftChar
= rc
.left
/ GuiData
->CharWidth
;
285 RightChar
= (rc
.right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1;
286 LastAttribute
= Buff
->Buffer
[(TopLine
* Buff
->MaxX
+ LeftChar
) * 2 + 1];
287 GuiConsoleSetTextColors(GuiData
->MemoryDC
, LastAttribute
);
289 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
291 if (Line
+ Buff
->ShowY
< Buff
->MaxY
)
293 From
= Buff
->Buffer
+ ((Line
+ Buff
->ShowY
) * Buff
->MaxX
+ LeftChar
) * 2;
297 From
= Buff
->Buffer
+
298 ((Line
- (Buff
->MaxY
- Buff
->ShowY
)) * Buff
->MaxX
+ LeftChar
) * 2;
301 To
= GuiData
->LineBuffer
;
302 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
304 if (*(From
+ 1) != LastAttribute
)
306 TextOutW(GuiData
->MemoryDC
, Start
* GuiData
->CharWidth
, Line
* GuiData
->CharHeight
,
307 GuiData
->LineBuffer
, Char
- Start
);
309 To
= GuiData
->LineBuffer
;
310 Attribute
= *(From
+ 1);
311 if (Attribute
!= LastAttribute
)
313 GuiConsoleSetTextColors(GuiData
->MemoryDC
, Attribute
);
314 LastAttribute
= Attribute
;
317 MultiByteToWideChar(Console
->OutputCodePage
, 0, (PCHAR
)From
, 1, To
, 1);
321 TextOutW(GuiData
->MemoryDC
, Start
* GuiData
->CharWidth
, Line
* GuiData
->CharHeight
,
322 GuiData
->LineBuffer
, RightChar
- Start
+ 1);
325 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
326 &&! GuiData
->ForceCursorOff
)
328 GuiConsoleGetLogicalCursorPos(Buff
, &CursorX
, &CursorY
);
329 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
330 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
332 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
333 if (CursorHeight
< 1)
337 From
= Buff
->Buffer
+ (Buff
->CurrentY
* Buff
->MaxX
+ Buff
->CurrentX
) * 2 + 1;
338 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(*From
));
339 OldBrush
= SelectObject(GuiData
->MemoryDC
, CursorBrush
);
340 PatBlt(GuiData
->MemoryDC
, CursorX
* GuiData
->CharWidth
,
341 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
342 GuiData
->CharWidth
, CursorHeight
, PATCOPY
);
343 SelectObject(GuiData
->MemoryDC
, OldBrush
);
344 DeleteObject(CursorBrush
);
348 LeaveCriticalSection(&GuiData
->Lock
);
350 LeaveCriticalSection(&Buff
->Header
.Lock
);
351 InvalidateRect(hWnd
, &rc
, FALSE
);
356 GuiConsoleHandlePaint(HWND hWnd
)
360 PCSRSS_CONSOLE Console
;
361 PGUI_CONSOLE_DATA GuiData
;
363 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
364 if (NULL
!= Console
&& NULL
!= GuiData
)
366 EnterCriticalSection(&GuiData
->Lock
);
367 Dc
= BeginPaint (hWnd
, &Ps
);
368 BitBlt(Dc
, Ps
.rcPaint
.left
, Ps
.rcPaint
.top
,
369 Ps
.rcPaint
.right
- Ps
.rcPaint
.left
+ 1,
370 Ps
.rcPaint
.bottom
- Ps
.rcPaint
.top
+ 1, GuiData
->MemoryDC
,
371 Ps
.rcPaint
.left
, Ps
.rcPaint
.top
, SRCCOPY
);
373 if (GuiData
->Selection
.left
!= -1)
375 RECT rc
= GuiData
->Selection
;
377 rc
.left
*= GuiData
->CharWidth
;
378 rc
.top
*= GuiData
->CharHeight
;
379 rc
.right
*= GuiData
->CharWidth
;
380 rc
.bottom
*= GuiData
->CharHeight
;
382 if (IntersectRect(&rc
, &Ps
.rcPaint
, &rc
))
384 PatBlt(Dc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, DSTINVERT
);
388 EndPaint (hWnd
, &Ps
);
389 LeaveCriticalSection(&GuiData
->Lock
);
393 Dc
= BeginPaint (hWnd
, &Ps
);
394 EndPaint (hWnd
, &Ps
);
399 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
401 PCSRSS_CONSOLE Console
;
402 PGUI_CONSOLE_DATA GuiData
;
405 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
407 Message
.message
= msg
;
408 Message
.wParam
= wParam
;
409 Message
.lParam
= lParam
;
411 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
413 /* clear the selection */
414 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
417 ConioProcessKey(&Message
, Console
, FALSE
);
421 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
425 RegionRect
.left
= Region
->left
* GuiData
->CharWidth
;
426 RegionRect
.top
= Region
->top
* GuiData
->CharHeight
;
427 RegionRect
.right
= (Region
->right
+ 1) * GuiData
->CharWidth
;
428 RegionRect
.bottom
= (Region
->bottom
+ 1) * GuiData
->CharHeight
;
430 GuiConsoleUpdateBitmap(Wnd
, RegionRect
);
434 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
436 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
438 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
443 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
447 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
456 GuiIntDrawRegion(GuiData
, Wnd
, &CellRect
);
460 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
461 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
463 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
464 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
465 LONG CursorEndX
, CursorEndY
;
468 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
473 if (0 != ScrolledLines
)
476 Source
.top
= ScrolledLines
;
477 Source
.right
= Console
->Size
.X
- 1;
478 Source
.bottom
= ScrolledLines
+ Region
->top
- 1;
481 Dest
.right
= Console
->Size
.X
- 1;
482 Dest
.bottom
= Region
->top
- 1;
484 GuiConsoleCopyRegion(Console
->hWindow
, &Source
, &Dest
);
487 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
489 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
490 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
492 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
495 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
496 &CursorEndX
, &CursorEndY
);
497 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
498 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
499 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
501 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
506 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
510 if (Console
->ActiveBuffer
== Buff
)
512 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
513 &UpdateRect
.left
, &UpdateRect
.top
);
514 UpdateRect
.right
= UpdateRect
.left
;
515 UpdateRect
.bottom
= UpdateRect
.top
;
516 ConioDrawRegion(Console
, &UpdateRect
);
523 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
527 if (Console
->ActiveBuffer
== Buff
)
529 /* Redraw char at old position (removes cursor) */
530 UpdateRect
.left
= OldCursorX
;
531 UpdateRect
.top
= OldCursorY
;
532 UpdateRect
.right
= OldCursorX
;
533 UpdateRect
.bottom
= OldCursorY
;
534 ConioDrawRegion(Console
, &UpdateRect
);
535 /* Redraw char at new position (shows cursor) */
536 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
537 &(UpdateRect
.left
), &(UpdateRect
.top
));
538 UpdateRect
.right
= UpdateRect
.left
;
539 UpdateRect
.bottom
= UpdateRect
.top
;
540 ConioDrawRegion(Console
, &UpdateRect
);
547 GuiConsoleHandleTimer(HWND hWnd
)
549 PCSRSS_CONSOLE Console
;
550 PGUI_CONSOLE_DATA GuiData
;
552 ULONG CursorX
, CursorY
;
554 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
555 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
557 GuiConsoleGetLogicalCursorPos(Console
->ActiveBuffer
, &CursorX
, &CursorY
);
558 CursorRect
.left
= CursorX
;
559 CursorRect
.top
= CursorY
;
560 CursorRect
.right
= CursorX
;
561 CursorRect
.bottom
= CursorY
;
562 GuiDrawRegion(Console
, &CursorRect
);
566 GuiConsoleHandleClose(HWND hWnd
)
568 PCSRSS_CONSOLE Console
;
569 PGUI_CONSOLE_DATA GuiData
;
570 PLIST_ENTRY current_entry
;
571 PCSRSS_PROCESS_DATA current
;
573 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
575 EnterCriticalSection(&Console
->Header
.Lock
);
577 current_entry
= Console
->ProcessList
.Flink
;
578 while (current_entry
!= &Console
->ProcessList
)
580 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
581 current_entry
= current_entry
->Flink
;
583 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
586 LeaveCriticalSection(&Console
->Header
.Lock
);
590 GuiConsoleHandleNcDestroy(HWND hWnd
)
592 PCSRSS_CONSOLE Console
;
593 PGUI_CONSOLE_DATA GuiData
;
595 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
597 Console
->PrivateData
= NULL
;
598 DeleteDC(GuiData
->MemoryDC
);
599 DeleteCriticalSection(&GuiData
->Lock
);
600 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
604 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
606 PCSRSS_CONSOLE Console
;
607 PGUI_CONSOLE_DATA GuiData
;
611 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
612 if (Console
== NULL
|| GuiData
== NULL
) return;
614 pt
= MAKEPOINTS(lParam
);
616 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
617 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
618 rc
.right
= rc
.left
+ 1;
619 rc
.bottom
= rc
.top
+ 1;
621 GuiData
->SelectionStart
.x
= rc
.left
;
622 GuiData
->SelectionStart
.y
= rc
.top
;
626 GuiData
->MouseDown
= TRUE
;
628 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
632 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
634 PCSRSS_CONSOLE Console
;
635 PGUI_CONSOLE_DATA GuiData
;
639 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
640 if (Console
== NULL
|| GuiData
== NULL
) return;
641 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
643 pt
= MAKEPOINTS(lParam
);
645 rc
.left
= GuiData
->SelectionStart
.x
;
646 rc
.top
= GuiData
->SelectionStart
.y
;
647 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
648 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
650 /* exchange left/top with right/bottom if required */
651 if(rc
.left
>= rc
.right
)
655 rc
.left
= max(rc
.right
- 1, 0);
658 if(rc
.top
>= rc
.bottom
)
662 rc
.top
= max(rc
.bottom
- 1, 0);
666 GuiData
->MouseDown
= FALSE
;
668 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
674 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
676 PCSRSS_CONSOLE Console
;
677 PGUI_CONSOLE_DATA GuiData
;
681 if (!(wParam
& MK_LBUTTON
)) return;
683 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
684 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
686 pt
= MAKEPOINTS(lParam
);
688 rc
.left
= GuiData
->SelectionStart
.x
;
689 rc
.top
= GuiData
->SelectionStart
.y
;
690 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
691 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
693 /* exchange left/top with right/bottom if required */
694 if(rc
.left
>= rc
.right
)
698 rc
.left
= max(rc
.right
- 1, 0);
701 if(rc
.top
>= rc
.bottom
)
705 rc
.top
= max(rc
.bottom
- 1, 0);
709 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
713 GuiConsoleRightMouseDown(HWND hWnd
)
715 PCSRSS_CONSOLE Console
;
716 PGUI_CONSOLE_DATA GuiData
;
718 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
719 if (Console
== NULL
|| GuiData
== NULL
) return;
721 if (GuiData
->Selection
.left
== -1)
723 /* FIXME - paste text from clipboard */
727 /* FIXME - copy selection to clipboard */
729 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
734 static LRESULT CALLBACK
735 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
742 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
745 GuiConsoleHandlePaint(hWnd
);
752 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
755 GuiConsoleHandleTimer(hWnd
);
758 GuiConsoleHandleClose(hWnd
);
761 GuiConsoleHandleNcDestroy(hWnd
);
764 GuiConsoleLeftMouseDown(hWnd
, lParam
);
767 GuiConsoleLeftMouseUp(hWnd
, lParam
);
770 GuiConsoleRightMouseDown(hWnd
);
773 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
776 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
783 static LRESULT CALLBACK
784 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
789 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
794 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
796 case PM_CREATE_CONSOLE
:
797 NewWindow
= CreateWindowW(L
"ConsoleWindowClass",
798 Console
->Title
.Buffer
,
799 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
,
806 (HINSTANCE
) GetModuleHandleW(NULL
),
808 Console
->hWindow
= NewWindow
;
809 if (NULL
!= NewWindow
)
811 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
812 ShowWindow(NewWindow
, SW_SHOW
);
814 return (LRESULT
) NewWindow
;
815 case PM_DESTROY_CONSOLE
:
816 /* Window creation is done using a PostMessage(), so it's possible that the
817 * window that we want to destroy doesn't exist yet. So first empty the message
819 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
821 TranslateMessage(&Msg
);
822 DispatchMessageW(&Msg
);
824 DestroyWindow(Console
->hWindow
);
825 Console
->hWindow
= NULL
;
826 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
828 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
829 if (0 == WindowCount
)
833 PrivateCsrssManualGuiCheck(-1);
838 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
843 GuiConsoleGuiThread(PVOID Data
)
846 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
848 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
857 (HINSTANCE
) GetModuleHandleW(NULL
),
859 if (NULL
== NotifyWnd
)
861 PrivateCsrssManualGuiCheck(-1);
862 SetEvent(*GraphicsStartupEvent
);
866 SetEvent(*GraphicsStartupEvent
);
868 while(GetMessageW(&msg
, NULL
, 0, 0))
870 TranslateMessage(&msg
);
871 DispatchMessageW(&msg
);
882 if (NULL
== NotifyWnd
)
884 PrivateCsrssManualGuiCheck(+1);
887 wc
.cbSize
= sizeof(WNDCLASSEXW
);
888 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
889 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
891 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
894 wc
.hbrBackground
= NULL
;
895 wc
.lpszMenuName
= NULL
;
899 if (RegisterClassExW(&wc
) == 0)
901 DPRINT1("Failed to register notify wndproc\n");
905 wc
.cbSize
= sizeof(WNDCLASSEXW
);
906 wc
.lpszClassName
= L
"ConsoleWindowClass";
907 wc
.lpfnWndProc
= GuiConsoleWndProc
;
909 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
910 wc
.hIcon
= LoadIconW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1));
911 wc
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
912 wc
.hbrBackground
= NULL
;
913 wc
.lpszMenuName
= NULL
;
916 wc
.hIconSm
= LoadImageW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1), IMAGE_ICON
,
917 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
919 if (RegisterClassExW(&wc
) == 0)
921 DPRINT1("Failed to register console wndproc\n");
929 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
931 Buffer
->DefaultAttrib
= 0x0f;
935 GuiChangeTitle(PCSRSS_CONSOLE Console
)
937 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Console
->Title
.Buffer
);
943 GuiChangeIcon(PCSRSS_CONSOLE Console
)
945 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)Console
->hWindowIcon
);
946 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Console
->hWindowIcon
);
952 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
954 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
957 static CSRSS_CONSOLE_VTBL GuiVtbl
=
970 GuiInitConsole(PCSRSS_CONSOLE Console
)
972 HANDLE GraphicsStartupEvent
;
975 if (! ConsInitialized
)
977 ConsInitialized
= TRUE
;
980 ConsInitialized
= FALSE
;
981 return STATUS_UNSUCCESSFUL
;
985 Console
->Vtbl
= &GuiVtbl
;
986 Console
->Size
.X
= 80;
987 Console
->Size
.Y
= 25;
988 if (NULL
== NotifyWnd
)
990 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
991 if (NULL
== GraphicsStartupEvent
)
993 return STATUS_UNSUCCESSFUL
;
996 ThreadHandle
= CreateThread(NULL
,
999 (PVOID
) &GraphicsStartupEvent
,
1002 if (NULL
== ThreadHandle
)
1004 NtClose(GraphicsStartupEvent
);
1005 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
1006 return STATUS_UNSUCCESSFUL
;
1008 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
1009 CloseHandle(ThreadHandle
);
1011 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
1012 CloseHandle(GraphicsStartupEvent
);
1014 if (NULL
== NotifyWnd
)
1016 DPRINT1("Win32Csr: Failed to create notification window.\n");
1017 return STATUS_UNSUCCESSFUL
;
1021 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
1023 return STATUS_SUCCESS
;
1027 GuiConsoleCopyRegion(HWND hWnd
,
1032 PGUI_CONSOLE_DATA GuiData
;
1033 PCSRSS_CONSOLE Console
;
1036 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1038 ScrollRect
.left
= Dest
->left
* GuiData
->CharWidth
;
1039 ScrollRect
.right
= (Dest
->right
+ 1) * GuiData
->CharWidth
;
1040 ScrollRect
.top
= Dest
->top
* GuiData
->CharHeight
;
1041 ScrollRect
.bottom
= (Dest
->bottom
+ 1) * GuiData
->CharHeight
;
1042 EnterCriticalSection(&GuiData
->Lock
);
1043 BitBlt(GuiData
->MemoryDC
, ScrollRect
.left
, ScrollRect
.top
,
1044 ScrollRect
.right
- ScrollRect
.left
, ScrollRect
.bottom
- ScrollRect
.top
,
1045 GuiData
->MemoryDC
, Source
->left
* GuiData
->CharWidth
, Source
->top
* GuiData
->CharHeight
, SRCCOPY
);
1047 LeaveCriticalSection(&GuiData
->Lock
);
1049 InvalidateRect(hWnd
, &ScrollRect
, FALSE
);