1 /* $Id: guiconsole.c,v 1.18 2004/07/29 13:54:45 weiden Exp $
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 ******************************************************************/
13 #include "guiconsole.h"
19 /* Not defined in any header file */
20 extern VOID STDCALL
PrivateCsrssManualGuiCheck(LONG Check
);
22 /* GLOBALS *******************************************************************/
24 typedef struct GUI_CONSOLE_DATA_TAG
32 CRITICAL_SECTION Lock
;
38 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
43 #define PM_CREATE_CONSOLE (WM_APP + 1)
44 #define PM_DESTROY_CONSOLE (WM_APP + 2)
46 #define CURSOR_BLINK_TIME 500
48 static BOOL Initialized
= FALSE
;
49 static HWND NotifyWnd
;
51 /* FUNCTIONS *****************************************************************/
54 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
56 *Console
= (PCSRSS_CONSOLE
) GetWindowLongW(hWnd
, GWL_USERDATA
);
57 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
61 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
64 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
65 PGUI_CONSOLE_DATA GuiData
;
70 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
71 sizeof(GUI_CONSOLE_DATA
) +
72 (Console
->Size
.X
+ 1) * sizeof(WCHAR
));
75 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
79 InitializeCriticalSection(&GuiData
->Lock
);
81 GuiData
->LineBuffer
= (PWCHAR
)(GuiData
+ 1);
83 GuiData
->Font
= CreateFontW(12, 0, 0, TA_BASELINE
, FW_NORMAL
,
84 FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
85 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
86 DEFAULT_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
87 L
"Bitstream Vera Sans Mono");
88 if (NULL
== GuiData
->Font
)
90 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
91 DeleteCriticalSection(&GuiData
->Lock
);
92 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
98 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
99 DeleteObject(GuiData
->Font
);
100 DeleteCriticalSection(&GuiData
->Lock
);
101 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
104 OldFont
= SelectObject(Dc
, GuiData
->Font
);
107 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
109 DeleteObject(GuiData
->Font
);
110 DeleteCriticalSection(&GuiData
->Lock
);
111 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
114 if (! GetTextMetricsW(Dc
, &Metrics
))
116 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
117 SelectObject(Dc
, OldFont
);
119 DeleteObject(GuiData
->Font
);
120 DeleteCriticalSection(&GuiData
->Lock
);
121 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
124 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
125 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
126 SelectObject(Dc
, OldFont
);
128 GuiData
->MemoryDC
= CreateCompatibleDC(Dc
);
129 GuiData
->MemoryBitmap
= CreateCompatibleBitmap(Dc
,
130 Console
->Size
.X
* GuiData
->CharWidth
,
131 Console
->Size
.Y
* GuiData
->CharHeight
);
132 DeleteObject(SelectObject(GuiData
->MemoryDC
, GuiData
->MemoryBitmap
));
133 DeleteObject(SelectObject(GuiData
->MemoryDC
, GuiData
->Font
));
137 GuiData
->CursorBlinkOn
= TRUE
;
138 GuiData
->ForceCursorOff
= FALSE
;
140 GuiData
->Selection
.left
= -1;
142 Console
->PrivateData
= GuiData
;
143 SetWindowLongW(hWnd
, GWL_USERDATA
, (LONG
) Console
);
145 GetWindowRect(hWnd
, &Rect
);
146 Rect
.right
= Rect
.left
+ Console
->Size
.X
* GuiData
->CharWidth
+
147 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
148 Rect
.bottom
= Rect
.top
+ Console
->Size
.Y
* GuiData
->CharHeight
+
149 2 * GetSystemMetrics(SM_CYFIXEDFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
150 MoveWindow(hWnd
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
151 Rect
.bottom
- Rect
.top
, FALSE
);
153 SetTimer(hWnd
, 1, CURSOR_BLINK_TIME
, NULL
);
155 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
158 static COLORREF FASTCALL
159 GuiConsoleRGBFromAttribute(BYTE Attribute
)
161 int Red
= (Attribute
& 0x04 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
162 int Green
= (Attribute
& 0x02 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
163 int Blue
= (Attribute
& 0x01 ? (Attribute
& 0x08 ? 0xff : 0x80) : 0x00);
165 return RGB(Red
, Green
, Blue
);
169 GuiConsoleSetTextColors(HDC Dc
, BYTE Attribute
)
171 SetTextColor(Dc
, GuiConsoleRGBFromAttribute(Attribute
& 0x0f));
172 SetBkColor(Dc
, GuiConsoleRGBFromAttribute((Attribute
& 0xf0) >> 4));
176 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff
, ULONG
*CursorX
, ULONG
*CursorY
)
178 *CursorX
= Buff
->CurrentX
;
179 if (Buff
->CurrentY
< Buff
->ShowY
)
181 *CursorY
= Buff
->MaxY
- Buff
->ShowY
+ Buff
->CurrentY
;
185 *CursorY
= Buff
->CurrentY
- Buff
->ShowY
;
191 GuiConsoleUpdateSelection(HWND hWnd
, PRECT rc
, PGUI_CONSOLE_DATA GuiData
)
193 RECT oldRect
= GuiData
->Selection
;
197 RECT changeRect
= *rc
;
199 GuiData
->Selection
= *rc
;
201 changeRect
.left
*= GuiData
->CharWidth
;
202 changeRect
.top
*= GuiData
->CharHeight
;
203 changeRect
.right
*= GuiData
->CharWidth
;
204 changeRect
.bottom
*= GuiData
->CharHeight
;
206 if(rc
->left
!= oldRect
.left
||
207 rc
->top
!= oldRect
.top
||
208 rc
->right
!= oldRect
.right
||
209 rc
->bottom
!= oldRect
.bottom
)
211 if(oldRect
.left
!= -1)
215 oldRect
.left
*= GuiData
->CharWidth
;
216 oldRect
.top
*= GuiData
->CharHeight
;
217 oldRect
.right
*= GuiData
->CharWidth
;
218 oldRect
.bottom
*= GuiData
->CharHeight
;
220 /* calculate the region that needs to be updated */
221 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
223 if((rgn2
= CreateRectRgnIndirect(&changeRect
)))
225 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
227 InvalidateRgn(hWnd
, rgn1
, FALSE
);
237 InvalidateRect(hWnd
, &changeRect
, FALSE
);
241 else if(oldRect
.left
!= -1)
243 /* clear the selection */
244 GuiData
->Selection
.left
= -1;
245 oldRect
.left
*= GuiData
->CharWidth
;
246 oldRect
.top
*= GuiData
->CharHeight
;
247 oldRect
.right
*= GuiData
->CharWidth
;
248 oldRect
.bottom
*= GuiData
->CharHeight
;
249 InvalidateRect(hWnd
, &oldRect
, FALSE
);
255 GuiConsoleUpdateBitmap(HWND hWnd
, RECT rc
)
257 PCSRSS_CONSOLE Console
;
258 PGUI_CONSOLE_DATA GuiData
;
259 PCSRSS_SCREEN_BUFFER Buff
;
261 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
262 ULONG Line
, Char
, Start
;
265 BYTE LastAttribute
, Attribute
;
266 ULONG CursorX
, CursorY
, CursorHeight
;
267 HBRUSH CursorBrush
, OldBrush
;
269 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
270 if (NULL
!= Console
&& NULL
!= GuiData
&& NULL
!= Console
->ActiveBuffer
)
272 Buff
= Console
->ActiveBuffer
;
273 EnterCriticalSection(&Buff
->Header
.Lock
);
275 if (rc
.right
<= rc
.left
|| rc
.bottom
<= rc
.top
)
278 LeaveCriticalSection(&Buff
->Header
.Lock
);
282 EnterCriticalSection(&GuiData
->Lock
);
284 TopLine
= rc
.top
/ GuiData
->CharHeight
;
285 BottomLine
= (rc
.bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1;
286 LeftChar
= rc
.left
/ GuiData
->CharWidth
;
287 RightChar
= (rc
.right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1;
288 LastAttribute
= Buff
->Buffer
[(TopLine
* Buff
->MaxX
+ LeftChar
) * 2 + 1];
289 GuiConsoleSetTextColors(GuiData
->MemoryDC
, LastAttribute
);
291 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
293 if (Line
+ Buff
->ShowY
< Buff
->MaxY
)
295 From
= Buff
->Buffer
+ ((Line
+ Buff
->ShowY
) * Buff
->MaxX
+ LeftChar
) * 2;
299 From
= Buff
->Buffer
+
300 ((Line
- (Buff
->MaxY
- Buff
->ShowY
)) * Buff
->MaxX
+ LeftChar
) * 2;
303 To
= GuiData
->LineBuffer
;
304 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
306 if (*(From
+ 1) != LastAttribute
)
308 TextOutW(GuiData
->MemoryDC
, Start
* GuiData
->CharWidth
, Line
* GuiData
->CharHeight
,
309 GuiData
->LineBuffer
, Char
- Start
);
311 To
= GuiData
->LineBuffer
;
312 Attribute
= *(From
+ 1);
313 if (Attribute
!= LastAttribute
)
315 GuiConsoleSetTextColors(GuiData
->MemoryDC
, Attribute
);
316 LastAttribute
= Attribute
;
319 *((PBYTE
) To
) = *From
;
320 *(((PBYTE
) To
) + 1) = '\0';
324 TextOutW(GuiData
->MemoryDC
, Start
* GuiData
->CharWidth
, Line
* GuiData
->CharHeight
,
325 GuiData
->LineBuffer
, RightChar
- Start
+ 1);
328 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
329 &&! GuiData
->ForceCursorOff
)
331 GuiConsoleGetLogicalCursorPos(Buff
, &CursorX
, &CursorY
);
332 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
333 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
335 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
336 if (CursorHeight
< 1)
340 From
= Buff
->Buffer
+ (Buff
->CurrentY
* Buff
->MaxX
+ Buff
->CurrentX
) * 2 + 1;
341 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(*From
));
342 OldBrush
= SelectObject(GuiData
->MemoryDC
, CursorBrush
);
343 PatBlt(GuiData
->MemoryDC
, CursorX
* GuiData
->CharWidth
,
344 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
345 GuiData
->CharWidth
, CursorHeight
, PATCOPY
);
346 SelectObject(GuiData
->MemoryDC
, OldBrush
);
347 DeleteObject(CursorBrush
);
351 LeaveCriticalSection(&GuiData
->Lock
);
353 LeaveCriticalSection(&Buff
->Header
.Lock
);
354 InvalidateRect(hWnd
, &rc
, FALSE
);
360 GuiConsoleHandlePaint(HWND hWnd
)
364 PCSRSS_CONSOLE Console
;
365 PGUI_CONSOLE_DATA GuiData
;
367 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
368 if (NULL
!= Console
&& NULL
!= GuiData
)
370 EnterCriticalSection(&GuiData
->Lock
);
371 Dc
= BeginPaint (hWnd
, &Ps
);
372 BitBlt(Dc
, Ps
.rcPaint
.left
, Ps
.rcPaint
.top
,
373 Ps
.rcPaint
.right
- Ps
.rcPaint
.left
+ 1,
374 Ps
.rcPaint
.bottom
- Ps
.rcPaint
.top
+ 1, GuiData
->MemoryDC
,
375 Ps
.rcPaint
.left
, Ps
.rcPaint
.top
, SRCCOPY
);
377 if (GuiData
->Selection
.left
!= -1)
379 RECT rc
= GuiData
->Selection
;
381 rc
.left
*= GuiData
->CharWidth
;
382 rc
.top
*= GuiData
->CharHeight
;
383 rc
.right
*= GuiData
->CharWidth
;
384 rc
.bottom
*= GuiData
->CharHeight
;
386 if (IntersectRect(&rc
, &Ps
.rcPaint
, &rc
))
388 PatBlt(Dc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, DSTINVERT
);
392 EndPaint (hWnd
, &Ps
);
393 LeaveCriticalSection(&GuiData
->Lock
);
397 Dc
= BeginPaint (hWnd
, &Ps
);
398 EndPaint (hWnd
, &Ps
);
403 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
405 PCSRSS_CONSOLE Console
;
406 PGUI_CONSOLE_DATA GuiData
;
409 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
411 Message
.message
= msg
;
412 Message
.wParam
= wParam
;
413 Message
.lParam
= lParam
;
415 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
417 /* clear the selection */
418 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
421 ConioProcessKey(&Message
, Console
, FALSE
);
425 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, RECT
*Region
)
429 RegionRect
.left
= Region
->left
* GuiData
->CharWidth
;
430 RegionRect
.top
= Region
->top
* GuiData
->CharHeight
;
431 RegionRect
.right
= (Region
->right
+ 1) * GuiData
->CharWidth
;
432 RegionRect
.bottom
= (Region
->bottom
+ 1) * GuiData
->CharHeight
;
434 GuiConsoleUpdateBitmap(Wnd
, RegionRect
);
438 GuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
440 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
442 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
447 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
451 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData
, HWND Wnd
, UINT x
, UINT y
)
460 GuiIntDrawRegion(GuiData
, Wnd
, &CellRect
);
464 GuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, UINT CursorStartX
, UINT CursorStartY
,
465 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
467 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
468 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
469 LONG CursorEndX
, CursorEndY
;
472 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
477 if (0 != ScrolledLines
)
480 Source
.top
= ScrolledLines
;
481 Source
.right
= Console
->Size
.X
- 1;
482 Source
.bottom
= ScrolledLines
+ Region
->top
- 1;
485 Dest
.right
= Console
->Size
.X
- 1;
486 Dest
.bottom
= Region
->top
- 1;
488 GuiConsoleCopyRegion(Console
->hWindow
, &Source
, &Dest
);
491 GuiIntDrawRegion(GuiData
, Console
->hWindow
, Region
);
493 if (CursorStartX
< Region
->left
|| Region
->right
< CursorStartX
494 || CursorStartY
< Region
->top
|| Region
->bottom
< CursorStartY
)
496 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorStartX
, CursorStartY
);
499 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
500 &CursorEndX
, &CursorEndY
);
501 if ((CursorEndX
< Region
->left
|| Region
->right
< CursorEndX
502 || CursorEndY
< Region
->top
|| Region
->bottom
< CursorEndY
)
503 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
505 GuiInvalidateCell(GuiData
, Console
->hWindow
, CursorEndX
, CursorEndY
);
510 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
514 if (Console
->ActiveBuffer
== Buff
)
516 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
517 &UpdateRect
.left
, &UpdateRect
.top
);
518 UpdateRect
.right
= UpdateRect
.left
;
519 UpdateRect
.bottom
= UpdateRect
.top
;
520 ConioDrawRegion(Console
, &UpdateRect
);
527 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
531 if (Console
->ActiveBuffer
== Buff
)
533 /* Redraw char at old position (removes cursor) */
534 UpdateRect
.left
= OldCursorX
;
535 UpdateRect
.top
= OldCursorY
;
536 UpdateRect
.right
= OldCursorX
;
537 UpdateRect
.bottom
= OldCursorY
;
538 ConioDrawRegion(Console
, &UpdateRect
);
539 /* Redraw char at new position (shows cursor) */
540 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
,
541 &(UpdateRect
.left
), &(UpdateRect
.top
));
542 UpdateRect
.right
= UpdateRect
.left
;
543 UpdateRect
.bottom
= UpdateRect
.top
;
544 ConioDrawRegion(Console
, &UpdateRect
);
551 GuiConsoleHandleTimer(HWND hWnd
)
553 PCSRSS_CONSOLE Console
;
554 PGUI_CONSOLE_DATA GuiData
;
556 ULONG CursorX
, CursorY
;
558 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
559 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
561 GuiConsoleGetLogicalCursorPos(Console
->ActiveBuffer
, &CursorX
, &CursorY
);
562 CursorRect
.left
= CursorX
;
563 CursorRect
.top
= CursorY
;
564 CursorRect
.right
= CursorX
;
565 CursorRect
.bottom
= CursorY
;
566 GuiDrawRegion(Console
, &CursorRect
);
570 GuiConsoleHandleClose(HWND hWnd
)
572 PCSRSS_CONSOLE Console
;
573 PGUI_CONSOLE_DATA GuiData
;
574 PLIST_ENTRY current_entry
;
575 PCSRSS_PROCESS_DATA current
;
579 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
581 EnterCriticalSection(&Console
->Header
.Lock
);
583 current_entry
= Console
->ProcessList
.Flink
;
584 while (current_entry
!= &Console
->ProcessList
)
586 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
587 current_entry
= current_entry
->Flink
;
589 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, current
->ProcessId
);
592 DPRINT1("Failed for handle duplication\n");
595 Result
= TerminateProcess(Process
, 0);
596 CloseHandle(Process
);
599 DPRINT1("Failed to terminate process %d\n", current
->ProcessId
);
603 LeaveCriticalSection(&Console
->Header
.Lock
);
607 GuiConsoleHandleNcDestroy(HWND hWnd
)
609 PCSRSS_CONSOLE Console
;
610 PGUI_CONSOLE_DATA GuiData
;
612 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
614 Console
->PrivateData
= NULL
;
615 DeleteDC(GuiData
->MemoryDC
);
616 DeleteCriticalSection(&GuiData
->Lock
);
617 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
621 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
623 PCSRSS_CONSOLE Console
;
624 PGUI_CONSOLE_DATA GuiData
;
628 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
629 if (Console
== NULL
|| GuiData
== NULL
) return;
631 pt
= MAKEPOINTS(lParam
);
633 rc
.left
= pt
.x
/ GuiData
->CharWidth
;
634 rc
.top
= pt
.y
/ GuiData
->CharHeight
;
635 rc
.right
= rc
.left
+ 1;
636 rc
.bottom
= rc
.top
+ 1;
638 GuiData
->SelectionStart
.x
= rc
.left
;
639 GuiData
->SelectionStart
.y
= rc
.top
;
643 GuiData
->MouseDown
= TRUE
;
645 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
649 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
651 PCSRSS_CONSOLE Console
;
652 PGUI_CONSOLE_DATA GuiData
;
656 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
657 if (Console
== NULL
|| GuiData
== NULL
) return;
658 if (GuiData
->Selection
.left
== -1 || !GuiData
->MouseDown
) return;
660 pt
= MAKEPOINTS(lParam
);
662 rc
.left
= GuiData
->SelectionStart
.x
;
663 rc
.top
= GuiData
->SelectionStart
.y
;
664 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
665 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
667 /* exchange left/top with right/bottom if required */
668 if(rc
.left
>= rc
.right
)
672 rc
.left
= max(rc
.right
- 1, 0);
675 if(rc
.top
>= rc
.bottom
)
679 rc
.top
= max(rc
.bottom
- 1, 0);
683 GuiData
->MouseDown
= FALSE
;
685 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
691 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
693 PCSRSS_CONSOLE Console
;
694 PGUI_CONSOLE_DATA GuiData
;
698 if (!(wParam
& MK_LBUTTON
)) return;
700 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
701 if (Console
== NULL
|| GuiData
== NULL
|| !GuiData
->MouseDown
) return;
703 pt
= MAKEPOINTS(lParam
);
705 rc
.left
= GuiData
->SelectionStart
.x
;
706 rc
.top
= GuiData
->SelectionStart
.y
;
707 rc
.right
= (pt
.x
>= 0 ? (pt
.x
/ GuiData
->CharWidth
) + 1 : 0);
708 rc
.bottom
= (pt
.y
>= 0 ? (pt
.y
/ GuiData
->CharHeight
) + 1 : 0);
710 /* exchange left/top with right/bottom if required */
711 if(rc
.left
>= rc
.right
)
715 rc
.left
= max(rc
.right
- 1, 0);
718 if(rc
.top
>= rc
.bottom
)
722 rc
.top
= max(rc
.bottom
- 1, 0);
726 GuiConsoleUpdateSelection(hWnd
, &rc
, GuiData
);
730 GuiConsoleRightMouseDown(HWND hWnd
)
732 PCSRSS_CONSOLE Console
;
733 PGUI_CONSOLE_DATA GuiData
;
735 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
736 if (Console
== NULL
|| GuiData
== NULL
) return;
738 if (GuiData
->Selection
.left
== -1)
740 /* FIXME - paste text from clipboard */
744 /* FIXME - copy selection to clipboard */
746 GuiConsoleUpdateSelection(hWnd
, NULL
, GuiData
);
751 static LRESULT CALLBACK
752 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
759 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
762 GuiConsoleHandlePaint(hWnd
);
770 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
774 GuiConsoleHandleTimer(hWnd
);
778 GuiConsoleHandleClose(hWnd
);
782 GuiConsoleHandleNcDestroy(hWnd
);
786 GuiConsoleLeftMouseDown(hWnd
, lParam
);
789 GuiConsoleLeftMouseUp(hWnd
, lParam
);
792 GuiConsoleRightMouseDown(hWnd
);
795 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
798 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
805 static LRESULT CALLBACK
806 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
810 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
815 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
817 case PM_CREATE_CONSOLE
:
818 NewWindow
= CreateWindowW(L
"Win32CsrConsole",
819 Console
->Title
.Buffer
,
820 WS_OVERLAPPED
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
,
827 (HINSTANCE
) GetModuleHandleW(NULL
),
829 Console
->hWindow
= NewWindow
;
830 if (NULL
!= NewWindow
)
832 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
833 ShowWindow(NewWindow
, SW_SHOW
);
835 return (LRESULT
) NewWindow
;
836 case PM_DESTROY_CONSOLE
:
837 DestroyWindow(Console
->hWindow
);
838 Console
->hWindow
= NULL
;
839 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
841 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
842 if (0 == WindowCount
)
846 PrivateCsrssManualGuiCheck(-1);
851 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
856 GuiConsoleGuiThread(PVOID Data
)
859 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
861 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
870 (HINSTANCE
) GetModuleHandleW(NULL
),
872 if (NULL
== NotifyWnd
)
874 PrivateCsrssManualGuiCheck(-1);
875 SetEvent(*GraphicsStartupEvent
);
879 SetEvent(*GraphicsStartupEvent
);
881 while(GetMessageW(&msg
, NULL
, 0, 0))
883 TranslateMessage(&msg
);
884 DispatchMessageW(&msg
);
897 Desktop
= OpenDesktopW(L
"Default", 0, FALSE
, GENERIC_ALL
);
900 DPRINT1("Failed to open desktop\n");
903 Status
= NtSetInformationProcess(NtCurrentProcess(),
907 if (!NT_SUCCESS(Status
))
909 DPRINT1("Cannot set default desktop.\n");
912 if (! SetThreadDesktop(Desktop
))
914 DPRINT1("Failed to set thread desktop\n");
918 if (NULL
== NotifyWnd
)
920 PrivateCsrssManualGuiCheck(+1);
923 wc
.cbSize
= sizeof(WNDCLASSEXW
);
924 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
925 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
927 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
930 wc
.hbrBackground
= NULL
;
931 wc
.lpszMenuName
= NULL
;
935 if (RegisterClassExW(&wc
) == 0)
937 DPRINT1("Failed to register notify wndproc\n");
941 wc
.cbSize
= sizeof(WNDCLASSEXW
);
942 wc
.lpszClassName
= L
"Win32CsrConsole";
943 wc
.lpfnWndProc
= GuiConsoleWndProc
;
945 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
946 wc
.hIcon
= LoadIconW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1));
947 wc
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
948 wc
.hbrBackground
= NULL
;
949 wc
.lpszMenuName
= NULL
;
952 wc
.hIconSm
= LoadImageW(Win32CsrDllHandle
, MAKEINTRESOURCEW(1), IMAGE_ICON
,
953 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
955 if (RegisterClassExW(&wc
) == 0)
957 DPRINT1("Failed to register console wndproc\n");
965 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
967 Buffer
->DefaultAttrib
= 0x0f;
971 GuiChangeTitle(PCSRSS_CONSOLE Console
)
973 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Console
->Title
.Buffer
);
979 GuiChangeIcon(PCSRSS_CONSOLE Console
)
981 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)Console
->hWindowIcon
);
982 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Console
->hWindowIcon
);
988 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
990 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
993 static CSRSS_CONSOLE_VTBL GuiVtbl
=
1006 GuiInitConsole(PCSRSS_CONSOLE Console
)
1008 HANDLE GraphicsStartupEvent
;
1009 HANDLE ThreadHandle
;
1016 Initialized
= FALSE
;
1017 return STATUS_UNSUCCESSFUL
;
1021 Console
->Vtbl
= &GuiVtbl
;
1022 Console
->Size
.X
= 80;
1023 Console
->Size
.Y
= 25;
1024 if (NULL
== NotifyWnd
)
1026 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1027 if (NULL
== GraphicsStartupEvent
)
1029 return STATUS_UNSUCCESSFUL
;
1032 ThreadHandle
= CreateThread(NULL
,
1034 GuiConsoleGuiThread
,
1035 (PVOID
) &GraphicsStartupEvent
,
1038 if (NULL
== ThreadHandle
)
1040 NtClose(GraphicsStartupEvent
);
1041 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
1042 return STATUS_UNSUCCESSFUL
;
1044 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
1045 CloseHandle(ThreadHandle
);
1047 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
1048 CloseHandle(GraphicsStartupEvent
);
1050 if (NULL
== NotifyWnd
)
1052 DPRINT1("Win32Csr: Failed to create notification window.\n");
1053 return STATUS_UNSUCCESSFUL
;
1057 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, 0, (LPARAM
) Console
);
1059 return STATUS_SUCCESS
;
1063 GuiConsoleCopyRegion(HWND hWnd
,
1068 PGUI_CONSOLE_DATA GuiData
;
1069 PCSRSS_CONSOLE Console
;
1072 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1074 ScrollRect
.left
= Dest
->left
* GuiData
->CharWidth
;
1075 ScrollRect
.right
= (Dest
->right
+ 1) * GuiData
->CharWidth
;
1076 ScrollRect
.top
= Dest
->top
* GuiData
->CharHeight
;
1077 ScrollRect
.bottom
= (Dest
->bottom
+ 1) * GuiData
->CharHeight
;
1078 EnterCriticalSection(&GuiData
->Lock
);
1079 BitBlt(GuiData
->MemoryDC
, ScrollRect
.left
, ScrollRect
.top
,
1080 ScrollRect
.right
- ScrollRect
.left
, ScrollRect
.bottom
- ScrollRect
.top
,
1081 GuiData
->MemoryDC
, Source
->left
* GuiData
->CharWidth
, Source
->top
* GuiData
->CharHeight
, SRCCOPY
);
1083 LeaveCriticalSection(&GuiData
->Lock
);
1085 InvalidateRect(hWnd
, &ScrollRect
, FALSE
);