Revert tree-restructure attempt: r66583, r66582, r66581, r66578, sauf ntdll changes...
[reactos.git] / reactos / win32ss / user / ntuser / caret.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Caret functions
5 * FILE: subsystems/win32/win32k/ntuser/caret.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserCaret);
11
12 /* DEFINES *****************************************************************/
13
14 #define MIN_CARETBLINKRATE 100
15 #define MAX_CARETBLINKRATE 10000
16
17 /* FUNCTIONS *****************************************************************/
18
19 VOID FASTCALL
20 co_IntDrawCaret(PWND pWnd, PTHRDCARETINFO CaretInfo)
21 {
22 HDC hdc, hdcMem;
23 HBITMAP hbmOld;
24 BOOL bDone = FALSE;
25
26 hdc = UserGetDCEx(pWnd, 0, DCX_USESTYLE | DCX_WINDOW);
27 if (!hdc)
28 {
29 ERR("GetDC failed\n");
30 return;
31 }
32
33 if (pWnd->hrgnUpdate)
34 {
35 NtGdiSaveDC(hdc);
36 }
37
38 if(CaretInfo->Bitmap && NtGdiGetBitmapDimension(CaretInfo->Bitmap, &CaretInfo->Size))
39 {
40 hdcMem = NtGdiCreateCompatibleDC(hdc);
41 if (hdcMem)
42 {
43 hbmOld = NtGdiSelectBitmap(hdcMem, CaretInfo->Bitmap);
44 bDone = NtGdiBitBlt(hdc,
45 CaretInfo->Pos.x,
46 CaretInfo->Pos.y,
47 CaretInfo->Size.cx,
48 CaretInfo->Size.cy,
49 hdcMem,
50 0,
51 0,
52 SRCINVERT,
53 0,
54 0);
55 NtGdiSelectBitmap(hdcMem, hbmOld);
56 GreDeleteObject(hdcMem);
57 }
58 }
59
60 if (!bDone)
61 {
62 NtGdiPatBlt(hdc,
63 CaretInfo->Pos.x,
64 CaretInfo->Pos.y,
65 CaretInfo->Size.cx,
66 CaretInfo->Size.cy,
67 DSTINVERT);
68 }
69
70 if (pWnd->hrgnUpdate)
71 {
72 NtGdiRestoreDC(hdc, -1);
73 }
74
75 UserReleaseDC(pWnd, hdc, FALSE);
76 }
77
78 VOID
79 CALLBACK
80 CaretSystemTimerProc(HWND hwnd,
81 UINT uMsg,
82 UINT_PTR idEvent,
83 DWORD dwTime)
84 {
85 PTHREADINFO pti;
86 PUSER_MESSAGE_QUEUE ThreadQueue;
87 PWND pWnd;
88
89 pti = PsGetCurrentThreadWin32Thread();
90 ThreadQueue = pti->MessageQueue;
91
92 if (ThreadQueue->CaretInfo->hWnd != hwnd)
93 {
94 ERR("Not the same caret window!\n");
95 return;
96 }
97
98 if (hwnd)
99 {
100 pWnd = UserGetWindowObject(hwnd);
101 if (!pWnd)
102 {
103 ERR("Caret System Timer Proc has invalid window handle! %p Id: %u\n", hwnd, idEvent);
104 return;
105 }
106 }
107 else
108 {
109 TRACE( "Windowless Caret Timer Running!\n" );
110 return;
111 }
112
113 switch (idEvent)
114 {
115 case IDCARETTIMER:
116 {
117 ThreadQueue->CaretInfo->Showing = (ThreadQueue->CaretInfo->Showing ? 0 : 1);
118 co_IntDrawCaret(pWnd, ThreadQueue->CaretInfo);
119 }
120 }
121 return;
122 }
123
124 static
125 BOOL FASTCALL
126 co_IntHideCaret(PTHRDCARETINFO CaretInfo)
127 {
128 PWND pWnd;
129 if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing)
130 {
131 pWnd = UserGetWindowObject(CaretInfo->hWnd);
132 CaretInfo->Showing = 0;
133
134 IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
135 return TRUE;
136 }
137 return FALSE;
138 }
139
140 BOOL FASTCALL
141 co_IntDestroyCaret(PTHREADINFO Win32Thread)
142 {
143 PUSER_MESSAGE_QUEUE ThreadQueue;
144 PWND pWnd;
145 ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue;
146
147 if(!ThreadQueue || !ThreadQueue->CaretInfo)
148 return FALSE;
149
150 pWnd = ValidateHwndNoErr(ThreadQueue->CaretInfo->hWnd);
151 co_IntHideCaret(ThreadQueue->CaretInfo);
152 ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
153 ThreadQueue->CaretInfo->hWnd = (HWND)0;
154 ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
155 ThreadQueue->CaretInfo->Showing = 0;
156 ThreadQueue->CaretInfo->Visible = 0;
157 if (pWnd)
158 {
159 IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0);
160 }
161 return TRUE;
162 }
163
164 BOOL FASTCALL
165 IntSetCaretBlinkTime(UINT uMSeconds)
166 {
167 /* Don't save the new value to the registry! */
168
169 /* Windows doesn't do this check */
170 if((uMSeconds < MIN_CARETBLINKRATE) || (uMSeconds > MAX_CARETBLINKRATE))
171 {
172 EngSetLastError(ERROR_INVALID_PARAMETER);
173 return FALSE;
174 }
175
176 gpsi->dtCaretBlink = uMSeconds;
177
178 return TRUE;
179 }
180
181 BOOL FASTCALL
182 co_IntSetCaretPos(int X, int Y)
183 {
184 PTHREADINFO pti;
185 PWND pWnd;
186 PUSER_MESSAGE_QUEUE ThreadQueue;
187
188 pti = PsGetCurrentThreadWin32Thread();
189 ThreadQueue = pti->MessageQueue;
190
191 if(ThreadQueue->CaretInfo->hWnd)
192 {
193 pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
194 if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y)
195 {
196 co_IntHideCaret(ThreadQueue->CaretInfo);
197 ThreadQueue->CaretInfo->Showing = 0;
198 ThreadQueue->CaretInfo->Pos.x = X;
199 ThreadQueue->CaretInfo->Pos.y = Y;
200
201 IntSetTimer(pWnd, IDCARETTIMER, gpsi->dtCaretBlink, CaretSystemTimerProc, TMRF_SYSTEM);
202 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
203 }
204 return TRUE;
205 }
206
207 return FALSE;
208 }
209
210 BOOL FASTCALL co_UserHideCaret(PWND Window OPTIONAL)
211 {
212 PTHREADINFO pti;
213 PUSER_MESSAGE_QUEUE ThreadQueue;
214
215 if (Window) ASSERT_REFS_CO(Window);
216
217 if(Window && Window->head.pti->pEThread != PsGetCurrentThread())
218 {
219 EngSetLastError(ERROR_ACCESS_DENIED);
220 return FALSE;
221 }
222
223 pti = PsGetCurrentThreadWin32Thread();
224 ThreadQueue = pti->MessageQueue;
225
226 if(Window && ThreadQueue->CaretInfo->hWnd != Window->head.h)
227 {
228 EngSetLastError(ERROR_ACCESS_DENIED);
229 return FALSE;
230 }
231
232 if(ThreadQueue->CaretInfo->Visible)
233 {
234 PWND pwnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
235 IntKillTimer(pwnd, IDCARETTIMER, TRUE);
236
237 co_IntHideCaret(ThreadQueue->CaretInfo);
238 ThreadQueue->CaretInfo->Visible = 0;
239 ThreadQueue->CaretInfo->Showing = 0;
240 }
241
242 return TRUE;
243 }
244
245 BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
246 {
247 PTHREADINFO pti;
248 PUSER_MESSAGE_QUEUE ThreadQueue;
249 PWND pWnd = NULL;
250
251 if (Window) ASSERT_REFS_CO(Window);
252
253 if(Window && Window->head.pti->pEThread != PsGetCurrentThread())
254 {
255 EngSetLastError(ERROR_ACCESS_DENIED);
256 return FALSE;
257 }
258
259 pti = PsGetCurrentThreadWin32Thread();
260 ThreadQueue = pti->MessageQueue;
261
262 if(Window && ThreadQueue->CaretInfo->hWnd != Window->head.h)
263 {
264 EngSetLastError(ERROR_ACCESS_DENIED);
265 return FALSE;
266 }
267
268 if (!ThreadQueue->CaretInfo->Visible)
269 {
270 ThreadQueue->CaretInfo->Visible = 1;
271 pWnd = ValidateHwndNoErr(ThreadQueue->CaretInfo->hWnd);
272 if (!ThreadQueue->CaretInfo->Showing && pWnd)
273 {
274 IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0);
275 }
276 IntSetTimer(pWnd, IDCARETTIMER, gpsi->dtCaretBlink, CaretSystemTimerProc, TMRF_SYSTEM);
277 }
278 return TRUE;
279 }
280
281 /* SYSCALLS *****************************************************************/
282
283 BOOL
284 APIENTRY
285 NtUserCreateCaret(
286 HWND hWnd,
287 HBITMAP hBitmap,
288 int nWidth,
289 int nHeight)
290 {
291 PWND Window;
292 PTHREADINFO pti;
293 PUSER_MESSAGE_QUEUE ThreadQueue;
294 DECLARE_RETURN(BOOL);
295
296 TRACE("Enter NtUserCreateCaret\n");
297 UserEnterExclusive();
298
299 if(!(Window = UserGetWindowObject(hWnd)))
300 {
301 RETURN(FALSE);
302 }
303
304 if(Window->head.pti->pEThread != PsGetCurrentThread())
305 {
306 EngSetLastError(ERROR_ACCESS_DENIED);
307 RETURN(FALSE);
308 }
309
310 pti = PsGetCurrentThreadWin32Thread();
311 ThreadQueue = pti->MessageQueue;
312
313 if (ThreadQueue->CaretInfo->Visible)
314 {
315 IntKillTimer(Window, IDCARETTIMER, TRUE);
316 co_IntHideCaret(ThreadQueue->CaretInfo);
317 }
318
319 ThreadQueue->CaretInfo->hWnd = hWnd;
320 if(hBitmap)
321 {
322 ThreadQueue->CaretInfo->Bitmap = hBitmap;
323 ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
324 }
325 else
326 {
327 if (nWidth == 0)
328 {
329 nWidth = UserGetSystemMetrics(SM_CXBORDER);
330 }
331 if (nHeight == 0)
332 {
333 nHeight = UserGetSystemMetrics(SM_CYBORDER);
334 }
335 ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
336 ThreadQueue->CaretInfo->Size.cx = nWidth;
337 ThreadQueue->CaretInfo->Size.cy = nHeight;
338 }
339 ThreadQueue->CaretInfo->Visible = 0;
340 ThreadQueue->CaretInfo->Showing = 0;
341
342 IntSetTimer( Window, IDCARETTIMER, gpsi->dtCaretBlink, CaretSystemTimerProc, TMRF_SYSTEM );
343
344 IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0);
345
346 RETURN(TRUE);
347
348 CLEANUP:
349 TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_);
350 UserLeave();
351 END_CLEANUP;
352 }
353
354 UINT
355 APIENTRY
356 NtUserGetCaretBlinkTime(VOID)
357 {
358 UINT ret;
359
360 UserEnterShared();
361
362 ret = gpsi->dtCaretBlink;
363
364 UserLeave();
365
366 return ret;
367 }
368
369 BOOL
370 APIENTRY
371 NtUserGetCaretPos(
372 LPPOINT lpPoint)
373 {
374 PTHREADINFO pti;
375 PUSER_MESSAGE_QUEUE ThreadQueue;
376 NTSTATUS Status;
377 DECLARE_RETURN(BOOL);
378
379 TRACE("Enter NtUserGetCaretPos\n");
380 UserEnterShared();
381
382 pti = PsGetCurrentThreadWin32Thread();
383 ThreadQueue = pti->MessageQueue;
384
385 Status = MmCopyToCaller(lpPoint, &(ThreadQueue->CaretInfo->Pos), sizeof(POINT));
386 if(!NT_SUCCESS(Status))
387 {
388 SetLastNtError(Status);
389 RETURN(FALSE);
390 }
391
392 RETURN(TRUE);
393
394 CLEANUP:
395 TRACE("Leave NtUserGetCaretPos, ret=%i\n",_ret_);
396 UserLeave();
397 END_CLEANUP;
398 }
399
400 BOOL
401 APIENTRY
402 NtUserShowCaret(HWND hWnd OPTIONAL)
403 {
404 PWND Window = NULL;
405 USER_REFERENCE_ENTRY Ref;
406 DECLARE_RETURN(BOOL);
407 BOOL ret;
408
409 TRACE("Enter NtUserShowCaret\n");
410 UserEnterExclusive();
411
412 if(hWnd && !(Window = UserGetWindowObject(hWnd)))
413 {
414 RETURN(FALSE);
415 }
416
417 if (Window) UserRefObjectCo(Window, &Ref);
418
419 ret = co_UserShowCaret(Window);
420
421 if (Window) UserDerefObjectCo(Window);
422
423 RETURN(ret);
424
425 CLEANUP:
426 TRACE("Leave NtUserShowCaret, ret=%i\n",_ret_);
427 UserLeave();
428 END_CLEANUP;
429 }
430
431 BOOL
432 APIENTRY
433 NtUserHideCaret(HWND hWnd OPTIONAL)
434 {
435 PWND Window = NULL;
436 USER_REFERENCE_ENTRY Ref;
437 DECLARE_RETURN(BOOL);
438 BOOL ret;
439
440 TRACE("Enter NtUserHideCaret\n");
441 UserEnterExclusive();
442
443 if(hWnd && !(Window = UserGetWindowObject(hWnd)))
444 {
445 RETURN(FALSE);
446 }
447
448 if (Window) UserRefObjectCo(Window, &Ref);
449
450 ret = co_UserHideCaret(Window);
451
452 if (Window) UserDerefObjectCo(Window);
453
454 RETURN(ret);
455
456 CLEANUP:
457 TRACE("Leave NtUserHideCaret, ret=%i\n",_ret_);
458 UserLeave();
459 END_CLEANUP;
460 }