Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

caret.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: caret.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Caret code. Every thread has a caret in its queue structure. 00007 * 00008 * History: 00009 * 11-17-90 ScottLu Created. 00010 * 01-Feb-1991 mikeke Added Revalidation code (None) 00011 * 02-12-91 JimA Added access checks 00012 \***************************************************************************/ 00013 00014 #include "precomp.h" 00015 #pragma hdrstop 00016 00017 00018 /***************************************************************************\ 00019 * UT_CaretSet 00020 * 00021 * Checks to see if the current queue has a caret. If pwnd != NULL, check 00022 * to see if the caret is for pwnd. 00023 * 00024 * History: 00025 * 11-17-90 ScottLu Ported. 00026 \***************************************************************************/ 00027 00028 BOOL UT_CaretSet( 00029 PWND pwnd) 00030 { 00031 PQ pq; 00032 PTHREADINFO ptiCurrent; 00033 00034 /* 00035 * Current queue have a caret? If not, return FALSE. 00036 */ 00037 ptiCurrent = PtiCurrent(); 00038 pq = ptiCurrent->pq; 00039 00040 if (pq->caret.spwnd == NULL) { 00041 RIPERR0(ERROR_ACCESS_DENIED, 00042 RIP_VERBOSE, 00043 "Access denied in UT_CaretSet to current queue's caret"); 00044 00045 return FALSE; 00046 } 00047 00048 /* 00049 * If the current task does not own the caret, then return FALSE 00050 * but we let 32 bit multithreaded apps set the caret position from 00051 * a second thread for compatibility to our NT 3.1 BETAs 00052 */ 00053 if (pq->caret.tid != TIDq(ptiCurrent)) { 00054 PTHREADINFO ptiCursorOwner; 00055 00056 ptiCursorOwner = PtiFromThreadId(pq->caret.tid); 00057 00058 if ((ptiCurrent->TIF_flags & TIF_16BIT) || ptiCursorOwner == NULL || 00059 (ptiCurrent->ppi != ptiCursorOwner->ppi)) { 00060 RIPERR0(ERROR_ACCESS_DENIED, 00061 RIP_VERBOSE, 00062 "Access denied in UT_CaretSet"); 00063 00064 return FALSE; 00065 } 00066 } 00067 00068 /* 00069 * If pwnd == NULL, just checking to see if current queue has caret. 00070 * It does, so return TRUE. 00071 */ 00072 if (pwnd == NULL) 00073 return TRUE; 00074 00075 /* 00076 * pwnd != NULL. Check to see if the caret is for pwnd. If so, return 00077 * TRUE. 00078 */ 00079 if (pwnd == pq->caret.spwnd) 00080 return TRUE; 00081 00082 return FALSE; 00083 } 00084 00085 /***************************************************************************\ 00086 * UT_InvertCaret 00087 * 00088 * Invert the caret. 00089 * 00090 * History: 00091 * 11-17-90 ScottLu Ported. 00092 \***************************************************************************/ 00093 00094 void UT_InvertCaret() 00095 { 00096 HDC hdc; 00097 PWND pwnd; 00098 PQ pq; 00099 HBITMAP hbmSave; 00100 BOOL fRestore; 00101 00102 pq = PtiCurrent()->pq; 00103 pwnd = pq->caret.spwnd; 00104 00105 00106 if (pwnd == NULL || !IsVisible(pwnd)) { 00107 pq->caret.fVisible = FALSE; 00108 return; 00109 } 00110 00111 /* 00112 * Don't have a dc. Get one for this window and draw the caret. 00113 */ 00114 hdc = _GetDC(pwnd); 00115 00116 if (fRestore = (pwnd->hrgnUpdate ? TRUE : FALSE)) { 00117 GreSaveDC(hdc); 00118 if (TestWF(pwnd, WFWIN31COMPAT)) 00119 _ExcludeUpdateRgn(hdc, pwnd); 00120 } 00121 00122 /* 00123 * If the caret bitmap is NULL, the caret is a white pattern invert 00124 * If the caret bitmap is == 1, the caret is a gray pattern. 00125 * If the caret bitmap is > 1, the caret is really a bitmap. 00126 */ 00127 if ((pq->caret.hBitmap) > (HBITMAP)1) { 00128 00129 /* 00130 * The caret is a bitmap... SRCINVERT it onto the screen. 00131 */ 00132 hbmSave = GreSelectBitmap(ghdcMem, pq->caret.hBitmap); 00133 GreBitBlt(hdc, pq->caret.x, pq->caret.y, pq->caret.cx, 00134 pq->caret.cy, ghdcMem, 0, 0, SRCINVERT, 0); 00135 00136 GreSelectBitmap(ghdcMem, hbmSave); 00137 00138 } else { 00139 00140 POLYPATBLT PolyData; 00141 00142 /* 00143 * The caret is a pattern (gray or white). PATINVERT it onto the 00144 * screen. Remember to unrealize the gray object so it aligns 00145 * to the window correctly. 00146 * 00147 * Remove call to UnrealizeObject. GDI handles this on NT for 00148 * brushes. 00149 * 00150 * UnrealizeObject(hbrGray); 00151 */ 00152 PolyData.x = pq->caret.x; 00153 PolyData.y = pq->caret.y; 00154 PolyData.cx = pq->caret.cx; 00155 PolyData.cy = pq->caret.cy; 00156 00157 if ((pq->caret.hBitmap) == (HBITMAP)1) { 00158 //hbrSave = GreSelectBrush(hdc, ghbrGray); 00159 PolyData.BrClr.hbr = gpsi->hbrGray; 00160 } else { 00161 //hbrSave = GreSelectBrush(hdc, ghbrWhite); 00162 PolyData.BrClr.hbr = ghbrWhite; 00163 } 00164 00165 GrePolyPatBlt(hdc,PATINVERT,&PolyData,1,PPB_BRUSH); 00166 00167 //GrePatBlt(hdc, pq->caret.x, pq->caret.y, pq->caret.cx, pq->caret.cy, 00168 // PATINVERT); 00169 // 00170 //GreSelectBrush(hdc,hbrSave); 00171 } 00172 00173 if (fRestore) 00174 GreRestoreDC(hdc, -1); 00175 00176 _ReleaseDC(hdc); 00177 } 00178 00179 00180 /***************************************************************************\ 00181 * zzzInternalDestroyCaret 00182 * 00183 * Internal routine for killing the caret for this thread. 00184 * 00185 * History: 00186 * 11-17-90 ScottLu Ported 00187 \***************************************************************************/ 00188 00189 void zzzInternalDestroyCaret() 00190 { 00191 PQ pq; 00192 PTHREADINFO ptiCurrent = PtiCurrent(); 00193 PWND pwndCaret; 00194 TL tlpwndCaret; 00195 00196 /* 00197 * Hide the caret, kill the timer, and null out the caret structure. 00198 */ 00199 zzzInternalHideCaret(); 00200 pq = ptiCurrent->pq; 00201 _KillSystemTimer(pq->caret.spwnd, IDSYS_CARET); 00202 00203 pq->caret.hTimer = 0; 00204 pq->caret.hBitmap = NULL; 00205 pq->caret.iHideLevel = 0; 00206 00207 pwndCaret = pq->caret.spwnd; 00208 if (pwndCaret != NULL) { 00209 /* 00210 * Threadlock caret's spwnd for WinEvent notification below 00211 */ 00212 ThreadLockWithPti(ptiCurrent, pwndCaret, &tlpwndCaret); 00213 Unlock(&pq->caret.spwnd); 00214 00215 if (FWINABLE()) { 00216 zzzWindowEvent(EVENT_OBJECT_DESTROY, pwndCaret, OBJID_CARET, INDEXID_CONTAINER, 0); 00217 } 00218 00219 ThreadUnlock(&tlpwndCaret); 00220 } 00221 } 00222 00223 00224 /***************************************************************************\ 00225 * zzzDestroyCaret 00226 * 00227 * External api for destroying the caret of the current thread. 00228 * 00229 * History: 00230 * 11-17-90 ScottLu Ported. 00231 * 16-May-1991 mikeke Changed to return BOOL 00232 \***************************************************************************/ 00233 00234 BOOL zzzDestroyCaret() 00235 { 00236 if (UT_CaretSet(NULL)) { 00237 zzzInternalDestroyCaret(); 00238 return TRUE; 00239 } 00240 return FALSE; 00241 } 00242 00243 00244 /***************************************************************************\ 00245 * xxxCreateCaret 00246 * 00247 * External api for creating the caret. 00248 * 00249 * History: 00250 * 11-17-90 ScottLu Ported. 00251 * 16-May-1991 mikeke Changed to return BOOL 00252 \***************************************************************************/ 00253 00254 BOOL xxxCreateCaret( 00255 PWND pwnd, 00256 HBITMAP hBitmap, 00257 int cx, 00258 int cy) 00259 { 00260 PQ pq; 00261 BITMAP bitmap; 00262 PTHREADINFO ptiCurrent = PtiCurrent(); 00263 00264 CheckLock(pwnd); 00265 UserAssert(IsWinEventNotifyDeferredOK()); 00266 00267 pq = ptiCurrent->pq; 00268 00269 /* 00270 * Don't allow the app to create a caret in a window 00271 * from another queue. 00272 */ 00273 if (GETPTI(pwnd)->pq != pq) { 00274 return FALSE; 00275 } 00276 00277 /* 00278 * Defer WinEvent notifications to preserve pq 00279 */ 00280 DeferWinEventNotify(); 00281 00282 if (pq->caret.spwnd != NULL) 00283 zzzInternalDestroyCaret(); 00284 00285 Lock(&pq->caret.spwnd, pwnd); 00286 pq->caret.iHideLevel = 1; 00287 pq->caret.fOn = TRUE; 00288 pq->caret.fVisible = FALSE; 00289 pq->caret.tid = TIDq(ptiCurrent); 00290 00291 if (cy == 0) 00292 cy = SYSMET(CYBORDER); 00293 if (cx == 0) 00294 cx = SYSMET(CXBORDER); 00295 00296 if ((pq->caret.hBitmap = hBitmap) > (HBITMAP)1) { 00297 GreExtGetObjectW(hBitmap, sizeof(BITMAP), &bitmap); 00298 cy = bitmap.bmHeight; 00299 cx = bitmap.bmWidth; 00300 } 00301 00302 pq->caret.cy = cy; 00303 pq->caret.cx = cx; 00304 00305 pq->caret.hTimer = _SetSystemTimer(pwnd, IDSYS_CARET, gpsi->dtCaretBlink, 00306 CaretBlinkProc); 00307 00308 UserAssert(pwnd == pq->caret.spwnd); 00309 zzzEndDeferWinEventNotify(); 00310 if (FWINABLE()) { 00311 /* 00312 * It's best to force this routine to be an xxx routine: that way we can 00313 * force pwnd to be locked and force notifications from within this routine 00314 * and all of the callers are happy with this. 00315 */ 00316 xxxWindowEvent(EVENT_OBJECT_CREATE, pwnd, OBJID_CARET, INDEXID_CONTAINER, 0); 00317 } 00318 00319 return TRUE; 00320 } 00321 00322 /***************************************************************************\ 00323 * zzzInternalShowCaret 00324 * 00325 * Internal routine for showing the caret for this thread. 00326 * 00327 * History: 00328 * 11-17-90 ScottLu Ported. 00329 \***************************************************************************/ 00330 00331 void zzzInternalShowCaret() 00332 { 00333 PQ pq; 00334 PTHREADINFO ptiCurrent = PtiCurrent(); 00335 00336 pq = ptiCurrent->pq; 00337 00338 /* 00339 * If the caret hide level is aleady 0 (meaning it's ok to show) and the 00340 * caret is not physically on, try to invert now if it's turned on. 00341 */ 00342 if (pq->caret.iHideLevel == 0) { 00343 if (!pq->caret.fVisible) { 00344 if ((pq->caret.fVisible = pq->caret.fOn) != 0) { 00345 UT_InvertCaret(); 00346 } 00347 } 00348 return; 00349 } 00350 00351 /* 00352 * Adjust the hide caret hide count. If we hit 0, we can show the 00353 * caret. Try to invert it if it's turned on. 00354 */ 00355 00356 if (--pq->caret.iHideLevel == 0) { 00357 if ((pq->caret.fVisible = pq->caret.fOn) != 0) 00358 UT_InvertCaret(); 00359 00360 if (FWINABLE()) { 00361 zzzWindowEvent(EVENT_OBJECT_SHOW, pq->caret.spwnd, OBJID_CARET, INDEXID_CONTAINER, 0); 00362 } 00363 } 00364 } 00365 00366 00367 /***************************************************************************\ 00368 * zzzInternalHideCaret 00369 * 00370 * Internal routine for hiding the caret. 00371 * 00372 * History: 00373 * 11-17-90 ScottLu Created. 00374 \***************************************************************************/ 00375 00376 void zzzInternalHideCaret() 00377 { 00378 PQ pq; 00379 PTHREADINFO ptiCurrent = PtiCurrent(); 00380 00381 pq = ptiCurrent->pq; 00382 00383 /* 00384 * If the caret is physically visible, invert it to turn off the bits. 00385 * Adjust the hide count upwards to remember this hide level. 00386 */ 00387 if (pq->caret.fVisible) 00388 UT_InvertCaret(); 00389 00390 pq->caret.fVisible = FALSE; 00391 pq->caret.iHideLevel++; 00392 00393 /* 00394 * Is the caret transitioning to being hidden? If so, iHideLevel is 00395 * going from 0 to 1. 00396 */ 00397 if (FWINABLE() && (pq->caret.iHideLevel == 1)) { 00398 zzzWindowEvent(EVENT_OBJECT_HIDE, pq->caret.spwnd, OBJID_CARET, INDEXID_CONTAINER, 0); 00399 } 00400 } 00401 00402 00403 /***************************************************************************\ 00404 * zzzShowCaret 00405 * 00406 * External routine for showing the caret! 00407 * 00408 * History: 00409 * 11-17-90 ScottLu Ported. 00410 * 16-May-1991 mikeke Changed to return BOOL 00411 \***************************************************************************/ 00412 00413 BOOL zzzShowCaret( 00414 PWND pwnd) 00415 { 00416 if (UT_CaretSet(pwnd)) { 00417 zzzInternalShowCaret(); 00418 return TRUE; 00419 } 00420 return FALSE; 00421 } 00422 00423 00424 /***************************************************************************\ 00425 * zzzHideCaret 00426 * 00427 * External api to hide the caret! 00428 * 00429 * History: 00430 * 11-17-90 ScottLu Ported. 00431 * 16-May-1991 mikeke Changed to return BOOL 00432 \***************************************************************************/ 00433 00434 BOOL zzzHideCaret( 00435 PWND pwnd) 00436 { 00437 if (UT_CaretSet(pwnd)) { 00438 zzzInternalHideCaret(); 00439 return TRUE; 00440 } 00441 return FALSE; 00442 } 00443 00444 /***************************************************************************\ 00445 * CaretBlinkProc 00446 * 00447 * This routine gets called by DispatchMessage when it gets the WM_SYSTIMER 00448 * message - it blinks the caret. 00449 * 00450 * History: 00451 * 11-17-90 ScottLu Ported. 00452 \***************************************************************************/ 00453 00454 VOID CaretBlinkProc( 00455 PWND pwnd, 00456 UINT message, 00457 UINT_PTR id, 00458 LPARAM lParam) 00459 { 00460 PQ pq; 00461 00462 /* 00463 * If this window doesn't even have a timer, just return. TRUE is 00464 * returned, which gets returned from DispatchMessage(). Why? Because 00465 * it is compatible with Win3. 00466 */ 00467 pq = PtiCurrent()->pq; 00468 if (pwnd != pq->caret.spwnd) 00469 return; 00470 00471 /* 00472 * leave caret on, don't blink it off for remote sessions 00473 */ 00474 00475 if (gbRemoteSession && (gpsi->dtCaretBlink >= 1200) && pq->caret.fOn && pq->caret.fVisible) { 00476 00477 /* 00478 * Kill the timer for performance 00479 */ 00480 _KillSystemTimer(pq->caret.spwnd, IDSYS_CARET); 00481 return; 00482 } 00483 00484 /* 00485 * Flip the logical cursor state. If the hide level permits it, flip 00486 * the physical state and draw the caret. 00487 */ 00488 pq->caret.fOn ^= 1; 00489 if (pq->caret.iHideLevel == 0) { 00490 pq->caret.fVisible ^= 1; 00491 UT_InvertCaret(); 00492 } 00493 00494 return; 00495 00496 DBG_UNREFERENCED_PARAMETER(message); 00497 DBG_UNREFERENCED_PARAMETER(id); 00498 DBG_UNREFERENCED_PARAMETER(lParam); 00499 } 00500 00501 00502 /***************************************************************************\ 00503 * _SetCaretBlinkTime 00504 * 00505 * Sets the system caret blink time. 00506 * 00507 * History: 00508 * 11-17-90 ScottLu Created. 00509 * 02-12-91 JimA Added access check 00510 * 16-May-1991 mikeke Changed to return BOOL 00511 \***************************************************************************/ 00512 00513 BOOL _SetCaretBlinkTime( 00514 UINT cmsBlink) 00515 { 00516 PQ pq; 00517 PTHREADINFO ptiCurrent = PtiCurrent(); 00518 00519 /* 00520 * Blow it off if the caller doesn't have the proper access rights 00521 */ 00522 if (!CheckWinstaWriteAttributesAccess()) { 00523 return FALSE; 00524 } 00525 00526 gpsi->dtCaretBlink = cmsBlink; 00527 00528 pq = ptiCurrent->pq; 00529 00530 if (pq->caret.spwnd) { 00531 _KillSystemTimer(pq->caret.spwnd, IDSYS_CARET); 00532 pq->caret.hTimer = _SetSystemTimer(pq->caret.spwnd, IDSYS_CARET, 00533 gpsi->dtCaretBlink, CaretBlinkProc); 00534 } 00535 00536 return TRUE; 00537 } 00538 00539 00540 /***************************************************************************\ 00541 * zzzSetCaretPos 00542 * 00543 * External routine for setting the caret pos. 00544 * 00545 * History: 00546 * 11-17-90 ScottLu Ported. 00547 * 02-12-91 JimA Added access check 00548 \***************************************************************************/ 00549 00550 BOOL zzzSetCaretPos( 00551 int x, 00552 int y) 00553 { 00554 PQ pq; 00555 PTHREADINFO ptiCurrent = PtiCurrent(); 00556 00557 /* 00558 * If this thread does not have the caret set, return FALSE. 00559 */ 00560 if (!UT_CaretSet(NULL)) { 00561 RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "Access denied in zzzSetCaretPos"); 00562 return FALSE; 00563 } 00564 00565 /* 00566 * If the caret isn't changing position, do nothing (but return success). 00567 */ 00568 pq = ptiCurrent->pq; 00569 if (pq->caret.x == x && pq->caret.y == y) 00570 return TRUE; 00571 00572 /* 00573 * If the caret is visible, turn it off while we move it. 00574 */ 00575 if (pq->caret.fVisible) 00576 UT_InvertCaret(); 00577 00578 /* 00579 * Adjust to the new position. 00580 */ 00581 pq->caret.x = x; 00582 pq->caret.y = y; 00583 00584 /* 00585 * Set a new timer so it'll blink in the new position dtCaretBlink 00586 * milliseconds from now. 00587 */ 00588 _KillSystemTimer(pq->caret.spwnd, IDSYS_CARET); 00589 pq->caret.hTimer = _SetSystemTimer(pq->caret.spwnd, IDSYS_CARET, 00590 gpsi->dtCaretBlink, CaretBlinkProc); 00591 00592 pq->caret.fOn = TRUE; 00593 00594 /* 00595 * Draw it immediately now if the hide level permits it. 00596 */ 00597 pq->caret.fVisible = FALSE; 00598 if (pq->caret.iHideLevel == 0) { 00599 pq->caret.fVisible = TRUE; 00600 UT_InvertCaret(); 00601 } 00602 00603 if (FWINABLE()) { 00604 zzzWindowEvent(EVENT_OBJECT_LOCATIONCHANGE, pq->caret.spwnd, OBJID_CARET, INDEXID_CONTAINER, 0); 00605 } 00606 00607 return TRUE; 00608 }

Generated on Sat May 15 19:39:21 2004 for test by doxygen 1.3.7