00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016 #define LB_KEYDOWN WM_USER+1
00017 #define NOMODIFIER 0
00018 #define SHIFTDOWN 1
00019 #define CTLDOWN 2
00020 #define SHCTLDOWN (SHIFTDOWN + CTLDOWN)
00021
00022
00023
00024
00025 #define MAX_TYPESEARCH 256
00026
00027
BOOL LBGetDC(
PLBIV plb);
00028
void LBReleaseDC(
PLBIV plb);
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 BOOL xxxLBInvalidateRect(
PLBIV plb, LPRECT lprc, BOOL fErase)
00039 {
00040
CheckLock(plb->
spwnd);
00041
00042
if (
IsLBoxVisible(plb)) {
00043
NtUserInvalidateRect(
HWq(plb->
spwnd), lprc, fErase);
00044
return(
TRUE);
00045 }
00046
00047
if (!plb->
fRedraw)
00048 plb->
fDeferUpdate =
TRUE;
00049
00050
return(
FALSE);
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 HBRUSH
xxxLBGetBrush(
PLBIV plb, HBRUSH *phbrOld)
00061 {
00062 HBRUSH hbr;
00063 HBRUSH hbrOld;
00064
TL tlpwndParent;
00065
00066
CheckLock(plb->
spwnd);
00067
00068 SetBkMode(plb->
hdc, OPAQUE);
00069
00070
00071
00072
00073
if ((plb->
spwnd->
spwndParent ==
NULL) ||
00074 (
REBASEPWND(plb->
spwnd, spwndParent) ==
_GetDesktopWindow())) {
00075
ThreadLock(plb->
spwndParent, &tlpwndParent);
00076 hbr =
GetControlColor(
HW(plb->
spwndParent),
HWq(plb->
spwnd),
00077 plb->
hdc, WM_CTLCOLORLISTBOX);
00078
ThreadUnlock(&tlpwndParent);
00079 }
else
00080 hbr =
GetControlBrush(
HWq(plb->
spwnd), plb->
hdc, WM_CTLCOLORLISTBOX);
00081
00082
00083
00084
00085
if (hbr !=
NULL) {
00086 hbrOld = SelectObject(plb->
hdc, hbr);
00087
if (phbrOld)
00088 *phbrOld = hbrOld;
00089 }
00090
00091
return(hbr);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void LBInitDC(
PLBIV plb)
00103 {
00104 RECT rc;
00105
00106
00107
if (plb->
hFont)
00108 SelectObject(plb->
hdc, plb->
hFont);
00109
00110
00111
_GetClientRect(plb->
spwnd, &rc);
00112 IntersectClipRect(plb->
hdc, rc.left, rc.top, rc.right, rc.bottom);
00113
00114 OffsetWindowOrgEx(plb->
hdc, plb->
xOrigin, 0,
NULL);
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 BOOL LBGetDC(
00127
PLBIV plb)
00128 {
00129
if (plb->
hdc)
00130
return(
FALSE);
00131
00132 plb->
hdc =
NtUserGetDC(
HWq(plb->
spwnd));
00133
00134
LBInitDC(plb);
00135
00136
return TRUE;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 void LBTermDC(
PLBIV plb)
00147 {
00148
if (plb->
hFont)
00149 SelectObject(plb->
hdc,
ghFontSys);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void LBReleaseDC(
00161
PLBIV plb)
00162 {
00163
LBTermDC(plb);
00164
NtUserReleaseDC(
HWq(plb->
spwnd), plb->
hdc);
00165 plb->
hdc =
NULL;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 BOOL LBGetItemRect(
00180
PLBIV plb,
00181 INT sItem,
00182 LPRECT lprc)
00183 {
00184
INT sTmp;
00185
int clientbottom;
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
if (sItem && (sItem != -1) && ((
UINT)sItem >= (
UINT)plb->
cMac))
00197 {
00198
SetRectEmpty(lprc);
00199 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,
"");
00200
return (LB_ERR);
00201 }
00202
00203
_GetClientRect(plb->
spwnd, lprc);
00204
00205
if (plb->
fMultiColumn) {
00206
00207
00208
00209
00210 lprc->top = plb->
cyChar * (sItem % plb->
itemsPerColumn);
00211 lprc->bottom = lprc->top + plb->
cyChar ;
00212
00213 UserAssert(plb->
itemsPerColumn);
00214
00215
if (plb->
fRightAlign) {
00216 lprc->right = lprc->right - plb->
cxColumn *
00217 ((sItem / plb->
itemsPerColumn) - (plb->
iTop / plb->
itemsPerColumn));
00218
00219 lprc->left = lprc->right - plb->
cxColumn;
00220 }
else {
00221
00222
00223
00224 lprc->left += plb->
cxColumn *
00225 ((sItem / plb->
itemsPerColumn) - (plb->
iTop / plb->
itemsPerColumn));
00226
00227 lprc->right = lprc->left + plb->
cxColumn;
00228 }
00229 }
else if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
00230
00231
00232
00233
00234 lprc->right += plb->
xOrigin;
00235 clientbottom = lprc->bottom;
00236
00237
if (sItem >= plb->
iTop) {
00238
for (sTmp = plb->
iTop; sTmp < sItem; sTmp++) {
00239 lprc->top = lprc->top +
LBGetVariableHeightItemHeight(plb, sTmp);
00240 }
00241
00242
00243
00244
00245
00246
00247 lprc->bottom = lprc->top + (sItem < plb->
cMac ?
LBGetVariableHeightItemHeight(plb, sItem) : plb->
cyChar);
00248
return (lprc->top < clientbottom);
00249 }
else {
00250
00251
00252
00253
00254
00255
for (sTmp = sItem; sTmp < plb->
iTop; sTmp++) {
00256 lprc->top = lprc->top -
LBGetVariableHeightItemHeight(plb, sTmp);
00257 }
00258 lprc->bottom = lprc->top +
LBGetVariableHeightItemHeight(plb, sItem);
00259
return FALSE;
00260 }
00261 }
else {
00262
00263
00264
00265
00266
if (plb->
fRightAlign && !(plb->
fMultiColumn || plb->
OwnerDraw) && plb->
fHorzBar)
00267 lprc->right += plb->
xOrigin + (plb->
xRightOrigin - plb->
xOrigin);
00268
else
00269 lprc->right += plb->
xOrigin;
00270 lprc->top = (sItem - plb->
iTop) * plb->
cyChar;
00271 lprc->bottom = lprc->top + plb->
cyChar;
00272 }
00273
00274
return (sItem >= plb->
iTop) &&
00275 (sItem < (plb->
iTop +
CItemInWindow(plb,
TRUE)));
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 BOOL CALLBACK
LBPrintCallback(HDC hdc, LPWSTR lpstr,
PLBIV plb,
int cx,
int cy)
00287 {
00288
int xStart;
00289
UINT cLen;
00290 RECT rc;
00291
UINT oldAlign;
00292
00293
if (!lpstr) {
00294
return FALSE;
00295 }
00296
00297
if (plb->
fMultiColumn)
00298 xStart = 0;
00299
else
00300 xStart = 2;
00301
00302
if (plb->
fRightAlign) {
00303 oldAlign = SetTextAlign(hdc, TA_RIGHT | GetTextAlign(hdc));
00304 xStart = cx - xStart;
00305 }
00306
00307 cLen = wcslen(lpstr);
00308
00309
if (plb->
fUseTabStops) {
00310
TabTextOut(hdc, xStart, 0, lpstr, cLen,
00311 (plb->
iTabPixelPositions ? plb->
iTabPixelPositions[0] : 0),
00312 (plb->
iTabPixelPositions ? (LPINT)&plb->
iTabPixelPositions[1] :
NULL),
00313 plb->
fRightAlign ? cx : 0,
TRUE, GetTextCharset(plb->
hdc));
00314 }
else {
00315 rc.left = 0;
00316 rc.top = 0;
00317 rc.right = cx;
00318 rc.bottom =
cy;
00319
00320
if (plb->
wMultiple)
00321 ExtTextOut(hdc, xStart, 0, ETO_OPAQUE, &rc, lpstr, cLen,
NULL);
00322
else if (plb->
fMultiColumn)
00323 ExtTextOut(hdc, xStart, 0, ETO_CLIPPED, &rc, lpstr, cLen,
NULL);
00324
else {
00325 ExtTextOut(hdc, xStart, 0, 0,
NULL, lpstr, cLen,
NULL);
00326
00327
00328
00329
00330
00331
00332
if ((plb->
iTypeSearch != 0) && (plb->
OwnerDraw == 0) &&
00333 (GetBkColor(hdc) ==
SYSRGB(HIGHLIGHT))) {
00334 SIZE size;
00335 GetTextExtentPointW(hdc, lpstr, plb->
iTypeSearch, &size);
00336 PatBlt(hdc, xStart + size.cx - 1, 1, 1,
cy - 2, DSTINVERT);
00337 }
00338 }
00339 }
00340
00341
if (plb->
fRightAlign)
00342 SetTextAlign(hdc, oldAlign);
00343
00344
return(
TRUE);
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354 void xxxLBDrawLBItem(
00355
PLBIV plb,
00356 INT sItem,
00357 LPRECT lprect,
00358 BOOL fHilite,
00359 HBRUSH hbr)
00360 {
00361 LPWSTR lpstr;
00362
DWORD rgbSave;
00363
DWORD rgbBkSave;
00364
UINT uFlags;
00365 HDC hdc = plb->
hdc;
00366
UINT oldAlign;
00367
00368
CheckLock(plb->
spwnd);
00369
00370
00371
00372
00373
if (fHilite) {
00374
FillRect(hdc, lprect,
SYSHBR(HIGHLIGHT));
00375 rgbBkSave = SetBkColor(hdc,
SYSRGB(HIGHLIGHT));
00376 rgbSave = SetTextColor(hdc,
SYSRGB(HIGHLIGHTTEXT));
00377 }
else {
00378
00379
00380
00381
00382
00383
00384
if ((hbr !=
NULL) && ((sItem == plb->
iSelBase) || (plb->
fUseTabStops))) {
00385
FillRect(hdc, lprect, hbr);
00386 }
00387 }
00388
00389 uFlags = DST_COMPLEX;
00390 lpstr =
GetLpszItem(plb, sItem);
00391
00392
if (
TestWF(plb->
spwnd,
WFDISABLED)) {
00393
if ((COLORREF)
SYSRGB(GRAYTEXT) != GetBkColor(hdc))
00394 SetTextColor(hdc,
SYSRGB(GRAYTEXT));
00395
else
00396 uFlags |= DSS_UNION;
00397 }
00398
00399
if (plb->
fRightAlign)
00400 uFlags |= DSS_RIGHT;
00401
00402
if (plb->
fRtoLReading)
00403 oldAlign = SetTextAlign(hdc, TA_RTLREADING | GetTextAlign(hdc));
00404
00405 DrawState(hdc,
SYSHBR(WINDOWTEXT),
00406 (DRAWSTATEPROC)
LBPrintCallback,
00407 (LPARAM)lpstr,
00408 (WPARAM)plb,
00409 lprect->left,
00410 lprect->top,
00411 lprect->right-lprect->left,
00412 lprect->bottom-lprect->top,
00413 uFlags);
00414
00415
if (plb->fRtoLReading)
00416 SetTextAlign(hdc, oldAlign);
00417
00418
if (fHilite) {
00419 SetTextColor(hdc, rgbSave);
00420 SetBkColor(hdc, rgbBkSave);
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 void xxxLBSetCaret(
PLBIV plb, BOOL fSetCaret)
00431 {
00432 RECT rc;
00433
BOOL fNewDC;
00434
00435
if (plb->
fCaret && ((
BOOL) plb->
fCaretOn != !!fSetCaret)) {
00436
if (
IsLBoxVisible(plb)) {
00437
00438 fNewDC =
LBGetDC(plb);
00439
00440
LBGetItemRect(plb, plb->
iSelBase, &rc);
00441
00442
if (fNewDC) {
00443 SetBkColor(plb->
hdc,
SYSRGB(
WINDOW));
00444 SetTextColor(plb->
hdc,
SYSRGB(WINDOWTEXT));
00445 }
00446
00447
if (plb->
OwnerDraw) {
00448
00449
UINT itemState = (fSetCaret) ? ODS_FOCUS : 0;
00450
00451
if (
IsSelected(plb, plb->
iSelBase,
HILITEONLY))
00452 itemState |= ODS_SELECTED;
00453
00454
xxxLBoxDrawItem(plb, plb->
iSelBase, ODA_FOCUS, itemState, &rc);
00455 }
else if (!
TestWF(plb->
spwnd,
WEFPUIFOCUSHIDDEN)) {
00456 COLORREF crBk = SetBkColor(plb->
hdc,
SYSRGB(
WINDOW));
00457 COLORREF crText = SetTextColor(plb->
hdc,
SYSRGB(WINDOWTEXT));
00458
00459
DrawFocusRect(plb->
hdc, &rc);
00460
00461 SetBkColor(plb->
hdc, crBk);
00462 SetTextColor(plb->
hdc, crText);
00463 }
00464
00465
if (fNewDC)
00466
LBReleaseDC(plb);
00467 }
00468 plb->
fCaretOn = !!fSetCaret;
00469 }
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 BOOL IsSelected(
00481
PLBIV plb,
00482 INT sItem,
00483 UINT wOpFlags)
00484 {
00485 LPBYTE lp;
00486
00487
if ((sItem >= plb->
cMac) || (sItem < 0)) {
00488 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,
"");
00489
00490
return(
FALSE);
00491 }
00492
00493
if (plb->
wMultiple ==
SINGLESEL) {
00494
return (sItem == plb->
iSel);
00495 }
00496
00497 lp = plb->
rgpch + sItem +
00498 (plb->
cMac * (plb->
fHasStrings
00499 ?
sizeof(
LBItem)
00500 : (plb->
fHasData
00501 ?
sizeof(
LBODItem)
00502 : 0)));
00503 sItem = *lp;
00504
00505
if (wOpFlags ==
HILITEONLY) {
00506 sItem >>= 4;
00507 }
else {
00508 sItem &= 0x0F;
00509 }
00510
00511
return sItem;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 INT CItemInWindow(
00527
PLBIV plb,
00528 BOOL fPartial)
00529 {
00530 RECT rect;
00531
00532
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
00533
return CItemInWindowVarOwnerDraw(plb, fPartial);
00534 }
00535
00536
if (plb->
fMultiColumn) {
00537
return plb->
itemsPerColumn * (plb->
numberOfColumns + (fPartial ? 1 : 0));
00538 }
00539
00540
_GetClientRect(plb->
spwnd, &rect);
00541
00542
00543
00544
00545
00546
00547 UserAssert(plb->
cyChar);
00548
return (
INT)((rect.bottom / plb->
cyChar) +
00549 ((rect.bottom % plb->
cyChar)? (fPartial ? 1 : 0) : 0));
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 void xxxLBoxCtlScroll(
00562
PLBIV plb,
00563 INT cmd,
00564
int yAmt)
00565 {
00566
INT iTopNew;
00567
INT cItemPageScroll;
00568
DWORD dwTime = 0;
00569
00570
CheckLock(plb->
spwnd);
00571
00572
if (plb->
fMultiColumn) {
00573
00574
00575
00576
00577
00578
return;
00579 }
00580
00581 cItemPageScroll = plb->
cItemFullMax;
00582
00583
if (cItemPageScroll > 1)
00584 cItemPageScroll--;
00585
00586
if (plb->
cMac) {
00587 iTopNew = plb->
iTop;
00588
switch (cmd) {
00589
case SB_LINEUP:
00590 dwTime = yAmt;
00591 iTopNew--;
00592
break;
00593
00594
case SB_LINEDOWN:
00595 dwTime = yAmt;
00596 iTopNew++;
00597
break;
00598
00599
case SB_PAGEUP:
00600
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
00601 iTopNew =
LBPage(plb, plb->
iTop,
FALSE);
00602 }
else {
00603 iTopNew -= cItemPageScroll;
00604 }
00605
break;
00606
00607
case SB_PAGEDOWN:
00608
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
00609 iTopNew =
LBPage(plb, plb->
iTop,
TRUE);
00610 }
else {
00611 iTopNew += cItemPageScroll;
00612 }
00613
break;
00614
00615
case SB_THUMBTRACK:
00616
case SB_THUMBPOSITION: {
00617
00618
00619
00620
00621
00622
00623
00624
if (plb->
cMac < 0xFFFF) {
00625 iTopNew = yAmt;
00626 }
else {
00627 SCROLLINFO si;
00628
00629 si.cbSize =
sizeof(SCROLLINFO);
00630 si.fMask = SIF_TRACKPOS;
00631
00632
GetScrollInfo(
HWq(plb->
spwnd), SB_VERT, &si);
00633
00634 iTopNew = si.nTrackPos;
00635 }
00636
break;
00637 }
00638
case SB_TOP:
00639 iTopNew = 0;
00640
break;
00641
00642
case SB_BOTTOM:
00643 iTopNew = plb->
cMac - 1;
00644
break;
00645
00646
case SB_ENDSCROLL:
00647 plb->
fSmoothScroll =
TRUE;
00648
xxxLBSetCaret(plb,
FALSE);
00649
xxxLBShowHideScrollBars(plb);
00650
xxxLBSetCaret(plb,
TRUE);
00651
return;
00652 }
00653
00654
xxxNewITopEx(plb, iTopNew, dwTime);
00655 }
00656 }
00657
00658
00659
00660
00661
00662
00663 DWORD LBGetScrollFlags(
PLBIV plb, DWORD dwTime)
00664 {
00665
DWORD dwFlags;
00666
00667
if (
GetAppCompatFlags(
NULL) & GACF_NOSMOOTHSCROLLING)
00668
goto NoSmoothScrolling;
00669
00670
if (dwTime != 0) {
00671
dwFlags = MAKELONG(SW_SCROLLWINDOW | SW_SMOOTHSCROLL | SW_SCROLLCHILDREN, dwTime);
00672 }
else if (
TEST_EffectPUSIF(
PUSIF_LISTBOXSMOOTHSCROLLING) && plb->
fSmoothScroll) {
00673
dwFlags = SW_SCROLLWINDOW | SW_SMOOTHSCROLL | SW_SCROLLCHILDREN;
00674 plb->
fSmoothScroll =
FALSE;
00675 }
else {
00676 NoSmoothScrolling:
00677
dwFlags = SW_SCROLLWINDOW | SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN;
00678 }
00679
00680
return dwFlags;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 void xxxLBoxCtlHScroll(
00692
PLBIV plb,
00693 INT cmd,
00694
int xAmt)
00695 {
00696
int newOrigin = plb->
xOrigin;
00697
int oldOrigin = plb->
xOrigin;
00698
int windowWidth;
00699 RECT rc;
00700
DWORD dwTime = 0;
00701
00702
CheckLock(plb->
spwnd);
00703
00704
00705
00706
00707
00708
if (plb->
fMultiColumn) {
00709
00710
00711
00712
00713
xxxLBoxCtlHScrollMultiColumn(plb, cmd, xAmt);
00714
return;
00715 }
00716
00717
_GetClientRect(plb->
spwnd, &rc);
00718 windowWidth = rc.right;
00719
00720
if (plb->
cMac) {
00721
00722
switch (cmd) {
00723
case SB_LINEUP:
00724 dwTime = xAmt;
00725 newOrigin -= plb->
cxChar;
00726
break;
00727
00728
case SB_LINEDOWN:
00729 dwTime = xAmt;
00730 newOrigin += plb->
cxChar;
00731
break;
00732
00733
case SB_PAGEUP:
00734 newOrigin -= (windowWidth / 3) * 2;
00735
break;
00736
00737
case SB_PAGEDOWN:
00738 newOrigin += (windowWidth / 3) * 2;
00739
break;
00740
00741
case SB_THUMBTRACK:
00742
case SB_THUMBPOSITION:
00743 newOrigin = xAmt;
00744
break;
00745
00746
case SB_TOP:
00747 newOrigin = 0;
00748
break;
00749
00750
case SB_BOTTOM:
00751 newOrigin = plb->
maxWidth;
00752
break;
00753
00754
case SB_ENDSCROLL:
00755 plb->
fSmoothScroll =
TRUE;
00756
xxxLBSetCaret(plb,
FALSE);
00757
xxxLBShowHideScrollBars(plb);
00758
xxxLBSetCaret(plb,
TRUE);
00759
return;
00760 }
00761
00762
xxxLBSetCaret(plb,
FALSE);
00763 plb->
xOrigin = newOrigin;
00764 plb->
xOrigin =
xxxSetLBScrollParms(plb, SB_HORZ);
00765
00766
if ((cmd == SB_BOTTOM) && plb->
fRightAlign) {
00767
00768
00769
00770 plb->
xRightOrigin = plb->
xOrigin;
00771 }
00772
00773
if(oldOrigin != plb->
xOrigin) {
00774 HWND hwnd =
HWq(plb->
spwnd);
00775
DWORD dwFlags;
00776
00777
dwFlags =
LBGetScrollFlags(plb, dwTime);
00778
ScrollWindowEx(hwnd, oldOrigin-plb->
xOrigin,
00779 0,
NULL, &rc,
NULL,
NULL,
dwFlags);
00780
UpdateWindow(hwnd);
00781 }
00782
00783
xxxLBSetCaret(plb,
TRUE);
00784 }
else {
00785
00786
00787
xxxSetLBScrollParms(plb, SB_HORZ);
00788 }
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798 void xxxLBPaint(
00799
PLBIV plb,
00800 HDC hdc,
00801 LPRECT lprcBounds)
00802 {
00803
INT i;
00804 RECT rect;
00805 RECT scratchRect;
00806
BOOL fHilite;
00807
INT iLastItem;
00808 HBRUSH hbrSave =
NULL;
00809 HBRUSH hbrControl;
00810
BOOL fCaretOn;
00811 RECT rcBounds;
00812 HDC hdcSave;
00813
00814
CheckLock(plb->
spwnd);
00815
00816
if (lprcBounds ==
NULL) {
00817 lprcBounds = &rcBounds;
00818
_GetClientRect(plb->
spwnd, lprcBounds);
00819 }
00820
00821 hdcSave = plb->
hdc;
00822 plb->
hdc = hdc;
00823
00824
00825
LBInitDC(plb);
00826
00827
00828
if (fCaretOn = plb->
fCaretOn)
00829
xxxLBSetCaret(plb,
FALSE);
00830
00831 hbrSave =
NULL;
00832 hbrControl =
xxxLBGetBrush(plb, &hbrSave);
00833
00834
00835
_GetClientRect(plb->
spwnd, &rect);
00836
00837
00838
00839
if (plb->
fRightAlign && !(plb->
fMultiColumn || plb->
OwnerDraw) && plb->
fHorzBar)
00840 rect.right += plb->
xOrigin + (plb->
xRightOrigin - plb->
xOrigin);
00841
else
00842 rect.right += plb->
xOrigin;
00843
00844
00845
00846 iLastItem = plb->
iTop +
CItemInWindow(plb,
TRUE);
00847 iLastItem =
min(iLastItem, plb->
cMac - 1);
00848
00849
00850
00851
if (iLastItem == -1)
00852
FillRect(plb->
hdc, &rect, hbrControl);
00853
00854
00855
00856
00857 SetBoundsRect(plb->
hdc,
NULL, DCB_RESET | DCB_ENABLE);
00858
00859
for (i = plb->
iTop; i <= iLastItem; i++) {
00860
00861
00862
00863
00864
00865
00866 rect.bottom = rect.top + plb->
cyChar;
00867
00868
if ((
UINT)i < (
UINT)plb->
cMac) {
00869
00870
00871
00872
00873
if (plb->
OwnerDraw ==
OWNERDRAWVAR || plb->
fMultiColumn) {
00874
LBGetItemRect(plb, i, &rect);
00875 }
00876
00877
if (
IntersectRect(&scratchRect, lprcBounds, &rect)) {
00878 fHilite = !plb->
fNoSel &&
IsSelected(plb, i,
HILITEONLY);
00879
00880
if (plb->
OwnerDraw) {
00881
00882
00883
00884
00885
xxxLBoxDrawItem(plb, i, ODA_DRAWENTIRE,
00886 (
UINT)(fHilite ? ODS_SELECTED : 0), &rect);
00887 }
else {
00888
xxxLBDrawLBItem(plb, i, &rect, fHilite, hbrControl);
00889 }
00890 }
00891 }
00892 rect.top = rect.bottom;
00893 }
00894
00895
if (hbrSave !=
NULL)
00896 SelectObject(hdc, hbrSave);
00897
00898
if (fCaretOn)
00899
xxxLBSetCaret(plb,
TRUE);
00900
00901
LBTermDC(plb);
00902
00903 plb->
hdc = hdcSave;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 BOOL ISelFromPt(
00921
PLBIV plb,
00922 POINT pt,
00923 LPDWORD piItem)
00924 {
00925 RECT rect;
00926
int y;
00927
UINT mouseHighWord = 0;
00928
INT sItem;
00929
INT sTmp;
00930
00931
_GetClientRect(plb->
spwnd, &rect);
00932
00933
if (pt.y < 0) {
00934
00935
00936
00937
00938 *piItem = plb->
iTop;
00939
return TRUE;
00940 }
else if ((y = pt.y) > rect.bottom) {
00941 y = rect.bottom;
00942 mouseHighWord = 1;
00943 }
00944
00945
if (pt.x < 0 || pt.x > rect.right)
00946 mouseHighWord = 1;
00947
00948
00949
00950
00951
if (plb->
OwnerDraw !=
OWNERDRAWVAR) {
00952
if (plb->
fMultiColumn) {
00953
if (y < plb->
itemsPerColumn * plb->
cyChar) {
00954
if (plb->
fRightAlign)
00955 sItem = plb->
iTop + (
INT)((y / plb->
cyChar) +
00956 ((rect.right - pt.x) / plb->
cxColumn) * plb->
itemsPerColumn);
00957
else
00958 sItem = plb->
iTop + (
INT)((y / plb->
cyChar) +
00959 (pt.x / plb->
cxColumn) * plb->
itemsPerColumn);
00960
00961 }
else {
00962
00963
00964
00965
00966
00967 mouseHighWord = 1;
00968 sItem = plb->
iTop + (plb->
itemsPerColumn - 1) +
00969 (
INT)((pt.x / plb->
cxColumn) * plb->
itemsPerColumn);
00970 }
00971 }
else {
00972 sItem = plb->
iTop + (
INT)(y / plb->
cyChar);
00973 }
00974 }
else {
00975
00976
00977
00978
00979
00980
00981
00982 pt.x = 8;
00983 pt.y = y;
00984
for (sTmp = plb->
iTop; sTmp < plb->
cMac; sTmp++) {
00985 (
void)
LBGetItemRect(plb, sTmp, &rect);
00986
if (
PtInRect(&rect, pt)) {
00987 *piItem = sTmp;
00988
return mouseHighWord;
00989 }
00990 }
00991
00992
00993
00994
00995 *piItem = plb->
cMac - 1;
00996
return mouseHighWord;
00997 }
00998
00999
01000
01001
01002
01003
if (sItem > plb->
cMac - 1) {
01004 mouseHighWord = 1;
01005 sItem = plb->
cMac - 1;
01006 }
01007
01008 *piItem = sItem;
01009
return mouseHighWord;
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 void SetSelected(
01029
PLBIV plb,
01030 INT iSel,
01031 BOOL fSelected,
01032 UINT wOpFlags)
01033 {
01034 LPSTR lp;
01035
BYTE cMask;
01036
BYTE cSelStatus;
01037
01038
if (iSel < 0 || iSel >= plb->
cMac)
01039
return;
01040
01041
if (plb->
wMultiple ==
SINGLESEL) {
01042
if (fSelected)
01043 plb->
iSel = iSel;
01044 }
else {
01045 cSelStatus = (
BYTE)fSelected;
01046
switch (wOpFlags) {
01047
case HILITEONLY:
01048
01049
01050
01051
01052 cSelStatus = (
BYTE)(cSelStatus << 4);
01053 cMask = 0x0F;
01054
break;
01055
case SELONLY:
01056
01057
01058
01059
01060 cMask = 0xF0;
01061
break;
01062
case HILITEANDSEL:
01063
01064
01065
01066
01067 cSelStatus |= (cSelStatus << 4);
01068 cMask = 0;
01069
break;
01070 }
01071 lp = (LPSTR)(plb->
rgpch) + iSel +
01072 (plb->
cMac * (plb->
fHasStrings
01073 ?
sizeof(
LBItem)
01074 : (plb->
fHasData ?
sizeof(
LBODItem) : 0)));
01075
01076 *lp = (*lp & cMask) | cSelStatus;
01077 }
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 INT LastFullVisible(
01091
PLBIV plb)
01092 {
01093
INT iLastItem;
01094
01095
if (plb->
OwnerDraw ==
OWNERDRAWVAR || plb->
fMultiColumn) {
01096 iLastItem = plb->
iTop +
CItemInWindow(plb,
FALSE) - 1;
01097 iLastItem =
max(iLastItem, plb->
iTop);
01098 }
else {
01099 iLastItem =
min(plb->
iTop + plb->
cItemFullMax - 1, plb->
cMac - 1);
01100 }
01101
return iLastItem;
01102 }
01103
01104
01105
01106
01107
01108
01109
01110
01111 void xxxInvertLBItem(
01112
PLBIV plb,
01113 INT i,
01114 BOOL fHilite)
01115 {
01116 RECT rect;
01117
BOOL fCaretOn;
01118 HBRUSH hbrControl;
01119
BOOL fNewDC;
01120
01121
CheckLock(plb->
spwnd);
01122
01123
01124
if (plb->
fNoSel || (i < plb->
iTop) || (i >= (plb->
iTop +
CItemInWindow(plb,
TRUE))))
01125
return;
01126
01127
if (
IsLBoxVisible(plb)) {
01128
LBGetItemRect(plb, i, &rect);
01129
01130
01131
01132
01133
01134
if (fCaretOn = plb->
fCaretOn) {
01135
xxxLBSetCaret(plb,
FALSE);
01136 }
01137
01138 fNewDC =
LBGetDC(plb);
01139
01140 hbrControl =
xxxLBGetBrush(plb,
NULL);
01141
01142
if (!plb->
OwnerDraw) {
01143
if (!fHilite) {
01144
FillRect(plb->
hdc, &rect, hbrControl);
01145 hbrControl =
NULL;
01146 }
01147
01148
xxxLBDrawLBItem(plb, i, &rect, fHilite, hbrControl);
01149 }
else {
01150
01151
01152
01153
01154
01155
xxxLBoxDrawItem(plb, i, ODA_SELECT,
01156 (
UINT)(fHilite ? ODS_SELECTED : 0), &rect);
01157 }
01158
01159
if (fNewDC)
01160
LBReleaseDC(plb);
01161
01162
01163
01164
01165
if (fCaretOn) {
01166
xxxLBSetCaret(plb,
TRUE);
01167 }
01168 }
01169 }
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 void xxxResetWorld(
01182
PLBIV plb,
01183 INT iStart,
01184 INT iEnd,
01185 BOOL fSelect)
01186 {
01187
INT i;
01188
INT iLastInWindow;
01189
BOOL fCaretOn;
01190
01191
CheckLock(plb->
spwnd);
01192
01193
01194
01195
01196
01197
if (iStart > iEnd) {
01198 i = iStart;
01199 iStart = iEnd;
01200 iEnd = i;
01201 }
01202
01203
if (plb->
wMultiple ==
SINGLESEL) {
01204
if (plb->
iSel != -1 && ((plb->
iSel < iStart) || (plb->
iSel > iEnd))) {
01205
xxxInvertLBItem(plb, plb->
iSel, fSelect);
01206 plb->
iSel = -1;
01207 }
01208
return;
01209 }
01210
01211 iLastInWindow = plb->
iTop +
CItemInWindow(plb,
TRUE);
01212
01213
if (fCaretOn = plb->
fCaretOn)
01214
xxxLBSetCaret(plb,
FALSE);
01215
01216
for (i = 0; i < plb->
cMac; i++) {
01217
if (i == iStart)
01218
01219 i = iEnd;
01220
else {
01221
if ((plb->
iTop <= i) && (i <= iLastInWindow) &&
01222 (fSelect !=
IsSelected(plb, i,
HILITEONLY)))
01223
01224
01225
xxxInvertLBItem(plb, i, fSelect);
01226
01227
01228
SetSelected(plb, i, fSelect,
HILITEANDSEL);
01229 }
01230 }
01231
01232
if (fCaretOn)
01233
xxxLBSetCaret(plb,
TRUE);
01234
01235 }
01236
01237
01238
01239
01240
01241
01242
01243
01244 void xxxNotifyOwner(
01245
PLBIV plb,
01246 INT sEvt)
01247 {
01248
TL tlpwndParent;
01249
01250
CheckLock(plb->
spwnd);
01251
01252
ThreadLock(plb->
spwndParent, &tlpwndParent);
01253
SendMessage(
HW(plb->
spwndParent), WM_COMMAND,
01254 MAKELONG(
PTR_TO_ID(plb->
spwnd->
spmenu), sEvt), (LPARAM)
HWq(plb->
spwnd));
01255
ThreadUnlock(&tlpwndParent);
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265 void xxxSetISelBase(
01266
PLBIV plb,
01267 INT sItem)
01268 {
01269
CheckLock(plb->
spwnd);
01270
01271
xxxLBSetCaret(plb,
FALSE);
01272 plb->
iSelBase = sItem;
01273
xxxLBSetCaret(plb,
TRUE);
01274
01275
if (
FWINABLE()) {
01276
xxxInsureVisible(plb, plb->
iSelBase,
FALSE);
01277
if (
_IsWindowVisible(plb->
spwnd)) {
01278
LBEvent(plb, EVENT_OBJECT_FOCUS, sItem);
01279 }
01280 }
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290 void xxxTrackMouse(
01291
PLBIV plb,
01292 UINT wMsg,
01293 POINT pt)
01294 {
01295
INT iSelFromPt;
01296
INT iSelTemp;
01297
BOOL mousetemp;
01298
BOOL fMouseInRect;
01299 RECT rcClient;
01300
UINT wModifiers = 0;
01301
BOOL fSelected;
01302
UINT uEvent = 0;
01303
INT trackPtRetn;
01304 HWND hwnd =
HWq(plb->
spwnd);
01305
TL tlpwndEdit;
01306
TL tlpwndParent;
01307
01308
CheckLock(plb->
spwnd);
01309
01310
01311
01312
01313
if ((wMsg != WM_LBUTTONDOWN) && (wMsg != WM_LBUTTONDBLCLK)) {
01314
if (!plb->
fCaptured) {
01315
return;
01316 }
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
if ((wMsg == WM_MOUSEMOVE) && RtlEqualMemory(&pt, &(plb->
ptPrev),
sizeof(POINT))
01327 &&
gpsi->bLastRITWasKeyboard) {
01328 RIPMSG0(RIP_WARNING,
"xxxTrackMouse ignoring WM_MOUSEMOVE with no mouse movement");
01329
return;
01330 }
01331 }
01332
01333 mousetemp =
ISelFromPt(plb, pt, &iSelFromPt);
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 fMouseInRect = !mousetemp || !plb->
pcbox;
01344
01345
_GetClientRect(plb->
spwnd, &rcClient);
01346
01347
switch (wMsg) {
01348
case WM_LBUTTONDBLCLK:
01349
case WM_LBUTTONDOWN:
01350
01351
01352
01353
01354
01355
if (plb->
fCaptured) {
01356
01357
01358
01359
01360
01361
01362
if (plb->
pcbox && mousetemp) {
01363
_ClientToScreen(plb->
spwnd, &pt);
01364
01365
if (!
PtInRect(&plb->
spwnd->
rcWindow, pt)) {
01366
01367
01368
01369
01370
xxxCBHideListBoxWindow(plb->
pcbox,
TRUE,
FALSE);
01371 }
else if (!
PtInRect(&plb->
spwnd->
rcClient, pt)) {
01372
01373
01374
01375
01376 plb->
fCaptured =
FALSE;
01377
NtUserReleaseCapture();
01378
01379
SendMessageWorker(plb->
spwnd, WM_NCLBUTTONDOWN,
01380
FindNCHit(plb->
spwnd, POINTTOPOINTS(pt)),
01381 MAKELONG(pt.x, pt.y),
FALSE);
01382
01383
NtUserSetCapture(hwnd);
01384 plb->
fCaptured =
TRUE;
01385 }
01386
01387
break;
01388 }
01389
01390 plb->
fCaptured =
FALSE;
01391
NtUserReleaseCapture();
01392 }
01393
01394
if (plb->
pcbox) {
01395
01396
01397
01398
01399
01400
01401
ThreadLock(plb->
pcbox->
spwndEdit, &tlpwndEdit);
01402
NtUserSetFocus(
HWq(plb->
pcbox->
spwndEdit));
01403
ThreadUnlock(&tlpwndEdit);
01404 }
else {
01405
01406
01407
01408
01409
01410
01411
NtUserSetFocus(hwnd);
01412
if (!plb->
fCaret)
01413
return;
01414 }
01415
01416
if (plb->
fAddSelMode) {
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
NtUserKillTimer(hwnd,
IDSYS_CARET);
01432
01433
01434
01435
01436
xxxLBSetCaret(plb,
TRUE);
01437 plb->
fAddSelMode =
FALSE;
01438 }
01439
01440
if (!plb->
cMac) {
01441
01442
01443
01444
01445
01446
01447
01448
break;
01449 }
01450
01451
if (mousetemp) {
01452
01453
01454
01455
01456
break;
01457 }
01458
01459 plb->
fDoubleClick = (wMsg == WM_LBUTTONDBLCLK);
01460
01461
if (!plb->
fDoubleClick) {
01462
01463
01464
01465
01466
01467
01468
01469
ThreadLock(plb->
spwndParent, &tlpwndParent);
01470 trackPtRetn = (
INT)
SendMessage(
HW(plb->
spwndParent), WM_LBTRACKPOINT,
01471 (
DWORD)iSelFromPt, MAKELONG(pt.x+plb->
xOrigin, pt.y));
01472
ThreadUnlock(&tlpwndParent);
01473
if (trackPtRetn) {
01474
if (trackPtRetn == 2) {
01475
01476
01477
01478
01479
NtUserCallNoParam(SFI__RESETDBLCLK);
01480 }
01481
return;
01482 }
01483 }
01484
01485
if (plb->
pcbox) {
01486
01487
01488
01489
01490
01491
01492 plb->
iLastSelection = plb->
iSel;
01493 }
01494
01495
01496
01497
01498 plb->
ptPrev = pt;
01499
01500 plb->
fMouseDown =
TRUE;
01501
NtUserSetCapture(hwnd);
01502 plb->
fCaptured =
TRUE;
01503
01504
if (plb->
fDoubleClick) {
01505
01506
01507
01508
01509
xxxTrackMouse(plb, WM_LBUTTONUP, pt);
01510
return;
01511 }
01512
01513
01514
01515
01516
01517
NtUserSetTimer(hwnd,
IDSYS_SCROLL,
gpsi->dtScroll,
NULL);
01518
01519
01520
01521
01522
01523
01524
if (plb->
wMultiple ==
EXTENDEDSEL) {
01525
if (
GetKeyState(VK_SHIFT) < 0)
01526 wModifiers =
SHIFTDOWN;
01527
if (
GetKeyState(VK_CONTROL) < 0)
01528 wModifiers +=
CTLDOWN;
01529
01530
01531
01532
01533 }
01534
01535
01536
switch (wModifiers) {
01537
case NOMODIFIER:
01538 MouseMoveHandler:
01539
if (plb->
iSelBase != iSelFromPt) {
01540
xxxLBSetCaret(plb,
FALSE);
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 iSelTemp = (fMouseInRect ? iSelFromPt : -1);
01555
01556
01557
01558
01559
01560
if (plb->
wMultiple !=
MULTIPLESEL) {
01561
xxxResetWorld(plb, iSelTemp, iSelTemp,
FALSE);
01562
01563
01564
01565
01566
if ((iSelTemp == -1) && (plb->
iSel != -1)) {
01567 uEvent = EVENT_OBJECT_SELECTIONREMOVE;
01568 }
01569 }
01570
01571 fSelected =
IsSelected(plb, iSelTemp,
HILITEONLY);
01572
if (iSelTemp != -1) {
01573
01574
01575
01576
01577
01578
if (((plb->
wMultiple ==
MULTIPLESEL) && (wMsg != WM_LBUTTONDBLCLK)) || !fSelected) {
01579
SetSelected(plb, iSelTemp, !fSelected,
HILITEANDSEL);
01580
01581
01582
01583
01584
xxxInvertLBItem(plb, iSelTemp, !fSelected);
01585 fSelected = !fSelected;
01586
if (plb->
wMultiple ==
MULTIPLESEL) {
01587 uEvent = (fSelected ? EVENT_OBJECT_SELECTIONADD :
01588 EVENT_OBJECT_SELECTIONREMOVE);
01589 }
else {
01590 uEvent = EVENT_OBJECT_SELECTION;
01591 }
01592 }
01593 }
01594
01595
01596
01597
01598 plb->
iSel = iSelTemp;
01599
01600
01601
01602
01603 plb->
iMouseDown = iSelFromPt;
01604 plb->
iLastMouseMove = iSelFromPt;
01605 plb->
fNewItemState = fSelected;
01606
01607
break;
01608
case SHIFTDOWN:
01609
01610
01611
01612
01613
01614 plb->
iLastMouseMove = plb->
iSel = iSelFromPt;
01615
01616
01617
01618
01619
01620
01621
if (plb->
iMouseDown == -1) {
01622 plb->
iMouseDown = iSelFromPt;
01623
01624
01625
01626
01627
xxxResetWorld(plb, plb->
iMouseDown, plb->
iMouseDown,
FALSE);
01628
01629
01630
01631
01632
SetSelected(plb, plb->
iMouseDown,
TRUE,
HILITEANDSEL);
01633
xxxInvertLBItem(plb, plb->
iMouseDown,
TRUE);
01634
01635
01636
01637 uEvent = EVENT_OBJECT_SELECTION;
01638 }
else {
01639
01640
01641
01642
01643
xxxResetWorld(plb, plb->
iMouseDown, plb->
iMouseDown,
FALSE);
01644
01645
01646
01647
01648
xxxAlterHilite(plb, plb->
iMouseDown, iSelFromPt,
HILITE,
HILITEONLY,
FALSE);
01649 uEvent = EVENT_OBJECT_SELECTIONWITHIN;
01650 }
01651 plb->
fNewItemState = (
UINT)
TRUE;
01652
break;
01653
01654
case CTLDOWN:
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 plb->
iMouseDown = plb->
iLastMouseMove = plb->
iSel = iSelFromPt;
01665
01666
01667
01668
01669 plb->
fNewItemState = (
UINT)!
IsSelected(plb, iSelFromPt, (
UINT)
HILITEONLY);
01670
01671
01672
01673
01674
SetSelected(plb, iSelFromPt, plb->
fNewItemState,
HILITEANDSEL);
01675
xxxInvertLBItem(plb, iSelFromPt, plb->
fNewItemState);
01676 uEvent = (plb->
fNewItemState ? EVENT_OBJECT_SELECTIONADD :
01677 EVENT_OBJECT_SELECTIONREMOVE);
01678
break;
01679
01680
case SHCTLDOWN:
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
if (plb->
fNewItemState) {
01697
xxxAlterHilite(plb, plb->
iMouseDown, plb->
iLastMouseMove,
FALSE,
HILITEANDSEL,
FALSE);
01698 }
01699 plb->
iLastMouseMove = plb->
iSel = iSelFromPt;
01700
01701
01702
01703
01704
if (plb->
iMouseDown == -1) {
01705
01706
01707
01708
01709 plb->
iMouseDown = iSelFromPt;
01710 }
01711
01712
01713
01714
01715
01716
01717
01718
01719 plb->
fNewItemState = (
UINT)
IsSelected(plb, plb->
iMouseDown,
HILITEONLY);
01720
01721
01722
01723
01724
xxxAlterHilite(plb, plb->
iMouseDown, iSelFromPt, plb->
fNewItemState,
HILITEONLY,
FALSE);
01725 uEvent = EVENT_OBJECT_SELECTIONWITHIN;
01726
break;
01727 }
01728
01729
01730
01731
01732
01733
if (plb->
iSelBase != iSelFromPt) {
01734
01735
01736
01737
01738
01739
xxxSetISelBase(plb, iSelFromPt);
01740 }
01741
01742
01743
01744
01745
01746
if (
FWINABLE() && uEvent) {
01747
LBEvent(plb, uEvent, iSelFromPt);
01748 }
01749
if (wMsg == WM_LBUTTONDOWN &&
TestWF(plb->
spwnd,
WEFDRAGOBJECT)) {
01750
if (
NtUserDragDetect(hwnd, pt)) {
01751
01752
01753
01754
01755
01756
01757
01758
01759
xxxTrackMouse(plb, WM_LBUTTONUP, pt);
01760
01761
01762
01763
01764
01765
01766
ThreadLock(plb->
spwndParent, &tlpwndParent);
01767
SendMessage(
HW(plb->
spwndParent), WM_BEGINDRAG, plb->
iSelBase,
01768 (LPARAM)hwnd);
01769
ThreadUnlock(&tlpwndParent);
01770 }
else {
01771
xxxTrackMouse(plb, WM_LBUTTONUP, pt);
01772 }
01773
return;
01774 }
01775
break;
01776
01777
case WM_MOUSEMOVE: {
01778
int dist;
01779
int iTimer;
01780
01781
01782
01783
01784 plb->
ptPrev = pt;
01785
01786
01787
01788
01789
if (plb->
fMouseDown) {
01790
if (plb->
fMultiColumn) {
01791
if ((pt.x < 0) || (pt.x >= rcClient.right - 1)) {
01792
01793
01794
01795
01796
01797 dist = pt.x < 0 ? -pt.x : (pt.x - rcClient.right + 1);
01798 iTimer = ((
gpsi->dtScroll * 3) / 2) - ((WORD) dist << 4);
01799
01800
if (plb->
fRightAlign)
01801
xxxLBoxCtlHScrollMultiColumn(plb, (pt.x < 0 ? SB_LINEDOWN : SB_LINEUP), 0);
01802
else
01803
xxxLBoxCtlHScrollMultiColumn(plb, (pt.x < 0 ? SB_LINEUP : SB_LINEDOWN), 0);
01804
01805
goto SetTimerAndSel;
01806 }
01807 }
else if ((pt.y < 0) || (pt.y >= rcClient.bottom - 1)) {
01808
01809
01810
01811 dist = pt.y < 0 ? -pt.y : (pt.y - rcClient.bottom + 1);
01812 iTimer =
gpsi->dtScroll - ((WORD) dist << 4);
01813
01814
xxxLBoxCtlScroll(plb, (pt.y < 0 ? SB_LINEUP : SB_LINEDOWN), 0);
01815 SetTimerAndSel:
01816
NtUserSetTimer(hwnd,
IDSYS_SCROLL,
max(iTimer, 1),
NULL);
01817
ISelFromPt(plb, pt, &iSelFromPt);
01818 }
01819 }
else {
01820
01821
01822
01823
if (!
PtInRect(&rcClient, pt))
01824
break;
01825 }
01826
01827
switch (plb->
wMultiple) {
01828
case SINGLESEL:
01829
01830
01831
01832
01833
goto MouseMoveHandler;
01834
break;
01835
01836
case MULTIPLESEL:
01837
case EXTENDEDSEL:
01838
01839
01840
01841
01842
if (plb->
iSelBase != iSelFromPt) {
01843
xxxSetISelBase(plb, iSelFromPt);
01844
01845
01846
01847
01848
01849
if (plb->
wMultiple ==
EXTENDEDSEL) {
01850
xxxLBBlockHilite(plb, iSelFromPt,
FALSE);
01851
if (
FWINABLE())
01852
LBEvent(plb, EVENT_OBJECT_SELECTIONWITHIN, iSelFromPt);
01853 }
01854 plb->
iLastMouseMove = iSelFromPt;
01855 }
01856
break;
01857 }
01858
break;
01859 }
01860
case WM_LBUTTONUP:
01861
if (plb->
fMouseDown)
01862
xxxLBButtonUp(plb,
LBUP_RELEASECAPTURE |
LBUP_NOTIFY |
01863 (mousetemp ?
LBUP_RESETSELECTION : 0) |
01864 (fMouseInRect ?
LBUP_SUCCESS : 0));
01865 }
01866 }
01867
01868
01869
01870
01871
01872
01873
01874
01875 void xxxLBButtonUp(
PLBIV plb, UINT uFlags)
01876 {
01877
01878
CheckLock(plb->
spwnd);
01879
01880
01881
01882
01883
01884
01885
if (plb->
wMultiple ==
EXTENDEDSEL)
01886
xxxAlterHilite(plb, plb->
iMouseDown, plb->
iLastMouseMove,
01887 plb->
fNewItemState,
SELONLY,
FALSE);
01888
01889
01890
01891
01892
01893
if (plb->
pcbox && (uFlags &
LBUP_RESETSELECTION)) {
01894
int iSelOld;
01895
01896 iSelOld = plb->
iSel;
01897
01898
if (iSelOld >= 0)
01899
xxxInvertLBItem(plb, plb->
iSel,
FALSE);
01900
01901 plb->
iSel = plb->
iLastSelection;
01902
xxxInvertLBItem(plb, plb->
iSel,
TRUE);
01903
01904
01905
01906
01907
01908
01909
01910
if (
FWINABLE())
01911
LBEvent(plb, EVENT_OBJECT_SELECTION, plb->
iSel);
01912
01913
01914
01915
01916
01917
if ((uFlags &
LBUP_NOTIFY) && plb->
fNotify && (iSelOld != plb->
iSel))
01918
xxxNotifyOwner(plb, LBN_SELCHANGE);
01919 }
01920
01921
NtUserKillTimer(
HWq(plb->
spwnd),
IDSYS_SCROLL);
01922 plb->
fMouseDown =
FALSE;
01923
if (plb->
fCaptured) {
01924 plb->
fCaptured =
FALSE;
01925
if (uFlags &
LBUP_RELEASECAPTURE)
01926
NtUserReleaseCapture();
01927 }
01928
01929
01930
01931
if (plb->
iSelBase < plb->
iTop ||
01932 plb->
iSelBase > plb->
iTop +
CItemInWindow(plb,
TRUE))
01933
xxxInsureVisible(plb, plb->
iSelBase,
FALSE);
01934
01935
if (plb->
fNotify) {
01936
if (uFlags &
LBUP_NOTIFY) {
01937
if (uFlags &
LBUP_SUCCESS) {
01938
01939
01940
01941
if ((plb->
fDoubleClick) && !
TestWF(plb->
spwnd,
WFWIN31COMPAT))
01942
xxxNotifyOwner(plb, LBN_SELCHANGE);
01943
01944
01945
01946
01947
xxxNotifyOwner(plb, (plb->
fDoubleClick) ? LBN_DBLCLK : LBN_SELCHANGE);
01948 }
else {
01949
01950
01951
01952
xxxNotifyOwner(plb, LBN_SELCANCEL);
01953 }
01954 }
else if (uFlags &
LBUP_SELCHANGE) {
01955
01956
01957
01958
01959
01960 UserAssert(
TestWF(plb->
spwnd,
WFWIN40COMPAT));
01961
if (plb->
iLastSelection != plb->
iSel)
01962
xxxNotifyOwner(plb, LBN_SELCHANGE);
01963
01964 }
01965 }
01966
01967 }
01968
01969
01970
01971
01972
01973
01974
01975
01976 INT IncrementISel(
01977
PLBIV plb,
01978 INT iSel,
01979 INT sInc)
01980 {
01981
01982
01983
01984
01985 iSel += sInc;
01986
if (iSel < 0) {
01987
return 0;
01988 }
else if (iSel >= plb->
cMac) {
01989
return plb->
cMac - 1;
01990 }
01991
return iSel;
01992 }
01993
01994
01995
01996
01997
01998
01999
02000 void xxxNewITop(
PLBIV plb, INT iTopNew)
02001 {
02002
xxxNewITopEx(plb, iTopNew, 0);
02003 }
02004
02005
02006
02007
02008
02009
02010
02011
02012 void xxxNewITopEx(
02013
PLBIV plb,
02014 INT iTopNew,
02015 DWORD dwTime)
02016 {
02017
int iTopOld;
02018
BOOL fCaretOn;
02019
BOOL fMulti = plb->
fMultiColumn;
02020
02021
CheckLock(plb->
spwnd);
02022
02023
02024
if (fCaretOn = plb->
fCaretOn)
02025
xxxLBSetCaret(plb,
FALSE);
02026
02027 iTopOld = (fMulti) ? (plb->
iTop / plb->
itemsPerColumn) : plb->
iTop;
02028 plb->
iTop = iTopNew;
02029 iTopNew =
xxxSetLBScrollParms(plb, (fMulti) ? SB_HORZ : SB_VERT);
02030 plb->
iTop = (fMulti) ? (iTopNew * plb->
itemsPerColumn) : iTopNew;
02031
02032
if (!
IsLBoxVisible(plb)) {
02033
return;
02034 }
02035
02036
if (iTopNew != iTopOld) {
02037
int xAmt, yAmt;
02038 RECT rc;
02039
DWORD dwFlags;
02040
02041
_GetClientRect(plb->
spwnd, &rc);
02042
02043
if (fMulti) {
02044 yAmt = 0;
02045
if (
abs(iTopNew - iTopOld) > plb->
numberOfColumns)
02046
02047
02048 xAmt = 32000;
02049
else {
02050 xAmt = (iTopOld - iTopNew) * plb->
cxColumn;
02051
if (plb->
fRightAlign)
02052 xAmt = -xAmt;
02053 }
02054 }
else {
02055 xAmt = 0;
02056
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
02057
02058
02059
02060
02061 plb->
iTop = iTopOld;
02062 yAmt =
LBCalcVarITopScrollAmt(plb, iTopOld, iTopNew);
02063 plb->
iTop = iTopNew;
02064 }
else if (
abs(iTopNew - iTopOld) > plb->
cItemFullMax)
02065 yAmt = 32000;
02066
else
02067 yAmt = (iTopOld - iTopNew) * plb->
cyChar;
02068 }
02069
02070
dwFlags =
LBGetScrollFlags(plb, dwTime);
02071
ScrollWindowEx(
HWq(plb->
spwnd), xAmt, yAmt,
NULL, &rc,
NULL,
02072
NULL,
dwFlags);
02073
UpdateWindow(
HWq(plb->
spwnd));
02074 }
02075
02076
02077
02078
02079
if (fCaretOn)
02080
02081
02082
xxxLBSetCaret(plb,
TRUE);
02083 }
02084
02085
02086
02087
02088
02089
02090
02091
02092 void xxxInsureVisible(
02093
PLBIV plb,
02094 INT iSel,
02095 BOOL fPartial)
02096 {
02097
INT sLastVisibleItem;
02098
02099
CheckLock(plb->
spwnd);
02100
02101
if (iSel < plb->
iTop) {
02102
xxxNewITop(plb, iSel);
02103 }
else {
02104
if (fPartial) {
02105
02106
02107
02108
02109
02110 sLastVisibleItem = plb->
iTop +
CItemInWindow(plb,
TRUE) - (
INT)1;
02111 }
else {
02112 sLastVisibleItem =
LastFullVisible(plb);
02113 }
02114
02115
if (plb->
OwnerDraw !=
OWNERDRAWVAR) {
02116
if (iSel > sLastVisibleItem) {
02117
if (plb->
fMultiColumn) {
02118
xxxNewITop(plb,
02119 ((iSel / plb->
itemsPerColumn) -
02120
max(plb->
numberOfColumns-1,0)) * plb->
itemsPerColumn);
02121 }
else {
02122
xxxNewITop(plb, (
INT)
max(0, iSel - sLastVisibleItem + plb->
iTop));
02123 }
02124 }
02125 }
else if (iSel > sLastVisibleItem)
02126
xxxNewITop(plb,
LBPage(plb, iSel,
FALSE));
02127 }
02128 }
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139 VOID xxxLBoxCaretBlinker(
02140 HWND hwnd,
02141 UINT wMsg,
02142 UINT_PTR nIDEvent,
02143 DWORD dwTime)
02144 {
02145
PWND pwnd;
02146
PLBIV plb;
02147
02148
02149
02150
02151
02152 UNREFERENCED_PARAMETER(wMsg);
02153 UNREFERENCED_PARAMETER(nIDEvent);
02154 UNREFERENCED_PARAMETER(dwTime);
02155
02156 pwnd =
ValidateHwnd(hwnd);
02157 plb = ((
PLBWND)pwnd)->pLBIV;
02158
02159
02160
02161
02162
if (
ISREMOTESESSION() && plb->
fCaretOn) {
02163
return;
02164 }
02165
02166
02167
02168
02169
xxxLBSetCaret(plb, !plb->
fCaretOn);
02170
return;
02171 }
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 void xxxLBoxCtlKeyInput(
02184
PLBIV plb,
02185 UINT msg,
02186 UINT vKey)
02187 {
02188
INT i;
02189
INT iNewISel;
02190
INT cItemPageScroll;
02191
PCBOX pcbox;
02192
BOOL fDropDownComboBox;
02193
BOOL fExtendedUIComboBoxClosed;
02194
BOOL hScrollBar =
TestWF(plb->
spwnd,
WFHSCROLL);
02195
UINT wModifiers = 0;
02196
BOOL fSelectKey =
FALSE;
02197
UINT uEvent = 0;
02198 HWND hwnd =
HWq(plb->
spwnd);
02199
TL tlpwndParent;
02200
TL tlpwnd;
02201
02202
CheckLock(plb->
spwnd);
02203
02204 pcbox = plb->
pcbox;
02205
02206
02207
02208
02209 fDropDownComboBox = pcbox && (pcbox->
CBoxStyle &
SDROPPABLE);
02210
02211
02212
02213
02214 fExtendedUIComboBoxClosed = fDropDownComboBox && pcbox->
fExtendedUI &&
02215 !pcbox->
fLBoxVisible;
02216
02217
if (plb->
fMouseDown || (!plb->
cMac && vKey != VK_F4)) {
02218
02219
02220
02221
02222
02223
02224
02225
return;
02226 }
02227
02228
02229
02230
02231
if (plb->
wMultiple ==
EXTENDEDSEL) {
02232
02233
02234
02235
02236
if (
GetKeyState(VK_SHIFT) < 0)
02237 wModifiers =
SHIFTDOWN;
02238
if (
GetKeyState(VK_CONTROL) < 0)
02239 wModifiers +=
CTLDOWN;
02240
02241
02242
02243
02244 }
02245
02246
if (
msg ==
LB_KEYDOWN) {
02247
02248
02249
02250
02251
02252
02253
02254 iNewISel = (
INT)vKey;
02255
goto TrackKeyDown;
02256 }
02257
02258 cItemPageScroll = plb->
cItemFullMax;
02259
02260
if (cItemPageScroll > 1)
02261 cItemPageScroll--;
02262
02263
if (plb->
fWantKeyboardInput) {
02264
02265
02266
02267
02268
ThreadLock(plb->
spwndParent, &tlpwndParent);
02269 iNewISel = (
INT)
SendMessage(
HW(plb->
spwndParent), WM_VKEYTOITEM,
02270 MAKELONG(vKey, plb->
iSelBase), (LPARAM)hwnd);
02271
ThreadUnlock(&tlpwndParent);
02272
02273
if (iNewISel == -2) {
02274
02275
02276
02277
02278
return;
02279 }
02280
if (iNewISel != -1) {
02281
02282
02283
02284
02285
goto TrackKeyDown;
02286 }
02287
02288
02289
02290
02291 }
02292
02293
switch (vKey) {
02294
02295
02296
02297
02298
02299
02300
02301
case VERKEY_BACKSLASH:
02302
02303
02304
02305
02306
if ((wModifiers &
CTLDOWN) && (plb->
wMultiple !=
SINGLESEL)) {
02307
xxxLBSetCaret(plb,
FALSE);
02308
xxxResetWorld(plb, plb->
iSelBase, plb->
iSelBase,
FALSE);
02309
02310
02311
02312
02313
SetSelected(plb, plb->
iSelBase,
TRUE,
HILITEANDSEL);
02314
xxxInvertLBItem(plb, plb->
iSelBase,
TRUE);
02315 uEvent = EVENT_OBJECT_SELECTION;
02316
goto CaretOnAndNotify;
02317 }
02318
return;
02319
break;
02320
02321
case VK_DIVIDE:
02322
02323
02324
02325
02326
case VERKEY_SLASH:
02327
02328
02329
02330
02331
if ((wModifiers &
CTLDOWN) && (plb->
wMultiple !=
SINGLESEL)) {
02332
xxxLBSetCaret(plb,
FALSE);
02333
xxxResetWorld(plb, -1, -1,
TRUE);
02334
02335 uEvent = EVENT_OBJECT_SELECTIONWITHIN;
02336
02337 CaretOnAndNotify:
02338
xxxLBSetCaret(plb,
TRUE);
02339
if (
FWINABLE()) {
02340
LBEvent(plb, uEvent, plb->
iSelBase);
02341 }
02342
xxxNotifyOwner(plb, LBN_SELCHANGE);
02343 }
02344
return;
02345
break;
02346
02347
case VK_F8:
02348
02349
02350
02351
02352
02353
02354
if (plb->
wMultiple !=
SINGLESEL && wModifiers ==
SHIFTDOWN) {
02355
02356
02357
02358
02359
if (plb->
fAddSelMode) {
02360
02361
02362
02363
02364
NtUserKillTimer(hwnd,
IDSYS_CARET);
02365
02366
02367
02368
02369
xxxLBSetCaret(plb,
TRUE);
02370 }
else {
02371
02372
02373
02374
02375
NtUserSetTimer(hwnd,
IDSYS_CARET,
gpsi->dtCaretBlink,
02376
xxxLBoxCaretBlinker);
02377 }
02378
02379
02380
02381
02382 plb->
fAddSelMode = (
UINT)!plb->
fAddSelMode;
02383 }
02384
return;
02385
case VK_SPACE:
02386 i = 0;
02387 fSelectKey =
TRUE;
02388
break;
02389
02390
case VK_PRIOR:
02391
if (fExtendedUIComboBoxClosed) {
02392
02393
02394
02395
02396
return;
02397 }
02398
02399
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
02400 i =
LBPage(plb, plb->
iSelBase,
FALSE) - plb->
iSelBase;
02401 }
else {
02402 i = -cItemPageScroll;
02403 }
02404
break;
02405
02406
case VK_NEXT:
02407
if (fExtendedUIComboBoxClosed) {
02408
02409
02410
02411
02412
return;
02413 }
02414
02415
if (plb->
OwnerDraw ==
OWNERDRAWVAR) {
02416 i =
LBPage(plb, plb->
iSelBase,
TRUE) - plb->
iSelBase;
02417 }
else {
02418 i = cItemPageScroll;
02419 }
02420
break;
02421
02422
case VK_HOME:
02423
if (fExtendedUIComboBoxClosed) {
02424
02425
02426
02427
02428
return;
02429 }
02430
02431 i = (INT_MIN/2)+1;
02432
break;
02433
02434
case VK_END:
02435
if (fExtendedUIComboBoxClosed) {
02436
02437
02438
02439
02440
return;
02441 }
02442
02443 i = (INT_MAX/2)-1;
02444
break;
02445
02446
case VK_LEFT:
02447
if (plb->
fMultiColumn) {
02448
if (plb->
fRightAlign
02449
#ifdef USE_MIRRORING
02450
^ (!!
TestWF(plb->
spwnd, WEFLAYOUTRTL))
02451
02452
#endif
02453
)
02454
goto ReallyRight;
02455 ReallyLeft:
02456
if (plb->
iSelBase / plb->
itemsPerColumn == 0) {
02457 i = 0;
02458 }
else {
02459 i = -plb->
itemsPerColumn;
02460 }
02461
break;
02462 }
02463
02464
if (hScrollBar) {
02465
goto HandleHScrolling;
02466 }
else {
02467
02468
02469
02470
02471
02472 vKey = VK_UP;
02473 }
02474
02475
02476
02477
02478
02479
case VK_UP:
02480
if (fExtendedUIComboBoxClosed)
02481
02482
return;
02483
02484 i = -1;
02485
break;
02486
02487
case VK_RIGHT:
02488
if (plb->
fMultiColumn) {
02489
if (plb->
fRightAlign
02490
#ifdef USE_MIRRORING
02491
^ (!!
TestWF(plb->
spwnd, WEFLAYOUTRTL))
02492
02493
#endif
02494
)
02495
goto ReallyLeft;
02496 ReallyRight:
02497
if (plb->
iSelBase / plb->
itemsPerColumn == plb->
cMac / plb->
itemsPerColumn) {
02498 i = 0;
02499 }
else {
02500 i = plb->
itemsPerColumn;
02501 }
02502
break;
02503 }
02504
if (hScrollBar) {
02505 HandleHScrolling:
02506
PostMessage(hwnd, WM_HSCROLL,
02507 (vKey == VK_RIGHT ? SB_LINEDOWN : SB_LINEUP), 0
L);
02508
return;
02509 }
else {
02510
02511
02512
02513
02514
02515 vKey = VK_DOWN;
02516 }
02517
02518
02519
02520
02521
02522
case VK_DOWN:
02523
if (fExtendedUIComboBoxClosed) {
02524
02525
02526
02527
02528
if (!pcbox->
fLBoxVisible) {
02529
02530
02531
02532
02533
ThreadLock(pcbox->
spwnd, &tlpwnd);
02534
xxxCBShowListBoxWindow(pcbox,
TRUE);
02535
ThreadUnlock(&tlpwnd);
02536 }
02537
return;
02538 }
02539 i = 1;
02540
break;
02541
02542
case VK_ESCAPE:
02543
case VK_RETURN:
02544
if (!fDropDownComboBox || !pcbox->
fLBoxVisible)
02545
return;
02546
02547
02548
02549
02550
02551
case VK_F4:
02552
if (fDropDownComboBox && !pcbox->
fExtendedUI) {
02553
02554
02555
02556
02557
02558
02559
ThreadLock(pcbox->
spwnd, &tlpwnd);
02560
if (!pcbox->
fLBoxVisible) {
02561
02562
02563
02564
02565
xxxCBShowListBoxWindow(pcbox, (vKey != VK_ESCAPE));
02566 }
else {
02567
02568
02569
02570
02571
xxxCBHideListBoxWindow(pcbox,
TRUE, (vKey != VK_ESCAPE));
02572 }
02573
ThreadUnlock(&tlpwnd);
02574 }
02575
02576
02577
02578
02579
02580
default:
02581
return;
02582 }
02583
02584
02585
02586
02587 iNewISel =
IncrementISel(plb, plb->
iSelBase, i);
02588
02589
02590
if (plb->
wMultiple ==
SINGLESEL) {
02591
if (plb->
iSel == iNewISel) {
02592
02593
02594
02595
02596
02597
return;
02598 }
02599
02600 uEvent = EVENT_OBJECT_SELECTION;
02601
02602 plb->
iTypeSearch = 0;
02603
if ((vKey == VK_UP || vKey == VK_DOWN) &&
02604 !
IsSelected(plb, plb->
iSelBase,
HILITEONLY)) {
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618 iNewISel = (plb->
iSelBase == -1) ? 0 : plb->
iSelBase;
02619 }
02620 }
02621
02622 TrackKeyDown:
02623
02624
xxxSetISelBase(plb, iNewISel);
02625
02626
xxxLBSetCaret(plb,
FALSE);
02627
02628
if (wModifiers &
SHIFTDOWN) {
02629
02630
if (plb->
iMouseDown == -1)
02631 plb->
iMouseDown = iNewISel;
02632
if (plb->
iLastMouseMove == -1)
02633 plb->
iLastMouseMove = iNewISel;
02634
02635
02636
if (plb->
fAddSelMode) {
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
if (!plb->
fNewItemState)
02647 plb->
iLastMouseMove = plb->
iMouseDown;
02648
02649
02650
02651
02652
02653
02654 }
else {
02655
02656
02657
02658
02659
02660
xxxResetWorld(plb, plb->
iMouseDown, plb->
iLastMouseMove,
FALSE);
02661 }
02662
02663 uEvent = EVENT_OBJECT_SELECTIONWITHIN;
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673 plb->
fNewItemState =
IsSelected(plb, plb->
iMouseDown,
SELONLY);
02674
xxxLBBlockHilite(plb, iNewISel,
TRUE);
02675
02676 plb->
iLastMouseMove = iNewISel;
02677
02678 }
else {
02679
02680
if ((plb->
fAddSelMode) || (plb->
wMultiple ==
MULTIPLESEL)) {
02681
02682
if (fSelectKey) {
02683
02684 plb->
fNewItemState = !
IsSelected(plb, iNewISel,
SELONLY);
02685
SetSelected(plb, iNewISel, plb->
fNewItemState,
HILITEANDSEL);
02686
02687
xxxInvertLBItem(plb, iNewISel, plb->
fNewItemState);
02688
02689
02690 plb->
iLastMouseMove = plb->
iMouseDown = iNewISel;
02691 uEvent = (plb->
fNewItemState ? EVENT_OBJECT_SELECTIONADD :
02692 EVENT_OBJECT_SELECTIONREMOVE);
02693 }
02694 }
else {
02695
02696
02697
02698
02699
xxxResetWorld(plb, iNewISel, iNewISel,
FALSE);
02700
02701
02702
SetSelected(plb, iNewISel,
TRUE,
HILITEANDSEL);
02703
xxxInvertLBItem(plb, iNewISel,
TRUE);
02704
02705
02706 plb->
iLastMouseMove = plb->
iMouseDown = iNewISel;
02707 uEvent = EVENT_OBJECT_SELECTION;
02708 }
02709 }
02710
02711
02712
02713
02714
xxxInsureVisible(plb, iNewISel,
FALSE);
02715
xxxLBShowHideScrollBars(plb);
02716
02717
xxxLBSetCaret(plb,
TRUE);
02718
02719
if (
FWINABLE() && uEvent) {
02720
LBEvent(plb, uEvent, iNewISel);
02721 }
02722
02723
02724
02725
02726
if (plb->
fNotify) {
02727
if (fDropDownComboBox && pcbox->
fLBoxVisible) {
02728
02729
02730
02731
02732
02733
02734
02735 pcbox->
fKeyboardSelInListBox =
TRUE;
02736 plb->
iLastSelection = iNewISel;
02737 }
02738
xxxNotifyOwner(plb, LBN_SELCHANGE);
02739 }
02740 }
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757 INT Compare(
02758 LPCWSTR pwsz1,
02759 LPCWSTR pwsz2,
02760 DWORD dwLocaleId)
02761 {
02762
UINT len1 = wcslen(pwsz1);
02763
UINT len2 = wcslen(pwsz2);
02764
INT result;
02765
02766
02767
02768
02769
02770
02771
02772 result = CompareStringW((LCID)dwLocaleId, NORM_IGNORECASE,
02773 pwsz1,
min(len1,len2), pwsz2,
min(len1, len2));
02774
02775
if (result == CSTR_LESS_THAN) {
02776
return LT;
02777 }
else if (result == CSTR_EQUAL) {
02778
if (len1 == len2) {
02779
return EQ;
02780 }
else if (len1 < len2) {
02781
02782
02783
02784
02785
return PREFIX;
02786 }
02787 }
02788
return GT;
02789 }
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802 INT xxxFindString(
02803
PLBIV plb,
02804 LPWSTR lpstr,
02805 INT sStart,
02806 INT code,
02807 BOOL fWrap)
02808 {
02809
02810
02811
02812
02813
02814
INT sInd;
02815
INT sStop;
02816
lpLBItem pRg;
02817
TL tlpwndParent;
02818
INT sortResult;
02819
02820
02821
02822
02823
#define pODRg ((lpLBODItem)pRg)
02824
COMPAREITEMSTRUCT cis;
02825 LPWSTR listboxString;
02826
02827
CheckLock(plb->
spwnd);
02828
02829
if (plb->
fHasStrings && (!lpstr || !*lpstr))
02830
return LB_ERR;
02831
02832
if (!plb->
fHasData) {
02833 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING,
"FindString called on NODATA lb");
02834
return LB_ERR;
02835 }
02836
02837
if ((sInd = sStart + 1) >= plb->
cMac)
02838 sInd = (fWrap ? 0 : plb->
cMac - 1);
02839
02840 sStop = (fWrap ? sInd : 0);
02841
02842
02843
02844
02845
if (((sStart >= plb->
cMac - 1) && !fWrap) || (plb->
cMac < 1)) {
02846
return LB_ERR;
02847 }
02848
02849
02850
02851
02852
02853
if (sInd < 0)
02854 sInd = 0;
02855
02856 pRg = (
lpLBItem)(plb->
rgpch);
02857
02858
do {
02859
if (plb->
fHasStrings) {
02860
02861
02862
02863
02864 listboxString = (LPWSTR)((LPBYTE)plb->
hStrings + pRg[sInd].
offsz);
02865
02866
if (code ==
PREFIX &&
02867 listboxString &&
02868 *lpstr != TEXT(
'[') &&
02869 *listboxString == TEXT(
'[')) {
02870
02871
02872
02873
02874
02875
02876
02877 listboxString++;
02878
if (*listboxString == TEXT(
'-'))
02879 listboxString++;
02880 }
02881
02882
if (
Compare(lpstr, listboxString, plb->
dwLocaleId) <= code) {
02883
goto FoundIt;
02884 }
02885
02886 }
else {
02887
if (plb->
fSort) {
02888
02889
02890
02891
02892 cis.CtlType = ODT_LISTBOX;
02893 cis.CtlID = PtrToUlong(plb->
spwnd->
spmenu);
02894 cis.hwndItem =
HWq(plb->
spwnd);
02895 cis.itemID1 = (
UINT)-1;
02896 cis.itemData1 = (ULONG_PTR)lpstr;
02897 cis.itemID2 = (
UINT)sInd;
02898 cis.itemData2 =
pODRg[sInd].itemData;
02899 cis.dwLocaleId = plb->
dwLocaleId;
02900
02901
ThreadLock(plb->
spwndParent, &tlpwndParent);
02902 sortResult = (
INT)
SendMessage(
HW(plb->
spwndParent), WM_COMPAREITEM,
02903 cis.CtlID, (LPARAM)&cis);
02904
ThreadUnlock(&tlpwndParent);
02905
02906
02907
if (sortResult == -1) {
02908 sortResult =
LT;
02909 }
else if (sortResult == 1) {
02910 sortResult =
GT;
02911 }
else {
02912 sortResult =
EQ;
02913 }
02914
02915
if (sortResult <= code) {
02916
goto FoundIt;
02917 }
02918 }
else {
02919
02920
02921
02922
02923
if ((ULONG_PTR)lpstr ==
pODRg[sInd].itemData)
02924
goto FoundIt;
02925 }
02926 }
02927
02928
02929
02930
02931
if (++sInd == plb->
cMac)
02932 sInd = 0;
02933 }
while (sInd != sStop);
02934
02935 sInd = -1;
02936
02937 FoundIt:
02938
return sInd;
02939 }
02940
02941
02942
02943
02944
02945
02946
02947
02948 void xxxLBoxCtlCharInput(
02949
PLBIV plb,
02950 UINT inputChar,
02951 BOOL fAnsi)
02952 {
02953
INT iSel;
02954
BOOL fControl;
02955
TL tlpwndParent;
02956
02957
CheckLock(plb->
spwnd);
02958
02959
if (plb->
cMac == 0 || plb->
fMouseDown) {
02960
02961
02962
02963
02964
02965
return;
02966 }
02967
02968 fControl = (
GetKeyState(VK_CONTROL) < 0);
02969
02970
switch (inputChar) {
02971
case VK_ESCAPE:
02972 plb->
iTypeSearch = 0;
02973
if (plb->
pszTypeSearch)
02974 plb->
pszTypeSearch[0] = 0;
02975
break;
02976
02977
case VK_BACK:
02978
if (plb->
iTypeSearch) {
02979 plb->
pszTypeSearch[plb->
iTypeSearch--] = 0;
02980
if (plb->
fSort) {
02981 iSel = -1;
02982
goto TypeSearch;
02983 }
02984 }
02985
break;
02986
02987
case VK_SPACE:
02988
if (plb->
fAddSelMode || plb->
wMultiple ==
MULTIPLESEL)
02989
break;
02990
02991
02992
02993
02994
02995
default:
02996
02997
02998
02999
03000
03001
03002
if (fAnsi &&
IS_DBCS_ENABLED() && IsDBCSLeadByteEx(
THREAD_CODEPAGE(), (
BYTE)inputChar)) {
03003 WCHAR wch;
03004 LPWSTR lpwstr = &wch;
03005
03006 inputChar =
DbcsCombine(
HWq(plb->
spwnd), (
BYTE)inputChar);
03007 RIPMSG1(RIP_VERBOSE,
"xxxLBoxCtlCharInput: combined DBCS. 0x%04x", inputChar);
03008
03009
if (inputChar == 0) {
03010 RIPMSG1(RIP_WARNING,
"xxxLBoxCtlCharInput: cannot combine two DBCS. LB=0x%02x",
03011 inputChar);
03012
break;
03013 }
03014
03015 fControl =
FALSE;
03016
03017
03018
03019
03020
03021
if (
MBToWCSEx(
THREAD_CODEPAGE(), (LPCSTR)&inputChar, 2, &lpwstr, 1,
FALSE) == 0) {
03022 RIPMSG1(RIP_WARNING,
"xxxLBoxCtlCharInput: cannot convert 0x%04x to UNICODE.",
03023 inputChar);
03024
break;
03025 }
03026 inputChar = wch;
03027 }
03028
03029
if (plb->
fHasStrings) {
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
if (fControl && inputChar < 0x20)
03043 inputChar += 0x40;
03044
03045
if (plb->
iTypeSearch ==
MAX_TYPESEARCH) {
03046
NtUserMessageBeep(0);
03047
break;
03048 }
03049 iSel = -1;
03050
03051
if (plb->
pszTypeSearch ==
NULL)
03052 plb->
pszTypeSearch = (LPWSTR)
UserLocalAlloc(HEAP_ZERO_MEMORY,
sizeof(WCHAR) * (
MAX_TYPESEARCH + 1));
03053
03054
if (plb->
pszTypeSearch ==
NULL) {
03055
NtUserMessageBeep(0);
03056
break;
03057 }
03058
03059 plb->
pszTypeSearch[plb->
iTypeSearch++] = (WCHAR) inputChar;
03060 plb->
pszTypeSearch[plb->
iTypeSearch] = 0;
03061
03062 TypeSearch:
03063
if (plb->
fSort) {
03064
03065
NtUserSetTimer(
HWq(plb->
spwnd),
IDSYS_LBSEARCH,
03066
gpsi->dtLBSearch,
NULL);
03067 }
else {
03068
03069 plb->
iTypeSearch = 0;
03070 iSel = plb->
iSelBase;
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081 iSel =
xxxFindString(plb, plb->
pszTypeSearch, iSel,
PREFIX,
TRUE);
03082
if (iSel == -1) {
03083
03084
03085
03086
if(plb->
iTypeSearch)
03087 {
03088 plb->
iTypeSearch--;
03089
if ((plb->
iTypeSearch == 1) && (plb->
pszTypeSearch[0] == plb->
pszTypeSearch[1]))
03090 {
03091 plb->
pszTypeSearch[1] = 0;
03092 iSel =
xxxFindString(plb, plb->
pszTypeSearch, plb->
iSelBase,
PREFIX,
TRUE);
03093 }
03094 }
03095 }
03096
03097
if (iSel != -1)
03098 {
03099 CtlKeyInput:
03100
xxxLBoxCtlKeyInput(plb,
LB_KEYDOWN, iSel);
03101
03102 }
03103 }
else {
03104
if (plb->
spwndParent !=
NULL) {
03105
ThreadLock(plb->
spwndParent, &tlpwndParent);
03106 iSel = (
INT)
SendMessageWorker(plb->
spwndParent, WM_CHARTOITEM,
03107 MAKELONG(inputChar, plb->
iSelBase), (LPARAM)
HWq(plb->
spwnd), fAnsi);
03108
ThreadUnlock(&tlpwndParent);
03109 }
else
03110 iSel = -1;
03111
03112
if (iSel != -1 && iSel != -2)
03113
goto CtlKeyInput;
03114
03115 }
03116
break;
03117 }
03118 }
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131 int LBoxGetSelItems(
03132
PLBIV plb,
03133 BOOL fCountOnly,
03134
int wParam,
03135 LPINT lParam)
03136 {
03137
int i;
03138
int itemsselected = 0;
03139
03140
if (plb->
wMultiple ==
SINGLESEL)
03141
return LB_ERR;
03142
03143
for (i = 0; i < plb->
cMac; i++) {
03144
if (
IsSelected(plb, i,
SELONLY)) {
03145
if (!fCountOnly) {
03146
if (itemsselected < wParam)
03147 *lParam++ = i;
03148
else {
03149
03150
03151
03152
03153
return itemsselected;
03154 }
03155 }
03156 itemsselected++;
03157 }
03158 }
03159
03160
return itemsselected;
03161 }
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172 void xxxLBSetRedraw(
03173
PLBIV plb,
03174 BOOL fRedraw)
03175 {
03176
CheckLock(plb->
spwnd);
03177
03178
if (fRedraw)
03179 fRedraw =
TRUE;
03180
03181
if (plb->
fRedraw != (
UINT)fRedraw) {
03182 plb->
fRedraw = !!fRedraw;
03183
03184
if (fRedraw) {
03185
xxxLBSetCaret(plb,
TRUE);
03186
xxxLBShowHideScrollBars(plb);
03187
03188
if (plb->
fDeferUpdate) {
03189 plb->
fDeferUpdate =
FALSE;
03190
RedrawWindow(
HWq(plb->
spwnd),
NULL,
NULL,
03191 RDW_INVALIDATE | RDW_ERASE |
03192 RDW_FRAME | RDW_ALLCHILDREN);
03193 }
03194 }
03195 }
03196 }
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206 void xxxLBSelRange(
03207
PLBIV plb,
03208
int iStart,
03209
int iEnd,
03210 BOOL fnewstate)
03211 {
03212
DWORD temp;
03213 RECT rc;
03214
03215
CheckLock(plb->
spwnd);
03216
03217
if (iStart > iEnd) {
03218 temp = iEnd;
03219 iEnd = iStart;
03220 iStart = temp;
03221 }
03222
03223
03224
03225
03226 iEnd =
min(plb->
cMac, iEnd);
03227 iStart =
max(iStart, 0);
03228
if (iStart > iEnd)
03229
return;
03230
03231
03232
03233
03234
03235
03236
for (temp = iStart; temp <= (
DWORD)iEnd; temp++) {
03237
03238
if (
IsSelected(plb, temp,
SELONLY) != fnewstate) {
03239
SetSelected(plb, temp, fnewstate,
HILITEANDSEL);
03240
LBGetItemRect(plb, temp, &rc);
03241
03242
xxxLBInvalidateRect(plb, (LPRECT)&rc,
FALSE);
03243 }
03244
03245 }
03246 UserAssert(plb->
wMultiple);
03247
if (
FWINABLE()) {
03248
LBEvent(plb, EVENT_OBJECT_SELECTIONWITHIN, iStart);
03249 }
03250 }
03251
03252
03253
03254
03255
03256
03257
03258
03259 int xxxLBSetCurSel(
03260
PLBIV plb,
03261
int iSel)
03262 {
03263
CheckLock(plb->
spwnd);
03264
03265
if (!(plb->
wMultiple || iSel < -1 || iSel >= plb->
cMac)) {
03266
xxxLBSetCaret(plb,
FALSE);
03267
if (plb->
iSel != -1) {
03268
03269
03270
03271
03272
if (iSel != -1)
03273
xxxInsureVisible(plb, iSel,
FALSE);
03274
03275
03276
03277
03278
xxxInvertLBItem(plb, plb->
iSel,
FALSE);
03279 }
03280
03281
if (iSel != -1) {
03282
xxxInsureVisible(plb, iSel,
FALSE);
03283 plb->
iSelBase = plb->
iSel = iSel;
03284
03285
03286
03287
03288
xxxInvertLBItem(plb, plb->
iSel,
TRUE);
03289 }
else {
03290 plb->
iSel = -1;
03291
if (plb->
cMac)
03292 plb->
iSelBase =
min(plb->
iSelBase, plb->
cMac-1);
03293
else
03294 plb->
iSelBase = 0;
03295 }
03296
03297
if (
FWINABLE()) {
03298
03299
03300
03301
if (
_IsWindowVisible(plb->
spwnd)) {
03302
LBEvent(plb, EVENT_OBJECT_FOCUS, plb->
iSelBase);
03303
LBEvent(plb, EVENT_OBJECT_SELECTION, plb->
iSel);
03304 }
03305 }
03306
03307
xxxLBSetCaret(plb,
TRUE);
03308
return plb->
iSel;
03309 }
03310
03311
return LB_ERR;
03312 }
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324 int LBSetItemData(
03325
PLBIV plb,
03326
int index,
03327 LONG_PTR data)
03328 {
03329 LPSTR lpItemText;
03330
03331
03332
03333
03334
if ((index != -1) && ((
UINT) index >= (
UINT) plb->
cMac)) {
03335 RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING,
"LBSetItemData with invalid index %x", index);
03336
return LB_ERR;
03337 }
03338
03339
03340
03341
03342
if (!plb->
fHasData) {
03343
return TRUE;
03344 }
03345
03346 lpItemText = (LPSTR)plb->
rgpch;
03347
03348
if (index == -1) {
03349
03350
03351
03352
03353
if (plb->
fHasStrings) {
03354
for (index = 0; index < plb->
cMac; index++) {
03355
03356 ((
lpLBItem)lpItemText)->itemData = data;
03357 lpItemText +=
sizeof(
LBItem);
03358 }
03359 }
else {
03360
for (index = 0; index < plb->
cMac; index++) {
03361
03362 ((
lpLBODItem)lpItemText)->itemData = data;
03363 lpItemText +=
sizeof(
LBODItem);
03364 }
03365 }
03366
return TRUE;
03367 }
03368
03369
if (plb->
fHasStrings) {
03370
03371 lpItemText = (LPSTR)(lpItemText + (index *
sizeof(
LBItem)));
03372 ((
lpLBItem)lpItemText)->itemData = data;
03373 }
else {
03374
03375 lpItemText = (LPSTR)(lpItemText + (index *
sizeof(
LBODItem)));
03376 ((
lpLBODItem)lpItemText)->itemData = data;
03377 }
03378
return TRUE;
03379 }
03380
03381
03382
03383
03384
03385
03386
03387 void xxxCheckRedraw(
03388
PLBIV plb,
03389 BOOL fConditional,
03390 INT sItem)
03391 {
03392
CheckLock(plb->
spwnd);
03393
03394
if (fConditional && plb->
cMac &&
03395 (sItem > (plb->
iTop +
CItemInWindow(plb,
TRUE))))
03396
return;
03397
03398
03399
03400
03401
xxxLBInvalidateRect(plb, (LPRECT)
NULL,
TRUE);
03402 }
03403
03404
03405
03406
03407
03408
03409
03410
03411 void xxxCaretDestroy(
03412
PLBIV plb)
03413 {
03414
CheckLock(plb->
spwnd);
03415
03416
03417
03418
03419
03420
if (plb->
fCaptured)
03421
03422
03423
03424
03425
03426
03427
03428
xxxLBButtonUp(plb,
LBUP_RELEASECAPTURE |
LBUP_NOTIFY |
03429 (plb->
fMouseDown ?
LBUP_SUCCESS : 0));
03430
03431
if (plb->
fAddSelMode) {
03432
03433
03434
03435
03436
NtUserKillTimer(
HWq(plb->
spwnd),
IDSYS_CARET);
03437
03438
03439
03440
03441
xxxLBSetCaret(plb,
FALSE);
03442 plb->
fAddSelMode =
FALSE;
03443 }
03444
03445 plb->
fCaret =
FALSE;
03446 }
03447
03448
03449
03450
03451
03452
03453
03454
03455 LONG
xxxLBSetSel(
03456
PLBIV plb,
03457 BOOL fSelect,
03458 INT iSel)
03459 {
03460
INT sItem;
03461 RECT rc;
03462
UINT uEvent = 0;
03463
03464
CheckLock(plb->
spwnd);
03465
03466
03467
03468
03469
03470
03471
03472
if ((iSel == (
UINT)0xffff) && (iSel >= plb->
cMac)) {
03473 iSel = -1;
03474 RIPMSG0(RIP_WARNING,
"Sign extending iSel=0xffff to 0xffffffff");
03475 }
03476
03477
03478
if ((plb->
wMultiple ==
SINGLESEL) || (iSel != -1 && iSel >= plb->
cMac)) {
03479 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING,
03480
"xxxLBSetSel:Invalid iSel or SINGLESEL listbox");
03481
return LB_ERR;
03482 }
03483
03484
xxxLBSetCaret(plb,
FALSE);
03485
03486
if (iSel == -1) {
03487
03488
03489
03490
03491
for (sItem = 0; sItem < plb->
cMac; sItem++) {
03492
if (
IsSelected(plb, sItem,
SELONLY) != fSelect) {
03493
SetSelected(plb, sItem, fSelect,
HILITEANDSEL);
03494
if (
LBGetItemRect(plb, sItem, &rc)) {
03495
xxxLBInvalidateRect(plb, &rc,
FALSE);
03496 }
03497 }
03498 }
03499
xxxLBSetCaret(plb,
TRUE);
03500 uEvent = EVENT_OBJECT_SELECTIONWITHIN;
03501 }
else {
03502
if (fSelect) {
03503
03504
03505
03506
03507
03508
03509
xxxInsureVisible(plb, iSel,
TRUE);
03510 plb->
iSelBase = plb->
iSel = iSel;
03511
03512 plb->
iMouseDown = plb->
iLastMouseMove = iSel;
03513 uEvent = EVENT_OBJECT_FOCUS;
03514 }
else {
03515 uEvent = EVENT_OBJECT_SELECTIONREMOVE;
03516 }
03517
SetSelected(plb, iSel, fSelect,
HILITEANDSEL);
03518
03519
03520
03521
03522
03523
03524
if (!fSelect && plb->
iSelBase != iSel) {
03525
xxxLBSetCaret(plb,
TRUE);
03526 }
else if (plb->
fCaret) {
03527 plb->
fCaretOn =
TRUE;
03528 }
03529
03530
if (
LBGetItemRect(plb, iSel, &rc)) {
03531
xxxLBInvalidateRect(plb, &rc,
FALSE);
03532 }
03533 }
03534
03535
if (
FWINABLE() &&
_IsWindowVisible(plb->
spwnd)) {
03536
if (uEvent == EVENT_OBJECT_FOCUS) {
03537
LBEvent(plb, uEvent, plb->
iSelBase);
03538 uEvent = EVENT_OBJECT_SELECTION;
03539 }
03540
LBEvent(plb, uEvent, iSel);
03541 }
03542
03543
return 0;
03544 }
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558 void xxxLBoxDrawItem(
03559
PLBIV plb,
03560 INT item,
03561 UINT itemAction,
03562 UINT itemState,
03563 LPRECT lprect)
03564 {
03565 DRAWITEMSTRUCT dis;
03566
TL tlpwndParent;
03567
03568
CheckLock(plb->
spwnd);
03569
03570
03571
03572
03573
03574 dis.CtlType = ODT_LISTBOX;
03575 dis.CtlID = PtrToUlong(plb->
spwnd->
spmenu);
03576
03577
03578
03579
03580
03581
03582 dis.itemID = (
UINT)(item < plb->
cMac ? item : -1);
03583 dis.itemAction = itemAction;
03584 dis.hwndItem =
HWq(plb->
spwnd);
03585 dis.hDC = plb->
hdc;
03586 dis.itemState = itemState |
03587 (
UINT)(
TestWF(plb->
spwnd,
WFDISABLED) ? ODS_DISABLED : 0);
03588
03589
if (
TestWF(plb->
spwnd,
WEFPUIFOCUSHIDDEN)) {
03590 dis.itemState |= ODS_NOFOCUSRECT;
03591 }
03592
if (
TestWF(plb->
spwnd,
WEFPUIACCELHIDDEN)) {
03593 dis.itemState |= ODS_NOACCEL;
03594 }
03595
03596
03597
03598
03599
if (!plb->
cMac || !plb->
fHasData) {
03600
03601
03602
03603
03604
03605
03606
03607 dis.itemData = 0
L;
03608 }
else {
03609 dis.itemData =
LBGetItemData(plb, item);
03610 }
03611
03612
CopyRect(&dis.rcItem, lprect);
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
ThreadLock(plb->
spwndParent, &tlpwndParent);
03625
SendMessage(
HW(plb->
spwndParent), WM_DRAWITEM,
03626
TestWF(plb->
spwndParent,
WFWIN31COMPAT) ? dis.CtlID : 0,
03627 (LPARAM)&dis);
03628
ThreadUnlock(&tlpwndParent);
03629 }
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651 void xxxLBBlockHilite(
03652
PLBIV plb,
03653 INT iSelFromPt,
03654 BOOL fKeyBoard)
03655 {
03656
INT sCurPosOffset;
03657
INT sLastPosOffset;
03658
INT sHiliteOrSel;
03659
BOOL fUseSelStatus;
03660
BOOL DeHiliteStatus;
03661
03662
CheckLock(plb->
spwnd);
03663
03664
if (fKeyBoard) {
03665
03666
03667
03668
03669 sHiliteOrSel =
HILITEANDSEL;
03670
03671
03672
03673
03674 fUseSelStatus =
FALSE;
03675 DeHiliteStatus =
FALSE;
03676 }
else {
03677
03678
03679
03680
03681 sHiliteOrSel =
HILITEONLY;
03682
03683
03684
03685
03686 fUseSelStatus =
TRUE;
03687 DeHiliteStatus = plb->
fNewItemState;
03688 }
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701 sCurPosOffset = plb->
iMouseDown - iSelFromPt;
03702
03703
03704
03705
03706 sLastPosOffset = plb->
iMouseDown - plb->
iLastMouseMove;
03707
03708
03709
03710
03711
03712
if ((sCurPosOffset * sLastPosOffset) >= 0) {
03713
03714
03715
03716
03717
03718
if (
abs(sCurPosOffset) >
abs(sLastPosOffset)) {
03719
xxxAlterHilite(plb, plb->
iLastMouseMove, iSelFromPt,
03720 plb->
fNewItemState, sHiliteOrSel,
FALSE);
03721 }
else {
03722
xxxAlterHilite(plb, iSelFromPt, plb->
iLastMouseMove, DeHiliteStatus,
03723 sHiliteOrSel, fUseSelStatus);
03724 }
03725 }
else {
03726
xxxAlterHilite(plb, plb->
iMouseDown, plb->
iLastMouseMove,
03727 DeHiliteStatus, sHiliteOrSel, fUseSelStatus);
03728
xxxAlterHilite(plb, plb->
iMouseDown, iSelFromPt,
03729 plb->
fNewItemState, sHiliteOrSel,
FALSE);
03730 }
03731 }
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754 void xxxAlterHilite(
03755
PLBIV plb,
03756 INT i,
03757 INT j,
03758 BOOL fHilite,
03759 INT OpFlags,
03760 BOOL fSelStatus)
03761 {
03762
INT low;
03763
INT high;
03764
INT sLastInWindow;
03765
BOOL fCaretOn;
03766
BOOL fSelected;
03767
03768
CheckLock(plb->
spwnd);
03769
03770 sLastInWindow = plb->
iTop +
CItemInWindow(plb,
TRUE);
03771 sLastInWindow =
min(sLastInWindow, plb->
cMac - 1);
03772
high =
max(i, j) + 1;
03773
03774
if (fCaretOn = plb->
fCaretOn) {
03775
xxxLBSetCaret(plb,
FALSE);
03776 }
03777
03778
for (
low =
min(i, j);
low <
high;
low++) {
03779
if (
low != i) {
03780
if (OpFlags &
HILITEONLY) {
03781
if (fSelStatus) {
03782 fSelected =
IsSelected(plb,
low,
SELONLY);
03783 }
else {
03784 fSelected = fHilite;
03785 }
03786
if (
IsSelected(plb,
low,
HILITEONLY) != fSelected) {
03787
if (plb->
iTop <=
low &&
low <= sLastInWindow) {
03788
03789
03790
03791
03792
xxxInvertLBItem(plb,
low, fSelected);
03793 }
03794
SetSelected(plb,
low, fSelected,
HILITEONLY);
03795 }
03796 }
03797
03798
if (OpFlags &
SELONLY) {
03799
SetSelected(plb,
low, fHilite,
SELONLY);
03800 }
03801 }
03802 }
03803
03804
if (fCaretOn) {
03805
xxxLBSetCaret(plb,
TRUE);
03806 }
03807 }