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

editsl.c

Go to the documentation of this file.
00001 /****************************************************************************\ 00002 * editsl.c - Edit controls rewrite. Version II of edit controls. 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Single Line Support Routines 00007 * 00008 * Created: 24-Jul-88 davidds 00009 * 00010 * Language pack notes: 00011 * With the language pack loaded all positional processing is based on 00012 * ped->xOffset rather than ped->ichScreenStart. The non-lpk optimisation of 00013 * maintaining ped->ichScreenStart doesn't work because of the 00014 * glyph reordering features of complex scripts. 00015 * 00016 \****************************************************************************/ 00017 00018 #include "precomp.h" 00019 #pragma hdrstop 00020 00021 #define SYS_ALTERNATE 0x2000 00022 00023 typedef BOOL (*FnGetTextExtentPoint)(HDC, PVOID, int, LPSIZE); 00024 00025 /***************************************************************************\ 00026 * SLCalcStringWidth 00027 * 00028 \***************************************************************************/ 00029 00030 int SLCalcStringWidth(PED ped, HDC hdc, ICH ich, ICH cch) 00031 { 00032 if (cch == 0) 00033 return 0; 00034 00035 if (ped->charPasswordChar) { 00036 return cch * ped->cPasswordCharWidth; 00037 } else { 00038 SIZE size; 00039 00040 if (ped->fNonPropFont && !ped->fDBCS) { 00041 size.cx = cch * ped->aveCharWidth; 00042 } else { 00043 PSTR pText = ECLock(ped); 00044 if (ped->fAnsi) { 00045 GetTextExtentPointA(hdc, (LPSTR)(pText + ich), cch, &size); 00046 } else { 00047 GetTextExtentPointW(hdc, (LPWSTR)pText + ich, cch, &size); 00048 } 00049 ECUnlock(ped); 00050 } 00051 return size.cx - ped->charOverhang; 00052 } 00053 } 00054 00055 /***************************************************************************\ 00056 * SLCalcXOffsetLeft 00057 * 00058 * Calculates the starting offset for left-aligned strings. 00059 * 00060 \***************************************************************************/ 00061 00062 int SLCalcXOffsetLeft(PED ped, HDC hdc, ICH ich) 00063 { 00064 int cch = (int)(ich - ped->ichScreenStart); 00065 00066 if (cch <= 0) 00067 return 0; 00068 00069 return SLCalcStringWidth(ped, hdc, ped->ichScreenStart, cch); 00070 } 00071 00072 /***************************************************************************\ 00073 * SLCalcXOffsetSpecial 00074 * 00075 * Calculates the horizontal offset (indent) required for right or center 00076 * justified lines. 00077 * 00078 \***************************************************************************/ 00079 00080 int SLCalcXOffsetSpecial(PED ped, HDC hdc, ICH ich) 00081 { 00082 PSTR pText; 00083 ICH cch, ichStart = ped->ichScreenStart; 00084 int cx; 00085 00086 /* 00087 * Calc the number of characters from start to right end. 00088 */ 00089 pText = ECLock(ped); 00090 cch = ECCchInWidth(ped, hdc, (LPSTR)(pText + ichStart * ped->cbChar), 00091 ped->cch - ichStart, ped->rcFmt.right - ped->rcFmt.left, TRUE); 00092 ECUnlock(ped); 00093 00094 /* 00095 * Once the last character of the string has been scrolled out of 00096 * the view, use normal offset calculation. 00097 */ 00098 if (ped->ichScreenStart + cch < ped->cch) 00099 return SLCalcXOffsetLeft(ped, hdc, ich); 00100 00101 cx = ped->rcFmt.right - ped->rcFmt.left - SLCalcStringWidth(ped, 00102 hdc, ichStart, cch); 00103 00104 if (ped->format == ES_CENTER) { 00105 cx = max(0, cx / 2); 00106 } else if (ped->format == ES_RIGHT) { 00107 /* 00108 * Subtract 1 so that the 1 pixel wide cursor will be in the visible 00109 * region on the very right side of the screen, mle does this. 00110 */ 00111 cx = max(0, cx - 1); 00112 } 00113 00114 return cx + SLCalcStringWidth(ped, hdc, ichStart, ich - ichStart); 00115 } 00116 00117 /***************************************************************************\ 00118 * SLSetCaretPosition AorW 00119 * 00120 * If the window has the focus, find where the caret belongs and move 00121 * it there. 00122 * 00123 * History: 00124 \***************************************************************************/ 00125 00126 void SLSetCaretPosition( 00127 PED ped, 00128 HDC hdc) 00129 { 00130 int xPosition; 00131 00132 /* 00133 * We will only position the caret if we have the focus since we don't want 00134 * to move the caret while another window could own it. 00135 */ 00136 if (!ped->fFocus) 00137 return; 00138 00139 if (ped->fCaretHidden) { 00140 NtUserSetCaretPos(-20000, -20000); 00141 return; 00142 } 00143 00144 xPosition = SLIchToLeftXPos(ped, hdc, ped->ichCaret); 00145 00146 /* 00147 * Don't let caret go out of bounds of edit control if there is too much 00148 * text. 00149 */ 00150 if (ped->pLpkEditCallout) { 00151 xPosition += ped->iCaretOffset; 00152 xPosition = max(xPosition , 0); 00153 xPosition = min(xPosition, ped->rcFmt.right - 1 - 00154 ((ped->cxSysCharWidth > ped->aveCharWidth) ? 1 : 2)); 00155 } else { 00156 xPosition = min(xPosition, ped->rcFmt.right - 00157 ((ped->cxSysCharWidth > ped->aveCharWidth) ? 1 : 2)); 00158 } 00159 00160 NtUserSetCaretPos(xPosition, ped->rcFmt.top); 00161 00162 // FE_IME SLSetCaretPosition - ECImmSetCompostionWindow( CFS_POINT ) 00163 if (fpImmIsIME(THREAD_HKL())) { 00164 ECImmSetCompositionWindow(ped, xPosition, ped->rcFmt.top); 00165 } 00166 } 00167 00168 /***************************************************************************\ 00169 * SLIchToLeftXPos AorW 00170 * 00171 * Given a character index, find its (left side) x coordinate within 00172 * the ped->rcFmt rectangle assuming the character ped->ichScreenStart is at 00173 * coordinates (ped->rcFmt.top, ped->rcFmt.left). A negative value is 00174 * return ed if the character ich is to the left of ped->ichScreenStart. WARNING: 00175 * ASSUMES AT MOST 1000 characters will be VISIBLE at one time on the screen. 00176 * There may be 64K total characters in the editcontrol, but we can only 00177 * display 1000 without scrolling. This shouldn't be a problem obviously. 00178 * !NT 00179 * History: 00180 \***************************************************************************/ 00181 00182 int SLIchToLeftXPos( 00183 PED ped, 00184 HDC hdc, 00185 ICH ich) 00186 { 00187 int textExtent; 00188 PSTR pText; 00189 SIZE size; 00190 int cchDiff; 00191 00192 if (ped->pLpkEditCallout) { 00193 00194 pText = ECLock(ped); 00195 textExtent = ped->pLpkEditCallout->EditIchToXY(ped, hdc, pText, ped->cch, ich); 00196 ECUnlock(ped); 00197 00198 return textExtent; 00199 00200 } 00201 00202 /* 00203 * Check if we are adding lots and lots of chars. A paste for example could 00204 * cause this and GetTextExtents could overflow on this. 00205 */ 00206 cchDiff = (int)ich - (int)ped->ichScreenStart; 00207 if (cchDiff > 1000) 00208 return (30000); 00209 else if (cchDiff < -1000) 00210 return (-30000); 00211 00212 if (ped->format != ES_LEFT) 00213 return (ped->rcFmt.left + SLCalcXOffsetSpecial(ped, hdc, ich)); 00214 00215 /* 00216 * Caret position /w DBCS text, we can not optimize... 00217 */ 00218 if (ped->fNonPropFont && !ped->fDBCS) 00219 return (ped->rcFmt.left + cchDiff*ped->aveCharWidth); 00220 00221 /* 00222 * Check if password hidden chars are being used. 00223 */ 00224 if (ped->charPasswordChar) 00225 return ( ped->rcFmt.left + cchDiff*ped->cPasswordCharWidth); 00226 00227 pText = ECLock(ped); 00228 00229 if (ped->fAnsi) { 00230 if (cchDiff >= 0) { 00231 00232 GetTextExtentPointA(hdc, (LPSTR)(pText + ped->ichScreenStart), 00233 cchDiff, &size); 00234 textExtent = size.cx; 00235 00236 /* 00237 * In case of signed/unsigned overflow since the text extent may be 00238 * greater than maxint. This happens with long single line edit 00239 * controls. The rect we edit text in will never be greater than 30000 00240 * pixels so we are ok if we just ignore them. 00241 */ 00242 if (textExtent < 0 || textExtent > 31000) 00243 textExtent = 30000; 00244 } else { 00245 GetTextExtentPointA(hdc,(LPSTR)(pText + ich), -cchDiff, &size); 00246 textExtent = (-1) * size.cx; 00247 } 00248 } else { 00249 if (cchDiff >= 0) { 00250 00251 GetTextExtentPointW(hdc, (LPWSTR)(pText + ped->ichScreenStart*sizeof(WCHAR)), 00252 cchDiff, &size); 00253 textExtent = size.cx; 00254 00255 /* 00256 * In case of signed/unsigned overflow since the text extent may be 00257 * greater than maxint. This happens with long single line edit 00258 * controls. The rect we edit text in will never be greater than 30000 00259 * pixels so we are ok if we just ignore them. 00260 */ 00261 if (textExtent < 0 || textExtent > 31000) 00262 textExtent = 30000; 00263 } else { 00264 GetTextExtentPointW(hdc,(LPWSTR)(pText + ich*sizeof(WCHAR)), -cchDiff, &size); 00265 textExtent = (-1) * size.cx; 00266 } 00267 } 00268 00269 ECUnlock(ped); 00270 00271 return (ped->rcFmt.left + textExtent - 00272 (textExtent ? ped->charOverhang : 0)); 00273 } 00274 00275 /***************************************************************************\ 00276 * SLSetSelection AorW 00277 * 00278 * Sets the PED to have the new selection specified. 00279 * 00280 * History: 00281 \***************************************************************************/ 00282 00283 void SLSetSelection( 00284 PED ped, 00285 ICH ichSelStart, 00286 ICH ichSelEnd) 00287 { 00288 HDC hdc = ECGetEditDC(ped, FALSE ); 00289 00290 if (ichSelStart == 0xFFFFFFFF) { 00291 00292 /* 00293 * Set no selection if we specify -1 00294 */ 00295 ichSelStart = ichSelEnd = ped->ichCaret; 00296 } 00297 00298 /* 00299 * Bounds ichSelStart, ichSelEnd are checked in SLChangeSelection... 00300 */ 00301 SLChangeSelection(ped, hdc, ichSelStart, ichSelEnd); 00302 00303 /* 00304 * Put the caret at the end of the selected text 00305 */ 00306 ped->ichCaret = ped->ichMaxSel; 00307 00308 SLSetCaretPosition(ped, hdc); 00309 00310 /* 00311 * We may need to scroll the text to bring the caret into view... 00312 */ 00313 SLScrollText(ped, hdc); 00314 00315 ECReleaseEditDC(ped, hdc, FALSE); 00316 } 00317 00318 /***************************************************************************\ 00319 * 00320 * SLGetClipRect() 00321 * 00322 \***************************************************************************/ 00323 void SLGetClipRect( 00324 PED ped, 00325 HDC hdc, 00326 ICH ichStart, 00327 int iCount, 00328 LPRECT lpClipRect ) 00329 { 00330 int iStCount; 00331 PSTR pText; 00332 00333 if (ped->pLpkEditCallout) { 00334 RIPMSG0(RIP_WARNING, "SLGetClipRect - Error - Invalid call with language pack loaded"); 00335 memset(lpClipRect, 0, sizeof(RECT)); 00336 return; 00337 } 00338 00339 CopyRect(lpClipRect, &ped->rcFmt); 00340 00341 pText = ECLock(ped) ; 00342 00343 // Calculates the starting pos for this piece of text 00344 if ((iStCount = (int)(ichStart - ped->ichScreenStart)) > 0) { 00345 if (ped->format == ES_LEFT) { 00346 lpClipRect->left += SLCalcXOffsetLeft(ped, hdc, ichStart); 00347 } 00348 } else { 00349 // Reset the values to visible portions 00350 iCount -= (ped->ichScreenStart - ichStart); 00351 ichStart = ped->ichScreenStart; 00352 } 00353 00354 if (ped->format != ES_LEFT) { 00355 lpClipRect->left += SLCalcXOffsetSpecial(ped, hdc, ichStart); 00356 } 00357 00358 if (iCount < 0) { 00359 /* 00360 * This is not in the visible area of the edit control, so return 00361 * an empty rect. 00362 */ 00363 SetRectEmpty(lpClipRect); 00364 ECUnlock(ped); 00365 return; 00366 } 00367 00368 if (ped->charPasswordChar) 00369 lpClipRect->right = lpClipRect->left + ped->cPasswordCharWidth * iCount; 00370 else { 00371 SIZE size ; 00372 00373 if ( ped->fAnsi) { 00374 GetTextExtentPointA(hdc, pText + ichStart, iCount, &size); 00375 } else { 00376 GetTextExtentPointW(hdc, ((LPWSTR)pText) + ichStart, iCount, &size); 00377 } 00378 lpClipRect->right = lpClipRect->left + size.cx - ped->charOverhang; 00379 } 00380 00381 ECUnlock(ped); 00382 } 00383 00384 /***************************************************************************\ 00385 * SLChangeSelection AorW 00386 * 00387 * Changes the current selection to have the specified starting and 00388 * ending values. Properly highlights the new selection and unhighlights 00389 * anything deselected. If NewMinSel and NewMaxSel are out of order, we swap 00390 * them. Doesn't update the caret position. 00391 * 00392 * History: 00393 \***************************************************************************/ 00394 00395 void SLChangeSelection( 00396 PED ped, 00397 HDC hdc, 00398 ICH ichNewMinSel, 00399 ICH ichNewMaxSel) 00400 { 00401 ICH temp; 00402 ICH ichOldMinSel; 00403 ICH ichOldMaxSel; 00404 00405 if (ichNewMinSel > ichNewMaxSel) { 00406 temp = ichNewMinSel; 00407 ichNewMinSel = ichNewMaxSel; 00408 ichNewMaxSel = temp; 00409 } 00410 ichNewMinSel = min(ichNewMinSel, ped->cch); 00411 ichNewMaxSel = min(ichNewMaxSel, ped->cch); 00412 00413 // 00414 // To avoid position to half of DBCS, check and ajust position if necessary 00415 // 00416 // We check ped->fDBCS and ped->fAnsi though ECAdjustIch checks these bits. 00417 // We're worrying about the overhead of EcLock and EcUnlock. 00418 // 00419 if (ped->fDBCS && ped->fAnsi) { 00420 PSTR pText; 00421 00422 pText = ECLock(ped); 00423 ichNewMinSel = ECAdjustIch( ped, pText, ichNewMinSel ); 00424 ichNewMaxSel = ECAdjustIch( ped, pText, ichNewMaxSel ); 00425 ECUnlock(ped); 00426 } 00427 00428 /* 00429 * Preserve the Old selection 00430 */ 00431 ichOldMinSel = ped->ichMinSel; 00432 ichOldMaxSel = ped->ichMaxSel; 00433 00434 /* 00435 * Set new selection 00436 */ 00437 ped->ichMinSel = ichNewMinSel; 00438 ped->ichMaxSel = ichNewMaxSel; 00439 00440 /* 00441 * We will find the intersection of current selection rectangle with the new 00442 * selection rectangle. We will then invert the parts of the two rectangles 00443 * not in the intersection. 00444 */ 00445 if (_IsWindowVisible(ped->pwnd) && (ped->fFocus || ped->fNoHideSel)) { 00446 BLOCK Blk[2]; 00447 int i; 00448 RECT rc; 00449 00450 if (ped->fFocus) 00451 NtUserHideCaret(ped->hwnd); 00452 00453 if (ped->pLpkEditCallout) { 00454 /* 00455 * The language pack handles display while complex script support present 00456 */ 00457 PSTR pText; 00458 00459 ECGetBrush(ped, hdc); // Give user a chance to manipulate the DC 00460 pText = ECLock(ped); 00461 ped->pLpkEditCallout->EditDrawText(ped, hdc, pText, ped->cch, ped->ichMinSel, ped->ichMaxSel, ped->rcFmt.top); 00462 ECUnlock(ped); 00463 } else { 00464 Blk[0].StPos = ichOldMinSel; 00465 Blk[0].EndPos = ichOldMaxSel; 00466 Blk[1].StPos = ped->ichMinSel; 00467 Blk[1].EndPos = ped->ichMaxSel; 00468 00469 if (ECCalcChangeSelection(ped, ichOldMinSel, ichOldMaxSel, 00470 (LPBLOCK)&Blk[0], (LPBLOCK)&Blk[1])) { 00471 00472 // 00473 // Paint the rectangles where selection has changed. 00474 // Paint both Blk[0] and Blk[1], if they exist. 00475 // 00476 for (i = 0; i < 2; i++) { 00477 if (Blk[i].StPos != 0xFFFFFFFF) { 00478 SLGetClipRect(ped, hdc, Blk[i].StPos, 00479 Blk[i].EndPos - Blk[i].StPos, (LPRECT)&rc); 00480 SLDrawLine(ped, hdc, rc.left, rc.right, Blk[i].StPos, 00481 Blk[i].EndPos - Blk[i].StPos, 00482 ((Blk[i].StPos >= ped->ichMinSel) && 00483 (Blk[i].StPos < ped->ichMaxSel))); 00484 } 00485 } 00486 } 00487 } 00488 00489 // 00490 // Update caret. 00491 // 00492 SLSetCaretPosition(ped, hdc); 00493 00494 if (ped->fFocus) 00495 NtUserShowCaret(ped->hwnd); 00496 } 00497 } 00498 00499 /***************************************************************************\ 00500 * 00501 * SLDrawLine() 00502 * 00503 * This draws the line starting from ichStart, iCount number of characters; 00504 * fSelStatus is TRUE if we're to draw the text as selected. 00505 * 00506 \***************************************************************************/ 00507 void SLDrawLine( 00508 PED ped, 00509 HDC hdc, 00510 int xClipStPos, 00511 int xClipEndPos, 00512 ICH ichStart, 00513 int iCount, 00514 BOOL fSelStatus ) 00515 { 00516 RECT rc; 00517 RECT rcClip; 00518 PSTR pText; 00519 DWORD rgbSaveBk; 00520 DWORD rgbSaveText; 00521 DWORD wSaveBkMode; 00522 int iStCount; 00523 ICH ichNewStart; 00524 HBRUSH hbrBack; 00525 00526 if (ped->pLpkEditCallout) { 00527 RIPMSG0(RIP_WARNING, "SLDrawLine - Error - Invalid call with language pack loaded"); 00528 return; 00529 } 00530 00531 // 00532 // Anything to draw? 00533 // 00534 if (xClipStPos >= xClipEndPos || !_IsWindowVisible(ped->pwnd) ) 00535 return; 00536 00537 if (ped->fAnsi && ped->fDBCS) { 00538 PSTR pT,pTOrg; 00539 int iTCount; 00540 00541 pText = ECLock(ped); 00542 ichNewStart = 0; 00543 if (ichStart > 0) { 00544 pT = pText + ichStart; 00545 ichNewStart = ichStart; 00546 00547 while (ichNewStart && 00548 (ichStart - ichNewStart < ped->wMaxNegCcharPos)) { 00549 pT = ECAnsiPrev(ped, pText, pT); 00550 ichNewStart = (ICH)(pT - pText); 00551 if (!ichNewStart) 00552 break; 00553 } 00554 00555 // B#16152 - win95. 00556 // In case of T2, SLE always set an additional margin 00557 // to erase a character (iCount == 0 case), using aveCharWidth. 00558 // It erases unexpected an extra char if we don't use ichNewStart 00559 // and it happens when wMaxNegCcharPos == 0. 00560 // 00561 if (ped->wMaxNegCcharPos == 0 && iCount == 0) { 00562 pT = ECAnsiPrev(ped, pText, pT); 00563 ichNewStart = (ICH)(pT - pText); 00564 } 00565 } 00566 00567 iTCount = 0; 00568 if (ichStart + iCount < ped->cch) { 00569 pTOrg = pT = pText + ichStart + iCount; 00570 while ((iTCount < (int)ped->wMaxNegAcharPos) && 00571 (ichStart + iCount + iTCount < ped->cch)) { 00572 pT = ECAnsiNext(ped, pT); 00573 iTCount = (int)(pT - pTOrg); 00574 } 00575 } 00576 00577 ECUnlock(ped); 00578 iCount = (int)(min(ichStart+iCount+iTCount, ped->cch) - ichNewStart); 00579 } else { 00580 // Reset ichStart to take care of the negative C widths 00581 ichNewStart = max((int)(ichStart - ped->wMaxNegCcharPos), 0); 00582 00583 // Reset ichCount to take care of the negative C and A widths 00584 iCount = (int)(min(ichStart+iCount+ped->wMaxNegAcharPos, ped->cch) 00585 - ichNewStart); 00586 } 00587 ichStart = ichNewStart; 00588 00589 // 00590 // Reset ichStart and iCount to the first one visible on the screen 00591 // 00592 if (ichStart < ped->ichScreenStart) { 00593 if (ichStart+iCount < ped->ichScreenStart) 00594 return; 00595 00596 iCount -= (ped->ichScreenStart-ichStart); 00597 ichStart = ped->ichScreenStart; 00598 } 00599 00600 CopyRect(&rc, &ped->rcFmt); 00601 00602 // 00603 // Set the drawing rectangle 00604 // 00605 rcClip.left = xClipStPos; 00606 rcClip.right = xClipEndPos; 00607 rcClip.top = rc.top; 00608 rcClip.bottom = rc.bottom; 00609 00610 // 00611 // Set the proper clipping rectangle 00612 // 00613 ECSetEditClip(ped, hdc, TRUE); 00614 00615 pText = ECLock(ped); 00616 00617 // 00618 // Calculate the starting pos for this piece of text 00619 // 00620 if (ped->format == ES_LEFT) { 00621 if (iStCount = (int)(ichStart - ped->ichScreenStart)) { 00622 rc.left += SLCalcXOffsetLeft(ped, hdc, ichStart); 00623 } 00624 } else { 00625 rc.left += SLCalcXOffsetSpecial(ped, hdc, ichStart); 00626 } 00627 00628 // 00629 // Set the background mode before calling NtUserGetControlBrush so that the app 00630 // can change it to TRANSPARENT if it wants to. 00631 // 00632 SetBkMode(hdc, OPAQUE); 00633 00634 if (fSelStatus) { 00635 hbrBack = SYSHBR(HIGHLIGHT); 00636 if (hbrBack == NULL) { 00637 goto sldl_errorexit; 00638 } 00639 rgbSaveBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); 00640 rgbSaveText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); 00641 00642 } else { 00643 // 00644 // We always want to send this so that the app has a chance to muck 00645 // with the DC. 00646 // 00647 // Note that ReadOnly and Disabled edit fields are drawn as "static" 00648 // instead of as "active." 00649 // 00650 hbrBack = ECGetBrush(ped, hdc); 00651 rgbSaveText = GetTextColor(hdc); 00652 } 00653 00654 // 00655 // Erase the rectangular area before text is drawn. Note that we inflate 00656 // the rect by 1 so that the selection color has a one pixel border around 00657 // the text. 00658 // 00659 InflateRect(&rcClip, 0, 1); 00660 FillRect(hdc, &rcClip, hbrBack); 00661 InflateRect(&rcClip, 0, -1); 00662 00663 if (ped->charPasswordChar) { 00664 wSaveBkMode = SetBkMode(hdc, TRANSPARENT); 00665 00666 for (iStCount = 0; iStCount < iCount; iStCount++) { 00667 if ( ped->fAnsi ) 00668 ExtTextOutA(hdc, rc.left, rc.top, ETO_CLIPPED, &rcClip, 00669 (LPSTR)&ped->charPasswordChar, 1, NULL); 00670 else 00671 ExtTextOutW(hdc, rc.left, rc.top, ETO_CLIPPED, &rcClip, 00672 (LPWSTR)&ped->charPasswordChar, 1, NULL); 00673 00674 rc.left += ped->cPasswordCharWidth; 00675 } 00676 00677 SetBkMode(hdc, wSaveBkMode); 00678 } else { 00679 if ( ped->fAnsi ) 00680 ExtTextOutA(hdc, rc.left, rc.top, ETO_CLIPPED, &rcClip, 00681 pText+ichStart,iCount, NULL); 00682 else 00683 ExtTextOutW(hdc, rc.left, rc.top, ETO_CLIPPED, &rcClip, 00684 ((LPWSTR)pText)+ichStart,iCount, NULL); 00685 } 00686 00687 SetTextColor(hdc, rgbSaveText); 00688 if (fSelStatus) { 00689 SetBkColor(hdc, rgbSaveBk); 00690 } 00691 00692 sldl_errorexit: 00693 ECUnlock(ped); 00694 } 00695 00696 /***************************************************************************\ 00697 * SLGetBlkEnd AorW 00698 * 00699 * Given a Starting point and and end point, this function return s whether the 00700 * first few characters fall inside or outside the selection block and if so, 00701 * howmany characters? 00702 * 00703 * History: 00704 \***************************************************************************/ 00705 00706 int SLGetBlkEnd( 00707 PED ped, 00708 ICH ichStart, 00709 ICH ichEnd, 00710 BOOL FAR *lpfStatus) 00711 { 00712 *lpfStatus = FALSE; 00713 if (ichStart >= ped->ichMinSel) { 00714 if (ichStart >= ped->ichMaxSel) 00715 return (ichEnd - ichStart); 00716 *lpfStatus = TRUE; 00717 return (min(ichEnd, ped->ichMaxSel) - ichStart); 00718 } 00719 return (min(ichEnd, ped->ichMinSel) - ichStart); 00720 } 00721 00722 /***************************************************************************\ 00723 * SLDrawText AorW 00724 * 00725 * Draws text for a single line edit control in the rectangle 00726 * specified by ped->rcFmt. If ichStart == 0, starts drawing text at the left 00727 * side of the window starting at character index ped->ichScreenStart and draws 00728 * as much as will fit. If ichStart > 0, then it appends the characters 00729 * starting at ichStart to the end of the text showing in the window. (ie. We 00730 * are just growing the text length and keeping the left side 00731 * (ped->ichScreenStart to ichStart characters) the same. Assumes the hdc came 00732 * from ECGetEditDC so that the caret and such are properly hidden. 00733 * 00734 * History: 00735 \***************************************************************************/ 00736 00737 void SLDrawText( 00738 PED ped, 00739 HDC hdc, 00740 ICH ichStart) 00741 { 00742 ICH cchToDraw; 00743 RECT rc; 00744 PSTR pText; 00745 BOOL fSelStatus; 00746 int iCount, iStCount; 00747 ICH ichEnd; 00748 BOOL fNoSelection; 00749 BOOL fCalcRect; 00750 BOOL fDrawLeftMargin = FALSE; 00751 BOOL fDrawEndOfLineStrip = FALSE; 00752 SIZE size; 00753 00754 if (!_IsWindowVisible(ped->pwnd)) 00755 return; 00756 00757 if (ped->pLpkEditCallout) { 00758 // The language pack handles display while complex script support present 00759 ECGetBrush(ped, hdc); // Give user a chance to manipulate the DC 00760 pText = ECLock(ped); 00761 ped->pLpkEditCallout->EditDrawText(ped, hdc, pText, ped->cch, ped->ichMinSel, ped->ichMaxSel, ped->rcFmt.top); 00762 ECUnlock(ped); 00763 SLSetCaretPosition(ped, hdc); 00764 return; 00765 } 00766 00767 /* 00768 * When drawing the entire visible content of special-aligned sle 00769 * erase the view. 00770 */ 00771 if (ped->format != ES_LEFT && ichStart == 0) 00772 FillRect(hdc, &ped->rcFmt, ECGetBrush(ped, hdc)); 00773 00774 pText = ECLock(ped); 00775 00776 if (ichStart < ped->ichScreenStart) { 00777 #if DBG 00778 ICH ichCompare = ECAdjustIch(ped, pText, ped->ichScreenStart); 00779 UserAssert(ichCompare == ped->ichScreenStart); 00780 #endif 00781 ichStart = ped->ichScreenStart; 00782 } 00783 else if (ped->fDBCS && ped->fAnsi) { 00784 /* 00785 * If ichStart stays on trailing byte of DBCS, we have to 00786 * adjust it. 00787 */ 00788 ichStart = ECAdjustIch(ped, pText, ichStart); 00789 } 00790 00791 CopyRect((LPRECT)&rc, (LPRECT)&ped->rcFmt); 00792 00793 /* 00794 * Find out how many characters will fit on the screen so that we don't do 00795 * any needless drawing. 00796 */ 00797 cchToDraw = ECCchInWidth(ped, hdc, 00798 (LPSTR)(pText + ped->ichScreenStart * ped->cbChar), 00799 ped->cch - ped->ichScreenStart, rc.right - rc.left, TRUE); 00800 ichEnd = ped->ichScreenStart + cchToDraw; 00801 00802 /* 00803 * There is no selection if, 00804 * 1. MinSel and MaxSel are equal OR 00805 * 2. (This has lost the focus AND Selection is to be hidden) 00806 */ 00807 fNoSelection = ((ped->ichMinSel == ped->ichMaxSel) || (!ped->fFocus && !ped->fNoHideSel)); 00808 00809 if (ped->format == ES_LEFT) { 00810 if (iStCount = (int)(ichStart - ped->ichScreenStart)) { 00811 rc.left += SLCalcXOffsetLeft(ped, hdc, ichStart); 00812 } 00813 } else { 00814 rc.left += SLCalcXOffsetSpecial(ped, hdc, ichStart); 00815 } 00816 00817 // 00818 // If this is the begining of the whole line, we may have to draw a blank 00819 // strip at the begining. 00820 // 00821 if ((ichStart == 0) && ped->wLeftMargin) 00822 fDrawLeftMargin = TRUE; 00823 00824 // 00825 // If there is nothing to draw, that means we need to draw the end of 00826 // line strip, which erases the last character. 00827 // 00828 if (ichStart == ichEnd) { 00829 fDrawEndOfLineStrip = TRUE; 00830 rc.left -= ped->wLeftMargin; 00831 } 00832 00833 while (ichStart < ichEnd) { 00834 fCalcRect = TRUE; 00835 00836 if (fNoSelection) { 00837 fSelStatus = FALSE; 00838 iCount = ichEnd - ichStart; 00839 } else { 00840 if (fDrawLeftMargin) { 00841 iCount = 0; 00842 fSelStatus = FALSE; 00843 fCalcRect = FALSE; 00844 rc.right = rc.left; 00845 } else 00846 iCount = SLGetBlkEnd(ped, ichStart, ichEnd, 00847 (BOOL *)&fSelStatus); 00848 } 00849 00850 00851 if (ichStart+iCount == ichEnd) { 00852 if (fSelStatus) 00853 fDrawEndOfLineStrip = TRUE; 00854 else { 00855 rc.right = ped->rcFmt.right + ped->wRightMargin; 00856 fCalcRect = FALSE; 00857 } 00858 } 00859 00860 if (fCalcRect) { 00861 if (ped->charPasswordChar) 00862 rc.right = rc.left + ped->cPasswordCharWidth * iCount; 00863 else { 00864 if ( ped->fAnsi ) 00865 GetTextExtentPointA(hdc, pText + ichStart, 00866 iCount, &size); 00867 else 00868 GetTextExtentPointW(hdc, ((LPWSTR)pText) + ichStart, 00869 iCount, &size); 00870 rc.right = rc.left + size.cx; 00871 /* 00872 * The extent is equal to the advance width. So for TrueType fonts 00873 * we need to take care of Neg A and C. For non TrueType, the extent 00874 * includes the overhang. 00875 * If drawing the selection, draw only the advance width 00876 */ 00877 if (fSelStatus) { 00878 rc.right -= ped->charOverhang; 00879 } else if (ped->fTrueType) { 00880 rc.right += ped->wMaxNegC; 00881 if (iStCount > 0) { 00882 rc.right += ped->wMaxNegA; 00883 iStCount = 0; 00884 } 00885 } 00886 00887 } /* if (ped->charPasswordChar) */ 00888 00889 } 00890 00891 if (fDrawLeftMargin) { 00892 fDrawLeftMargin = FALSE; 00893 rc.left -= ped->wLeftMargin; 00894 if (rc.right < rc.left) { 00895 rc.right = rc.left; 00896 } 00897 } 00898 00899 SLDrawLine(ped, hdc, rc.left, rc.right, ichStart, iCount, fSelStatus); 00900 ichStart += iCount; 00901 rc.left = rc.right; 00902 /* 00903 * If we're going to draw the selection, adjust rc.left 00904 * to include advance width of the selected text 00905 * For non TT fonts, ped->wMaxNegC equals ped->charOverhang 00906 */ 00907 if (!fSelStatus && (iCount != 0) && (ichStart < ichEnd)) { 00908 rc.left -= ped->wMaxNegC; 00909 } 00910 } 00911 00912 ECUnlock(ped); 00913 00914 // Check if anything to be erased on the right hand side 00915 if (fDrawEndOfLineStrip && 00916 (rc.left < (rc.right = (ped->rcFmt.right+ped->wRightMargin)))) 00917 SLDrawLine(ped, hdc, rc.left, rc.right, ichStart, 0, FALSE); 00918 00919 SLSetCaretPosition(ped, hdc); 00920 } 00921 00922 /***************************************************************************\ 00923 * SLScrollText AorW 00924 * 00925 * Scrolls the text to bring the caret into view. If the text is 00926 * scrolled, the current selection is unhighlighted. Returns TRUE if the text 00927 * is scrolled else return s false. 00928 * 00929 * History: 00930 \***************************************************************************/ 00931 00932 BOOL SLScrollText( 00933 PED ped, 00934 HDC hdc) 00935 { 00936 PSTR pTextScreenStart; 00937 ICH scrollAmount; 00938 ICH newScreenStartX = ped->ichScreenStart; 00939 ICH cch; 00940 BOOLEAN fAdjustNext = FALSE; 00941 00942 if (!ped->fAutoHScroll) 00943 return (FALSE); 00944 00945 if (ped->pLpkEditCallout) { 00946 BOOL fChanged; 00947 00948 // With complex script glyph reordering, use lpk to do horz scroll 00949 pTextScreenStart = ECLock(ped); 00950 fChanged = ped->pLpkEditCallout->EditHScroll(ped, hdc, pTextScreenStart); 00951 ECUnlock(ped); 00952 00953 if (fChanged) { 00954 SLDrawText(ped, hdc, 0); 00955 } 00956 00957 return fChanged; 00958 } 00959 00960 /* 00961 * Calculate the new starting screen position 00962 */ 00963 if (ped->ichCaret <= ped->ichScreenStart) { 00964 00965 /* 00966 * Caret is to the left of the starting text on the screen we must 00967 * scroll the text backwards to bring it into view. Watch out when 00968 * subtracting unsigned numbers when we have the possibility of going 00969 * negative. 00970 */ 00971 pTextScreenStart = ECLock(ped); 00972 00973 scrollAmount = ECCchInWidth(ped, hdc, (LPSTR)pTextScreenStart, 00974 ped->ichCaret, (ped->rcFmt.right - ped->rcFmt.left) / 4, FALSE); 00975 00976 newScreenStartX = ped->ichCaret - scrollAmount; 00977 ECUnlock(ped); 00978 } else if (ped->ichCaret != ped->ichScreenStart) { 00979 pTextScreenStart = ECLock(ped); 00980 pTextScreenStart += ped->ichScreenStart * ped->cbChar; 00981 00982 cch = ECCchInWidth(ped, hdc, (LPSTR)pTextScreenStart, 00983 ped->ichCaret - ped->ichScreenStart, 00984 ped->rcFmt.right - ped->rcFmt.left, FALSE); 00985 00986 if (cch < ped->ichCaret - ped->ichScreenStart) { 00987 fAdjustNext = TRUE; 00988 00989 /* 00990 * Scroll Forward 1/4 -- if that leaves some empty space 00991 * at the end, scroll back enough to fill the space 00992 */ 00993 newScreenStartX = ped->ichCaret - (3 * cch / 4); 00994 00995 cch = ECCchInWidth(ped, hdc, (LPSTR)pTextScreenStart, 00996 ped->cch - ped->ichScreenStart, 00997 ped->rcFmt.right - ped->rcFmt.left, FALSE); 00998 00999 if (newScreenStartX > (ped->cch - cch)) 01000 newScreenStartX = ped->cch - cch; 01001 } else if (ped->format != ES_LEFT) { 01002 01003 cch = ECCchInWidth(ped, hdc, (LPSTR)pTextScreenStart, 01004 ped->cch - ped->ichScreenStart, 01005 ped->rcFmt.right - ped->rcFmt.left, FALSE); 01006 01007 /* 01008 * Scroll the text hidden behind the left border back 01009 * into view. 01010 */ 01011 if (ped->ichScreenStart == ped->cch - cch) { 01012 01013 pTextScreenStart -= ped->ichScreenStart * ped->cbChar; 01014 cch = ECCchInWidth(ped, hdc, (LPSTR)pTextScreenStart, 01015 ped->cch, ped->rcFmt.right - ped->rcFmt.left, FALSE); 01016 01017 newScreenStartX = ped->cch - cch; 01018 } 01019 } 01020 01021 ECUnlock(ped); 01022 } 01023 01024 // 01025 // Adjust newScreenStartX 01026 // 01027 if (ped->fAnsi && ped->fDBCS) { 01028 newScreenStartX = (fAdjustNext ? ECAdjustIchNext : ECAdjustIch)(ped, 01029 ECLock(ped), 01030 newScreenStartX); 01031 ECUnlock(ped); 01032 } 01033 01034 if (ped->ichScreenStart != newScreenStartX) { 01035 // Check if we have to wipe out the left margin 01036 if (ped->wLeftMargin && (ped->ichScreenStart == 0)) { 01037 RECT rc; 01038 HBRUSH hBrush; 01039 01040 hBrush = ECGetBrush(ped, hdc); 01041 01042 CopyInflateRect(&rc, &ped->rcFmt, 0, 1); 01043 rc.right = rc.left; 01044 rc.left -= ped->wLeftMargin; 01045 01046 FillRect(hdc, &rc, hBrush); 01047 } 01048 01049 ped->ichScreenStart = newScreenStartX; 01050 SLDrawText(ped, hdc, 0); 01051 01052 // Caret pos is set by SLDrawText(). 01053 return TRUE; 01054 } 01055 01056 return FALSE; 01057 } 01058 01059 /***************************************************************************\ 01060 * SLInsertText AorW 01061 * 01062 * Adds up to cchInsert characters from lpText to the ped starting at 01063 * ichCaret. If the ped only allows a maximum number of characters, then we 01064 * will only add that many characters to the ped and send a EN_MAXTEXT 01065 * notification code to the parent of the ec. Also, if !fAutoHScroll, then we 01066 * only allow as many chars as will fit in the client rectangle. The number of 01067 * characters actually added is return ed (could be 0). If we can't allocate 01068 * the required space, we notify the parent with EN_ERRSPACE and no characters 01069 * are added. 01070 * 01071 * History: 01072 \***************************************************************************/ 01073 01074 ICH SLInsertText( 01075 PED ped, 01076 LPSTR lpText, 01077 ICH cchInsert) 01078 { 01079 HDC hdc; 01080 PSTR pText; 01081 ICH cchInsertCopy = cchInsert; 01082 ICH cchT; 01083 int textWidth; 01084 SIZE size; 01085 01086 /* 01087 * First determine exactly how many characters from lpText we can insert 01088 * into the ped. 01089 */ 01090 if( ped->cchTextMax <= ped->cch) 01091 cchInsert = 0; 01092 else { 01093 if (!ped->fAutoHScroll) { 01094 pText = ECLock(ped); 01095 hdc = ECGetEditDC(ped, TRUE); 01096 01097 cchInsert = min(cchInsert, (unsigned)(ped->cchTextMax - ped->cch)); 01098 if (ped->charPasswordChar) 01099 textWidth = ped->cch * ped->cPasswordCharWidth; 01100 else { 01101 if (ped->fAnsi) 01102 GetTextExtentPointA(hdc, (LPSTR)pText, ped->cch, &size); 01103 else 01104 GetTextExtentPointW(hdc, (LPWSTR)pText, ped->cch, &size); 01105 textWidth = size.cx; 01106 } 01107 cchT = ECCchInWidth(ped, hdc, lpText, cchInsert, 01108 ped->rcFmt.right - ped->rcFmt.left - 01109 textWidth, TRUE); 01110 cchInsert = min(cchInsert, cchT); 01111 01112 ECUnlock(ped); 01113 ECReleaseEditDC(ped, hdc, TRUE); 01114 } else { 01115 cchInsert = min((unsigned)(ped->cchTextMax - ped->cch), cchInsert); 01116 } 01117 } 01118 01119 01120 /* 01121 * Now try actually adding the text to the ped 01122 */ 01123 if (cchInsert && !ECInsertText(ped, lpText, &cchInsert)) { 01124 ECNotifyParent(ped, EN_ERRSPACE); 01125 return (0); 01126 } 01127 if (cchInsert) 01128 ped->fDirty = TRUE; /* Set modify flag */ 01129 01130 if (cchInsert < cchInsertCopy) { 01131 01132 /* 01133 * Notify parent that we couldn't insert all the text requested 01134 */ 01135 ECNotifyParent(ped, EN_MAXTEXT); 01136 } 01137 01138 /* 01139 * Update selection extents and the caret position. Note that ECInsertText 01140 * updates ped->ichCaret, ped->ichMinSel, and ped->ichMaxSel to all be after 01141 * the inserted text. 01142 */ 01143 return (cchInsert); 01144 } 01145 01146 /***************************************************************************\ 01147 * SLPasteText AorW 01148 * 01149 * Pastes a line of text from the clipboard into the edit control 01150 * starting at ped->ichMaxSel. Updates ichMaxSel and ichMinSel to point to 01151 * the end of the inserted text. Notifies the parent if space cannot be 01152 * allocated. Returns how many characters were inserted. 01153 * 01154 * History: 01155 \***************************************************************************/ 01156 01157 ICH PASCAL NEAR SLPasteText( 01158 PED ped) 01159 { 01160 HANDLE hData; 01161 LPSTR lpchClip; 01162 ICH cchAdded = 0; 01163 ICH clipLength; 01164 01165 if (!OpenClipboard(ped->hwnd)) 01166 goto PasteExitNoCloseClip; 01167 01168 if (!(hData = GetClipboardData(ped->fAnsi ? CF_TEXT : CF_UNICODETEXT)) || 01169 (GlobalFlags(hData) == GMEM_INVALID_HANDLE)) { 01170 RIPMSG1(RIP_WARNING, "SLPasteText(): couldn't get a valid handle(%x)", hData); 01171 goto PasteExit; 01172 } 01173 01174 USERGLOBALLOCK(hData, lpchClip); 01175 if (lpchClip == NULL) { 01176 RIPMSG1(RIP_WARNING, "SLPasteText(): USERGLOBALLOCK(%x) failed.", hData); 01177 goto PasteExit; 01178 } 01179 01180 if (ped->fAnsi) { 01181 LPSTR lpchClip2 = lpchClip; 01182 01183 /* 01184 * Find the first carrage return or line feed. Just add text to that point. 01185 */ 01186 clipLength = (UINT)strlen(lpchClip); 01187 for (cchAdded = 0; cchAdded < clipLength; cchAdded++) 01188 if (*lpchClip2++ == 0x0D) 01189 break; 01190 01191 } else { // !fAnsi 01192 LPWSTR lpwstrClip2 = (LPWSTR)lpchClip; 01193 01194 /* 01195 * Find the first carrage return or line feed. Just add text to that point. 01196 */ 01197 clipLength = (UINT)wcslen((LPWSTR)lpchClip); 01198 for (cchAdded = 0; cchAdded < clipLength; cchAdded++) 01199 if (*lpwstrClip2++ == 0x0D) 01200 break; 01201 } 01202 01203 /* 01204 * Insert the text (SLInsertText checks line length) 01205 */ 01206 cchAdded = SLInsertText(ped, lpchClip, cchAdded); 01207 01208 USERGLOBALUNLOCK(hData); 01209 01210 PasteExit: 01211 NtUserCloseClipboard(); 01212 01213 PasteExitNoCloseClip: 01214 return (cchAdded); 01215 } 01216 01217 /***************************************************************************\ 01218 * SLReplaceSel AorW 01219 * 01220 * Replaces the text in the current selection with the given text. 01221 * 01222 * History: 01223 \***************************************************************************/ 01224 01225 void SLReplaceSel( 01226 PED ped, 01227 LPSTR lpText) 01228 { 01229 UINT cchText; 01230 01231 // 01232 // Delete text, putting it into the clean undo buffer. 01233 // 01234 ECEmptyUndo(Pundo(ped)); 01235 ECDeleteText(ped); 01236 01237 // 01238 // B#3356 01239 // Some apps do "clear" by selecting all of the text, then replacing it 01240 // with "", in which case SLInsertText() will return 0. But that 01241 // doesn't mean failure... 01242 // 01243 if ( ped->fAnsi ) 01244 cchText = strlen(lpText); 01245 else 01246 cchText = wcslen((LPWSTR)lpText); 01247 01248 if (cchText) { 01249 BOOL fFailed; 01250 UNDO undo; 01251 HWND hwndSave; 01252 01253 // 01254 // Save undo buffer, but DO NOT CLEAR IT! 01255 // 01256 ECSaveUndo(Pundo(ped), &undo, FALSE); 01257 01258 hwndSave = ped->hwnd; 01259 fFailed = (BOOL) !SLInsertText(ped, lpText, cchText); 01260 if (!IsWindow(hwndSave)) 01261 return; 01262 01263 if (fFailed) { 01264 // 01265 // UNDO the previous edit. 01266 // 01267 ECSaveUndo(&undo, Pundo(ped), FALSE); 01268 SLUndo(ped); 01269 return; 01270 } 01271 } 01272 01273 // 01274 // Success. So update the display 01275 // 01276 ECNotifyParent(ped, EN_UPDATE); 01277 01278 if (_IsWindowVisible(ped->pwnd)) { 01279 HDC hdc; 01280 01281 hdc = ECGetEditDC(ped, FALSE); 01282 01283 if (!SLScrollText(ped, hdc)) 01284 SLDrawText(ped, hdc, 0); 01285 01286 ECReleaseEditDC(ped, hdc, FALSE); 01287 } 01288 01289 ECNotifyParent(ped, EN_CHANGE); 01290 01291 if (FWINABLE()) { 01292 NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, ped->hwnd, OBJID_CLIENT, INDEXID_CONTAINER); 01293 } 01294 } 01295 01296 /***************************************************************************\ 01297 * SLChar AorW 01298 * 01299 * Handles character input 01300 * 01301 * History: 01302 \***************************************************************************/ 01303 01304 void SLChar( 01305 PED ped, 01306 DWORD keyValue) 01307 { 01308 HDC hdc; 01309 WCHAR keyPress; 01310 BOOL updateText = FALSE; 01311 HWND hwndSave = ped->hwnd; 01312 int InsertTextLen = 1; 01313 int DBCSkey; 01314 01315 if (ped->fAnsi) 01316 keyPress = LOBYTE(keyValue); 01317 else 01318 keyPress = LOWORD(keyValue); 01319 01320 if (ped->fMouseDown || (ped->fReadOnly && keyPress != 3)) { 01321 01322 /* 01323 * Don't do anything if we are in the middle of a mousedown deal or if 01324 * this is a read only edit control, with exception of allowing 01325 * ctrl-C in order to copy to the clipboard. 01326 */ 01327 return ; 01328 } 01329 01330 if (IS_IME_ENABLED()) { 01331 ECInOutReconversionMode(ped, FALSE); 01332 } 01333 01334 switch (keyPress) { 01335 case VK_BACK: 01336 DeleteSelection: 01337 if (ECDeleteText(ped)) 01338 updateText = TRUE; 01339 break; 01340 01341 default: 01342 if (keyPress >= TEXT(' ')) 01343 { 01344 /* 01345 * If this is in [a-z],[A-Z] and we are an ES_NUMBER 01346 * edit field, bail. 01347 */ 01348 if (ped->f40Compat && TestWF(ped->pwnd, EFNUMBER)) { 01349 if (!ECIsCharNumeric(ped, keyPress)) { 01350 goto IllegalChar; 01351 } 01352 } 01353 goto DeleteSelection; 01354 } 01355 break; 01356 } 01357 01358 switch (keyPress) { 01359 case 3: 01360 01361 /* 01362 * CTRL-C Copy 01363 */ 01364 SendMessage(ped->hwnd, WM_COPY, 0, 0L); 01365 return; 01366 01367 case VK_BACK: 01368 01369 /* 01370 * Delete any selected text or delete character left if no sel 01371 */ 01372 if (!updateText && ped->ichMinSel) { 01373 01374 /* 01375 * There was no selection to delete so we just delete character 01376 left if available 01377 */ 01378 // 01379 // Calling PrevIch rather than just doing a decrement for VK_BACK 01380 // 01381 ped->ichMinSel = ECPrevIch( ped, NULL, ped->ichMinSel); 01382 ECDeleteText(ped); 01383 updateText = TRUE; 01384 } 01385 break; 01386 01387 case 22: /* CTRL-V Paste */ 01388 SendMessage(ped->hwnd, WM_PASTE, 0, 0L); 01389 return; 01390 01391 case 24: /* CTRL-X Cut */ 01392 if (ped->ichMinSel == ped->ichMaxSel) 01393 goto IllegalChar; 01394 01395 SendMessage(ped->hwnd, WM_CUT, 0, 0L); 01396 return; 01397 01398 case 26: /* CTRL-Z Undo */ 01399 SendMessage(ped->hwnd, EM_UNDO, 0, 0L); 01400 return; 01401 01402 case VK_RETURN: 01403 case VK_ESCAPE: 01404 // 01405 // If this is an edit control for a combobox and the dropdown list 01406 // is visible, forward it up to the combo. 01407 // 01408 if (ped->listboxHwnd && SendMessage(ped->hwndParent, CB_GETDROPPEDSTATE, 0, 0L)) { 01409 SendMessage(ped->hwndParent, WM_KEYDOWN, (WPARAM)keyPress, 0L); 01410 } else 01411 goto IllegalChar; 01412 return; 01413 01414 default: 01415 if (keyPress >= 0x1E) { // 1E,1F are unicode block and segment separators 01416 /* 01417 * Hide the cursor if typing, if the mouse is captured, do not mess with this 01418 * as it is going to desapear forever (no WM_SETCURSOR is sent to restore it 01419 * at the first mouse-move) 01420 * MCostea #166951 01421 */ 01422 NtUserCallNoParam(SFI_ZZZHIDECURSORNOCAPTURE); 01423 01424 if (IS_DBCS_ENABLED() && ped->fAnsi && (ECIsDBCSLeadByte(ped,(BYTE)keyPress))) { 01425 if ((DBCSkey = DbcsCombine(ped->hwnd, keyPress)) != 0 && 01426 SLInsertText(ped,(LPSTR)&DBCSkey, 2) == 2) { 01427 InsertTextLen = 2; 01428 updateText = TRUE; 01429 } else { 01430 NtUserMessageBeep(0); 01431 } 01432 } else { // Here the original code begins 01433 InsertTextLen = 1; 01434 if (SLInsertText(ped, (LPSTR)&keyPress, 1)) 01435 updateText = TRUE; 01436 else 01437 01438 /* 01439 * Beep. Since we couldn't add the text 01440 */ 01441 NtUserMessageBeep(0); 01442 } // Here the original code ends 01443 } else { 01444 01445 /* 01446 * User hit an illegal control key 01447 */ 01448 IllegalChar: 01449 NtUserMessageBeep(0); 01450 } 01451 01452 if (!IsWindow(hwndSave)) 01453 return; 01454 break; 01455 } 01456 01457 if (updateText) { 01458 01459 /* 01460 * Dirty flag (ped->fDirty) was set when we inserted text 01461 */ 01462 ECNotifyParent(ped, EN_UPDATE); 01463 hdc = ECGetEditDC(ped, FALSE); 01464 if (!SLScrollText(ped, hdc)) { 01465 if (ped->format == ES_LEFT) { 01466 // 01467 // Call SLDrawText with correct ichStart 01468 // 01469 SLDrawText(ped, hdc, max(0, (int)(ped->ichCaret - InsertTextLen - ped->wMaxNegCcharPos))); 01470 } else { 01471 /* 01472 * We can't just draw from ichStart because string may have 01473 * shifted because of alignment. 01474 */ 01475 SLDrawText(ped, hdc, 0); 01476 } 01477 } 01478 ECReleaseEditDC(ped, hdc, FALSE); 01479 ECNotifyParent(ped, EN_CHANGE); 01480 01481 if (FWINABLE()) { 01482 NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, ped->hwnd, OBJID_CLIENT, INDEXID_CONTAINER); 01483 } 01484 } 01485 } 01486 01487 /***************************************************************************\ 01488 * SLMoveSelectionRestricted AorW 01489 * 01490 * Moves the selection like MLMoveSelection, but also obeys limitations 01491 * imposed by some languages such as Thai, where the cursor cannot stop 01492 * between a character and it's attached vowel or tone marks. 01493 * 01494 * Only called if the language pack is loaded. 01495 * 01496 \***************************************************************************/ 01497 01498 ICH SLMoveSelectionRestricted( 01499 PED ped, 01500 ICH ich, 01501 BOOL fLeft) 01502 { 01503 PSTR pText; 01504 HDC hdc; 01505 ICH ichResult; 01506 01507 pText = ECLock(ped); 01508 hdc = ECGetEditDC(ped, TRUE); 01509 ichResult = ped->pLpkEditCallout->EditMoveSelection(ped, hdc, pText, ich, fLeft); 01510 ECReleaseEditDC(ped, hdc, TRUE); 01511 ECUnlock(ped); 01512 01513 return ichResult; 01514 } 01515 01516 /***************************************************************************\ 01517 * SLKeyDown AorW 01518 * 01519 * Handles cursor movement and other VIRT KEY stuff. keyMods allows 01520 * us to make SLKeyDownHandler calls and specify if the modifier keys (shift 01521 * and control) are up or down. This is useful for imnplementing the 01522 * cut/paste/clear messages for single line edit controls. If keyMods == 0, 01523 * we get the keyboard state using GetKeyState(VK_SHIFT) etc. Otherwise, the 01524 * bits in keyMods define the state of the shift and control keys. 01525 * 01526 * History: 01527 \***************************************************************************/ 01528 01529 void SLKeyDown( 01530 PED ped, 01531 DWORD virtKeyCode, 01532 int keyMods) 01533 { 01534 HDC hdc; 01535 01536 /* 01537 * Variables we will use for redrawing the updated text 01538 */ 01539 ICH newMaxSel = ped->ichMaxSel; 01540 ICH newMinSel = ped->ichMinSel; 01541 01542 /* 01543 * Flags for drawing the updated text 01544 */ 01545 BOOL updateText = FALSE; 01546 BOOL changeSelection = FALSE; /* new selection is specified by 01547 newMinSel, newMaxSel */ 01548 01549 /* 01550 * Comparisons we do often 01551 */ 01552 BOOL MinEqMax = (newMaxSel == newMinSel); 01553 BOOL MinEqCar = (ped->ichCaret == newMinSel); 01554 BOOL MaxEqCar = (ped->ichCaret == newMaxSel); 01555 01556 /* 01557 * State of shift and control keys. 01558 */ 01559 int scState; 01560 01561 /* 01562 * Combo box support 01563 */ 01564 BOOL fIsListVisible; 01565 BOOL fIsExtendedUI; 01566 01567 if (ped->fMouseDown) { 01568 01569 /* 01570 * If we are in the middle of a mouse down handler, then don't do 01571 * anything. ie. ignore keyboard input. 01572 */ 01573 return; 01574 } 01575 01576 scState = ECGetModKeys(keyMods); 01577 01578 switch (virtKeyCode) { 01579 case VK_UP: 01580 if ( ped->listboxHwnd ) { 01581 01582 /* 01583 * Handle Combobox support 01584 */ 01585 fIsExtendedUI = (BOOL)SendMessage(ped->hwndParent, CB_GETEXTENDEDUI, 0, 0); 01586 fIsListVisible = (BOOL)SendMessage(ped->hwndParent, CB_GETDROPPEDSTATE, 0, 0); 01587 01588 if (!fIsListVisible && fIsExtendedUI) { 01589 01590 /* 01591 * For TandyT 01592 */ 01593 DropExtendedUIListBox: 01594 01595 /* 01596 * Since an extendedui combo box doesn't do anything on f4, we 01597 * turn off the extended ui, send the f4 to drop, and turn it 01598 * back on again. 01599 */ 01600 SendMessage(ped->hwndParent, CB_SETEXTENDEDUI, 0, 0); 01601 SendMessage(ped->listboxHwnd, WM_KEYDOWN, VK_F4, 0); 01602 SendMessage(ped->hwndParent, CB_SETEXTENDEDUI, 1, 0); 01603 return; 01604 } else 01605 goto SendKeyToListBox; 01606 } 01607 01608 /* 01609 * else fall through 01610 */ 01611 case VK_LEFT: 01612 // 01613 // If the caret isn't at the beginning, we can move left 01614 // 01615 if (ped->ichCaret) { 01616 // 01617 // Get new caret pos. 01618 // 01619 if (scState & CTRLDOWN) { 01620 // Move caret word left 01621 ECWord(ped, ped->ichCaret, TRUE, &ped->ichCaret, NULL); 01622 } else { 01623 // Move caret char left 01624 if (ped->pLpkEditCallout) { 01625 ped->ichCaret = SLMoveSelectionRestricted(ped, ped->ichCaret, TRUE); 01626 } else 01627 ped->ichCaret = ECPrevIch(ped,NULL,ped->ichCaret); 01628 } 01629 01630 // 01631 // Get new selection 01632 // 01633 if (scState & SHFTDOWN) { 01634 if (MaxEqCar && !MinEqMax) { 01635 // Reduce selection 01636 newMaxSel = ped->ichCaret; 01637 01638 UserAssert(newMinSel == ped->ichMinSel); 01639 } else { 01640 // Extend selection 01641 newMinSel = ped->ichCaret; 01642 } 01643 } else { 01644 // 01645 // Clear selection 01646 // 01647 newMaxSel = newMinSel = ped->ichCaret; 01648 } 01649 01650 changeSelection = TRUE; 01651 } else { 01652 // 01653 // If the user tries to move left and we are at the 0th 01654 // character and there is a selection, then cancel the 01655 // selection. 01656 // 01657 if ( (ped->ichMaxSel != ped->ichMinSel) && 01658 !(scState & SHFTDOWN) ) { 01659 changeSelection = TRUE; 01660 newMaxSel = newMinSel = ped->ichCaret; 01661 } 01662 } 01663 break; 01664 01665 case VK_DOWN: 01666 if (ped->listboxHwnd) { 01667 01668 /* 01669 * Handle Combobox support 01670 */ 01671 fIsExtendedUI = (BOOL)SendMessage(ped->hwndParent, CB_GETEXTENDEDUI, 0, 0); 01672 fIsListVisible = (BOOL)SendMessage(ped->hwndParent, CB_GETDROPPEDSTATE, 0, 0); 01673 01674 if (!fIsListVisible && fIsExtendedUI) { 01675 01676 /* 01677 * For TandyT 01678 */ 01679 goto DropExtendedUIListBox; 01680 } else 01681 goto SendKeyToListBox; 01682 } 01683 01684 /* 01685 * else fall through 01686 */ 01687 case VK_RIGHT: 01688 // 01689 // If the caret isn't at the end, we can move right. 01690 // 01691 if (ped->ichCaret < ped->cch) { 01692 // 01693 // Get new caret pos. 01694 // 01695 if (scState & CTRLDOWN) { 01696 // Move caret word right 01697 ECWord(ped, ped->ichCaret, FALSE, NULL, &ped->ichCaret); 01698 } else { 01699 // Move caret char right 01700 if (ped->pLpkEditCallout) { 01701 ped->ichCaret = SLMoveSelectionRestricted(ped, ped->ichCaret, FALSE); 01702 } else 01703 ped->ichCaret = ECNextIch(ped,NULL,ped->ichCaret); 01704 } 01705 01706 // 01707 // Get new selection. 01708 // 01709 if (scState & SHFTDOWN) { 01710 if (MinEqCar && !MinEqMax) { 01711 // Reduce selection 01712 newMinSel = ped->ichCaret; 01713 01714 UserAssert(newMaxSel == ped->ichMaxSel); 01715 } else { 01716 // Extend selection 01717 newMaxSel = ped->ichCaret; 01718 } 01719 } else { 01720 // Clear selection 01721 newMaxSel = newMinSel = ped->ichCaret; 01722 } 01723 01724 changeSelection = TRUE; 01725 } else { 01726 // 01727 // If the user tries to move right and we are at the last 01728 // character and there is a selection, then cancel the 01729 // selection. 01730 // 01731 if ( (ped->ichMaxSel != ped->ichMinSel) && 01732 !(scState & SHFTDOWN) ) { 01733 newMaxSel = newMinSel = ped->ichCaret; 01734 changeSelection = TRUE; 01735 } 01736 } 01737 break; 01738 01739 case VK_HOME: 01740 // 01741 // Move caret to top. 01742 // 01743 ped->ichCaret = 0; 01744 01745 // 01746 // Update selection. 01747 // 01748 if (scState & SHFTDOWN) { 01749 if (MaxEqCar && !MinEqMax) { 01750 // Reduce selection 01751 newMinSel = ped->ichCaret; 01752 newMaxSel = ped->ichMinSel; 01753 } else { 01754 // Extend selection 01755 newMinSel = ped->ichCaret; 01756 } 01757 } else { 01758 // Clear selection 01759 newMaxSel = newMinSel = ped->ichCaret; 01760 } 01761 01762 changeSelection = TRUE; 01763 break; 01764 01765 case VK_END: 01766 // 01767 // Move caret to end. 01768 // 01769 ped->ichCaret = ped->cch; 01770 01771 // 01772 // Update selection. 01773 // 01774 newMaxSel = ped->ichCaret; 01775 if (scState & SHFTDOWN) { 01776 if (MinEqCar && !MinEqMax) { 01777 // Reduce selection 01778 newMinSel = ped->ichMaxSel; 01779 } 01780 } else { 01781 // Clear selection 01782 newMinSel = ped->ichCaret; 01783 } 01784 01785 changeSelection = TRUE; 01786 break; 01787 01788 case VK_DELETE: 01789 if (ped->fReadOnly) 01790 break; 01791 01792 switch (scState) { 01793 case NONEDOWN: 01794 01795 /* 01796 * Clear selection. If no selection, delete (clear) character 01797 * right. 01798 */ 01799 if ((ped->ichMaxSel < ped->cch) && (ped->ichMinSel == ped->ichMaxSel)) { 01800 01801 /* 01802 * Move cursor forwards and simulate a backspace. 01803 */ 01804 if (ped->pLpkEditCallout) { 01805 ped->ichMinSel = ped->ichCaret; 01806 ped->ichMaxSel = ped->ichCaret = SLMoveSelectionRestricted(ped, ped->ichCaret, FALSE); 01807 } else { 01808 ped->ichCaret = ECNextIch(ped,NULL,ped->ichCaret); 01809 ped->ichMaxSel = ped->ichMinSel = ped->ichCaret; 01810 } 01811 SLChar(ped, (UINT)VK_BACK); 01812 } 01813 if (ped->ichMinSel != ped->ichMaxSel) 01814 SLChar(ped, (UINT)VK_BACK); 01815 break; 01816 01817 case SHFTDOWN: 01818 01819 // 01820 // Send ourself a WM_CUT message if a selection exists. 01821 // Otherwise, delete the left character. 01822 // 01823 if (ped->ichMinSel == ped->ichMaxSel) { 01824 UserAssert(!ped->fEatNextChar); 01825 SLChar(ped, VK_BACK); 01826 } else 01827 SendMessage(ped->hwnd, WM_CUT, 0, 0L); 01828 01829 break; 01830 01831 case CTRLDOWN: 01832 01833 /* 01834 * Delete to end of line if no selection else delete (clear) 01835 * selection. 01836 */ 01837 if ((ped->ichMaxSel < ped->cch) && (ped->ichMinSel == ped->ichMaxSel)) { 01838 01839 /* 01840 * Move cursor to end of line and simulate a backspace. 01841 */ 01842 ped->ichMaxSel = ped->ichCaret = ped->cch; 01843 } 01844 if (ped->ichMinSel != ped->ichMaxSel) 01845 SLChar(ped, (UINT)VK_BACK); 01846 break; 01847 01848 } 01849 01850 /* 01851 * No need to update text or selection since BACKSPACE message does it 01852 * for us. 01853 */ 01854 break; 01855 01856 case VK_INSERT: 01857 switch (scState) { 01858 case CTRLDOWN: 01859 01860 /* 01861 * Copy current selection to clipboard 01862 */ 01863 SendMessage(ped->hwnd, WM_COPY, 0, 0); 01864 break; 01865 01866 case SHFTDOWN: 01867 SendMessage(ped->hwnd, WM_PASTE, 0, 0L); 01868 break; 01869 } 01870 break; 01871 01872 // VK_HANJA support 01873 case VK_HANJA: 01874 if ( HanjaKeyHandler( ped ) ) { 01875 changeSelection = TRUE; 01876 newMinSel = ped->ichCaret; 01877 newMaxSel = ped->ichCaret + (ped->fAnsi ? 2 : 1); 01878 } 01879 break; 01880 01881 case VK_F4: 01882 case VK_PRIOR: 01883 case VK_NEXT: 01884 01885 /* 01886 * Send keys to the listbox if we are a part of a combo box. This 01887 * assumes the listbox ignores keyup messages which is correct right 01888 * now. 01889 */ 01890 SendKeyToListBox: 01891 if (ped->listboxHwnd) { 01892 01893 /* 01894 * Handle Combobox support 01895 */ 01896 SendMessage(ped->listboxHwnd, WM_KEYDOWN, virtKeyCode, 0L); 01897 return; 01898 } 01899 } 01900 01901 if (changeSelection || updateText) { 01902 hdc = ECGetEditDC(ped, FALSE); 01903 01904 /* 01905 * Scroll if needed 01906 */ 01907 SLScrollText(ped, hdc); 01908 01909 if (changeSelection) 01910 SLChangeSelection(ped, hdc, newMinSel, newMaxSel); 01911 01912 if (updateText) 01913 SLDrawText(ped, hdc, 0); 01914 01915 ECReleaseEditDC(ped, hdc, FALSE); 01916 if (updateText) { 01917 ECNotifyParent(ped, EN_CHANGE); 01918 01919 if (FWINABLE()) { 01920 NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, ped->hwnd, OBJID_CLIENT, INDEXID_CONTAINER); 01921 } 01922 } 01923 } 01924 } 01925 01926 /***************************************************************************\ 01927 * SLMouseToIch AorW 01928 * 01929 * Returns the closest cch to where the mouse point is. 01930 * 01931 * History: 01932 \***************************************************************************/ 01933 01934 ICH SLMouseToIch( 01935 PED ped, 01936 HDC hdc, 01937 LPPOINT mousePt) 01938 { 01939 PSTR pText; 01940 int width = mousePt->x; 01941 int lastHighWidth, lastLowWidth; 01942 SIZE size; 01943 ICH cch; 01944 ICH cchLo, cchHi; 01945 LPSTR lpText; 01946 FnGetTextExtentPoint pGetTextExtentPoint; 01947 01948 if (ped->pLpkEditCallout) { 01949 pText = ECLock(ped); 01950 cch = ped->pLpkEditCallout->EditMouseToIch(ped, hdc, pText, ped->cch, width); 01951 ECUnlock(ped); 01952 return cch; 01953 } 01954 01955 if (width <= ped->rcFmt.left) { 01956 01957 /* 01958 * Return either the first non visible character or return 0 if at 01959 * beginning of text 01960 */ 01961 if (ped->ichScreenStart) 01962 return (ped->ichScreenStart - 1); 01963 else 01964 return (0); 01965 } 01966 01967 if (width > ped->rcFmt.right) { 01968 pText = ECLock(ped); 01969 01970 /* 01971 * Return last char in text or one plus the last char visible 01972 */ 01973 cch = ECCchInWidth(ped, hdc, 01974 (LPSTR)(pText + ped->ichScreenStart * ped->cbChar), 01975 ped->cch - ped->ichScreenStart, ped->rcFmt.right - 01976 ped->rcFmt.left, TRUE) + ped->ichScreenStart; 01977 01978 // 01979 // This is marked as JAPAN in Win31J. But it should be a DBCS 01980 // issue. LiZ -- 5/5/93 01981 // We must check DBCS Lead byte. Because ECAdjustIch() pick up Prev Char. 01982 // 1993.3.9 by yutakas 01983 // 01984 if (ped->fAnsi && ped->fDBCS) { 01985 if (cch >= ped->cch) { 01986 cch = ped->cch; 01987 } else { 01988 if (ECIsDBCSLeadByte(ped,*(pText+cch))) { 01989 cch += 2; 01990 } else { 01991 cch ++; 01992 } 01993 } 01994 ECUnlock(ped); 01995 return cch; 01996 } else { 01997 ECUnlock(ped); 01998 if (cch >= ped->cch) 01999 return (ped->cch); 02000 else 02001 return (cch + 1); 02002 } 02003 } 02004 02005 if (ped->format != ES_LEFT) { 02006 width -= SLCalcXOffsetSpecial(ped, hdc, ped->ichScreenStart); 02007 } 02008 02009 /* 02010 * Check if password hidden chars are being used. 02011 */ 02012 if (ped->charPasswordChar) 02013 return min( (DWORD)( (width - ped->rcFmt.left) / ped->cPasswordCharWidth), 02014 ped->cch); 02015 02016 if (!ped->cch) 02017 return (0); 02018 02019 pText = ECLock(ped); 02020 lpText = pText + ped->ichScreenStart * ped->cbChar; 02021 02022 pGetTextExtentPoint = ped->fAnsi ? (FnGetTextExtentPoint)GetTextExtentPointA 02023 : (FnGetTextExtentPoint)GetTextExtentPointW; 02024 width -= ped->rcFmt.left; 02025 02026 /* 02027 * If the user clicked past the end of the text, return the last character 02028 */ 02029 cchHi = ped->cch - ped->ichScreenStart; 02030 pGetTextExtentPoint(hdc, lpText, cchHi, &size); 02031 if (size.cx <= width) { 02032 cch = cchHi; 02033 goto edAdjust; 02034 } 02035 /* 02036 * Initialize Binary Search Bounds 02037 */ 02038 cchLo = 0; 02039 cchHi ++; 02040 lastLowWidth = 0; 02041 lastHighWidth = size.cx; 02042 02043 /* 02044 * Binary search for closest char 02045 */ 02046 while (cchLo < cchHi - 1) { 02047 02048 cch = (cchHi + cchLo) / 2; 02049 pGetTextExtentPoint(hdc, lpText, cch, &size); 02050 02051 if (size.cx <= width) { 02052 cchLo = cch; 02053 lastLowWidth = size.cx; 02054 } else { 02055 cchHi = cch; 02056 lastHighWidth = size.cx; 02057 } 02058 } 02059 02060 /* 02061 * When the while ends, you can't know the exact position. 02062 * Try to see if the mouse pointer was on the farest half 02063 * of the char we got and if so, adjust cch. 02064 */ 02065 if (cchLo == cch) { 02066 /* 02067 * Need to compare with lastHighWidth 02068 */ 02069 if ((lastHighWidth - width) < (width - size.cx)) { 02070 cch++; 02071 } 02072 } else { 02073 /* 02074 * Need to compare with lastLowWidth 02075 */ 02076 if ((width - lastLowWidth) < (size.cx - width)) { 02077 cch--; 02078 } 02079 } 02080 02081 edAdjust: 02082 // 02083 // Avoid to point the intermediate of double byte character 02084 // 02085 cch = ECAdjustIch( ped, pText, cch + ped->ichScreenStart ); 02086 ECUnlock(ped); 02087 return ( cch ); 02088 } 02089 02090 /***************************************************************************\ 02091 * SLMouseMotion AorW 02092 * 02093 * <brief description> 02094 * 02095 * History: 02096 \***************************************************************************/ 02097 02098 void SLMouseMotion( 02099 PED ped, 02100 UINT message, 02101 UINT virtKeyDown, 02102 LPPOINT mousePt) 02103 { 02104 DWORD selectionl; 02105 DWORD selectionh; 02106 BOOL changeSelection; 02107 ICH newMaxSel; 02108 ICH newMinSel; 02109 HDC hdc; 02110 ICH mouseIch; 02111 LPSTR pText; 02112 02113 changeSelection = FALSE; 02114 02115 newMinSel = ped->ichMinSel; 02116 newMaxSel = ped->ichMaxSel; 02117 02118 hdc = ECGetEditDC(ped, FALSE); 02119 mouseIch = SLMouseToIch(ped, hdc, mousePt); 02120 02121 switch (message) { 02122 case WM_LBUTTONDBLCLK: 02123 02124 // if shift key is down, extend selection to word we double clicked on 02125 // else clear current selection and select word. 02126 02127 // in DBCS, we have different word breaking. LiZ -- 5/5/93 02128 // In Hangeul Environment we use word selection feature because Hangeul 02129 // use SPACE as word break 02130 if (ped->fAnsi && ped->fDBCS) { 02131 pText = ECLock(ped) + mouseIch; 02132 ECWord(ped, mouseIch, 02133 (ECIsDBCSLeadByte(ped,*pText) && mouseIch < ped->cch) ? FALSE : TRUE, 02134 &selectionl, &selectionh); 02135 ECUnlock(ped); 02136 } else { 02137 ECWord(ped, mouseIch, (mouseIch) ? TRUE : FALSE, &selectionl, &selectionh); 02138 } 02139 02140 if (!(virtKeyDown & MK_SHIFT)) { 02141 // If shift key isn't down, move caret to mouse point and clear 02142 // old selection 02143 newMinSel = selectionl; 02144 newMaxSel = ped->ichCaret = selectionh; 02145 } else { 02146 // Shiftkey is down so we want to maintain the current selection 02147 // (if any) and just extend or reduce it 02148 if (ped->ichMinSel == ped->ichCaret) { 02149 newMinSel = ped->ichCaret = selectionl; 02150 ECWord(ped, newMaxSel, TRUE, &selectionl, &selectionh); 02151 } else { 02152 newMaxSel = ped->ichCaret = selectionh; 02153 ECWord(ped, newMinSel, FALSE, &selectionl, &selectionh); 02154 } 02155 /* 02156 * v-ronaar: fix bug 24627 - edit selection is weird. 02157 */ 02158 ped->ichMaxSel = ped->ichCaret; 02159 } 02160 02161 ped->ichStartMinSel = selectionl; 02162 ped->ichStartMaxSel = selectionh; 02163 02164 goto InitDragSelect; 02165 02166 case WM_MOUSEMOVE: 02167 // 02168 // We know the mouse button's down -- otherwise the OPTIMIZE 02169 // test would've failed in SLEditWndProc and never called 02170 // 02171 changeSelection = TRUE; 02172 02173 // Extend selection, move caret word right 02174 if (ped->ichStartMinSel || ped->ichStartMaxSel) { 02175 // We're in WORD SELECT mode 02176 BOOL fReverse = (mouseIch <= ped->ichStartMinSel); 02177 02178 ECWord(ped, mouseIch, !fReverse, &selectionl, &selectionh); 02179 02180 if (fReverse) { 02181 newMinSel = ped->ichCaret = selectionl; 02182 newMaxSel = ped->ichStartMaxSel; 02183 } else { 02184 newMinSel = ped->ichStartMinSel; 02185 newMaxSel = ped->ichCaret = selectionh; 02186 } 02187 } else if ((ped->ichMinSel == ped->ichCaret) && 02188 (ped->ichMinSel != ped->ichMaxSel)) 02189 // Reduce selection extent 02190 newMinSel = ped->ichCaret = mouseIch; 02191 else 02192 // Extend selection extent 02193 newMaxSel = ped->ichCaret=mouseIch; 02194 break; 02195 02196 case WM_LBUTTONDOWN: 02197 // If we currently don't have the focus yet, try to get it. 02198 if (!ped->fFocus) { 02199 if (!ped->fNoHideSel) 02200 // Clear the selection before setting the focus so that we 02201 // don't get refresh problems and flicker. Doesn't matter 02202 // since the mouse down will end up changing it anyway. 02203 ped->ichMinSel = ped->ichMaxSel = ped->ichCaret; 02204 02205 NtUserSetFocus(ped->hwnd); 02206 02207 // 02208 // BOGUS 02209 // (1) We should see if SetFocus() succeeds. 02210 // (2) We should ignore mouse messages if the first window 02211 // ancestor with a caption isn't "active." 02212 // 02213 02214 // If we are part of a combo box, then this is the first time 02215 // the edit control is getting the focus so we just want to 02216 // highlight the selection and we don't really want to position 02217 // the caret. 02218 if (ped->listboxHwnd) 02219 break; 02220 02221 // We yield at SetFocus -- text might have changed at that point 02222 // update selection and caret info accordingly 02223 // FIX for bug # 11743 -- JEFFBOG 8/23/91 02224 newMaxSel = ped->ichMaxSel; 02225 newMinSel = ped->ichMinSel; 02226 mouseIch = min(mouseIch, ped->cch); 02227 } 02228 02229 if (ped->fFocus) { 02230 // Only do this if we have the focus since a clever app may not 02231 // want to give us the focus at the SetFocus call above. 02232 if (!(virtKeyDown & MK_SHIFT)) { 02233 // If shift key isn't down, move caret to mouse point and 02234 // clear old selection 02235 newMinSel = newMaxSel = ped->ichCaret = mouseIch; 02236 } else { 02237 // Shiftkey is down so we want to maintain the current 02238 // selection (if any) and just extend or reduce it 02239 if (ped->ichMinSel == ped->ichCaret) 02240 newMinSel = ped->ichCaret = mouseIch; 02241 else 02242 newMaxSel = ped->ichCaret = mouseIch; 02243 } 02244 02245 ped->ichStartMinSel = ped->ichStartMaxSel = 0; 02246 02247 InitDragSelect: 02248 ped->fMouseDown = FALSE; 02249 NtUserSetCapture(ped->hwnd); 02250 ped->fMouseDown = TRUE; 02251 changeSelection = TRUE; 02252 } 02253 break; 02254 02255 case WM_LBUTTONUP: 02256 if (ped->fMouseDown) { 02257 ped->fMouseDown = FALSE; 02258 NtUserReleaseCapture(); 02259 } 02260 break; 02261 } 02262 02263 if (changeSelection) { 02264 SLScrollText(ped,hdc); 02265 SLChangeSelection(ped, hdc, newMinSel, newMaxSel); 02266 } 02267 02268 ECReleaseEditDC(ped, hdc, FALSE); 02269 } 02270 02271 /***************************************************************************\ 02272 * SLPaint AorW 02273 * 02274 * Handles painting of the edit control window. Draws the border if 02275 * necessary and draws the text in its current state. 02276 * 02277 * History: 02278 \***************************************************************************/ 02279 02280 void SLPaint( 02281 PED ped, 02282 HDC hdc) 02283 { 02284 HWND hwnd = ped->hwnd; 02285 HBRUSH hBrushRemote; 02286 RECT rcEdit; 02287 HANDLE hOldFont; 02288 02289 /* 02290 * Had to put in hide/show carets. The first one needs to be done before 02291 * beginpaint to correctly paint the caret if part is in the update region 02292 * and part is out. The second is for 1.03 compatibility. It breaks 02293 * micrografix's worksheet edit control if not there. 02294 */ 02295 NtUserHideCaret(hwnd); 02296 02297 if (_IsWindowVisible(ped->pwnd)) { 02298 /* 02299 * Erase the background since we don't do it in the erasebkgnd message. 02300 */ 02301 hBrushRemote = ECGetBrush(ped, hdc); 02302 _GetClientRect(ped->pwnd, (LPRECT)&rcEdit); 02303 FillRect(hdc, &rcEdit, hBrushRemote); 02304 02305 if (ped->fFlatBorder) 02306 { 02307 RECT rcT; 02308 02309 _GetClientRect(ped->pwnd, &rcT); 02310 DrawFrame(hdc, &rcT, 1, DF_WINDOWFRAME); 02311 } 02312 02313 if (ped->hFont != NULL) { 02314 /* 02315 * We have to select in the font since this may be a subclassed dc 02316 * or a begin paint dc which hasn't been initialized with out fonts 02317 * like ECGetEditDC does. 02318 */ 02319 hOldFont = SelectObject(hdc, ped->hFont); 02320 } 02321 02322 SLDrawText(ped, hdc, 0); 02323 02324 if (ped->hFont != NULL && hOldFont != NULL) { 02325 SelectObject(hdc, hOldFont); 02326 } 02327 } 02328 02329 NtUserShowCaret(hwnd); 02330 } 02331 02332 /***************************************************************************\ 02333 * SLSetFocus AorW 02334 * 02335 * Gives the edit control the focus and notifies the parent 02336 * EN_SETFOCUS. 02337 * 02338 * History: 02339 \***************************************************************************/ 02340 02341 void SLSetFocus( 02342 PED ped) 02343 { 02344 HDC hdc; 02345 02346 if (!ped->fFocus) { 02347 02348 ped->fFocus = TRUE; /* Set focus */ 02349 02350 /* 02351 * We don't want to muck with the caret since it isn't created. 02352 */ 02353 hdc = ECGetEditDC(ped, TRUE); 02354 02355 /* 02356 * Show the current selection if necessary. 02357 */ 02358 if (!ped->fNoHideSel) 02359 SLDrawText(ped, hdc, 0); 02360 02361 /* 02362 * Create the caret 02363 */ 02364 if (ped->pLpkEditCallout) { 02365 ped->pLpkEditCallout->EditCreateCaret (ped, hdc, ECGetCaretWidth(), 02366 ped->lineHeight, 0); 02367 } 02368 else { 02369 NtUserCreateCaret(ped->hwnd, (HBITMAP)NULL, 02370 ECGetCaretWidth(), 02371 ped->lineHeight ); 02372 } 02373 SLSetCaretPosition(ped, hdc); 02374 ECReleaseEditDC(ped, hdc, TRUE); 02375 NtUserShowCaret(ped->hwnd); 02376 02377 } 02378 02379 /* 02380 * Notify parent we have the focus 02381 */ 02382 ECNotifyParent(ped, EN_SETFOCUS); 02383 } 02384 02385 /***************************************************************************\ 02386 * SLKillFocus AorW 02387 * 02388 * The edit control loses the focus and notifies the parent via 02389 * EN_KILLFOCUS. 02390 * 02391 * History: 02392 \***************************************************************************/ 02393 02394 void SLKillFocus( 02395 PED ped, 02396 HWND newFocusHwnd) 02397 { 02398 if (ped->fFocus) { 02399 02400 /* 02401 * Destroy the caret (Win31/Chicago hides it first) 02402 */ 02403 NtUserDestroyCaret(); 02404 02405 ped->fFocus = FALSE; /* Clear focus */ 02406 /* 02407 * Do this only if we still have the focus. But we always notify the 02408 * parent that we lost the focus whether or not we originally had the 02409 * focus. 02410 */ 02411 02412 /* 02413 * Hide the current selection if needed 02414 */ 02415 if (!ped->fNoHideSel && (ped->ichMinSel != ped->ichMaxSel)) { 02416 NtUserInvalidateRect(ped->hwnd, NULL, FALSE); 02417 #if 0 02418 SLSetSelection(ped, ped->ichCaret, ped->ichCaret); 02419 #endif 02420 } 02421 } 02422 02423 /* 02424 * If we aren't a combo box, notify parent that we lost the focus. 02425 */ 02426 if (!ped->listboxHwnd) 02427 ECNotifyParent(ped, EN_KILLFOCUS); 02428 else { 02429 02430 /* 02431 * This editcontrol is part of a combo box and is losing the focus. If 02432 * the focus is NOT being sent to another control in the combo box 02433 * window, then it means the combo box is losing the focus. So we will 02434 * notify the combo box of this fact. 02435 */ 02436 if ((newFocusHwnd == NULL) || 02437 (!IsChild(ped->hwndParent, newFocusHwnd))) { 02438 // Excel has a slaker in it's midst. They're not using our combo 02439 // boxes, but they still expect to get all the internal messages 02440 // that we give to OUR comboboxes. And they expect them to be at 02441 // the same offset from WM_USER as they were in 3.1. 02442 // (JEFFBOG - 01/26/94) 02443 /* 02444 * Windows NT won't fix the bug described above: it only applies 02445 * to old 16-bit excel, and WOW converts msgs to Win3.1 values. 02446 */ 02447 02448 /* 02449 * Focus is being sent to a window which is not a child of the combo 02450 * box window which implies that the combo box is losing the focus. 02451 * Send a message to the combo box informing him of this fact so 02452 * that he can clean up... 02453 */ 02454 SendMessage(ped->hwndParent, CBEC_KILLCOMBOFOCUS, 0, 0L); 02455 } 02456 } 02457 } 02458 02459 02460 /***************************************************************************\ 02461 * 02462 * SLPaste() 02463 * 02464 * Does actual text paste and update. 02465 * 02466 \***************************************************************************/ 02467 void SLPaste(PED ped) 02468 { 02469 HDC hdc; 02470 02471 // 02472 // Insert contents of clipboard, after unhilighting current selection 02473 // and deleting it. 02474 // 02475 ECDeleteText(ped); 02476 SLPasteText(ped); 02477 02478 // 02479 // Update display 02480 // 02481 ECNotifyParent(ped, EN_UPDATE); 02482 02483 hdc = ECGetEditDC(ped,FALSE); 02484 02485 SLScrollText(ped, hdc); 02486 SLDrawText(ped, hdc, 0); 02487 02488 ECReleaseEditDC(ped,hdc,FALSE); 02489 02490 /* 02491 * Tell parent our text contents changed. 02492 */ 02493 ECNotifyParent(ped, EN_CHANGE); 02494 if (FWINABLE()) { 02495 NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, ped->hwnd, OBJID_CLIENT, INDEXID_CONTAINER); 02496 } 02497 } 02498 02499 02500 02501 /***************************************************************************\ 02502 * SLEditWndProc 02503 * 02504 * Class procedure for all single line edit controls. 02505 * Dispatches all messages to the appropriate handlers which are named 02506 * as follows: 02507 * SL (single line) prefixes all single line edit control procedures while 02508 * EC (edit control) prefixes all common handlers. 02509 * 02510 * The SLEditWndProc only handles messages specific to single line edit 02511 * controls. 02512 * 02513 * WARNING: If you add a message here, add it to gawEditWndProc[] in 02514 * kernel\server.c too, otherwise EditWndProcA/W will send it straight to 02515 * DefWindowProcWorker 02516 * 02517 * History: 02518 \***************************************************************************/ 02519 02520 LRESULT SLEditWndProc( 02521 HWND hwnd, 02522 PED ped, 02523 UINT message, 02524 WPARAM wParam, 02525 LPARAM lParam) 02526 { 02527 HDC hdc; 02528 PAINTSTRUCT ps; 02529 POINT pt; 02530 02531 /* 02532 * Dispatch the various messages we can receive 02533 */ 02534 switch (message) { 02535 02536 case WM_INPUTLANGCHANGE: 02537 if (ped && ped->fFocus && ped->pLpkEditCallout) { 02538 NtUserHideCaret(hwnd); 02539 hdc = ECGetEditDC(ped, TRUE); 02540 NtUserDestroyCaret(); 02541 ped->pLpkEditCallout->EditCreateCaret (ped, hdc, ECGetCaretWidth(), ped->lineHeight, (UINT)lParam); 02542 SLSetCaretPosition(ped, hdc); 02543 ECReleaseEditDC(ped, hdc, TRUE); 02544 NtUserShowCaret(hwnd); 02545 } 02546 goto PassToDefaultWindowProc; 02547 02548 case WM_STYLECHANGED: 02549 if (ped && ped->pLpkEditCallout) { 02550 switch (wParam) { 02551 02552 case GWL_STYLE: 02553 ECUpdateFormat(ped, 02554 ((LPSTYLESTRUCT)lParam)->styleNew, 02555 GetWindowLong(ped->hwnd, GWL_EXSTYLE)); 02556 return 1L; 02557 02558 case GWL_EXSTYLE: 02559 ECUpdateFormat(ped, 02560 GetWindowLong(ped->hwnd, GWL_STYLE), 02561 ((LPSTYLESTRUCT)lParam)->styleNew); 02562 return 1L; 02563 } 02564 } 02565 02566 goto PassToDefaultWindowProc; 02567 02568 case WM_CHAR: 02569 02570 /* 02571 * wParam - the value of the key 02572 lParam - modifiers, repeat count etc (not used) 02573 */ 02574 if (!ped->fEatNextChar) 02575 SLChar(ped, (UINT)wParam); 02576 else 02577 ped->fEatNextChar = FALSE; 02578 break; 02579 02580 case WM_ERASEBKGND: 02581 02582 /* 02583 * wParam - device context handle 02584 * lParam - not used 02585 * We do nothing on this message and we don't want DefWndProc to do 02586 * anything, so return 1 02587 */ 02588 return (1L); 02589 break; 02590 02591 case WM_GETDLGCODE: { 02592 LONG code = DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS; 02593 02594 /* 02595 * If this is a WM_SYSCHAR message generated by the UNDO keystroke 02596 * we want this message so we can EAT IT in "case WM_SYSCHAR:" 02597 */ 02598 if (lParam) { 02599 switch (((LPMSG)lParam)->message) { 02600 case WM_SYSCHAR: 02601 if ((HIWORD(((LPMSG)lParam)->lParam) & SYS_ALTERNATE) && 02602 ((WORD)wParam == VK_BACK)) { 02603 code |= DLGC_WANTMESSAGE; 02604 } 02605 break; 02606 02607 case WM_KEYDOWN: 02608 if (( (((WORD)wParam == VK_RETURN) || 02609 ((WORD)wParam == VK_ESCAPE)) && 02610 (ped->listboxHwnd) && 02611 TestWF(ValidateHwnd(ped->hwndParent), CBFDROPDOWN) && 02612 SendMessage(ped->hwndParent, CB_GETDROPPEDSTATE, 0, 0L))) { 02613 code |= DLGC_WANTMESSAGE; 02614 } 02615 break; 02616 } 02617 } 02618 return code; 02619 } 02620 02621 break; 02622 02623 case WM_KEYDOWN: 02624 02625 /* 02626 * wParam - virt keycode of the given key 02627 * lParam - modifiers such as repeat count etc. (not used) 02628 */ 02629 SLKeyDown(ped, (UINT)wParam, 0); 02630 break; 02631 02632 case WM_KILLFOCUS: 02633 02634 /* 02635 * wParam - handle of the window that receives the input focus 02636 lParam - not used 02637 */ 02638 02639 SLKillFocus(ped, (HWND)wParam); 02640 break; 02641 02642 case WM_CAPTURECHANGED: 02643 if (ped->fMouseDown) 02644 ped->fMouseDown = FALSE; 02645 break; 02646 02647 case WM_MOUSEMOVE: 02648 UserAssert(ped->fMouseDown); 02649 /* 02650 * FALL THRU 02651 */ 02652 02653 case WM_LBUTTONDBLCLK: 02654 case WM_LBUTTONDOWN: 02655 case WM_LBUTTONUP: 02656 /* 02657 * wParam - contains a value that indicates which virtual keys are down 02658 * lParam - contains x and y coords of the mouse cursor 02659 */ 02660 POINTSTOPOINT(pt, lParam); 02661 SLMouseMotion(ped, message, (UINT)wParam, &pt); 02662 break; 02663 02664 case WM_CREATE: 02665 02666 /* 02667 * wParam - handle to window being created 02668 lParam - points to a CREATESTRUCT that contains copies of parameters 02669 passed to the CreateWindow function. 02670 */ 02671 return (SLCreate(ped, (LPCREATESTRUCT)lParam)); 02672 break; 02673 02674 case WM_PRINTCLIENT: 02675 // wParam -- can be hdc from subclassed paint 02676 // lParam -- unused 02677 SLPaint(ped, (HDC) wParam); 02678 break; 02679 02680 case WM_PAINT: 02681 02682 /* 02683 * wParam -- can be hdc from subclassed paint 02684 * lParam -- unused 02685 */ 02686 if (wParam) 02687 hdc = (HDC) wParam; 02688 else { 02689 // this hide/show caret is outside Begin/EndPaint to handle the 02690 // case when the caret is half in/half out of the update region 02691 NtUserHideCaret(hwnd); 02692 hdc = NtUserBeginPaint(hwnd, &ps); 02693 } 02694 02695 if (_IsWindowVisible(ped->pwnd)) 02696 SLPaint(ped, hdc); 02697 02698 if (!wParam) { 02699 NtUserEndPaint(hwnd, &ps); 02700 NtUserShowCaret(hwnd); 02701 } 02702 break; 02703 02704 case WM_PASTE: 02705 02706 /* 02707 * wParam - not used 02708 * lParam - not used 02709 */ 02710 if (!ped->fReadOnly) 02711 SLPaste(ped); 02712 break; 02713 02714 case WM_SETFOCUS: 02715 02716 /* 02717 * wParam - handle of window that loses the input focus (may be NULL) 02718 lParam - not used 02719 */ 02720 SLSetFocus(ped); 02721 break; 02722 02723 case WM_SIZE: 02724 02725 /* 02726 * wParam - defines the type of resizing fullscreen, sizeiconic, 02727 sizenormal etc. 02728 lParam - new width in LOWORD, new height in HIGHWORD of client area 02729 */ 02730 ECSize(ped, NULL, TRUE); 02731 return 0L; 02732 02733 case WM_SYSKEYDOWN: 02734 /* 02735 * wParam -- virtual key code 02736 * lParam -- modifiers 02737 */ 02738 02739 /* 02740 * Are we in a combobox with the Alt key down? 02741 */ 02742 if (ped->listboxHwnd && (lParam & 0x20000000L)) { 02743 /* 02744 * Handle Combobox support. We want alt up or down arrow to behave 02745 * like F4 key which completes the combo box selection 02746 */ 02747 if (lParam & 0x1000000) { 02748 02749 /* 02750 * This is an extended key such as the arrow keys not on the 02751 * numeric keypad so just drop the combobox. 02752 */ 02753 if (wParam == VK_DOWN || wParam == VK_UP) 02754 goto DropCombo; 02755 else 02756 goto foo; 02757 } 02758 02759 if (!(GetKeyState(VK_NUMLOCK) & 1) && 02760 (wParam == VK_DOWN || wParam == VK_UP)) { 02761 02762 /* 02763 * NUMLOCK is up and the keypad up or down arrow hit: 02764 * eat character generated by keyboard driver. 02765 */ 02766 ped->fEatNextChar = TRUE; 02767 } else { 02768 goto foo; 02769 } 02770 02771 DropCombo: 02772 if (SendMessage(ped->hwndParent, 02773 CB_GETEXTENDEDUI, 0, 0) & 0x00000001) { 02774 02775 /* 02776 * Extended ui doesn't honor VK_F4. 02777 */ 02778 if (SendMessage(ped->hwndParent, CB_GETDROPPEDSTATE, 0, 0)) 02779 return(SendMessage(ped->hwndParent, CB_SHOWDROPDOWN, 0, 0)); 02780 else 02781 return (SendMessage(ped->hwndParent, CB_SHOWDROPDOWN, 1, 0)); 02782 } else 02783 return (SendMessage(ped->listboxHwnd, WM_KEYDOWN, VK_F4, 0)); 02784 } 02785 foo: 02786 if (wParam == VK_BACK) { 02787 SendMessage(ped->hwnd, WM_UNDO, 0, 0L); 02788 break; 02789 } 02790 else 02791 goto PassToDefaultWindowProc; 02792 break; 02793 02794 case EM_GETLINE: 02795 02796 /* 02797 * wParam - line number to copy (always the first line for SL) 02798 * lParam - buffer to copy text to. FIrst word is max # of bytes to copy 02799 */ 02800 return ECGetText(ped, (*(LPWORD)lParam), (LPSTR)lParam, FALSE); 02801 02802 case EM_LINELENGTH: 02803 02804 /* 02805 * wParam - ignored 02806 * lParam - ignored 02807 */ 02808 return (LONG)ped->cch; 02809 break; 02810 02811 case EM_SETSEL: 02812 /* 02813 * wParam -- start pos 02814 * lParam -- end pos 02815 */ 02816 SLSetSelection(ped, (ICH)wParam, (ICH)lParam); 02817 break; 02818 02819 case EM_REPLACESEL: 02820 02821 /* 02822 * wParam - flag for 4.0+ apps saying whether to clear undo 02823 * lParam - points to a null terminated string of replacement text 02824 */ 02825 SLReplaceSel(ped, (LPSTR)lParam); 02826 if (!ped->f40Compat || !wParam) 02827 ECEmptyUndo(Pundo(ped)); 02828 break; 02829 02830 case EM_GETFIRSTVISIBLELINE: 02831 02832 /* 02833 * wParam - not used 02834 * lParam - not used 02835 * 02836 * effects: Returns the first visible line for single line edit controls. 02837 */ 02838 return ped->ichScreenStart; 02839 break; 02840 02841 case EM_POSFROMCHAR: 02842 // 02843 // wParam -- char index in text 02844 // lParam -- not used 02845 // This function returns the (x,y) position of the character. 02846 // y is always 0 for single. 02847 // 02848 case EM_CHARFROMPOS: 02849 // 02850 // wParam -- unused 02851 // lParam -- pt in edit client coords 02852 // This function returns 02853 // LOWORD: the position of the _closest_ char 02854 // to the passed in point. 02855 // HIWORD: the index of the line (always 0 for single) 02856 02857 { 02858 LONG xyPos; 02859 02860 hdc = ECGetEditDC(ped, TRUE); 02861 02862 if (message == EM_POSFROMCHAR) 02863 xyPos = MAKELONG(SLIchToLeftXPos(ped, hdc, (ICH)wParam), 0); 02864 else { 02865 POINTSTOPOINT(pt, lParam); 02866 xyPos = SLMouseToIch(ped, hdc, &pt); 02867 } 02868 02869 ECReleaseEditDC(ped, hdc, TRUE); 02870 return((LRESULT)xyPos); 02871 break; 02872 } 02873 02874 case WM_UNDO: 02875 case EM_UNDO: 02876 SLUndo(ped); 02877 break; 02878 02879 #if 0 02880 case WM_NCPAINT: // not in server.c gawEditWndProc[] anyway. 02881 02882 /* 02883 * LATER - This is an NT optimization. It needs to be revisited 02884 * for validity once all of the Chicago changes are done - Johnl 02885 */ 02886 02887 pwnd = (PWND)HtoP(hwnd); 02888 02889 /* 02890 * Check to see if this window has any non-client areas that 02891 * would be painted. If not, don't bother calling DefWindowProc() 02892 * since it'll be a wasted c/s transition. 02893 */ 02894 if (!ped->fBorder && 02895 TestWF(pwnd, WEFDLGMODALFRAME) == 0 && 02896 !TestWF(pwnd, (WFMPRESENT | WFVPRESENT | WFHPRESENT)) && 02897 TestWF(pwnd, WFSIZEBOX) == 0) { 02898 break; 02899 } else { 02900 goto PassToDefaultWindowProc; 02901 } 02902 break; 02903 #endif 02904 02905 default: 02906 PassToDefaultWindowProc: 02907 return DefWindowProcWorker(ped->pwnd, message, wParam, lParam, ped->fAnsi); 02908 break; 02909 } /* switch (message) */ 02910 02911 return 1L; 02912 } /* SLEditWndProc */

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