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
;
33 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
38 #define PM_CREATE_CONSOLE (WM_APP + 1)
39 #define PM_DESTROY_CONSOLE (WM_APP + 2)
41 #define CURSOR_BLINK_TIME 500
43 static BOOL ConsInitialized
= FALSE
;
44 static HWND NotifyWnd
;
46 /* FUNCTIONS *****************************************************************/
49 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
51 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
52 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
56 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
59 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
60 PGUI_CONSOLE_DATA GuiData
;
65 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
66 sizeof(GUI_CONSOLE_DATA
) +
67 (Console
->Size
.X
+ 1) * sizeof(WCHAR
));
70 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
74 InitializeCriticalSection(&GuiData
->Lock
);
76 GuiData
->LineBuffer
= (PWCHAR
)(GuiData
+ 1);
78 GuiData
->Font
= CreateFontW(12, 0, 0, TA_BASELINE
, FW_NORMAL
,
79 FALSE
, FALSE
, FALSE
, OEM_CHARSET
,
80 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
81 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
82 L
"Bitstream Vera Sans Mono");
83 if (NULL
== GuiData
->Font
)
85 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
86 DeleteCriticalSection(&GuiData
->Lock
);
87 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
93 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
94 DeleteObject(GuiData
->Font
);
95 DeleteCriticalSection(&GuiData
->Lock
);
96 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
99 OldFont
= SelectObject(Dc
, GuiData
->Font
);
102 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
104 DeleteObject(GuiData
->Font
);
105 DeleteCriticalSection(&GuiData
->Lock
);
106 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
109 if (! GetTextMetricsW(Dc
, &Metrics
))
111 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
112 SelectObject(Dc
, OldFont
);
114 DeleteObject(GuiData
->Font
);
115 DeleteCriticalSection(&GuiData
->Lock
);
116 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
119 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
120 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
121 SelectObject(Dc
, OldFont
);
124 GuiData
->CursorBlinkOn
= TRUE
;
125 GuiData
->ForceCursorOff
= FALSE
;
127 GuiData
->Selection
.left
= -1;
129 Console
->PrivateData
= GuiData
;
130 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
132 GetWindowRect(hWnd
, &Rect
);
133 Rect
.right
= Rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+
134 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
135 Rect
.bottom
= Rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+
136 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
137 MoveWindow(hWnd
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
138 Rect
.bottom
- Rect
.top
, FALSE
);
140 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
142 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
145 static COLORREF FASTCALL
146 GuiConsoleRGBFromAttribute(BYTE Attribute
)
148 int Red
= (Attribute
& 0x04 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
149 int Green
= (Attribute
& 0x02 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
150 int Blue
= (Attribute
& 0x01 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
152 return RGB(Red
, Green
, Blue
);
156 GuiConsoleSetTextColors(HDC Dc
, BYTE Attribute
)
158 SetTextColor(Dc
, GuiConsoleRGBFromAttribute(Attribute
& 0x0f));
159 SetBkColor(Dc
, GuiConsoleRGBFromAttribute((Attribute
& 0xf0) >> 4));
163 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff
, ULONG
*CursorX
, ULONG
*CursorY
)
165 *CursorX
= Buff
->CurrentX
;
166 if (Buff
->CurrentY
< Buff
->ShowY
)
168 *CursorY
= Buff
->MaxY
- Buff
->ShowY
+ Buff
->CurrentY
;
172 *CursorY
= Buff
->CurrentY
- Buff
->ShowY
;
178 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
180 RECT oldRect
= GuiData
->Selection
;
184 RECT changeRect
= *rc
;
186 GuiData
->Selection
= *rc
;
188 changeRect
.left
*= GuiData
->CharWidth
;
189 changeRect
.top
*= GuiData
->CharHeight
;
190 changeRect
.right
*= GuiData
->CharWidth
;
191 changeRect
.bottom
*= GuiData
->CharHeight
;
193 if(rc
->left
!= oldRect
.left
||
194 rc
->top
!= oldRect
.top
||
195 rc
->right
!= oldRect
.right
||
196 rc
->bottom
!= oldRect
.bottom
)
198 if(oldRect
.left
!= -1)
202 oldRect
.left
*= GuiData
->CharWidth
;
203 oldRect
.top
*= GuiData
->CharHeight
;
204 oldRect
.right
*= GuiData
->CharWidth
;
205 oldRect
.bottom
*= GuiData
->CharHeight
;
207 /* calculate the region that needs to be updated */
208 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
210 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
212 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
214 InvalidateRgn(hWnd
, rgn1
, FALSE
);
224 InvalidateRect(hWnd
, &changeRect
, FALSE
);
228 else if(oldRect
.left
!= -1)
230 /* clear the selection */
231 GuiData
->Selection
.left
= -1;
232 oldRect
.left
*= GuiData
->CharWidth
;
233 oldRect
.top
*= GuiData
->CharHeight
;
234 oldRect
.right
*= GuiData
->CharWidth
;
235 oldRect
.bottom
*= GuiData
->CharHeight
;
236 InvalidateRect(hWnd
, &oldRect
, FALSE
);
242 GuiConsolePaint(PCSRSS_CONSOLE Console
,
243 PGUI_CONSOLE_DATA GuiData
,
247 PCSRSS_SCREEN_BUFFER Buff
;
248 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
249 ULONG Line
, Char
, Start
;
252 BYTE LastAttribute
, Attribute
;
253 ULONG CursorX
, CursorY
, CursorHeight
;
254 HBRUSH CursorBrush
, OldBrush
;
257 Buff
= Console
->ActiveBuffer
;
259 TopLine
= rc
->top
/ GuiData
->CharHeight
;
260 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1;
261 LeftChar
= rc
->left
/ GuiData
->CharWidth
;
262 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1;
263 LastAttribute
= Buff
->Buffer
[(TopLine
* Buff
->MaxX
+ LeftChar
) * 2 + 1];
265 GuiConsoleSetTextColors(hDC
,
268 EnterCriticalSection(&Buff
->Header
.Lock
);
270 OldFont
= SelectObject(hDC
,
273 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
275 if (Line
+ Buff
->ShowY
< Buff
->MaxY
)
277 From
= Buff
->Buffer
+ ((Line
+ Buff
->ShowY
) * Buff
->MaxX
+ LeftChar
) * 2;
281 From
= Buff
->Buffer
+
282 ((Line
- (Buff
->MaxY
- Buff
->ShowY
)) * Buff
->MaxX
+ LeftChar
) * 2;
285 To
= GuiData
->LineBuffer
;
287 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
289 if (*(From
+ 1) != LastAttribute
)
292 Start
* GuiData
->CharWidth
,
293 Line
* GuiData
->CharHeight
,
297 To
= GuiData
->LineBuffer
;
298 Attribute
= *(From
+ 1);
299 if (Attribute
!= LastAttribute
)
301 GuiConsoleSetTextColors(hDC
,
303 LastAttribute
= Attribute
;
307 MultiByteToWideChar(Console
->OutputCodePage
,
318 Start
* GuiData
->CharWidth
,
319 Line
* GuiData
->CharHeight
,
321 RightChar
- Start
+ 1);
324 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
325 !GuiData
->ForceCursorOff
)
327 GuiConsoleGetLogicalCursorPos(Buff
,
330 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
331 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
333 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
334 if (CursorHeight
< 1)
338 From
= Buff
->Buffer
+ (Buff
->CurrentY
* Buff
->MaxX
+ Buff
->CurrentX
) * 2 + 1;
339 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(*From
));
340 OldBrush
= SelectObject(hDC
,
343 CursorX
* GuiData
->CharWidth
,
344 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
350 DeleteObject(CursorBrush
);
354 LeaveCriticalSection(&Buff
->Header
.Lock
);
361 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
365 PCSRSS_CONSOLE Console
;
366 PGUI_CONSOLE_DATA GuiData
;
368 hDC
= BeginPaint(hWnd
, &ps
);
370 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
371 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
373 GuiConsoleGetDataPointers(hWnd
,
376 if (Console
!= NULL
&& GuiData
!= NULL
&&
377 Console
->ActiveBuffer
!= NULL
)
379 EnterCriticalSection(&GuiData
->Lock
);
381 GuiConsolePaint(Console
,
386 if (GuiData
->Selection
.left
!= -1)
388 RECT rc
= GuiData
->Selection
;
390 rc
.left
*= GuiData
->CharWidth
;
391 rc
.top
*= GuiData
->CharHeight
;
392 rc
.right
*= GuiData
->CharWidth
;
393 rc
.bottom
*= GuiData
->CharHeight
;
395 /* invert the selection */
396 if (IntersectRect(&rc
,
409 LeaveCriticalSection(&GuiData
->Lock
);
417 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
419 PCSRSS_CONSOLE Console
;
420 PGUI_CONSOLE_DATA GuiData
;
423 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
425 Message
.message
= msg
;
426 Message
.wParam
= wParam
;
427 Message
.lParam
= lParam
;
429 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
431 /* clear the selection */
432 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
435 ConioProcessKey(&Message
, Console
, FALSE
);
439 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
443 RegionRect
.left
= Region
->left
* GuiData
->CharWidth
;
444 RegionRect
.top
= Region
->top
* GuiData
->CharHeight
;
445 RegionRect
.right
= (Region
->right
+ 1) * GuiData
->CharWidth
;
446 RegionRect
.bottom
= (Region
->bottom
+ 1) * GuiData
->CharHeight
;
448 InvalidateRect(Wnd
, &RegionRect
, FALSE
);
452 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
454 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
456 if (NULL
!= Console
->hWindow
&& NULL
!= GuiData
)
458 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
463 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
472 GuiIntDrawRegion(GuiData
, Wnd
, &CellRect
);
476 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
477 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
479 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
480 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
481 LONG CursorEndX
, CursorEndY
;
484 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
489 if (0 != ScrolledLines
)
493 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
494 ScrollRect
.bottom
= Region
->top
* GuiData
->CharHeight
;
496 if (GuiData
->Selection
.left
!= -1)
498 /* scroll the selection */
499 if (GuiData
->Selection
.top
> ScrolledLines
)
501 GuiData
->Selection
.top
-= ScrolledLines
;
502 GuiData
->Selection
.bottom
-= ScrolledLines
;
504 else if (GuiData
->Selection
.bottom
< ScrolledLines
)
506 GuiData
->Selection
.left
= -1;
510 GuiData
->Selection
.top
= 0;
511 GuiData
->Selection
.bottom
-= ScrolledLines
;
515 ScrollWindowEx(Console
->hWindow
,
517 -(ScrolledLines
* GuiData
->CharHeight
),
525 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
527 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
528 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
530 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
533 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
534 &CursorEndX
, &CursorEndY
);
535 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
536 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
537 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
539 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
544 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
548 if (Console
->ActiveBuffer
== Buff
)
550 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
551 &UpdateRect
.left
, &UpdateRect
.top
);
552 UpdateRect
.right
= UpdateRect
.left
;
553 UpdateRect
.bottom
= UpdateRect
.top
;
554 ConioDrawRegion(Console
, &UpdateRect
);
561 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
565 if (Console
->ActiveBuffer
== Buff
)
567 /* Redraw char at old position (removes cursor) */
568 UpdateRect
.left
= OldCursorX
;
569 UpdateRect
.top
= OldCursorY
;
570 UpdateRect
.right
= OldCursorX
;
571 UpdateRect
.bottom
= OldCursorY
;
572 ConioDrawRegion(Console
, &UpdateRect
);
573 /* Redraw char at new position (shows cursor) */
574 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
575 &(UpdateRect
.left
), &(UpdateRect
.top
));
576 UpdateRect
.right
= UpdateRect
.left
;
577 UpdateRect
.bottom
= UpdateRect
.top
;
578 ConioDrawRegion(Console
, &UpdateRect
);
585 GuiConsoleHandleTimer(HWND hWnd
)
587 PCSRSS_CONSOLE Console
;
588 PGUI_CONSOLE_DATA GuiData
;
590 ULONG CursorX
, CursorY
;
592 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
593 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
595 GuiConsoleGetLogicalCursorPos(Console
->ActiveBuffer
, &CursorX
, &CursorY
);
596 CursorRect
.left
= CursorX
;
597 CursorRect
.top
= CursorY
;
598 CursorRect
.right
= CursorX
;
599 CursorRect
.bottom
= CursorY
;
600 GuiDrawRegion(Console
, &CursorRect
);
604 GuiConsoleHandleClose(HWND hWnd
)
606 PCSRSS_CONSOLE Console
;
607 PGUI_CONSOLE_DATA GuiData
;
608 PLIST_ENTRY current_entry
;
609 PCSRSS_PROCESS_DATA current
;
611 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
613 EnterCriticalSection(&Console
->Header
.Lock
);
615 current_entry
= Console
->ProcessList
.Flink
;
616 while (current_entry
!= &Console
->ProcessList
)
618 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
619 current_entry
= current_entry
->Flink
;
621 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
624 LeaveCriticalSection(&Console
->Header
.Lock
);
628 GuiConsoleHandleNcDestroy(HWND hWnd
)
630 PCSRSS_CONSOLE Console
;
631 PGUI_CONSOLE_DATA GuiData
;
633 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
635 Console
->PrivateData
= NULL
;
636 DeleteCriticalSection(&GuiData
->Lock
);
637 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
641 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
643 PCSRSS_CONSOLE Console
;
644 PGUI_CONSOLE_DATA GuiData
;
648 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
649 if (Console
== NULL
|| GuiData
== NULL
) return;
651 pt
= MAKEPOINTS(lParam
);
653 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
654 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
655 rc
.right
= rc
.left
+ 1;
656 rc
.bottom
= rc
.top
+ 1;
658 GuiData
->SelectionStart
.x
= rc
.left
;
659 GuiData
->SelectionStart
.y
= rc
.top
;
663 GuiData
->MouseDown
= TRUE
;
665 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
669 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
671 PCSRSS_CONSOLE Console
;
672 PGUI_CONSOLE_DATA GuiData
;
676 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
677 if (Console
== NULL
|| GuiData
== NULL
) return;
678 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
680 pt
= MAKEPOINTS(lParam
);
682 rc
.left
= GuiData
->SelectionStart
.x
;
683 rc
.top
= GuiData
->SelectionStart
.y
;
684 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
685 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
687 /* exchange left/top with right/bottom if required */
688 if(rc
.left
>= rc
.right
)
692 rc
.left
= max(rc
.right
- 1, 0);
695 if(rc
.top
>= rc
.bottom
)
699 rc
.top
= max(rc
.bottom
- 1, 0);
703 GuiData
->MouseDown
= FALSE
;
705 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
711 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
713 PCSRSS_CONSOLE Console
;
714 PGUI_CONSOLE_DATA GuiData
;
718 if (!(wParam
& MK_LBUTTON
)) return;
720 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
721 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
723 pt
= MAKEPOINTS(lParam
);
725 rc
.left
= GuiData
->SelectionStart
.x
;
726 rc
.top
= GuiData
->SelectionStart
.y
;
727 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
728 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
730 /* exchange left/top with right/bottom if required */
731 if(rc
.left
>= rc
.right
)
735 rc
.left
= max(rc
.right
- 1, 0);
738 if(rc
.top
>= rc
.bottom
)
742 rc
.top
= max(rc
.bottom
- 1, 0);
746 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
750 GuiConsoleRightMouseDown(HWND hWnd
)
752 PCSRSS_CONSOLE Console
;
753 PGUI_CONSOLE_DATA GuiData
;
755 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
756 if (Console
== NULL
|| GuiData
== NULL
) return;
758 if (GuiData
->Selection
.left
== -1)
760 /* FIXME - paste text from clipboard */
764 /* FIXME - copy selection to clipboard */
766 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
771 static LRESULT CALLBACK
772 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
779 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
782 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
789 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
792 GuiConsoleHandleTimer(hWnd
);
795 GuiConsoleHandleClose(hWnd
);
798 GuiConsoleHandleNcDestroy(hWnd
);
801 GuiConsoleLeftMouseDown(hWnd
, lParam
);
804 GuiConsoleLeftMouseUp(hWnd
, lParam
);
807 GuiConsoleRightMouseDown(hWnd
);
810 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
813 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
820 static LRESULT CALLBACK
821 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
826 PWCHAR Buffer
, Title
;
827 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
832 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
834 case PM_CREATE_CONSOLE
:
835 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
836 Console
->Title
.Length
+ sizeof(WCHAR
));
839 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
840 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
847 NewWindow
= CreateWindowW(L
"ConsoleWindowClass",
849 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
,
856 (HINSTANCE
) GetModuleHandleW(NULL
),
860 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
862 Console
->hWindow
= NewWindow
;
863 if (NULL
!= NewWindow
)
865 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
866 ShowWindow(NewWindow
, SW_SHOW
);
868 return (LRESULT
) NewWindow
;
869 case PM_DESTROY_CONSOLE
:
870 /* Window creation is done using a PostMessage(), so it's possible that the
871 * window that we want to destroy doesn't exist yet. So first empty the message
873 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
875 TranslateMessage(&Msg
);
876 DispatchMessageW(&Msg
);
878 DestroyWindow(Console
->hWindow
);
879 Console
->hWindow
= NULL
;
880 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
882 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
883 if (0 == WindowCount
)
887 PrivateCsrssManualGuiCheck(-1);
892 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
897 GuiConsoleGuiThread(PVOID Data
)
900 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
902 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
911 (HINSTANCE
) GetModuleHandleW(NULL
),
913 if (NULL
== NotifyWnd
)
915 PrivateCsrssManualGuiCheck(-1);
916 SetEvent(*GraphicsStartupEvent
);
920 SetEvent(*GraphicsStartupEvent
);
922 while(GetMessageW(&msg
, NULL
, 0, 0))
924 TranslateMessage(&msg
);
925 DispatchMessageW(&msg
);
936 if (NULL
== NotifyWnd
)
938 PrivateCsrssManualGuiCheck(+1);
941 wc
.cbSize
= sizeof(WNDCLASSEXW
);
942 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
943 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
945 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
948 wc
.hbrBackground
= NULL
;
949 wc
.lpszMenuName
= NULL
;
953 if (RegisterClassExW(&wc
) == 0)
955 DPRINT1("Failed to register notify wndproc\n");
959 wc
.cbSize
= sizeof(WNDCLASSEXW
);
960 wc
.lpszClassName
= L
"ConsoleWindowClass";
961 wc
.lpfnWndProc
= GuiConsoleWndProc
;
963 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
964 wc
.hIcon
= LoadIconW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1));
965 wc
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
966 wc
.hbrBackground
= NULL
;
967 wc
.lpszMenuName
= NULL
;
970 wc
.hIconSm
= LoadImageW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1), IMAGE_ICON
,
971 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
973 if (RegisterClassExW(&wc
) == 0)
975 DPRINT1("Failed to register console wndproc\n");
983 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
985 Buffer
->DefaultAttrib
= 0x0f;
989 GuiChangeTitle(PCSRSS_CONSOLE Console
)
991 PWCHAR Buffer
, Title
;
993 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
994 Console
->Title
.Length
+ sizeof(WCHAR
));
997 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
998 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1005 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
1008 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1015 GuiChangeIcon(PCSRSS_CONSOLE Console
)
1017 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)Console
->hWindowIcon
);
1018 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Console
->hWindowIcon
);
1024 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
1026 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
1029 static CSRSS_CONSOLE_VTBL GuiVtbl
=
1031 GuiInitScreenBuffer
,
1042 GuiInitConsole(PCSRSS_CONSOLE Console
)
1044 HANDLE GraphicsStartupEvent
;
1045 HANDLE ThreadHandle
;
1047 if (! ConsInitialized
)
1049 ConsInitialized
= TRUE
;
1052 ConsInitialized
= FALSE
;
1053 return STATUS_UNSUCCESSFUL
;
1057 Console
->Vtbl
= &GuiVtbl
;
1058 Console
->Size
.X
= 80;
1059 Console
->Size
.Y
= 25;
1060 if (NULL
== NotifyWnd
)
1062 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1063 if (NULL
== GraphicsStartupEvent
)
1065 return STATUS_UNSUCCESSFUL
;
1068 ThreadHandle
= CreateThread(NULL
,
1070 GuiConsoleGuiThread
,
1071 (PVOID
) &GraphicsStartupEvent
,
1074 if (NULL
== ThreadHandle
)
1076 NtClose(GraphicsStartupEvent
);
1077 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
1078 return STATUS_UNSUCCESSFUL
;
1080 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
1081 CloseHandle(ThreadHandle
);
1083 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
1084 CloseHandle(GraphicsStartupEvent
);
1086 if (NULL
== NotifyWnd
)
1088 DPRINT1("Win32Csr: Failed to create notification window.\n");
1089 return STATUS_UNSUCCESSFUL
;
1093 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
1095 return STATUS_SUCCESS
;