- Timestamp:
- Jul 14, 2003, 4:00:08 PM (22 years ago)
- Location:
- trunk/src/comctl32
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/comctl32/propsheet.c
r10098 r10165 222 222 add_flag(PSH_NOCONTEXTHELP); 223 223 if (string[0] != '\0') 224 224 FIXME("%s\n", string); 225 225 } 226 226 #undef add_flag … … 294 294 memcpy(&psInfo->ppshheader,lppsh,dwSize); 295 295 TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%ld\ndwFlags\t\t%08lx\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n", 296 297 296 lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, 297 debugstr_a(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback); 298 298 299 299 PROPSHEET_UnImplementedFlags(lppsh->dwFlags); … … 301 301 if (HIWORD(lppsh->pszCaption)) 302 302 { 303 #ifdef __WIN32OS2__ 304 int len = MultiByteToWideChar( CP_ACP, 0, lppsh->pszCaption, -1, 0, 0 ); 305 psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); 306 MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, (LPWSTR) psInfo->ppshheader.pszCaption, len); 307 #else 303 308 int len = strlen(lppsh->pszCaption); 304 309 psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof (WCHAR) ); 305 310 MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, (LPWSTR) psInfo->ppshheader.pszCaption, len+1); 311 #endif 306 312 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */ 307 313 } … … 507 513 { 508 514 pTitle = pszNull; 509 515 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp->pszTitle)); 510 516 } 511 517 else … … 538 544 { 539 545 if (psInfo->hImageList == 0 ) 540 546 psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1); 541 547 542 548 ImageList_AddIcon(psInfo->hImageList, hIcon); … … 826 832 TRACE("Biggest page %ld %ld %ld %ld\n", rc.left, rc.top, rc.right, rc.bottom); 827 833 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n", 828 834 padding.x, padding.y, buttonHeight, lineHeight); 829 835 830 836 /* Make room */ … … 1092 1098 if (psInfo->hasHelp) 1093 1099 { 1094 1100 idButton = IDHELP; 1095 1101 } 1096 1102 else … … 1098 1104 if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) 1099 1105 { 1100 1106 idButton = IDC_NEXT_BUTTON; 1101 1107 } 1102 1108 else 1103 1109 { 1104 1105 1110 /* hopefully this is ok */ 1111 idButton = IDCANCEL; 1106 1112 } 1107 1113 } … … 1127 1133 1128 1134 if (padding.y < 0) 1129 1135 ERR("padding negative ! Please report this !\n"); 1130 1136 1131 1137 /* this is most probably not correct, but the best we have now */ … … 1255 1261 /* font, if DS_SETFONT set */ 1256 1262 if ((DS_SETFONT & ((istemplateex)? ((MyDLGTEMPLATEEX*)pTemplate)->style : 1257 1263 pTemplate->style))) 1258 1264 { 1259 1265 p+=(istemplateex)?3:1; … … 1268 1274 { 1269 1275 p = (WORD*)(((DWORD)p + 3) & ~3); /* DWORD align */ 1270 1276 1271 1277 /* skip header */ 1272 1278 p += (istemplateex ? sizeof(MyDLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE))/sizeof(WORD); 1273 1279 1274 1280 /* check class */ 1275 1281 switch ((WORD)*p) 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1282 { 1283 case 0x0000: 1284 p++; 1285 break; 1286 case 0xffff: 1287 TRACE("class ordinal 0x%08lx\n",*(DWORD*)p); 1288 p += 2; 1289 break; 1290 default: 1291 TRACE("class %s\n",debugstr_w((LPCWSTR)p)); 1292 p += lstrlenW( (LPCWSTR)p ) + 1; 1293 break; 1294 } 1289 1295 1290 1296 /* check title text */ 1291 1297 switch ((WORD)*p) 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1298 { 1299 case 0x0000: 1300 p++; 1301 break; 1302 case 0xffff: 1303 TRACE("text ordinal 0x%08lx\n",*(DWORD*)p); 1304 p += 2; 1305 break; 1306 default: 1307 TRACE("text %s\n",debugstr_w((LPCWSTR)p)); 1308 p += lstrlenW( (LPCWSTR)p ) + 1; 1309 break; 1310 } 1305 1311 p += *p + 1; /* Skip extra data */ 1306 1312 --nrofitems; 1307 1313 } 1308 1314 1309 1315 TRACE("%p %p size 0x%08x\n",p, (WORD*)pTemplate,sizeof(WORD)*(p - (WORD*)pTemplate)); 1310 1316 return (p - (WORD*)pTemplate)*sizeof(WORD); 1311 1317 1312 1318 } 1313 1319 … … 1352 1358 RT_DIALOGW); 1353 1359 if(!hResource) 1354 1360 return FALSE; 1355 1361 1356 1362 resSize = SizeofResource(ppshpage->hInstance, hResource); … … 1358 1364 hTemplate = LoadResource(ppshpage->hInstance, hResource); 1359 1365 if(!hTemplate) 1360 1366 return FALSE; 1361 1367 1362 1368 pTemplate = (LPDLGTEMPLATEW)LockResource(hTemplate); … … 1368 1374 if (!temp) 1369 1375 return FALSE; 1370 1376 1371 1377 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate, temp, resSize); 1372 1378 memcpy(temp, pTemplate, resSize); … … 1402 1408 1403 1409 hwndPage = CreateDialogIndirectParamW(ppshpage->hInstance, 1404 1405 1406 1407 1410 pTemplate, 1411 hwndParent, 1412 ppshpage->pfnDlgProc, 1413 (LPARAM)ppshpage); 1408 1414 /* Free a no more needed copy */ 1409 1415 if(temp) … … 1428 1434 padding = PROPSHEET_GetPaddingInfoWizard(hwndParent, psInfo); 1429 1435 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n", 1430 1431 1436 (DWORD)hwndPage, rc.left, rc.top, rc.right, rc.bottom, 1437 pageWidth, pageHeight, padding.x, padding.y); 1432 1438 SetWindowPos(hwndPage, HWND_TOP, 1433 1434 1435 1439 rc.left + padding.x/2, 1440 rc.top + padding.y/2, 1441 pageWidth, pageHeight, 0); 1436 1442 } 1437 1443 else { … … 1444 1450 pageHeight = rc.bottom - rc.top; 1445 1451 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n", 1446 1447 1452 (DWORD)hwndPage, rc.left, rc.top, rc.right, rc.bottom, 1453 pageWidth, pageHeight); 1448 1454 SetWindowPos(hwndPage, HWND_TOP, 1449 1450 1455 rc.left, rc.top, 1456 pageWidth, pageHeight, 0); 1451 1457 } 1452 1458 … … 1897 1903 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, 1898 1904 int index, 1899 1905 int skipdir, 1900 1906 HPROPSHEETPAGE hpage 1901 1907 ) 1902 1908 { 1903 1909 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); … … 1921 1927 1922 1928 if (hwndTabControl) 1923 1929 SendMessageW(hwndTabControl, TCM_SETCURSEL, index, 0); 1924 1930 1925 1931 psn.hdr.code = PSN_SETACTIVE; … … 1939 1945 index+=skipdir; 1940 1946 if (index < 0) { 1941 1942 1943 1947 index = 0; 1948 FIXME("Tried to skip before first property sheet page!\n"); 1949 break; 1944 1950 } 1945 1951 if (index >= psInfo->nPages) { 1946 1947 1948 1952 FIXME("Tried to skip after last property sheet page!\n"); 1953 index = psInfo->nPages-1; 1954 break; 1949 1955 } 1950 1956 } … … 1996 2002 WCHAR szTitle[256]; 1997 2003 MultiByteToWideChar(CP_ACP, 0, lpszText, -1, 2004 #ifdef __WIN32OS2__ 2005 szTitle, sizeof( szTitle ) / sizeof( WCHAR )); 2006 #else 1998 2007 szTitle, sizeof szTitle); 2008 #endif 1999 2009 PROPSHEET_SetTitleW(hwndDlg, dwStyle, szTitle); 2000 2010 } … … 2010 2020 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText) 2011 2021 { 2012 PropSheetInfo* 2013 WCHAR 2022 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); 2023 WCHAR szTitle[256]; 2014 2024 2015 2025 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText), dwStyle); … … 2415 2425 psInfo, n)) 2416 2426 { 2417 2418 2419 2420 2427 if (lppsh->dwFlags & PSH_PROPSHEETPAGE) 2428 DestroyPropertySheetPage(psInfo->proppage[n].hpage); 2429 n--; 2430 psInfo->nPages--; 2421 2431 } 2422 2432 } … … 2459 2469 psInfo, n)) 2460 2470 { 2461 2462 2463 2464 2471 if (lppsh->dwFlags & PSH_PROPSHEETPAGE) 2472 DestroyPropertySheetPage(psInfo->proppage[n].hpage); 2473 n--; 2474 psInfo->nPages--; 2465 2475 } 2466 2476 } … … 2623 2633 case IDOK: 2624 2634 case IDC_APPLY_BUTTON: 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2635 { 2636 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON); 2637 2638 if (PROPSHEET_Apply(hwnd, wID == IDOK ? 1: 0) == FALSE) 2639 break; 2640 2641 if (wID == IDOK) 2642 { 2643 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, 2644 PropSheetInfoStr); 2645 int result = TRUE; 2646 2647 if (psInfo->restartWindows) 2648 result = ID_PSRESTARTWINDOWS; 2649 2650 /* reboot system takes precedence over restart windows */ 2651 if (psInfo->rebootSystem) 2652 result = ID_PSREBOOTSYSTEM; 2653 2654 if (psInfo->isModeless) 2655 psInfo->activeValid = FALSE; 2656 else 2657 EndDialog(hwnd, result); 2658 } 2659 else 2660 EnableWindow(hwndApplyBtn, FALSE); 2661 2662 break; 2663 } 2654 2664 2655 2665 case IDC_BACK_BUTTON: 2656 2657 2666 PROPSHEET_Back(hwnd); 2667 break; 2658 2668 2659 2669 case IDC_NEXT_BUTTON: 2660 2661 2670 PROPSHEET_Next(hwnd); 2671 break; 2662 2672 2663 2673 case IDC_FINISH_BUTTON: 2664 2665 2674 PROPSHEET_Finish(hwnd); 2675 break; 2666 2676 2667 2677 case IDCANCEL: 2668 2669 2678 PROPSHEET_Cancel(hwnd, 0); 2679 break; 2670 2680 2671 2681 case IDHELP: 2672 2673 2682 PROPSHEET_Help(hwnd); 2683 break; 2674 2684 } 2675 2685 … … 2684 2694 { 2685 2695 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n", 2686 2696 hwnd, uMsg, wParam, lParam); 2687 2697 2688 2698 switch (uMsg) … … 2757 2767 if (psInfo->useCallback) 2758 2768 (*(psInfo->ppshheader.pfnCallback))(hwnd, 2759 2769 PSCB_INITIALIZED, (LPARAM)0); 2760 2770 2761 2771 idx = psInfo->active_page; … … 2859 2869 msgResult = PROPSHEET_SetCurSel(hwnd, 2860 2870 (int)wParam, 2861 2871 1, 2862 2872 (HPROPSHEETPAGE)lParam); 2863 2873 } -
trunk/src/comctl32/treeview.c
r10098 r10165 96 96 UINT uNumItems; /* number of valid TREEVIEW_ITEMs */ 97 97 INT cdmode; /* last custom draw setting */ 98 UINT uScrollTime; 99 BOOL bRedraw;/* if FALSE we validate but don't redraw in TREEVIEW_Paint() */98 UINT uScrollTime; /* max. time for scrolling in milliseconds */ 99 BOOL bRedraw; /* if FALSE we validate but don't redraw in TREEVIEW_Paint() */ 100 100 101 101 UINT uItemHeight; /* item height */ … … 111 111 HTREEITEM selectedItem; /* handle to selected item or 0 if none */ 112 112 HTREEITEM hotItem; /* handle currently under cursor, 0 if none */ 113 HTREEITEM 113 HTREEITEM focusedItem; /* item that was under the cursor when WM_LBUTTONDOWN was received */ 114 114 115 115 HTREEITEM firstVisible; /* handle to first visible item */ … … 155 155 /* bitflags for infoPtr->uInternalStatus */ 156 156 157 #define TV_HSCROLL 158 #define TV_VSCROLL 0x02/* (horizontal/vertical) */159 #define TV_LDRAG 0x04/* Lbutton pushed to start drag */160 #define TV_LDRAGGING 0x08/* Lbutton pushed, mouse moved. */161 #define TV_RDRAG 0x10/* dito Rbutton */162 #define TV_RDRAGGING 157 #define TV_HSCROLL 0x01 /* treeview too large to fit in window */ 158 #define TV_VSCROLL 0x02 /* (horizontal/vertical) */ 159 #define TV_LDRAG 0x04 /* Lbutton pushed to start drag */ 160 #define TV_LDRAGGING 0x08 /* Lbutton pushed, mouse moved. */ 161 #define TV_RDRAG 0x10 /* dito Rbutton */ 162 #define TV_RDRAGGING 0x20 163 163 164 164 /* bitflags for infoPtr->timer */ … … 241 241 if (TREEVIEW_GetItemIndex(infoPtr, handle) == -1) 242 242 { 243 244 243 TRACE("invalid item %p\n", handle); 244 return FALSE; 245 245 } 246 246 else 247 247 return TRUE; 248 248 } 249 249 … … 280 280 do 281 281 { 282 283 282 child = child->parent; 283 if (child == parent) return TRUE; 284 284 } while (child != NULL); 285 285 … … 323 323 if (tvItem->prevSibling) 324 324 { 325 /* This item has a prevSibling, get the last item in the sibling's tree. */ 326 TREEVIEW_ITEM *upItem = tvItem->prevSibling; 327 328 if ((upItem->state & TVIS_EXPANDED) && upItem->lastChild != NULL) 329 return TREEVIEW_GetLastListItem(infoPtr, upItem->lastChild); 330 else 331 return upItem; 332 } 325 /* This item has a prevSibling, get the last item in the sibling's tree. */ 326 TREEVIEW_ITEM *upItem = tvItem->prevSibling; 327 328 if ((upItem->state & TVIS_EXPANDED) && upItem->lastChild != NULL) 329 return TREEVIEW_GetLastListItem(infoPtr, upItem->lastChild); 333 330 else 334 { 335 /* this item does not have a prevSibling, get the parent */ 336 return (tvItem->parent != infoPtr->root) ? tvItem->parent : NULL; 331 return upItem; 332 } 333 else 334 { 335 /* this item does not have a prevSibling, get the parent */ 336 return (tvItem->parent != infoPtr->root) ? tvItem->parent : NULL; 337 337 } 338 338 } … … 353 353 if ((tvItem->state & TVIS_EXPANDED) && tvItem->firstChild != NULL) 354 354 { 355 355 return tvItem->firstChild; 356 356 } 357 357 … … 361 361 */ 362 362 if (tvItem->nextSibling) 363 363 return tvItem->nextSibling; 364 364 365 365 /* … … 368 368 while (tvItem->parent) 369 369 { 370 371 372 373 370 tvItem = tvItem->parent; 371 372 if (tvItem->nextSibling) 373 return tvItem->nextSibling; 374 374 } 375 375 … … 386 386 static TREEVIEW_ITEM * 387 387 TREEVIEW_GetListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 388 388 LONG count) 389 389 { 390 390 TREEVIEW_ITEM *(*next_item)(TREEVIEW_INFO *, TREEVIEW_ITEM *); … … 395 395 if (count > 0) 396 396 { 397 397 next_item = TREEVIEW_GetNextListItem; 398 398 } 399 399 else if (count < 0) 400 400 { 401 402 401 count = -count; 402 next_item = TREEVIEW_GetPrevListItem; 403 403 } 404 404 else 405 405 return wineItem; 406 406 407 407 do 408 408 { 409 410 409 previousItem = wineItem; 410 wineItem = next_item(infoPtr, wineItem); 411 411 412 412 } while (--count && wineItem != NULL); … … 421 421 { 422 422 if (!infoPtr->bNtfUnicode) { 423 424 case TVN_SELCHANGINGW:return TVN_SELCHANGINGA;425 case TVN_SELCHANGEDW:return TVN_SELCHANGEDA;426 case TVN_GETDISPINFOW:return TVN_GETDISPINFOA;427 case TVN_SETDISPINFOW:return TVN_SETDISPINFOA;428 429 case TVN_ITEMEXPANDEDW:return TVN_ITEMEXPANDEDA;430 case TVN_BEGINDRAGW:return TVN_BEGINDRAGA;431 case TVN_BEGINRDRAGW:return TVN_BEGINRDRAGA;432 case TVN_DELETEITEMW:return TVN_DELETEITEMA;433 434 case TVN_ENDLABELEDITW:return TVN_ENDLABELEDITA;435 case TVN_GETINFOTIPW:return TVN_GETINFOTIPA;436 423 switch (code) { 424 case TVN_SELCHANGINGW: return TVN_SELCHANGINGA; 425 case TVN_SELCHANGEDW: return TVN_SELCHANGEDA; 426 case TVN_GETDISPINFOW: return TVN_GETDISPINFOA; 427 case TVN_SETDISPINFOW: return TVN_SETDISPINFOA; 428 case TVN_ITEMEXPANDINGW: return TVN_ITEMEXPANDINGA; 429 case TVN_ITEMEXPANDEDW: return TVN_ITEMEXPANDEDA; 430 case TVN_BEGINDRAGW: return TVN_BEGINDRAGA; 431 case TVN_BEGINRDRAGW: return TVN_BEGINRDRAGA; 432 case TVN_DELETEITEMW: return TVN_DELETEITEMA; 433 case TVN_BEGINLABELEDITW: return TVN_BEGINLABELEDITA; 434 case TVN_ENDLABELEDITW: return TVN_ENDLABELEDITA; 435 case TVN_GETINFOTIPW: return TVN_GETINFOTIPA; 436 } 437 437 } 438 438 return code; … … 458 458 459 459 return (BOOL)TREEVIEW_SendRealNotify(infoPtr, 460 460 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); 461 461 } 462 462 … … 484 484 if (len > 1) { 485 485 tvItem->pszText = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR)); 486 #ifdef __WIN32OS2__ 487 MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, (LPWSTR)tvItem->pszText, len); 488 #else 486 489 MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, (LPWSTR)tvItem->pszText, len*sizeof(WCHAR) ); 487 } 490 #endif 491 } 488 492 } 489 493 else 490 494 tvItem->pszText = item->pszText; 491 495 } 492 496 493 497 static BOOL 494 498 TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr, UINT code, UINT action, 495 499 UINT mask, HTREEITEM oldItem, HTREEITEM newItem) 496 500 { 497 501 HWND hwnd = infoPtr->hwnd; … … 500 504 501 505 TRACE("code:%d action:%x olditem:%p newitem:%p\n", 502 506 code, action, oldItem, newItem); 503 507 504 508 ZeroMemory(&nmhdr, sizeof(NMTREEVIEWA)); … … 510 514 511 515 if (oldItem) 512 516 TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemOld, oldItem); 513 517 514 518 if (newItem) 515 519 TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemNew, newItem); 516 520 517 521 nmhdr.ptDrag.x = 0; … … 519 523 520 524 ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, 521 522 525 (WPARAM)GetWindowLongA(hwnd, GWL_ID), 526 (LPARAM)&nmhdr); 523 527 if (infoPtr->bNtfUnicode) { 524 525 528 COMCTL32_Free(nmhdr.itemOld.pszText); 529 COMCTL32_Free(nmhdr.itemNew.pszText); 526 530 } 527 531 return ret; … … 530 534 static BOOL 531 535 TREEVIEW_SendTreeviewDnDNotify(TREEVIEW_INFO *infoPtr, UINT code, 532 536 HTREEITEM dragItem, POINT pt) 533 537 { 534 538 HWND hwnd = infoPtr->hwnd; … … 550 554 551 555 return (BOOL)TREEVIEW_SendRealNotify(infoPtr, 552 553 556 (WPARAM)GetWindowLongA(hwnd, GWL_ID), 557 (LPARAM)&nmhdr); 554 558 } 555 559 … … 557 561 static BOOL 558 562 TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage, 559 563 HDC hdc, RECT rc) 560 564 { 561 565 HWND hwnd = infoPtr->hwnd; … … 580 584 581 585 return (BOOL)TREEVIEW_SendRealNotify(infoPtr, 582 583 586 (WPARAM)GetWindowLongA(hwnd, GWL_ID), 587 (LPARAM)&nmcdhdr); 584 588 } 585 589 … … 590 594 static BOOL 591 595 TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc, 592 596 TREEVIEW_ITEM *wineItem, UINT uItemDrawState) 593 597 { 594 598 HWND hwnd = infoPtr->hwnd; … … 603 607 uItemState = 0; 604 608 if (wineItem->state & TVIS_SELECTED) 605 609 uItemState |= CDIS_SELECTED; 606 610 if (wineItem == infoPtr->selectedItem) 607 611 uItemState |= CDIS_FOCUS; 608 612 if (wineItem == infoPtr->hotItem) 609 613 uItemState |= CDIS_HOT; 610 614 611 615 nmcd = &nmcdhdr.nmcd; … … 624 628 625 629 TRACE("drawstage:%lx hdc:%p item:%lx, itemstate:%x, lItemlParam:%lx\n", 626 627 630 nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec, 631 nmcd->uItemState, nmcd->lItemlParam); 628 632 629 633 retval = TREEVIEW_SendRealNotify(infoPtr, 630 631 634 (WPARAM)GetWindowLongA(hwnd, GWL_ID), 635 (LPARAM)&nmcdhdr); 632 636 633 637 infoPtr->clrText = nmcdhdr.clrText; … … 656 660 if (len > 1) { 657 661 tvdi.item.pszText = allocated = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR)); 662 #ifdef __WIN32OS2__ 663 MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, (LPWSTR)tvdi.item.pszText, len); 664 tvdi.item.cchTextMax = len; 665 #else 658 666 MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, (LPWSTR)tvdi.item.pszText, len*sizeof(WCHAR) ); 659 667 tvdi.item.cchTextMax = len*sizeof(WCHAR); 660 } 661 else { 662 tvdi.item.pszText = editItem->pszText; /* ??? */ 663 tvdi.item.cchTextMax = editItem->cchTextMax; /* ??? */ 664 } 668 #endif 665 669 } 666 670 else { 667 tvdi.item.pszText = editItem->pszText; 668 tvdi.item.cchTextMax = editItem->cchTextMax; 671 tvdi.item.pszText = editItem->pszText; /* ??? */ 672 tvdi.item.cchTextMax = editItem->cchTextMax; /* ??? */ 673 } 674 } 675 else { 676 tvdi.item.pszText = editItem->pszText; 677 tvdi.item.cchTextMax = editItem->cchTextMax; 669 678 } 670 679 671 680 ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, 672 673 681 tvdi.hdr.idFrom, 682 (LPARAM)&tvdi); 674 683 if (allocated) 675 684 COMCTL32_Free(allocated); 676 685 return ret; 677 686 } … … 679 688 static void 680 689 TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 681 690 UINT mask) 682 691 { 683 692 NMTVDISPINFOA callback; … … 714 723 if ((mask & TVIF_TEXT) && callback.item.pszText != wineItem->pszText) 715 724 { 716 717 718 719 725 /* Instead of copying text into our buffer user specified its own */ 726 if (infoPtr->bNtfUnicode) { 727 LPWSTR newText; 728 int buflen; 720 729 int len = WideCharToMultiByte( CP_ACP, 0, 721 730 (LPWSTR)callback.item.pszText, -1, 722 731 NULL, 0, NULL, NULL ); 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 732 buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE); 733 newText = (LPWSTR)COMCTL32_ReAlloc(wineItem->pszText, buflen); 734 735 TRACE("returned wstr %s, len=%d, buflen=%d\n", 736 debugstr_w((LPWSTR)callback.item.pszText), len, buflen); 737 738 if (newText) 739 { 740 wineItem->pszText = (LPSTR)newText; 741 WideCharToMultiByte( CP_ACP, 0, 742 (LPWSTR)callback.item.pszText, -1, 743 wineItem->pszText, buflen, 744 NULL, NULL ); 745 wineItem->cchTextMax = buflen; 746 } 747 /* If ReAlloc fails we have nothing to do, but keep original text */ 748 } 749 else { 750 int len = max(lstrlenA(callback.item.pszText) + 1, 751 TEXT_CALLBACK_SIZE); 752 LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len); 753 754 TRACE("returned str %s, len=%d\n", 755 debugstr_a(callback.item.pszText), len); 756 757 if (newText) 758 { 759 wineItem->pszText = newText; 760 strcpy(wineItem->pszText, callback.item.pszText); 761 wineItem->cchTextMax = len; 762 } 763 /* If ReAlloc fails we have nothing to do, but keep original text */ 764 } 756 765 } 757 766 else if (mask & TVIF_TEXT) { 758 759 760 761 762 767 /* User put text into our buffer, that is ok unless W string */ 768 if (infoPtr->bNtfUnicode) { 769 LPWSTR newText; 770 LPSTR oldText = NULL; 771 int buflen; 763 772 int len = WideCharToMultiByte( CP_ACP, 0, 764 773 (LPWSTR)callback.item.pszText, -1, 765 774 NULL, 0, NULL, NULL ); 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 775 buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE); 776 newText = (LPWSTR)COMCTL32_Alloc(buflen); 777 778 TRACE("same buffer wstr %s, len=%d, buflen=%d\n", 779 debugstr_w((LPWSTR)callback.item.pszText), len, buflen); 780 781 if (newText) 782 { 783 oldText = wineItem->pszText; 784 wineItem->pszText = (LPSTR)newText; 785 WideCharToMultiByte( CP_ACP, 0, 786 (LPWSTR)callback.item.pszText, -1, 787 wineItem->pszText, buflen, NULL, NULL ); 788 wineItem->cchTextMax = buflen; 789 if (oldText) 790 COMCTL32_Free(oldText); 791 } 792 } 784 793 } 785 794 786 795 if (mask & TVIF_IMAGE) 787 796 wineItem->iImage = callback.item.iImage; 788 797 789 798 if (mask & TVIF_SELECTEDIMAGE) 790 799 wineItem->iSelectedImage = callback.item.iSelectedImage; 791 800 792 801 if (mask & TVIF_CHILDREN) 793 802 wineItem->cChildren = callback.item.cChildren; 794 803 795 804 /* These members are now permanently set. */ 796 805 if (callback.item.mask & TVIF_DI_SETITEM) 797 806 wineItem->callbackMask &= ~callback.item.mask; 798 807 } 799 808 … … 820 829 static VOID 821 830 TREEVIEW_ComputeItemInternalMetrics(TREEVIEW_INFO *infoPtr, 822 831 TREEVIEW_ITEM *item) 823 832 { 824 833 /* Same effect, different optimisation. */ 825 834 #if 0 826 835 BOOL lar = ((infoPtr->dwStyle & TVS_LINESATROOT) 827 836 && (infoPtr->dwStyle & (TVS_HASLINES|TVS_HASBUTTONS))); 828 837 #else 829 838 BOOL lar = ((infoPtr->dwStyle 830 831 839 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS)) 840 > TVS_LINESATROOT); 832 841 #endif 833 842 834 843 item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1) 835 844 - infoPtr->scrollX; 836 845 item->stateOffset = item->linesOffset + infoPtr->uIndent; 837 846 item->imageOffset = item->stateOffset 838 847 + (STATEIMAGEINDEX(item->state) ? infoPtr->stateImageWidth : 0); 839 848 item->textOffset = item->imageOffset + infoPtr->normalImageWidth; 840 849 } … … 850 859 if (item->pszText == NULL) 851 860 { 852 853 861 item->textWidth = 0; 862 return; 854 863 } 855 864 … … 859 868 if (hDC != 0) 860 869 { 861 870 hdc = hDC; 862 871 } 863 872 else 864 873 { 865 866 874 hdc = GetDC(infoPtr->hwnd); 875 hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, item)); 867 876 } 868 877 … … 872 881 if (hDC == 0) 873 882 { 874 875 883 SelectObject(hdc, hOldFont); 884 ReleaseDC(0, hdc); 876 885 } 877 886 } … … 881 890 { 882 891 item->rect.top = infoPtr->uItemHeight * 883 892 (item->visibleOrder - infoPtr->firstVisible->visibleOrder); 884 893 885 894 item->rect.bottom = item->rect.top 886 895 + infoPtr->uItemHeight * item->iIntegral - 1; 887 896 888 897 item->rect.left = 0; … … 899 908 if (!start) 900 909 { 901 902 910 start = infoPtr->root->firstChild; 911 order = 0; 903 912 } 904 913 else 905 914 order = start->visibleOrder; 906 915 907 916 for (item = start; item != NULL; 908 917 item = TREEVIEW_GetNextListItem(infoPtr, item)) 909 918 { 910 911 919 item->visibleOrder = order; 920 order += item->iIntegral; 912 921 } 913 922 … … 915 924 916 925 for (item = start; item != NULL; 917 918 { 919 926 item = TREEVIEW_GetNextListItem(infoPtr, item)) 927 { 928 TREEVIEW_ComputeItemRect(infoPtr, item); 920 929 } 921 930 } … … 969 978 970 979 if (!newItem) 971 980 return NULL; 972 981 973 982 if (DPA_InsertPtr(infoPtr->items, INT_MAX, newItem) == -1) 974 983 { 975 976 984 COMCTL32_Free(newItem); 985 return NULL; 977 986 } 978 987 … … 1010 1019 static void 1011 1020 TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling, 1012 1021 TREEVIEW_ITEM *parent) 1013 1022 { 1014 1023 assert(newItem != NULL); … … 1017 1026 if (sibling != NULL) 1018 1027 { 1019 1020 1021 1022 1023 1024 1025 1028 assert(sibling->parent == parent); 1029 1030 if (sibling->prevSibling != NULL) 1031 sibling->prevSibling->nextSibling = newItem; 1032 1033 newItem->prevSibling = sibling->prevSibling; 1034 sibling->prevSibling = newItem; 1026 1035 } 1027 1036 else … … 1031 1040 1032 1041 if (parent->firstChild == sibling) 1033 1042 parent->firstChild = newItem; 1034 1043 1035 1044 if (parent->lastChild == NULL) 1036 1045 parent->lastChild = newItem; 1037 1046 } 1038 1047 … … 1043 1052 static void 1044 1053 TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling, 1045 1054 TREEVIEW_ITEM *parent) 1046 1055 { 1047 1056 assert(newItem != NULL); … … 1050 1059 if (sibling != NULL) 1051 1060 { 1052 1053 1054 1055 1056 1057 1058 1061 assert(sibling->parent == parent); 1062 1063 if (sibling->nextSibling != NULL) 1064 sibling->nextSibling->prevSibling = newItem; 1065 1066 newItem->nextSibling = sibling->nextSibling; 1067 sibling->nextSibling = newItem; 1059 1068 } 1060 1069 else … … 1064 1073 1065 1074 if (parent->lastChild == sibling) 1066 1075 parent->lastChild = newItem; 1067 1076 1068 1077 if (parent->firstChild == NULL) 1069 1078 parent->firstChild = newItem; 1070 1079 } 1071 1080 1072 1081 static BOOL 1073 1082 TREEVIEW_DoSetItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 1074 1083 const TVITEMEXA *tvItem) 1075 1084 { 1076 1085 UINT callbackClear = 0; … … 1081 1090 { 1082 1091 wineItem->textWidth = 0; /* force width recalculation */ 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1092 if (tvItem->pszText != LPSTR_TEXTCALLBACKA) 1093 { 1094 int len = lstrlenA(tvItem->pszText) + 1; 1095 LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len); 1096 1097 if (newText == NULL) return FALSE; 1098 1099 callbackClear |= TVIF_TEXT; 1100 1101 wineItem->pszText = newText; 1102 wineItem->cchTextMax = len; 1103 lstrcpynA(wineItem->pszText, tvItem->pszText, len); 1104 TRACE("setting text %s, item %p\n", 1105 debugstr_a(wineItem->pszText), wineItem); 1106 } 1107 else 1108 { 1109 callbackSet |= TVIF_TEXT; 1110 1111 wineItem->pszText = COMCTL32_ReAlloc(wineItem->pszText, 1112 TEXT_CALLBACK_SIZE); 1113 wineItem->cchTextMax = TEXT_CALLBACK_SIZE; 1114 TRACE("setting callback, item %p\n", 1115 wineItem); 1116 } 1108 1117 } 1109 1118 1110 1119 if (tvItem->mask & TVIF_CHILDREN) 1111 1120 { 1112 1113 1114 1115 1116 1117 1121 wineItem->cChildren = tvItem->cChildren; 1122 1123 if (wineItem->cChildren == I_CHILDRENCALLBACK) 1124 callbackSet |= TVIF_CHILDREN; 1125 else 1126 callbackClear |= TVIF_CHILDREN; 1118 1127 } 1119 1128 1120 1129 if (tvItem->mask & TVIF_IMAGE) 1121 1130 { 1122 1123 1124 1125 1126 1127 1131 wineItem->iImage = tvItem->iImage; 1132 1133 if (wineItem->iImage == I_IMAGECALLBACK) 1134 callbackSet |= TVIF_IMAGE; 1135 else 1136 callbackClear |= TVIF_IMAGE; 1128 1137 } 1129 1138 1130 1139 if (tvItem->mask & TVIF_SELECTEDIMAGE) 1131 1140 { 1132 1133 1134 1135 1136 1137 1141 wineItem->iSelectedImage = tvItem->iSelectedImage; 1142 1143 if (wineItem->iSelectedImage == I_IMAGECALLBACK) 1144 callbackSet |= TVIF_SELECTEDIMAGE; 1145 else 1146 callbackClear |= TVIF_SELECTEDIMAGE; 1138 1147 } 1139 1148 1140 1149 if (tvItem->mask & TVIF_PARAM) 1141 1150 wineItem->lParam = tvItem->lParam; 1142 1151 1143 1152 /* If the application sets TVIF_INTEGRAL without 1144 1153 * supplying a TVITEMEX structure, it's toast. */ 1145 1154 if (tvItem->mask & TVIF_INTEGRAL) 1146 1155 wineItem->iIntegral = tvItem->iIntegral; 1147 1156 1148 1157 if (tvItem->mask & TVIF_STATE) 1149 1158 { 1150 1151 1152 1153 1159 TRACE("prevstate,state,mask:%x,%x,%x\n", wineItem->state, tvItem->state, 1160 tvItem->stateMask); 1161 wineItem->state &= ~tvItem->stateMask; 1162 wineItem->state |= (tvItem->state & tvItem->stateMask); 1154 1163 } 1155 1164 … … 1172 1181 if (ptdi->hParent == TVI_ROOT || ptdi->hParent == 0) 1173 1182 { 1174 1183 parentItem = infoPtr->root; 1175 1184 } 1176 1185 else 1177 1186 { 1178 1179 1180 1181 1182 1183 1184 1187 parentItem = ptdi->hParent; 1188 1189 if (!TREEVIEW_ValidItem(infoPtr, parentItem)) 1190 { 1191 WARN("invalid parent %p\n", parentItem); 1192 return (LRESULT)(HTREEITEM)NULL; 1193 } 1185 1194 } 1186 1195 … … 1193 1202 case (DWORD)TVI_LAST: 1194 1203 case (DWORD)TVI_SORT: 1195 1204 break; 1196 1205 1197 1206 default: 1198 1207 if (!TREEVIEW_ValidItem(infoPtr, insertAfter) || 1199 1208 insertAfter->parent != parentItem) 1200 1201 1202 1203 1209 { 1210 WARN("invalid insert after %p\n", insertAfter); 1211 insertAfter = TVI_LAST; 1212 } 1204 1213 } 1205 1214 1206 1215 TRACE("parent %p position %p: '%s'\n", parentItem, insertAfter, 1207 1208 1209 1210 1216 (tvItem->mask & TVIF_TEXT) 1217 ? ((tvItem->pszText == LPSTR_TEXTCALLBACKA) ? "<callback>" 1218 : tvItem->pszText) 1219 : "<no label>"); 1211 1220 1212 1221 newItem = TREEVIEW_AllocateItem(infoPtr); 1213 1222 if (newItem == NULL) 1214 1223 return (LRESULT)(HTREEITEM)NULL; 1215 1224 1216 1225 newItem->parent = parentItem; … … 1218 1227 1219 1228 if (!TREEVIEW_DoSetItem(infoPtr, newItem, tvItem)) 1220 1229 return (LRESULT)(HTREEITEM)NULL; 1221 1230 1222 1231 /* After this point, nothing can fail. (Except for TVI_SORT.) */ … … 1233 1242 TREEVIEW_SetFirstVisible(infoPtr, newItem, TRUE); 1234 1243 } 1235 1244 break; 1236 1245 1237 1246 case (DWORD)TVI_LAST: 1238 1239 1240 1241 1247 TREEVIEW_InsertAfter(newItem, parentItem->lastChild, parentItem); 1248 break; 1249 1250 /* hInsertAfter names a specific item we want to insert after */ 1242 1251 default: 1243 1244 1252 TREEVIEW_InsertAfter(newItem, insertAfter, insertAfter->parent); 1253 break; 1245 1254 1246 1255 case (DWORD)TVI_SORT: 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 if (comp < 0)/* we are smaller than the current one */1266 1267 1268 1269 1270 1271 else if (comp > 0)/* we are bigger than the current one */1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1256 { 1257 TREEVIEW_ITEM *aChild; 1258 TREEVIEW_ITEM *previousChild = NULL; 1259 BOOL bItemInserted = FALSE; 1260 1261 aChild = parentItem->firstChild; 1262 1263 bTextUpdated = TRUE; 1264 TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT); 1265 1266 /* Iterate the parent children to see where we fit in */ 1267 while (aChild != NULL) 1268 { 1269 INT comp; 1270 1271 TREEVIEW_UpdateDispInfo(infoPtr, aChild, TVIF_TEXT); 1272 comp = lstrcmpA(newItem->pszText, aChild->pszText); 1273 1274 if (comp < 0) /* we are smaller than the current one */ 1275 { 1276 TREEVIEW_InsertBefore(newItem, aChild, parentItem); 1277 bItemInserted = TRUE; 1278 break; 1279 } 1280 else if (comp > 0) /* we are bigger than the current one */ 1281 { 1282 previousChild = aChild; 1283 1284 /* This will help us to exit if there is no more sibling */ 1285 aChild = (aChild->nextSibling == 0) 1286 ? NULL 1287 : aChild->nextSibling; 1288 1289 /* Look at the next item */ 1290 continue; 1291 } 1292 else if (comp == 0) 1293 { 1294 /* 1295 * An item with this name is already existing, therefore, 1296 * we add after the one we found 1297 */ 1298 TREEVIEW_InsertAfter(newItem, aChild, parentItem); 1299 bItemInserted = TRUE; 1300 break; 1301 } 1302 } 1303 1304 /* 1305 * we reach the end of the child list and the item has not 1306 * yet been inserted, therefore, insert it after the last child. 1307 */ 1308 if ((!bItemInserted) && (aChild == NULL)) 1309 TREEVIEW_InsertAfter(newItem, previousChild, parentItem); 1310 1311 break; 1312 } 1304 1313 } 1305 1314 1306 1315 1307 1316 TRACE("new item %p; parent %p, mask %x\n", newItem, 1308 1317 newItem->parent, tvItem->mask); 1309 1318 1310 1319 newItem->iLevel = newItem->parent->iLevel + 1; 1311 1320 1312 1321 if (newItem->parent->cChildren == 0) 1313 1322 newItem->parent->cChildren = 1; 1314 1323 1315 1324 if (infoPtr->dwStyle & TVS_CHECKBOXES) 1316 1325 { 1317 1318 1326 if (STATEIMAGEINDEX(newItem->state) == 0) 1327 newItem->state |= INDEXTOSTATEIMAGEMASK(1); 1319 1328 } 1320 1329 1321 1330 if (infoPtr->firstVisible == NULL) 1322 1331 infoPtr->firstVisible = newItem; 1323 1332 1324 1333 TREEVIEW_VerifyTree(infoPtr); … … 1344 1353 for (item = newItem; 1345 1354 item != NULL; 1346 1355 item = TREEVIEW_GetNextListItem(infoPtr, item)) 1347 1356 TREEVIEW_Invalidate(infoPtr, item); 1348 1357 } … … 1380 1389 tvisA.DUMMYUNIONNAME.item.stateMask = tvisW->DUMMYUNIONNAME.item.stateMask; 1381 1390 tvisA.DUMMYUNIONNAME.item.cchTextMax = 1382 1391 tvisW->DUMMYUNIONNAME.item.cchTextMax; 1383 1392 1384 1393 if (tvisW->DUMMYUNIONNAME.item.pszText) 1385 1394 { 1386 1387 1395 if (tvisW->DUMMYUNIONNAME.item.pszText != LPSTR_TEXTCALLBACKW) 1396 { 1388 1397 int len = WideCharToMultiByte( CP_ACP, 0, tvisW->DUMMYUNIONNAME.item.pszText, -1, 1389 1398 NULL, 0, NULL, NULL ); 1390 1399 tvisA.DUMMYUNIONNAME.item.pszText = COMCTL32_Alloc(len); 1391 1400 WideCharToMultiByte( CP_ACP, 0, tvisW->DUMMYUNIONNAME.item.pszText, -1, 1392 1401 tvisA.DUMMYUNIONNAME.item.pszText, len, NULL, NULL ); 1393 1394 1395 1396 1397 1398 1402 } 1403 else 1404 { 1405 tvisA.DUMMYUNIONNAME.item.pszText = LPSTR_TEXTCALLBACKA; 1406 tvisA.DUMMYUNIONNAME.item.cchTextMax = 0; 1407 } 1399 1408 } 1400 1409 1401 1410 tvisA.DUMMYUNIONNAME.item.iImage = tvisW->DUMMYUNIONNAME.item.iImage; 1402 1411 tvisA.DUMMYUNIONNAME.item.iSelectedImage = 1403 1412 tvisW->DUMMYUNIONNAME.item.iSelectedImage; 1404 1413 tvisA.DUMMYUNIONNAME.item.cChildren = tvisW->DUMMYUNIONNAME.item.cChildren; 1405 1414 tvisA.DUMMYUNIONNAME.item.lParam = tvisW->DUMMYUNIONNAME.item.lParam; … … 1409 1418 if (tvisA.DUMMYUNIONNAME.item.pszText != LPSTR_TEXTCALLBACKA) 1410 1419 { 1411 1420 COMCTL32_Free(tvisA.DUMMYUNIONNAME.item.pszText); 1412 1421 } 1413 1422 … … 1428 1437 while (kill != NULL) 1429 1438 { 1430 1431 1432 1433 1434 1439 TREEVIEW_ITEM *next = kill->nextSibling; 1440 1441 TREEVIEW_RemoveItem(infoPtr, kill); 1442 1443 kill = next; 1435 1444 } 1436 1445 … … 1449 1458 1450 1459 if (parentItem->firstChild == item) 1451 1460 parentItem->firstChild = item->nextSibling; 1452 1461 1453 1462 if (parentItem->lastChild == item) 1454 1463 parentItem->lastChild = item->prevSibling; 1455 1464 1456 1465 if (parentItem->firstChild == NULL && parentItem->lastChild == NULL 1457 1458 1466 && parentItem->cChildren > 0) 1467 parentItem->cChildren = 0; 1459 1468 1460 1469 if (item->prevSibling) 1461 1470 item->prevSibling->nextSibling = item->nextSibling; 1462 1471 1463 1472 if (item->nextSibling) 1464 1473 item->nextSibling->prevSibling = item->prevSibling; 1465 1474 } 1466 1475 … … 1471 1480 1472 1481 TREEVIEW_SendTreeviewNotify(infoPtr, TVN_DELETEITEMW, TVC_UNKNOWN, 1473 1482 TVIF_HANDLE | TVIF_PARAM, wineItem, 0); 1474 1483 1475 1484 if (wineItem->firstChild) 1476 1485 TREEVIEW_RemoveAllChildren(infoPtr, wineItem); 1477 1486 1478 1487 TREEVIEW_UnlinkItem(wineItem); … … 1481 1490 1482 1491 if (wineItem->pszText != LPSTR_TEXTCALLBACKA) 1483 1492 COMCTL32_Free(wineItem->pszText); 1484 1493 1485 1494 TREEVIEW_FreeItem(infoPtr, wineItem); … … 1493 1502 TREEVIEW_RemoveAllChildren(infoPtr, infoPtr->root); 1494 1503 1495 assert(infoPtr->uNumItems == 0); 1504 assert(infoPtr->uNumItems == 0); /* root isn't counted in uNumItems */ 1496 1505 } 1497 1506 … … 1507 1516 if (wineItem == TVI_ROOT) 1508 1517 { 1509 1510 1511 1512 1513 1518 TRACE("TVI_ROOT\n"); 1519 parent = infoPtr->root; 1520 newSelection = NULL; 1521 visible = TRUE; 1522 TREEVIEW_RemoveTree(infoPtr); 1514 1523 } 1515 1524 else 1516 1525 { 1517 1518 1519 1520 1521 1526 if (!TREEVIEW_ValidItem(infoPtr, wineItem)) 1527 return FALSE; 1528 1529 TRACE("%p (%s)\n", wineItem, TREEVIEW_ItemName(wineItem)); 1530 parent = wineItem->parent; 1522 1531 1523 1532 if (ISVISIBLE(wineItem)) … … 1527 1536 } 1528 1537 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1538 if (infoPtr->selectedItem != NULL 1539 && (wineItem == infoPtr->selectedItem 1540 || TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem))) 1541 { 1542 if (wineItem->nextSibling) 1543 newSelection = wineItem->nextSibling; 1544 else if (wineItem->parent != infoPtr->root) 1545 newSelection = wineItem->parent; 1546 } 1547 1548 if (infoPtr->firstVisible == wineItem) 1549 { 1550 if (wineItem->nextSibling) 1551 newFirstVisible = wineItem->nextSibling; 1552 else if (wineItem->prevSibling) 1553 newFirstVisible = wineItem->prevSibling; 1554 else if (wineItem->parent != infoPtr->root) 1555 newFirstVisible = wineItem->parent; 1556 TREEVIEW_SetFirstVisible(infoPtr, NULL, TRUE); 1557 } 1558 else 1559 newFirstVisible = infoPtr->firstVisible; 1560 1561 TREEVIEW_RemoveItem(infoPtr, wineItem); 1553 1562 } 1554 1563 … … 1556 1565 if (oldSelection == infoPtr->selectedItem) 1557 1566 { 1558 1559 1560 1561 1567 if (TREEVIEW_ValidItem(infoPtr, newSelection)) 1568 TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, TVC_UNKNOWN); 1569 else 1570 infoPtr->selectedItem = 0; 1562 1571 } 1563 1572 … … 1566 1575 */ 1567 1576 if (!TREEVIEW_ValidItem(infoPtr, infoPtr->insertMarkItem)) 1568 1577 infoPtr->insertMarkItem = 0; 1569 1578 1570 1579 if (!TREEVIEW_ValidItem(infoPtr, infoPtr->dropItem)) 1571 1580 infoPtr->dropItem = 0; 1572 1581 1573 1582 if (!TREEVIEW_ValidItem(infoPtr, newFirstVisible)) … … 1619 1628 1620 1629 if (newIndent < MINIMUM_INDENT) 1621 1630 newIndent = MINIMUM_INDENT; 1622 1631 1623 1632 if (infoPtr->uIndent != newIndent) 1624 1633 { 1625 1626 1627 1628 1634 infoPtr->uIndent = newIndent; 1635 TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root); 1636 TREEVIEW_UpdateScrollBars(infoPtr); 1637 TREEVIEW_Invalidate(infoPtr, NULL); 1629 1638 } 1630 1639 … … 1678 1687 { 1679 1688 case (WPARAM)TVSIL_NORMAL: 1680 1689 return (LRESULT)infoPtr->himlNormal; 1681 1690 1682 1691 case (WPARAM)TVSIL_STATE: 1683 1692 return (LRESULT)infoPtr->himlState; 1684 1693 1685 1694 default: 1686 1695 return 0; 1687 1696 } 1688 1697 } … … 1701 1710 { 1702 1711 case (WPARAM)TVSIL_NORMAL: 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1712 himlOld = infoPtr->himlNormal; 1713 infoPtr->himlNormal = himlNew; 1714 1715 if (himlNew != NULL) 1716 ImageList_GetIconSize(himlNew, &infoPtr->normalImageWidth, 1717 &infoPtr->normalImageHeight); 1718 else 1719 { 1720 infoPtr->normalImageWidth = 0; 1721 infoPtr->normalImageHeight = 0; 1722 } 1723 1724 break; 1716 1725 1717 1726 case (WPARAM)TVSIL_STATE: 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1727 himlOld = infoPtr->himlState; 1728 infoPtr->himlState = himlNew; 1729 1730 if (himlNew != NULL) 1731 ImageList_GetIconSize(himlNew, &infoPtr->stateImageWidth, 1732 &infoPtr->stateImageHeight); 1733 else 1734 { 1735 infoPtr->stateImageWidth = 0; 1736 infoPtr->stateImageHeight = 0; 1737 } 1738 1739 break; 1731 1740 } 1732 1741 … … 1769 1778 if (newHeight == -1) 1770 1779 { 1771 1772 1780 infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); 1781 infoPtr->bHeightSet = FALSE; 1773 1782 } 1774 1783 else 1775 1784 { 1776 1777 1785 infoPtr->uItemHeight = newHeight; 1786 infoPtr->bHeightSet = TRUE; 1778 1787 } 1779 1788 1780 1789 /* Round down, unless we support odd ("non even") heights. */ 1781 1790 if (!(infoPtr->dwStyle) & TVS_NONEVENHEIGHT) 1782 1791 infoPtr->uItemHeight &= ~1; 1783 1792 1784 1793 if (infoPtr->uItemHeight != prevHeight) 1785 1794 { 1786 1787 1788 1795 TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); 1796 TREEVIEW_UpdateScrollBars(infoPtr); 1797 TREEVIEW_Invalidate(infoPtr, NULL); 1789 1798 } 1790 1799 … … 1831 1840 1832 1841 if (!infoPtr->bHeightSet) 1833 1842 infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); 1834 1843 1835 1844 if (uHeight != infoPtr->uItemHeight) … … 1842 1851 1843 1852 if (bRedraw) 1844 1853 TREEVIEW_Invalidate(infoPtr, NULL); 1845 1854 1846 1855 return 0; … … 1882 1891 1883 1892 if (infoPtr->clrText != prevColor) 1884 1893 TREEVIEW_Invalidate(infoPtr, NULL); 1885 1894 1886 1895 return (LRESULT)prevColor; … … 1904 1913 1905 1914 if (newColor != prevColor) 1906 1915 TREEVIEW_Invalidate(infoPtr, NULL); 1907 1916 1908 1917 return (LRESULT)prevColor; … … 1935 1944 1936 1945 if (!TREEVIEW_ValidItem(infoPtr, item)) 1937 1946 return 0; 1938 1947 1939 1948 infoPtr->insertBeforeorAfter = wParam; … … 1961 1970 */ 1962 1971 if (pItem == NULL) 1963 1972 return FALSE; 1964 1973 1965 1974 wineItem = *pItem; 1966 1975 if (!TREEVIEW_ValidItem(infoPtr, wineItem) || !ISVISIBLE(wineItem)) 1967 1976 return FALSE; 1968 1977 1969 1978 /* … … 1973 1982 if (fTextRect) 1974 1983 { 1975 1976 1977 1978 1979 1980 1981 1984 /* Windows does not send TVN_GETDISPINFO here. */ 1985 1986 lpRect->top = wineItem->rect.top; 1987 lpRect->bottom = wineItem->rect.bottom; 1988 1989 lpRect->left = wineItem->textOffset; 1990 lpRect->right = wineItem->textOffset + wineItem->textWidth; 1982 1991 } 1983 1992 else 1984 1993 { 1985 1994 *lpRect = wineItem->rect; 1986 1995 } 1987 1996 1988 1997 TRACE("%s [L:%ld R:%ld T:%ld B:%ld]\n", fTextRect ? "text" : "item", 1989 1998 lpRect->left, lpRect->right, lpRect->top, lpRect->bottom); 1990 1999 1991 2000 return TRUE; … … 2007 2016 wineItem = tvItem->hItem; 2008 2017 if (!TREEVIEW_ValidItem(infoPtr, wineItem)) 2009 2018 return FALSE; 2010 2019 2011 2020 TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask); 2012 2021 2013 2022 if (tvItem->mask & TVIF_CHILDREN) 2014 2023 tvItem->cChildren = wineItem->cChildren; 2015 2024 2016 2025 if (tvItem->mask & TVIF_HANDLE) 2017 2026 tvItem->hItem = wineItem; 2018 2027 2019 2028 if (tvItem->mask & TVIF_IMAGE) 2020 2029 tvItem->iImage = wineItem->iImage; 2021 2030 2022 2031 if (tvItem->mask & TVIF_INTEGRAL) 2023 2032 tvItem->iIntegral = wineItem->iIntegral; 2024 2033 2025 2034 /* undocumented: windows ignores TVIF_PARAM and … … 2029 2038 2030 2039 if (tvItem->mask & TVIF_SELECTEDIMAGE) 2031 2040 tvItem->iSelectedImage = wineItem->iSelectedImage; 2032 2041 2033 2042 if (tvItem->mask & TVIF_STATE) { 2034 2043 /* Careful here - Windows ignores the stateMask when you get the state 2035 2036 2044 That contradicts the documentation, but makes more common sense, masking 2045 retrieval in this way seems overkill */ 2037 2046 tvItem->state = wineItem->state; 2038 2047 } 2039 2048 2040 2049 if (tvItem->mask & TVIF_TEXT) 2041 2050 lstrcpynA(tvItem->pszText, wineItem->pszText, tvItem->cchTextMax); 2042 2051 2043 2052 TRACE("item <%p>, txt %p, img %p, mask %x\n", 2044 2053 wineItem, tvItem->pszText, &tvItem->iImage, tvItem->mask); 2045 2054 2046 2055 return TRUE; … … 2058 2067 2059 2068 TRACE("item %d,mask %x\n", TREEVIEW_GetItemIndex(infoPtr, wineItem), 2060 2069 tvItem->mask); 2061 2070 2062 2071 if (!TREEVIEW_ValidItem(infoPtr, wineItem)) 2063 2064 2072 return FALSE; 2073 2065 2074 /* store the orignal item values */ 2066 2075 originalItem = *wineItem; 2067 2076 2068 2077 if (!TREEVIEW_DoSetItem(infoPtr, wineItem, tvItem)) 2069 2078 return FALSE; 2070 2079 2071 2080 /* If the text or TVIS_BOLD was changed, and it is visible, recalculate. */ 2072 2081 if ((tvItem->mask & TVIF_TEXT 2073 2074 2075 { 2076 2077 2082 || (tvItem->mask & TVIF_STATE && tvItem->stateMask & TVIS_BOLD)) 2083 && ISVISIBLE(wineItem)) 2084 { 2085 TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_TEXT); 2086 TREEVIEW_ComputeTextWidth(infoPtr, wineItem, 0); 2078 2087 } 2079 2088 2080 2089 if (tvItem->mask != 0 && ISVISIBLE(wineItem)) 2081 2090 { 2082 2083 2091 /* The refresh updates everything, but we can't wait until then. */ 2092 TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem); 2084 2093 2085 2094 /* if any of the items values changed, redraw the item */ … … 2087 2096 { 2088 2097 if (tvItem->mask & TVIF_INTEGRAL) 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2098 { 2099 TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); 2100 TREEVIEW_UpdateScrollBars(infoPtr); 2101 2102 TREEVIEW_Invalidate(infoPtr, NULL); 2103 } 2104 else 2105 { 2106 TREEVIEW_UpdateScrollBars(infoPtr); 2107 TREEVIEW_Invalidate(infoPtr, wineItem); 2108 } 2100 2109 } 2101 2110 } … … 2148 2157 } 2149 2158 else if (wineItem->pszText) { 2150 2151 2159 TRACE("orig str %s at %p\n", 2160 debugstr_a(wineItem->pszText), wineItem->pszText); 2152 2161 MultiByteToWideChar(CP_ACP, 0, wineItem->pszText, 2153 2162 -1 , tvItem->pszText, tvItem->cchTextMax); … … 2156 2165 2157 2166 TRACE("item %d<%p>, txt %p<%s>, img %p, action %x\n", 2158 2159 2167 iItem, tvItem, tvItem->pszText, debugstr_w(tvItem->pszText), 2168 &tvItem->iImage, tvItem->mask); 2160 2169 return TRUE; 2161 2170 } … … 2173 2182 tvItemA.stateMask = tvItem->stateMask; 2174 2183 if (tvItem->mask & TVIF_TEXT) { 2175 len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1, 2176 NULL ,0 , NULL,NULL); 2177 if (len) { 2178 len ++; 2184 len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1, 2185 NULL ,0 , NULL,NULL); 2186 if (len) { 2187 len ++; 2188 #ifdef __WIN32OS2__ 2189 tvItemA.pszText = HeapAlloc(GetProcessHeap(),0,len); 2190 len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1, 2191 tvItemA.pszText ,len, 2192 NULL,NULL); 2193 #else 2179 2194 tvItemA.pszText = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); 2180 2195 len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1, 2181 2196 tvItemA.pszText ,len*sizeof(WCHAR), 2182 2197 NULL,NULL); 2183 } 2184 else 2185 tvItemA.pszText = NULL; 2198 #endif 2199 } 2200 else 2201 tvItemA.pszText = NULL; 2186 2202 } 2187 2203 tvItemA.cchTextMax = tvItem->cchTextMax; … … 2203 2219 2204 2220 if (!wineItem || !TREEVIEW_ValidItem(infoPtr, wineItem)) 2205 2221 return 0; 2206 2222 2207 2223 return (wineItem->state & mask); … … 2218 2234 switch (which) 2219 2235 { 2220 case TVGN_CHILD: 2221 2222 2223 2236 case TVGN_CHILD: /* Special case: child of 0 is root */ 2237 if (wineItem) 2238 break; 2239 /* fall through */ 2224 2240 case TVGN_ROOT: 2225 2226 2241 retval = infoPtr->root->firstChild; 2242 break; 2227 2243 2228 2244 case TVGN_CARET: 2229 2230 2245 retval = infoPtr->selectedItem; 2246 break; 2231 2247 2232 2248 case TVGN_FIRSTVISIBLE: 2233 2234 2249 retval = infoPtr->firstVisible; 2250 break; 2235 2251 2236 2252 case TVGN_DROPHILITE: 2237 2238 2253 retval = infoPtr->dropItem; 2254 break; 2239 2255 2240 2256 case TVGN_LASTVISIBLE: 2241 2242 2257 retval = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); 2258 break; 2243 2259 } 2244 2260 2245 2261 if (retval) 2246 2262 { 2247 2248 2263 TRACE("flags:%x, returns %p\n", which, retval); 2264 return (LRESULT)retval; 2249 2265 } 2250 2266 … … 2252 2268 2253 2269 if (!TREEVIEW_ValidItem(infoPtr, wineItem)) 2254 2270 return FALSE; 2255 2271 2256 2272 switch (which) 2257 2273 { 2258 2274 case TVGN_NEXT: 2259 2260 2275 retval = wineItem->nextSibling; 2276 break; 2261 2277 case TVGN_PREVIOUS: 2262 2263 2278 retval = wineItem->prevSibling; 2279 break; 2264 2280 case TVGN_PARENT: 2265 2266 2281 retval = (wineItem->parent != infoPtr->root) ? wineItem->parent : NULL; 2282 break; 2267 2283 case TVGN_CHILD: 2268 2269 2284 retval = wineItem->firstChild; 2285 break; 2270 2286 case TVGN_NEXTVISIBLE: 2271 2272 2287 retval = TREEVIEW_GetNextListItem(infoPtr, wineItem); 2288 break; 2273 2289 case TVGN_PREVIOUSVISIBLE: 2274 2275 2290 retval = TREEVIEW_GetPrevListItem(infoPtr, wineItem); 2291 break; 2276 2292 default: 2277 2278 2293 TRACE("Unknown msg %x,item %p\n", which, wineItem); 2294 break; 2279 2295 } 2280 2296 … … 2296 2312 if (infoPtr->dwStyle & TVS_CHECKBOXES) 2297 2313 { 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2314 static const unsigned int state_table[] = { 0, 2, 1 }; 2315 2316 unsigned int state; 2317 2318 state = STATEIMAGEINDEX(item->state); 2319 TRACE("state:%x\n", state); 2320 item->state &= ~TVIS_STATEIMAGEMASK; 2321 2322 if (state < 3) 2323 state = state_table[state]; 2324 2325 item->state |= INDEXTOSTATEIMAGEMASK(state); 2326 2327 TRACE("state:%x\n", state); 2328 TREEVIEW_Invalidate(infoPtr, item); 2313 2329 } 2314 2330 } … … 2324 2340 LONG centerx, centery; 2325 2341 BOOL lar = ((infoPtr->dwStyle 2326 2327 2342 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS)) 2343 > TVS_LINESATROOT); 2328 2344 2329 2345 if (!lar && item->iLevel == 0) 2330 2346 return; 2331 2347 2332 2348 centerx = (item->linesOffset + item->stateOffset) / 2; … … 2335 2351 if (infoPtr->dwStyle & TVS_HASLINES) 2336 2352 { 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2353 HPEN hOldPen, hNewPen; 2354 HTREEITEM parent; 2355 2356 /* 2357 * Get a dotted grey pen 2358 */ 2359 hNewPen = CreatePen(PS_ALTERNATE, 0, infoPtr->clrLine); 2360 hOldPen = SelectObject(hdc, hNewPen); 2361 2362 MoveToEx(hdc, item->stateOffset, centery, NULL); 2363 LineTo(hdc, centerx - 1, centery); 2364 2365 if (item->prevSibling || item->parent != infoPtr->root) 2366 { 2367 MoveToEx(hdc, centerx, item->rect.top, NULL); 2368 LineTo(hdc, centerx, centery); 2369 } 2370 2371 if (item->nextSibling) 2372 { 2373 MoveToEx(hdc, centerx, centery, NULL); 2374 LineTo(hdc, centerx, item->rect.bottom + 1); 2375 } 2376 2377 /* Draw the line from our parent to its next sibling. */ 2378 parent = item->parent; 2379 while (parent != infoPtr->root) 2380 { 2381 int pcenterx = (parent->linesOffset + parent->stateOffset) / 2; 2382 2383 if (parent->nextSibling 2384 /* skip top-levels unless TVS_LINESATROOT */ 2385 && parent->stateOffset > parent->linesOffset) 2386 { 2387 MoveToEx(hdc, pcenterx, item->rect.top, NULL); 2388 LineTo(hdc, pcenterx, item->rect.bottom + 1); 2389 } 2390 2391 parent = parent->parent; 2392 } 2393 2394 SelectObject(hdc, hOldPen); 2395 DeleteObject(hNewPen); 2380 2396 } 2381 2397 … … 2386 2402 if (infoPtr->dwStyle & TVS_HASBUTTONS) 2387 2403 { 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2404 if (item->cChildren) 2405 { 2406 LONG height = item->rect.bottom - item->rect.top; 2407 LONG width = item->stateOffset - item->linesOffset; 2408 LONG rectsize = min(height, width) / 4; 2409 /* plussize = ceil(rectsize * 3/4) */ 2410 LONG plussize = (rectsize + 1) * 3 / 4; 2411 2412 HPEN hNewPen = CreatePen(PS_SOLID, 0, infoPtr->clrLine); 2413 HPEN hOldPen = SelectObject(hdc, hNewPen); 2414 HBRUSH hbr = CreateSolidBrush(infoPtr->clrBk); 2415 HBRUSH hbrOld = SelectObject(hdc, hbr); 2416 2417 Rectangle(hdc, centerx - rectsize, centery - rectsize, 2418 centerx + rectsize + 1, centery + rectsize + 1); 2419 2420 SelectObject(hdc, hbrOld); 2421 DeleteObject(hbr); 2422 2423 SelectObject(hdc, hOldPen); 2424 DeleteObject(hNewPen); 2425 2426 MoveToEx(hdc, centerx - plussize + 1, centery, NULL); 2427 LineTo(hdc, centerx + plussize, centery); 2428 2429 if (!(item->state & TVIS_EXPANDED)) 2430 { 2431 MoveToEx(hdc, centerx, centery - plussize + 1, NULL); 2432 LineTo(hdc, centerx, centery + plussize); 2433 } 2434 } 2419 2435 } 2420 2436 } … … 2439 2455 if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW) 2440 2456 { 2441 2442 2443 2444 2445 2446 2447 2448 2449 2457 cditem = TREEVIEW_SendCustomDrawItemNotify 2458 (infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT); 2459 TRACE("prepaint:cditem-app returns 0x%x\n", cditem); 2460 2461 if (cditem & CDRF_SKIPDEFAULT) 2462 { 2463 SelectObject(hdc, hOldFont); 2464 return; 2465 } 2450 2466 } 2451 2467 2452 2468 if (cditem & CDRF_NEWFONT) 2453 2469 TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc); 2454 2470 2455 2471 TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem); … … 2461 2477 */ 2462 2478 { 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2479 INT imageIndex; 2480 2481 /* State images are displayed to the left of the Normal image 2482 * image number is in state; zero should be `display no image'. 2483 */ 2484 imageIndex = STATEIMAGEINDEX(wineItem->state); 2485 2486 if (infoPtr->himlState && imageIndex) 2487 { 2488 ImageList_Draw(infoPtr->himlState, imageIndex, hdc, 2489 wineItem->stateOffset, 2490 centery - infoPtr->stateImageHeight / 2, 2491 ILD_NORMAL); 2492 } 2493 2494 /* Now, draw the normal image; can be either selected or 2495 * non-selected image. 2496 */ 2497 2498 if ((wineItem->state & TVIS_SELECTED) && (wineItem->iSelectedImage)) 2499 { 2500 /* The item is currently selected */ 2501 imageIndex = wineItem->iSelectedImage; 2502 } 2503 else 2504 { 2505 /* The item is not selected */ 2506 imageIndex = wineItem->iImage; 2507 } 2508 2509 if (infoPtr->himlNormal) 2510 { 2511 int ovlIdx = wineItem->state & TVIS_OVERLAYMASK; 2512 2513 ImageList_Draw(infoPtr->himlNormal, imageIndex, hdc, 2514 wineItem->imageOffset, 2515 centery - infoPtr->normalImageHeight / 2, 2516 ILD_NORMAL | ovlIdx); 2517 } 2502 2518 } 2503 2519 … … 2510 2526 if (!infoPtr->hwndEdit || (infoPtr->selectedItem != wineItem)) 2511 2527 { 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2528 if (wineItem->pszText) 2529 { 2530 COLORREF oldTextColor = 0; 2531 INT oldBkMode; 2532 HBRUSH hbrBk = 0; 2533 BOOL inFocus = (GetFocus() == infoPtr->hwnd); 2534 RECT rcText; 2535 2536 oldBkMode = SetBkMode(hdc, TRANSPARENT); 2537 2538 /* - If item is drop target or it is selected and window is in focus - 2539 * use blue background (COLOR_HIGHLIGHT). 2540 * - If item is selected, window is not in focus, but it has style 2541 * TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE) 2542 * - Otherwise - don't fill background 2543 */ 2544 if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) || 2545 ((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) && 2546 (inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS)))) 2547 { 2548 if ((wineItem->state & TVIS_DROPHILITED) || inFocus) 2549 { 2550 hbrBk = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); 2551 oldTextColor = 2552 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); 2553 } 2554 else 2555 { 2556 hbrBk = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); 2557 2558 if (infoPtr->clrText == -1) 2559 oldTextColor = 2560 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); 2561 else 2562 oldTextColor = SetTextColor(hdc, infoPtr->clrText); 2563 } 2564 } 2565 else 2566 { 2567 if (infoPtr->clrText == -1) 2568 oldTextColor = 2569 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); 2570 else 2571 oldTextColor = SetTextColor(hdc, infoPtr->clrText); 2572 } 2573 2574 rcText.top = wineItem->rect.top; 2575 rcText.bottom = wineItem->rect.bottom; 2576 rcText.left = wineItem->textOffset; 2577 rcText.right = rcText.left + wineItem->textWidth + 4; 2578 2579 if (hbrBk) 2580 { 2581 FillRect(hdc, &rcText, hbrBk); 2582 DeleteObject(hbrBk); 2583 } 2584 2585 /* Draw the box around the selected item */ 2586 if ((wineItem == infoPtr->selectedItem) && inFocus) 2587 { 2588 DrawFocusRect(hdc,&rcText); 2589 } 2590 2591 InflateRect(&rcText, -2, -1); /* allow for the focus rect */ 2592 2593 TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n", 2594 debugstr_a(wineItem->pszText), 2595 rcText.left, rcText.top, rcText.right, rcText.bottom); 2596 2597 /* Draw it */ 2598 DrawTextA(hdc, 2599 wineItem->pszText, 2600 lstrlenA(wineItem->pszText), 2601 &rcText, 2602 DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); 2603 2604 /* Restore the hdc state */ 2605 SetTextColor(hdc, oldTextColor); 2606 2607 if (oldBkMode != TRANSPARENT) 2608 SetBkMode(hdc, oldBkMode); 2609 } 2594 2610 } 2595 2611 … … 2597 2613 2598 2614 if (infoPtr->insertMarkItem) 2599 2600 2601 2615 TRACE("item:%d,mark:%d\n", 2616 TREEVIEW_GetItemIndex(infoPtr, wineItem), 2617 (int)infoPtr->insertMarkItem); 2602 2618 2603 2619 if (wineItem == infoPtr->insertMarkItem) 2604 2620 { 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2621 HPEN hNewPen, hOldPen; 2622 int offset; 2623 int left, right; 2624 2625 hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark); 2626 hOldPen = SelectObject(hdc, hNewPen); 2627 2628 if (infoPtr->insertBeforeorAfter) 2629 offset = wineItem->rect.bottom - 1; 2630 else 2631 offset = wineItem->rect.top + 1; 2632 2633 left = wineItem->textOffset - 2; 2634 right = wineItem->textOffset + wineItem->textWidth + 2; 2635 2636 MoveToEx(hdc, left, offset - 3, NULL); 2637 LineTo(hdc, left, offset + 4); 2638 2639 MoveToEx(hdc, left, offset, NULL); 2640 LineTo(hdc, right + 1, offset); 2641 2642 MoveToEx(hdc, right, offset + 3, NULL); 2643 LineTo(hdc, right, offset - 4); 2644 2645 SelectObject(hdc, hOldPen); 2646 DeleteObject(hNewPen); 2631 2647 } 2632 2648 2633 2649 if (cditem & CDRF_NOTIFYPOSTPAINT) 2634 2650 { 2635 2636 2637 2651 cditem = TREEVIEW_SendCustomDrawItemNotify 2652 (infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT); 2653 TRACE("postpaint:cditem-app returns 0x%x\n", cditem); 2638 2654 } 2639 2655 … … 2662 2678 while (wineItem != NULL) 2663 2679 { 2664 2665 2680 if (ISVISIBLE(wineItem)) 2681 { 2666 2682 /* actually we draw text at textOffset + 2 */ 2667 2668 2669 2670 2671 2672 2673 2674 2683 if (2+wineItem->textOffset+wineItem->textWidth > infoPtr->treeWidth) 2684 infoPtr->treeWidth = wineItem->textOffset+wineItem->textWidth+2; 2685 2686 /* This is scroll-adjusted, but we fix this below. */ 2687 infoPtr->treeHeight = wineItem->rect.bottom; 2688 } 2689 2690 wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem); 2675 2691 } 2676 2692 2677 2693 /* Fix the scroll adjusted treeHeight and treeWidth. */ 2678 2694 if (infoPtr->root->firstChild) 2679 2695 infoPtr->treeHeight -= infoPtr->root->firstChild->rect.top; 2680 2696 2681 2697 infoPtr->treeWidth += infoPtr->scrollX; … … 2687 2703 if (infoPtr->treeHeight > infoPtr->clientHeight) 2688 2704 { 2689 2690 2691 2692 2693 2705 vert = TRUE; 2706 2707 if (infoPtr->treeWidth 2708 > infoPtr->clientWidth - GetSystemMetrics(SM_CXVSCROLL)) 2709 horz = TRUE; 2694 2710 } 2695 2711 else if (infoPtr->treeWidth > infoPtr->clientWidth) 2696 2712 horz = TRUE; 2697 2713 2698 2714 if (!vert && horz && infoPtr->treeHeight 2699 2700 2715 > infoPtr->clientHeight - GetSystemMetrics(SM_CYVSCROLL)) 2716 vert = TRUE; 2701 2717 2702 2718 if (horz && (infoPtr->dwStyle & TVS_NOHSCROLL)) horz = FALSE; … … 2708 2724 if (vert) 2709 2725 { 2710 2726 si.nPage = TREEVIEW_GetVisibleCount(infoPtr); 2711 2727 if ( si.nPage ) 2712 2728 { … … 2729 2745 else 2730 2746 { 2731 2732 2733 2747 if (infoPtr->uInternalStatus & TV_VSCROLL) 2748 ShowScrollBar(hwnd, SB_VERT, FALSE); 2749 infoPtr->uInternalStatus &= ~TV_VSCROLL; 2734 2750 } 2735 2751 2736 2752 if (horz) 2737 2753 { 2738 2739 2740 2741 2742 2754 si.nPage = infoPtr->clientWidth; 2755 si.nPos = infoPtr->scrollX; 2756 si.nMax = infoPtr->treeWidth - 1; 2757 2758 if (si.nPos > si.nMax - max( si.nPage-1, 0 )) 2743 2759 { 2744 2760 si.nPos = si.nMax - max( si.nPage-1, 0 ); … … 2746 2762 } 2747 2763 2748 2749 2750 2751 2752 2764 if (!(infoPtr->uInternalStatus & TV_HSCROLL)) 2765 ShowScrollBar(hwnd, SB_HORZ, TRUE); 2766 infoPtr->uInternalStatus |= TV_HSCROLL; 2767 2768 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); 2753 2769 } 2754 2770 else 2755 2771 { 2756 2757 2758 2759 2760 2772 if (infoPtr->uInternalStatus & TV_HSCROLL) 2773 ShowScrollBar(hwnd, SB_HORZ, FALSE); 2774 infoPtr->uInternalStatus &= ~TV_HSCROLL; 2775 2776 scrollX = 0; 2761 2777 } 2762 2778 2763 2779 if (infoPtr->scrollX != scrollX) 2764 2780 { 2765 2766 2781 TREEVIEW_HScroll(infoPtr, 2782 MAKEWPARAM(SB_THUMBPOSITION, scrollX)); 2767 2783 } 2768 2784 2769 2785 if (!horz) 2770 2786 infoPtr->uInternalStatus &= ~TV_HSCROLL; 2771 2787 } 2772 2788 … … 2794 2810 if (infoPtr->clientHeight == 0 || infoPtr->clientWidth == 0) 2795 2811 { 2796 2797 2812 TRACE("empty window\n"); 2813 return; 2798 2814 } 2799 2815 2800 2816 infoPtr->cdmode = TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_PREPAINT, 2801 2817 hdc, rect); 2802 2818 2803 2819 if (infoPtr->cdmode == CDRF_SKIPDEFAULT) 2804 2820 { 2805 2806 2821 ReleaseDC(hwnd, hdc); 2822 return; 2807 2823 } 2808 2824 … … 2811 2827 wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem)) 2812 2828 { 2813 2814 2829 if (ISVISIBLE(wineItem)) 2830 { 2815 2831 /* Avoid unneeded calculations */ 2816 2832 if (wineItem->rect.top > rect.bottom) … … 2819 2835 continue; 2820 2836 2821 2822 2837 TREEVIEW_DrawItem(infoPtr, hdc, wineItem); 2838 } 2823 2839 } 2824 2840 … … 2826 2842 2827 2843 if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT) 2828 2829 2844 infoPtr->cdmode = 2845 TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect); 2830 2846 } 2831 2847 … … 2834 2850 { 2835 2851 if (item != NULL) 2836 2852 InvalidateRect(infoPtr->hwnd, &item->rect, TRUE); 2837 2853 else 2838 2854 InvalidateRect(infoPtr->hwnd, NULL, TRUE); … … 2874 2890 2875 2891 if (!wParam) 2876 2892 EndPaint(infoPtr->hwnd, &ps); 2877 2893 2878 2894 return 0; … … 2890 2906 /* Forward the call to the client-defined callback */ 2891 2907 return pCallBackSort->lpfnCompare(first->lParam, 2892 2893 2908 second->lParam, 2909 pCallBackSort->lParam); 2894 2910 } 2895 2911 … … 2915 2931 2916 2932 for (hti = item->firstChild; hti != NULL; hti = hti->nextSibling) 2917 2933 cChildren++; 2918 2934 2919 2935 return cChildren; … … 2932 2948 for (child = item->firstChild; child != NULL; child = child->nextSibling) 2933 2949 { 2934 2935 2936 2937 2938 2950 if (DPA_InsertPtr(list, INT_MAX, child) == -1) 2951 { 2952 DPA_Destroy(list); 2953 return NULL; 2954 } 2939 2955 } 2940 2956 … … 2955 2971 static LRESULT 2956 2972 TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent, 2957 2973 LPTVSORTCB pSort) 2958 2974 { 2959 2975 INT cChildren; … … 2963 2979 /* undocumented feature: TVI_ROOT or NULL means `sort the whole tree' */ 2964 2980 if (parent == TVI_ROOT || parent == NULL) 2965 2981 parent = infoPtr->root; 2966 2982 2967 2983 /* Check for a valid handle to the parent item */ 2968 2984 if (!TREEVIEW_ValidItem(infoPtr, parent)) 2969 2985 { 2970 2971 2986 ERR("invalid item hParent=%x\n", (INT)parent); 2987 return FALSE; 2972 2988 } 2973 2989 2974 2990 if (pSort) 2975 2991 { 2976 2977 2992 pfnCompare = (PFNDPACOMPARE)TREEVIEW_CallBackCompare; 2993 lpCompare = (LPARAM)pSort; 2978 2994 } 2979 2995 else 2980 2996 { 2981 2982 2997 pfnCompare = (PFNDPACOMPARE)TREEVIEW_SortOnName; 2998 lpCompare = (LPARAM)infoPtr; 2983 2999 } 2984 3000 … … 2988 3004 if (cChildren > 1) 2989 3005 { 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3006 /* TREEVIEW_ITEM rechaining */ 3007 INT count = 0; 3008 HTREEITEM item = 0; 3009 HTREEITEM nextItem = 0; 3010 HTREEITEM prevItem = 0; 3011 3012 HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent); 3013 3014 if (sortList == NULL) 3015 return FALSE; 3016 3017 /* let DPA sort the list */ 3018 DPA_Sort(sortList, pfnCompare, lpCompare); 3019 3020 /* The order of DPA entries has been changed, so fixup the 3021 * nextSibling and prevSibling pointers. */ 3022 3023 item = (HTREEITEM)DPA_GetPtr(sortList, count++); 3024 while ((nextItem = (HTREEITEM)DPA_GetPtr(sortList, count++)) != NULL) 3025 { 3026 /* link the two current item toghether */ 3027 item->nextSibling = nextItem; 3028 nextItem->prevSibling = item; 3029 3030 if (prevItem == NULL) 3031 { 3032 /* this is the first item, update the parent */ 3033 parent->firstChild = item; 3034 item->prevSibling = NULL; 3035 } 3036 else 3037 { 3038 /* fix the back chaining */ 3039 item->prevSibling = prevItem; 3040 } 3041 3042 /* get ready for the next one */ 3043 prevItem = item; 3044 item = nextItem; 3045 } 3046 3047 /* the last item is pointed to by item and never has a sibling */ 3048 item->nextSibling = NULL; 3049 parent->lastChild = item; 3050 3051 DPA_Destroy(sortList); 3052 3053 TREEVIEW_VerifyTree(infoPtr); 3054 3055 if (parent->state & TVIS_EXPANDED) 3056 { 3057 int visOrder = infoPtr->firstVisible->visibleOrder; 3042 3058 3043 3059 if (parent == infoPtr->root) … … 3046 3062 TREEVIEW_RecalculateVisibleOrder(infoPtr, parent); 3047 3063 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3064 if (TREEVIEW_IsChildOf(parent, infoPtr->firstVisible)) 3065 { 3066 TREEVIEW_ITEM *item; 3067 3068 for (item = infoPtr->root->firstChild; item != NULL; 3069 item = TREEVIEW_GetNextListItem(infoPtr, item)) 3070 { 3071 if (item->visibleOrder == visOrder) 3072 break; 3073 } 3058 3074 3059 3075 TREEVIEW_SetFirstVisible(infoPtr, item, FALSE); 3060 3061 3062 3063 3064 3065 3076 } 3077 3078 TREEVIEW_Invalidate(infoPtr, NULL); 3079 } 3080 3081 return TRUE; 3066 3082 } 3067 3083 return FALSE; … … 3094 3110 static BOOL 3095 3111 TREEVIEW_SendExpanding(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 3096 3112 UINT action) 3097 3113 { 3098 3114 return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, 3099 3100 3101 3115 TVIF_HANDLE | TVIF_STATE | TVIF_PARAM 3116 | TVIF_IMAGE | TVIF_SELECTEDIMAGE, 3117 0, wineItem); 3102 3118 } 3103 3119 3104 3120 static VOID 3105 3121 TREEVIEW_SendExpanded(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 3106 3122 UINT action) 3107 3123 { 3108 3124 TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDEDW, action, 3109 3110 3111 3125 TVIF_HANDLE | TVIF_STATE | TVIF_PARAM 3126 | TVIF_IMAGE | TVIF_SELECTEDIMAGE, 3127 0, wineItem); 3112 3128 } 3113 3129 … … 3117 3133 static BOOL 3118 3134 TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 3119 3135 BOOL bRemoveChildren, BOOL bUser) 3120 3136 { 3121 3137 UINT action = TVE_COLLAPSE | (bRemoveChildren ? TVE_COLLAPSERESET : 0); … … 3125 3141 3126 3142 if (!(wineItem->state & TVIS_EXPANDED) || wineItem->firstChild == NULL) 3127 3143 return FALSE; 3128 3144 3129 3145 if (bUser) 3130 3146 TREEVIEW_SendExpanding(infoPtr, wineItem, action); 3131 3147 3132 3148 wineItem->state &= ~TVIS_EXPANDED; 3133 3149 3134 3150 if (bUser) 3135 3151 TREEVIEW_SendExpanded(infoPtr, wineItem, action); 3136 3152 3137 3153 bSetSelection = (infoPtr->selectedItem != NULL 3138 3154 && TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem)); 3139 3155 3140 3156 bSetFirstVisible = (infoPtr->firstVisible != NULL … … 3143 3159 if (bRemoveChildren) 3144 3160 { 3145 3146 3147 3161 TRACE("TVE_COLLAPSERESET\n"); 3162 wineItem->state &= ~TVIS_EXPANDEDONCE; 3163 TREEVIEW_RemoveAllChildren(infoPtr, wineItem); 3148 3164 } 3149 3165 … … 3152 3168 TREEVIEW_ITEM *item, *sibling; 3153 3169 3154 3155 3156 3157 3158 3159 3160 3170 sibling = TREEVIEW_GetNextListItem(infoPtr, wineItem); 3171 3172 for (item = wineItem->firstChild; item != sibling; 3173 item = TREEVIEW_GetNextListItem(infoPtr, item)) 3174 { 3175 item->visibleOrder = -1; 3176 } 3161 3177 } 3162 3178 … … 3164 3180 3165 3181 TREEVIEW_SetFirstVisible(infoPtr, bSetFirstVisible ? wineItem 3166 3182 : infoPtr->firstVisible, TRUE); 3167 3183 3168 3184 if (bSetSelection) 3169 3185 { 3170 3171 3172 3173 3174 3175 3176 3186 /* Don't call DoSelectItem, it sends notifications. */ 3187 if (TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem)) 3188 infoPtr->selectedItem->state &= ~TVIS_SELECTED; 3189 wineItem->state |= TVIS_SELECTED; 3190 infoPtr->selectedItem = wineItem; 3191 3192 TREEVIEW_EnsureVisible(infoPtr, wineItem, FALSE); 3177 3193 } 3178 3194 … … 3185 3201 static BOOL 3186 3202 TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, 3187 3203 BOOL bExpandPartial, BOOL bUser) 3188 3204 { 3189 3205 TRACE("\n"); 3190 3206 3191 3207 if (!TREEVIEW_HasChildren(infoPtr, wineItem) 3192 3193 3208 || wineItem->state & TVIS_EXPANDED) 3209 return FALSE; 3194 3210 3195 3211 TRACE("TVE_EXPAND %p %s\n", wineItem, TREEVIEW_ItemName(wineItem)); … … 3197 3213 if (bUser || !(wineItem->state & TVIS_EXPANDEDONCE)) 3198 3214 { 3199 3200 3201 3202 3203 3204 3205 3206 3207 3215 if (!TREEVIEW_SendExpanding(infoPtr, wineItem, TVE_EXPAND)) 3216 { 3217 TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); 3218 return FALSE; 3219 } 3220 3221 wineItem->state |= TVIS_EXPANDED; 3222 TREEVIEW_SendExpanded(infoPtr, wineItem, TVE_EXPAND); 3223 wineItem->state |= TVIS_EXPANDEDONCE; 3208 3224 } 3209 3225 else 3210 3226 { 3211 3212 3227 /* this item has already been expanded */ 3228 wineItem->state |= TVIS_EXPANDED; 3213 3229 } 3214 3230 3215 3231 if (bExpandPartial) 3216 3232 FIXME("TVE_EXPANDPARTIAL not implemented\n"); 3217 3233 3218 3234 TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); … … 3225 3241 if (wineItem->firstChild != NULL) 3226 3242 { 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3243 int nChildren = wineItem->lastChild->visibleOrder 3244 - wineItem->firstChild->visibleOrder + 1; 3245 3246 int visible_pos = wineItem->visibleOrder 3247 - infoPtr->firstVisible->visibleOrder; 3248 3249 int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1; 3250 3251 if (visible_pos > 0 && nChildren > rows_below) 3252 { 3253 int scroll = nChildren - rows_below; 3254 3255 if (scroll > visible_pos) 3256 scroll = visible_pos; 3257 3258 if (scroll > 0) 3259 { 3260 TREEVIEW_ITEM *newFirstVisible 3261 = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible, 3262 scroll); 3263 3264 3265 TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE); 3266 } 3267 } 3252 3268 } 3253 3269 … … 3263 3279 3264 3280 if (wineItem->state & TVIS_EXPANDED) 3265 3281 return TREEVIEW_Collapse(infoPtr, wineItem, FALSE, bUser); 3266 3282 else 3267 3283 return TREEVIEW_Expand(infoPtr, wineItem, FALSE, bUser); 3268 3284 } 3269 3285 … … 3275 3291 for (item = item->firstChild; item != NULL; item = item->nextSibling) 3276 3292 { 3277 3278 3293 if (TREEVIEW_HasChildren(infoPtr, item)) 3294 TREEVIEW_ExpandAll(infoPtr, item); 3279 3295 } 3280 3296 } … … 3290 3306 { 3291 3307 if (!TREEVIEW_ValidItem(infoPtr, wineItem)) 3292 3308 return 0; 3293 3309 3294 3310 TRACE("For (%s) item:%d, flags %x, state:%d\n", 3295 3296 3311 TREEVIEW_ItemName(wineItem), flag, 3312 TREEVIEW_GetItemIndex(infoPtr, wineItem), wineItem->state); 3297 3313 3298 3314 switch (flag & TVE_TOGGLE) 3299 3315 { 3300 3316 case TVE_COLLAPSE: 3301 3302 3317 return TREEVIEW_Collapse(infoPtr, wineItem, flag & TVE_COLLAPSERESET, 3318 FALSE); 3303 3319 3304 3320 case TVE_EXPAND: 3305 3306 3321 return TREEVIEW_Expand(infoPtr, wineItem, flag & TVE_EXPANDPARTIAL, 3322 FALSE); 3307 3323 3308 3324 case TVE_TOGGLE: 3309 3325 return TREEVIEW_Toggle(infoPtr, wineItem, TRUE); 3310 3326 3311 3327 default: 3312 3328 return 0; 3313 3329 } 3314 3330 … … 3327 3343 3328 3344 if (!infoPtr->firstVisible) 3329 3345 return NULL; 3330 3346 3331 3347 row = pt.y / infoPtr->uItemHeight + infoPtr->firstVisible->visibleOrder; 3332 3348 3333 3349 for (wineItem = infoPtr->firstVisible; wineItem != NULL; 3334 3335 { 3336 3337 3338 3350 wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem)) 3351 { 3352 if (row >= wineItem->visibleOrder 3353 && row < wineItem->visibleOrder + wineItem->iIntegral) 3354 break; 3339 3355 } 3340 3356 … … 3358 3374 if (x < rect.left) 3359 3375 { 3360 3376 status |= TVHT_TOLEFT; 3361 3377 } 3362 3378 else if (x > rect.right) 3363 3379 { 3364 3380 status |= TVHT_TORIGHT; 3365 3381 } 3366 3382 3367 3383 if (y < rect.top) 3368 3384 { 3369 3385 status |= TVHT_ABOVE; 3370 3386 } 3371 3387 else if (y > rect.bottom) 3372 3388 { 3373 3389 status |= TVHT_BELOW; 3374 3390 } 3375 3391 3376 3392 if (status) 3377 3393 { 3378 3379 3394 lpht->flags = status; 3395 return (LRESULT)(HTREEITEM)NULL; 3380 3396 } 3381 3397 … … 3383 3399 if (!wineItem) 3384 3400 { 3385 3386 3401 lpht->flags = TVHT_NOWHERE; 3402 return (LRESULT)(HTREEITEM)NULL; 3387 3403 } 3388 3404 3389 3405 if (x >= wineItem->textOffset + wineItem->textWidth) 3390 3406 { 3391 3407 lpht->flags = TVHT_ONITEMRIGHT; 3392 3408 } 3393 3409 else if (x >= wineItem->textOffset) 3394 3410 { 3395 3411 lpht->flags = TVHT_ONITEMLABEL; 3396 3412 } 3397 3413 else if (x >= wineItem->imageOffset) 3398 3414 { 3399 3415 lpht->flags = TVHT_ONITEMICON; 3400 3416 } 3401 3417 else if (x >= wineItem->stateOffset) 3402 3418 { 3403 3419 lpht->flags = TVHT_ONITEMSTATEICON; 3404 3420 } 3405 3421 else if (x >= wineItem->linesOffset && infoPtr->dwStyle & TVS_HASBUTTONS) 3406 3422 { 3407 3423 lpht->flags = TVHT_ONITEMBUTTON; 3408 3424 } 3409 3425 else 3410 3426 { 3411 3427 lpht->flags = TVHT_ONITEMINDENT; 3412 3428 } 3413 3429 … … 3435 3451 { 3436 3452 case WM_PAINT: 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3453 { 3454 LRESULT rc; 3455 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd)); 3456 3457 TRACE("WM_PAINT start\n"); 3458 rc = CallWindowProcA(infoPtr->wpEditOrig, hwnd, uMsg, wParam, 3459 lParam); 3460 TRACE("WM_PAINT done\n"); 3461 return rc; 3462 } 3447 3463 3448 3464 case WM_KILLFOCUS: 3449 3465 { 3450 3451 3452 3453 3454 3466 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd)); 3467 if (infoPtr->bIgnoreEditKillFocus) 3468 return TRUE; 3469 3470 break; 3455 3471 } 3456 3472 3457 3473 case WM_GETDLGCODE: 3458 3474 return DLGC_WANTARROWS | DLGC_WANTALLKEYS; 3459 3475 3460 3476 case WM_KEYDOWN: 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3477 if (wParam == (WPARAM)VK_ESCAPE) 3478 { 3479 bCancel = TRUE; 3480 break; 3481 } 3482 else if (wParam == (WPARAM)VK_RETURN) 3483 { 3484 break; 3485 } 3486 3487 /* fall through */ 3472 3488 default: 3473 3474 3475 3476 3477 3478 3489 { 3490 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd)); 3491 3492 return CallWindowProcA(infoPtr->wpEditOrig, hwnd, uMsg, wParam, 3493 lParam); 3494 } 3479 3495 } 3480 3496 … … 3501 3517 { 3502 3518 case EN_UPDATE: 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3519 { 3520 /* 3521 * Adjust the edit window size 3522 */ 3523 char buffer[1024]; 3524 TREEVIEW_ITEM *editItem = infoPtr->selectedItem; 3525 HDC hdc = GetDC(infoPtr->hwndEdit); 3526 SIZE sz; 3527 int len; 3528 HFONT hFont, hOldFont = 0; 3529 3530 infoPtr->bLabelChanged = TRUE; 3531 3532 len = GetWindowTextA(infoPtr->hwndEdit, buffer, sizeof(buffer)); 3533 3534 /* Select font to get the right dimension of the string */ 3535 hFont = (HFONT)SendMessageA(infoPtr->hwndEdit, WM_GETFONT, 0, 0); 3536 if (hFont != 0) 3537 { 3538 hOldFont = SelectObject(hdc, hFont); 3539 } 3540 3541 if (GetTextExtentPoint32A(hdc, buffer, strlen(buffer), &sz)) 3542 { 3543 TEXTMETRICA textMetric; 3544 3545 /* Add Extra spacing for the next character */ 3546 GetTextMetricsA(hdc, &textMetric); 3547 sz.cx += (textMetric.tmMaxCharWidth * 2); 3548 3549 sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3); 3550 sz.cx = min(sz.cx, 3551 infoPtr->clientWidth - editItem->textOffset + 2); 3552 3553 SetWindowPos(infoPtr->hwndEdit, 3554 HWND_TOP, 3555 0, 3556 0, 3557 sz.cx, 3558 editItem->rect.bottom - editItem->rect.top + 3, 3559 SWP_NOMOVE | SWP_DRAWFRAME); 3560 } 3561 3562 if (hFont != 0) 3563 { 3564 SelectObject(hdc, hOldFont); 3565 } 3566 3567 ReleaseDC(infoPtr->hwnd, hdc); 3568 break; 3569 } 3554 3570 3555 3571 default: 3556 3572 return SendMessageA(GetParent(infoPtr->hwnd), WM_COMMAND, wParam, lParam); 3557 3573 } 3558 3574 … … 3574 3590 TRACE("%x %p\n", (unsigned)hwnd, hItem); 3575 3591 if (!TREEVIEW_ValidItem(infoPtr, editItem)) 3576 3592 return NULL; 3577 3593 3578 3594 if (infoPtr->hwndEdit) 3579 3595 return infoPtr->hwndEdit; 3580 3596 3581 3597 infoPtr->bLabelChanged = FALSE; … … 3591 3607 if (infoPtr->hFont != 0) 3592 3608 { 3593 3609 hOldFont = SelectObject(hdc, infoPtr->hFont); 3594 3610 } 3595 3611 3596 3612 /* Get string length in pixels */ 3597 3613 GetTextExtentPoint32A(hdc, editItem->pszText, strlen(editItem->pszText), 3598 3614 &sz); 3599 3615 3600 3616 /* Add Extra spacing for the next character */ … … 3607 3623 if (infoPtr->hFont != 0) 3608 3624 { 3609 3625 SelectObject(hdc, hOldFont); 3610 3626 } 3611 3627 3612 3628 ReleaseDC(hwnd, hdc); 3613 3629 hwndEdit = CreateWindowExA(WS_EX_LEFT, 3614 3615 3616 3617 3618 3619 3620 3621 3630 "EDIT", 3631 0, 3632 WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | 3633 WS_CLIPSIBLINGS | ES_WANTRETURN | 3634 ES_LEFT, editItem->textOffset - 2, 3635 editItem->rect.top - 1, sz.cx + 3, 3636 editItem->rect.bottom - 3637 editItem->rect.top + 3, hwnd, 0, hinst, 0); 3622 3638 /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0); */ 3623 3639 … … 3626 3642 /* Get a 2D border. */ 3627 3643 SetWindowLongA(hwndEdit, GWL_EXSTYLE, 3628 3644 GetWindowLongA(hwndEdit, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE); 3629 3645 SetWindowLongA(hwndEdit, GWL_STYLE, 3630 3646 GetWindowLongA(hwndEdit, GWL_STYLE) | WS_BORDER); 3631 3647 3632 3648 SendMessageA(hwndEdit, WM_SETFONT, 3633 3649 (WPARAM)TREEVIEW_FontForItem(infoPtr, editItem), FALSE); 3634 3650 3635 3651 infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA(hwndEdit, GWL_WNDPROC, 3636 3637 3652 (DWORD) 3653 TREEVIEW_Edit_SubclassProc); 3638 3654 3639 3655 if (TREEVIEW_BeginLabelEditNotify(infoPtr, editItem)) 3640 3656 { 3641 3642 3643 3657 DestroyWindow(hwndEdit); 3658 infoPtr->hwndEdit = 0; 3659 return NULL; 3644 3660 } 3645 3661 … … 3665 3681 3666 3682 if (!infoPtr->hwndEdit) 3667 3683 return FALSE; 3668 3684 3669 3685 tvdi.hdr.hwndFrom = hwnd; … … 3677 3693 if (!bCancel) 3678 3694 { 3679 3680 3681 3682 3683 3684 3685 3686 3687 3695 iLength = GetWindowTextA(infoPtr->hwndEdit, tmpText, 1023); 3696 3697 if (iLength >= 1023) 3698 { 3699 ERR("Insufficient space to retrieve new item label\n"); 3700 } 3701 3702 tvdi.item.pszText = tmpText; 3703 tvdi.item.cchTextMax = iLength + 1; 3688 3704 } 3689 3705 else 3690 3706 { 3691 3692 3707 tvdi.item.pszText = NULL; 3708 tvdi.item.cchTextMax = 0; 3693 3709 } 3694 3710 3695 3711 bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr, 3696 3697 3698 if (!bCancel && bCommit) 3699 { 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3712 (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi); 3713 3714 if (!bCancel && bCommit) /* Apply the changes */ 3715 { 3716 if (strcmp(tmpText, editedItem->pszText) != 0) 3717 { 3718 if (NULL == COMCTL32_ReAlloc(editedItem->pszText, iLength + 1)) 3719 { 3720 ERR("OutOfMemory, cannot allocate space for label\n"); 3721 DestroyWindow(infoPtr->hwndEdit); 3722 infoPtr->hwndEdit = 0; 3723 return FALSE; 3724 } 3725 else 3726 { 3727 editedItem->cchTextMax = iLength + 1; 3728 lstrcpyA(editedItem->pszText, tmpText); 3729 } 3730 } 3715 3731 } 3716 3732 … … 3726 3742 if (wParam != TV_EDIT_TIMER) 3727 3743 { 3728 3729 3744 ERR("got unknown timer\n"); 3745 return 1; 3730 3746 } 3731 3747 … … 3762 3778 while (1) 3763 3779 { 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3780 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) 3781 { 3782 if (msg.message == WM_MOUSEMOVE) 3783 { 3784 pt.x = SLOWORD(msg.lParam); 3785 pt.y = SHIWORD(msg.lParam); 3786 if (PtInRect(&r, pt)) 3787 continue; 3788 else 3789 { 3790 ReleaseCapture(); 3791 return 1; 3792 } 3793 } 3794 else if (msg.message >= WM_LBUTTONDOWN && 3795 msg.message <= WM_RBUTTONDBLCLK) 3796 { 3797 if (msg.message == WM_RBUTTONUP) 3798 TREEVIEW_RButtonUp(infoPtr, &pt); 3799 break; 3800 } 3801 3802 DispatchMessageA(&msg); 3803 } 3804 3805 if (GetCapture() != infoPtr->hwnd) 3806 return 0; 3791 3807 } 3792 3808 … … 3807 3823 if (infoPtr->Timer & TV_EDIT_TIMER_SET) 3808 3824 { 3809 3810 3825 /* If there is pending 'edit label' event - kill it now */ 3826 KillTimer(infoPtr->hwnd, TV_EDIT_TIMER); 3811 3827 } 3812 3828 … … 3816 3832 wineItem = (TREEVIEW_ITEM *)TREEVIEW_HitTest(infoPtr, &hit); 3817 3833 if (!wineItem) 3818 3834 return 0; 3819 3835 TRACE("item %d\n", TREEVIEW_GetItemIndex(infoPtr, wineItem)); 3820 3836 3821 3837 if (TREEVIEW_SendSimpleNotify(infoPtr, NM_DBLCLK) == FALSE) 3822 { 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3838 { /* FIXME! */ 3839 switch (hit.flags) 3840 { 3841 case TVHT_ONITEMRIGHT: 3842 /* FIXME: we should not have sent NM_DBLCLK in this case. */ 3843 break; 3844 3845 case TVHT_ONITEMINDENT: 3846 if (!(infoPtr->dwStyle & TVS_HASLINES)) 3847 { 3848 break; 3849 } 3850 else 3851 { 3852 int level = hit.pt.x / infoPtr->uIndent; 3853 if (!(infoPtr->dwStyle & TVS_LINESATROOT)) level++; 3854 3855 while (wineItem->iLevel > level) 3856 { 3857 wineItem = wineItem->parent; 3858 } 3859 3860 /* fall through */ 3861 } 3862 3863 case TVHT_ONITEMLABEL: 3864 case TVHT_ONITEMICON: 3865 case TVHT_ONITEMBUTTON: 3866 TREEVIEW_Toggle(infoPtr, wineItem, TRUE); 3867 break; 3868 3869 case TVHT_ONITEMSTATEICON: 3870 if (infoPtr->dwStyle & TVS_CHECKBOXES) 3871 TREEVIEW_ToggleItemState(infoPtr, wineItem); 3872 else 3873 TREEVIEW_Toggle(infoPtr, wineItem, TRUE); 3874 break; 3875 } 3860 3876 } 3861 3877 return TRUE; … … 3878 3894 if (infoPtr->hwndEdit) 3879 3895 { 3880 3881 3896 SetFocus(hwnd); 3897 return 0; 3882 3898 } 3883 3899 … … 3899 3915 3900 3916 bTrack = (ht.flags & TVHT_ONITEM) 3901 3917 && !(infoPtr->dwStyle & TVS_DISABLEDRAGDROP); 3902 3918 3903 3919 /* Send NM_CLICK right away */ 3904 3920 if (!bTrack) 3905 3906 3921 if (TREEVIEW_SendSimpleNotify(infoPtr, NM_CLICK)) 3922 goto setfocus; 3907 3923 3908 3924 if (ht.flags & TVHT_ONITEMBUTTON) 3909 3925 { 3910 3911 3926 TREEVIEW_Toggle(infoPtr, ht.hItem, TRUE); 3927 goto setfocus; 3912 3928 } 3913 3929 else if (bTrack) 3914 3930 { /* if TREEVIEW_TrackMouse == 1 dragging occurred and the cursor left the dragged item's rectangle */ 3915 3916 3917 3918 3931 if (TREEVIEW_TrackMouse(infoPtr, ht.pt)) 3932 { 3933 TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINDRAGW, ht.hItem, ht.pt); 3934 infoPtr->dropItem = ht.hItem; 3919 3935 3920 3936 /* clean up focusedItem as we dragged and won't select this item */ … … 3930 3946 } 3931 3947 3932 3948 return 0; 3933 3949 } 3934 3950 } … … 3942 3958 */ 3943 3959 if ((infoPtr->dwStyle & TVS_EDITLABELS) && 3944 3945 { 3946 3947 3948 3949 3950 3960 (ht.flags & TVHT_ONITEMLABEL) && (infoPtr->selectedItem == ht.hItem)) 3961 { 3962 if (infoPtr->Timer & TV_EDIT_TIMER_SET) 3963 KillTimer(hwnd, TV_EDIT_TIMER); 3964 3965 SetTimer(hwnd, TV_EDIT_TIMER, GetDoubleClickTime(), 0); 3966 infoPtr->Timer |= TV_EDIT_TIMER_SET; 3951 3967 } 3952 3968 else if (ht.flags & TVHT_ONITEM) /* select the item if the hit was inside of the icon or text */ … … 4007 4023 else if (ht.flags & TVHT_ONITEMSTATEICON) 4008 4024 { 4009 4010 4011 4025 /* TVS_CHECKBOXES requires us to toggle the current state */ 4026 if (infoPtr->dwStyle & TVS_CHECKBOXES) 4027 TREEVIEW_ToggleItemState(infoPtr, ht.hItem); 4012 4028 } 4013 4029 … … 4025 4041 if (infoPtr->hwndEdit) 4026 4042 { 4027 4028 4043 SetFocus(infoPtr->hwnd); 4044 return 0; 4029 4045 } 4030 4046 … … 4036 4052 if (TREEVIEW_TrackMouse(infoPtr, ht.pt)) 4037 4053 { 4038 4039 4040 4041 4042 4054 if (ht.hItem) 4055 { 4056 TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINRDRAGW, ht.hItem, ht.pt); 4057 infoPtr->dropItem = ht.hItem; 4058 } 4043 4059 } 4044 4060 else 4045 4061 { 4046 4047 4062 SetFocus(infoPtr->hwnd); 4063 TREEVIEW_SendSimpleNotify(infoPtr, NM_RCLICK); 4048 4064 } 4049 4065 … … 4073 4089 4074 4090 if (!(infoPtr->himlNormal)) 4075 4091 return 0; 4076 4092 4077 4093 if (!dragItem || !TREEVIEW_ValidItem(infoPtr, dragItem)) 4078 4094 return 0; 4079 4095 4080 4096 TREEVIEW_UpdateDispInfo(infoPtr, dragItem, TVIF_TEXT); … … 4086 4102 hOldFont = SelectObject(hdc, infoPtr->hFont); 4087 4103 GetTextExtentPoint32A(hdc, dragItem->pszText, lstrlenA(dragItem->pszText), 4088 4104 &size); 4089 4105 TRACE("%ld %ld %s %d\n", size.cx, size.cy, dragItem->pszText, 4090 4106 lstrlenA(dragItem->pszText)); 4091 4107 hbmp = CreateCompatibleBitmap(htopdc, size.cx, size.cy); 4092 4108 hOldbmp = SelectObject(hdc, hbmp); … … 4095 4111 size.cx += cx; 4096 4112 if (cy > size.cy) 4097 4113 size.cy = cy; 4098 4114 4099 4115 infoPtr->dragList = ImageList_Create(size.cx, size.cy, ILC_COLOR, 10, 10); 4100 4116 ImageList_Draw(infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, 4101 4117 ILD_NORMAL); 4102 4118 4103 4119 /* … … 4110 4126 SetRect(&rc, cx, 0, size.cx, size.cy); 4111 4127 DrawTextA(hdc, dragItem->pszText, lstrlenA(dragItem->pszText), &rc, 4112 4128 DT_LEFT); 4113 4129 SelectObject(hdc, hOldFont); 4114 4130 SelectObject(hdc, hOldbmp); … … 4127 4143 static LRESULT 4128 4144 TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect, 4129 4145 INT cause) 4130 4146 { 4131 4147 TREEVIEW_ITEM *prevSelect; … … 4135 4151 4136 4152 TRACE("Entering item %p (%s), flag %x, cause %x, state %d\n", 4137 4138 4153 newSelect, TREEVIEW_ItemName(newSelect), action, cause, 4154 newSelect ? newSelect->state : 0); 4139 4155 4140 4156 /* reset and redraw focusedItem if focusedItem was set so we don't */ … … 4150 4166 { 4151 4167 case TVGN_CARET: 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4168 prevSelect = infoPtr->selectedItem; 4169 4170 if (prevSelect == newSelect) 4171 return FALSE; 4172 4173 if (TREEVIEW_SendTreeviewNotify(infoPtr, 4174 TVN_SELCHANGINGW, 4175 cause, 4176 TVIF_HANDLE | TVIF_STATE | TVIF_PARAM, 4177 prevSelect, 4178 newSelect)) 4179 return FALSE; 4180 4181 if (prevSelect) 4182 prevSelect->state &= ~TVIS_SELECTED; 4183 if (newSelect) 4184 newSelect->state |= TVIS_SELECTED; 4185 4186 infoPtr->selectedItem = newSelect; 4187 4188 TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE); 4189 4190 TREEVIEW_SendTreeviewNotify(infoPtr, 4191 TVN_SELCHANGEDW, 4192 cause, 4193 TVIF_HANDLE | TVIF_STATE | TVIF_PARAM, 4194 prevSelect, 4195 newSelect); 4196 TREEVIEW_Invalidate(infoPtr, prevSelect); 4197 TREEVIEW_Invalidate(infoPtr, newSelect); 4198 break; 4183 4199 4184 4200 case TVGN_DROPHILITE: 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4201 prevSelect = infoPtr->dropItem; 4202 4203 if (prevSelect) 4204 prevSelect->state &= ~TVIS_DROPHILITED; 4205 4206 infoPtr->dropItem = newSelect; 4207 4208 if (newSelect) 4209 newSelect->state |= TVIS_DROPHILITED; 4210 4211 TREEVIEW_Invalidate(infoPtr, prevSelect); 4212 TREEVIEW_Invalidate(infoPtr, newSelect); 4213 break; 4198 4214 4199 4215 case TVGN_FIRSTVISIBLE: 4200 4201 4202 4203 4216 TREEVIEW_EnsureVisible(infoPtr, newSelect, FALSE); 4217 TREEVIEW_SetFirstVisible(infoPtr, newSelect, TRUE); 4218 TREEVIEW_Invalidate(infoPtr, NULL); 4219 break; 4204 4220 } 4205 4221 … … 4213 4229 { 4214 4230 if (item != NULL && !TREEVIEW_ValidItem(infoPtr, item)) 4215 4231 return FALSE; 4216 4232 4217 4233 TRACE("%p (%s) %d\n", item, TREEVIEW_ItemName(item), wParam); 4218 4234 4219 4235 if (!TREEVIEW_DoSelectItem(infoPtr, wParam, item, TVC_UNKNOWN)) 4220 4236 return FALSE; 4221 4237 4222 4238 return TRUE; … … 4224 4240 4225 4241 /************************************************************************* 4226 * 4242 * TREEVIEW_ProcessLetterKeys 4227 4243 * 4228 4244 * Processes keyboard messages generated by pressing the letter keys … … 4382 4398 4383 4399 if (!TREEVIEW_ValidItem(infoPtr, item)) 4384 4400 return FALSE; 4385 4401 4386 4402 if (!ISVISIBLE(item)) 4387 4403 { 4388 4389 4404 /* Expand parents as necessary. */ 4405 HTREEITEM parent; 4390 4406 4391 4407 /* see if we are trying to ensure that root is vislble */ … … 4395 4411 parent = item; /* this item is the topmost item */ 4396 4412 4397 4398 4399 4400 4401 4402 4403 4413 while (parent != infoPtr->root) 4414 { 4415 if (!(parent->state & TVIS_EXPANDED)) 4416 TREEVIEW_Expand(infoPtr, parent, FALSE, FALSE); 4417 4418 parent = parent->parent; 4419 } 4404 4420 } 4405 4421 4406 4422 TRACE("%p (%s) %ld - %ld\n", item, TREEVIEW_ItemName(item), item->visibleOrder, 4407 4423 infoPtr->firstVisible->visibleOrder); 4408 4424 4409 4425 visible_pos = item->visibleOrder - infoPtr->firstVisible->visibleOrder; … … 4411 4427 if (visible_pos < 0) 4412 4428 { 4413 4414 4429 /* item is before the start of the list: put it at the top. */ 4430 newFirstVisible = item; 4415 4431 } 4416 4432 else if (visible_pos >= TREEVIEW_GetVisibleCount(infoPtr) 4417 4418 4419 4420 { 4421 4422 4423 4424 4425 4433 /* Sometimes, before we are displayed, GVC is 0, causing us to 4434 * spuriously scroll up. */ 4435 && visible_pos > 0) 4436 { 4437 /* item is past the end of the list. */ 4438 int scroll = visible_pos - TREEVIEW_GetVisibleCount(infoPtr); 4439 4440 newFirstVisible = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible, 4441 scroll + 1); 4426 4442 } 4427 4443 … … 4442 4458 x = max(x, textMetric.tmMaxCharWidth * 3); 4443 4459 4444 4445 4446 4460 if (item->textOffset < 0) 4461 pos = item->textOffset; 4462 else if (item->textOffset + x > infoPtr->clientWidth) 4447 4463 { 4448 4464 if (x > infoPtr->clientWidth) … … 4454 4470 pos = 0; 4455 4471 4456 4472 TREEVIEW_HScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, infoPtr->scrollX + pos)); 4457 4473 } 4458 4474 4459 4475 if (newFirstVisible != NULL && newFirstVisible != infoPtr->firstVisible) 4460 4476 { 4461 4462 4463 4477 TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE); 4478 4479 return TRUE; 4464 4480 } 4465 4481 … … 4478 4494 if (newFirstVisible != NULL) 4479 4495 { 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4496 /* Prevent an empty gap from appearing at the bottom... */ 4497 gap_size = TREEVIEW_GetVisibleCount(infoPtr) 4498 - infoPtr->maxVisibleOrder + newFirstVisible->visibleOrder; 4499 4500 if (gap_size > 0) 4501 { 4502 newFirstVisible = TREEVIEW_GetListItem(infoPtr, newFirstVisible, 4503 -gap_size); 4504 4505 /* ... unless we just don't have enough items. */ 4506 if (newFirstVisible == NULL) 4507 newFirstVisible = infoPtr->root->firstChild; 4508 } 4493 4509 } 4494 4510 4495 4511 if (infoPtr->firstVisible != newFirstVisible) 4496 4512 { 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4513 if (infoPtr->firstVisible == NULL || newFirstVisible == NULL) 4514 { 4515 infoPtr->firstVisible = newFirstVisible; 4516 TREEVIEW_Invalidate(infoPtr, NULL); 4517 } 4518 else 4519 { 4520 TREEVIEW_ITEM *item; 4521 int scroll = infoPtr->uItemHeight * 4522 (infoPtr->firstVisible->visibleOrder 4523 - newFirstVisible->visibleOrder); 4524 4525 infoPtr->firstVisible = newFirstVisible; 4526 4527 for (item = infoPtr->root->firstChild; item != NULL; 4528 item = TREEVIEW_GetNextListItem(infoPtr, item)) 4529 { 4530 item->rect.top += scroll; 4531 item->rect.bottom += scroll; 4532 } 4533 4534 if (bUpdateScrollPos) 4535 SetScrollPos(infoPtr->hwnd, SB_VERT, 4536 newFirstVisible->visibleOrder, TRUE); 4537 4538 ScrollWindow(infoPtr->hwnd, 0, scroll, NULL, NULL); 4539 UpdateWindow(infoPtr->hwnd); 4540 } 4525 4541 } 4526 4542 } … … 4542 4558 4543 4559 if (!(infoPtr->uInternalStatus & TV_VSCROLL)) 4544 4560 return 0; 4545 4561 4546 4562 if (infoPtr->hwndEdit) 4547 4563 SetFocus(infoPtr->hwnd); 4548 4564 4549 4565 if (!oldFirstVisible) 4550 4566 { 4551 4552 4567 assert(infoPtr->root->firstChild == NULL); 4568 return 0; 4553 4569 } 4554 4570 … … 4556 4572 { 4557 4573 case SB_TOP: 4558 4559 4574 newFirstVisible = infoPtr->root->firstChild; 4575 break; 4560 4576 4561 4577 case SB_BOTTOM: 4562 4563 4578 newFirstVisible = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); 4579 break; 4564 4580 4565 4581 case SB_LINEUP: 4566 4567 4582 newFirstVisible = TREEVIEW_GetPrevListItem(infoPtr, oldFirstVisible); 4583 break; 4568 4584 4569 4585 case SB_LINEDOWN: 4570 4571 4586 newFirstVisible = TREEVIEW_GetNextListItem(infoPtr, oldFirstVisible); 4587 break; 4572 4588 4573 4589 case SB_PAGEUP: 4574 4575 4576 4590 newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible, 4591 -max(1, TREEVIEW_GetVisibleCount(infoPtr))); 4592 break; 4577 4593 4578 4594 case SB_PAGEDOWN: 4579 4580 4581 4595 newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible, 4596 max(1, TREEVIEW_GetVisibleCount(infoPtr))); 4597 break; 4582 4598 4583 4599 case SB_THUMBTRACK: 4584 4600 case SB_THUMBPOSITION: 4585 4586 4587 4588 4601 newFirstVisible = TREEVIEW_GetListItem(infoPtr, 4602 infoPtr->root->firstChild, 4603 (LONG)(SHORT)HIWORD(wParam)); 4604 break; 4589 4605 4590 4606 case SB_ENDSCROLL: 4591 4607 return 0; 4592 4608 } 4593 4609 4594 4610 if (newFirstVisible != NULL) 4595 4611 { 4596 4597 4598 4599 4600 4601 4612 if (newFirstVisible != oldFirstVisible) 4613 TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, 4614 nScrollCode != SB_THUMBTRACK); 4615 else if (nScrollCode == SB_THUMBPOSITION) 4616 SetScrollPos(infoPtr->hwnd, SB_VERT, 4617 newFirstVisible->visibleOrder, TRUE); 4602 4618 } 4603 4619 … … 4615 4631 4616 4632 if (!(infoPtr->uInternalStatus & TV_HSCROLL)) 4617 4633 return FALSE; 4618 4634 4619 4635 if (infoPtr->hwndEdit) 4620 4636 SetFocus(infoPtr->hwnd); 4621 4637 4622 4638 maxWidth = infoPtr->treeWidth - infoPtr->clientWidth; … … 4631 4647 { 4632 4648 case SB_LINELEFT: 4633 4634 4649 scrollX -= infoPtr->uItemHeight; 4650 break; 4635 4651 case SB_LINERIGHT: 4636 4637 4652 scrollX += infoPtr->uItemHeight; 4653 break; 4638 4654 case SB_PAGELEFT: 4639 4640 4655 scrollX -= infoPtr->clientWidth; 4656 break; 4641 4657 case SB_PAGERIGHT: 4642 4643 4658 scrollX += infoPtr->clientWidth; 4659 break; 4644 4660 4645 4661 case SB_THUMBTRACK: 4646 4662 case SB_THUMBPOSITION: 4647 4648 4663 scrollX = (int)(SHORT)HIWORD(wParam); 4664 break; 4649 4665 4650 4666 case SB_ENDSCROLL: … … 4672 4688 } 4673 4689 4674 4675 4676 4690 ScrollWindow(infoPtr->hwnd, scroll_pixels, 0, NULL, NULL); 4691 infoPtr->scrollX = scrollX; 4692 UpdateWindow(infoPtr->hwnd); 4677 4693 } 4678 4694 … … 4690 4706 4691 4707 if (infoPtr->firstVisible == NULL) 4692 4708 return TRUE; 4693 4709 4694 4710 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0); … … 4699 4715 if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines) 4700 4716 { 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4717 int newDy = infoPtr->firstVisible->visibleOrder + pulScrollLines; 4718 int maxDy = infoPtr->maxVisibleOrder; 4719 4720 if (newDy > maxDy) 4721 newDy = maxDy; 4722 4723 if (newDy < 0) 4724 newDy = 0; 4725 4726 TREEVIEW_VScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, newDy)); 4711 4727 } 4712 4728 return TRUE; … … 4727 4743 if (infoPtr == NULL) 4728 4744 { 4729 4730 4745 ERR("could not allocate info memory!\n"); 4746 return 0; 4731 4747 } 4732 4748 … … 4739 4755 infoPtr->uNumItems = 0; 4740 4756 infoPtr->cdmode = 0; 4741 infoPtr->uScrollTime = 300; 4757 infoPtr->uScrollTime = 300; /* milliseconds */ 4742 4758 infoPtr->bRedraw = TRUE; 4743 4759 … … 4765 4781 4766 4782 infoPtr->clrBk = GetSysColor(COLOR_WINDOW); 4767 infoPtr->clrText = -1; 4783 infoPtr->clrText = -1; /* use system color */ 4768 4784 infoPtr->clrLine = RGB(128, 128, 128); 4769 4785 infoPtr->clrInsertMark = GetSysColor(COLOR_BTNTEXT); … … 4809 4825 4810 4826 if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS)) 4811 4827 infoPtr->hwndToolTip = COMCTL32_CreateToolTip(hwnd); 4812 4828 4813 4829 if (infoPtr->dwStyle & TVS_CHECKBOXES) 4814 4830 { 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4831 RECT rc; 4832 HBITMAP hbm, hbmOld; 4833 HDC hdc; 4834 int nIndex; 4835 4836 infoPtr->himlState = 4837 ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 3, 0); 4838 4839 hdc = CreateCompatibleDC(0); 4840 hbm = CreateCompatibleBitmap(hdc, 48, 16); 4841 hbmOld = SelectObject(hdc, hbm); 4842 4843 rc.left = 0; rc.top = 0; 4844 rc.right = 48; rc.bottom = 16; 4845 FillRect(hdc, &rc, (HBRUSH)(COLOR_WINDOW+1)); 4846 4847 rc.left = 18; rc.top = 2; 4848 rc.right = 30; rc.bottom = 14; 4849 DrawFrameControl(hdc, &rc, DFC_BUTTON, 4850 DFCS_BUTTONCHECK|DFCS_FLAT); 4851 4852 rc.left = 34; rc.right = 46; 4853 DrawFrameControl(hdc, &rc, DFC_BUTTON, 4854 DFCS_BUTTONCHECK|DFCS_FLAT|DFCS_CHECKED); 4855 4856 nIndex = ImageList_AddMasked(infoPtr->himlState, hbm, 4857 GetSysColor(COLOR_WINDOW)); 4858 TRACE("chckbox index %d\n", nIndex); 4859 SelectObject(hdc, hbmOld); 4860 DeleteObject(hbm); 4861 DeleteDC(hdc); 4862 4863 infoPtr->stateImageWidth = 16; 4864 infoPtr->stateImageHeight = 16; 4849 4865 } 4850 4866 return 0; … … 4863 4879 /* Restore original wndproc */ 4864 4880 if (infoPtr->hwndEdit) 4865 4866 4881 SetWindowLongA(infoPtr->hwndEdit, GWL_WNDPROC, 4882 (LONG)infoPtr->wpEditOrig); 4867 4883 4868 4884 /* Deassociate treeview from the window before doing anything drastic. */ … … 4882 4898 static const struct 4883 4899 { 4884 4900 unsigned char code; 4885 4901 } 4886 4902 scroll[] = 4887 4903 { 4888 4904 #define SCROLL_ENTRY(dir, code) { ((dir) << 7) | (code) } 4889 SCROLL_ENTRY(SB_VERT, SB_PAGEUP),/* VK_PRIOR */4890 SCROLL_ENTRY(SB_VERT, SB_PAGEDOWN),/* VK_NEXT */4891 SCROLL_ENTRY(SB_VERT, SB_BOTTOM),/* VK_END */4892 SCROLL_ENTRY(SB_VERT, SB_TOP),/* VK_HOME */4893 SCROLL_ENTRY(SB_HORZ, SB_LINEUP),/* VK_LEFT */4894 SCROLL_ENTRY(SB_VERT, SB_LINEUP),/* VK_UP */4895 SCROLL_ENTRY(SB_HORZ, SB_LINEDOWN),/* VK_RIGHT */4896 SCROLL_ENTRY(SB_VERT, SB_LINEDOWN)/* VK_DOWN */4905 SCROLL_ENTRY(SB_VERT, SB_PAGEUP), /* VK_PRIOR */ 4906 SCROLL_ENTRY(SB_VERT, SB_PAGEDOWN), /* VK_NEXT */ 4907 SCROLL_ENTRY(SB_VERT, SB_BOTTOM), /* VK_END */ 4908 SCROLL_ENTRY(SB_VERT, SB_TOP), /* VK_HOME */ 4909 SCROLL_ENTRY(SB_HORZ, SB_LINEUP), /* VK_LEFT */ 4910 SCROLL_ENTRY(SB_VERT, SB_LINEUP), /* VK_UP */ 4911 SCROLL_ENTRY(SB_HORZ, SB_LINEDOWN), /* VK_RIGHT */ 4912 SCROLL_ENTRY(SB_VERT, SB_LINEDOWN) /* VK_DOWN */ 4897 4913 #undef SCROLL_ENTRY 4898 4914 }; … … 4900 4916 if (key >= VK_PRIOR && key <= VK_DOWN) 4901 4917 { 4902 4903 4904 4905 4906 4918 unsigned char code = scroll[key - VK_PRIOR].code; 4919 4920 (((code & (1 << 7)) == (SB_HORZ << 7)) 4921 ? TREEVIEW_HScroll 4922 : TREEVIEW_VScroll)(infoPtr, code & 0x7F); 4907 4923 } 4908 4924 … … 4938 4954 4939 4955 if (prevItem == NULL) 4940 4956 return FALSE; 4941 4957 4942 4958 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) 4943 4959 return TREEVIEW_ScrollKeyDown(infoPtr, wParam); 4944 4960 4945 4961 switch (wParam) 4946 4962 { 4947 4963 case VK_UP: 4948 4949 4950 4951 4964 newSelection = TREEVIEW_GetPrevListItem(infoPtr, prevItem); 4965 if (!newSelection) 4966 newSelection = infoPtr->root->firstChild; 4967 break; 4952 4968 4953 4969 case VK_DOWN: 4954 4955 4970 newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem); 4971 break; 4956 4972 4957 4973 case VK_HOME: 4958 4959 4974 newSelection = infoPtr->root->firstChild; 4975 break; 4960 4976 4961 4977 case VK_END: 4962 4963 4978 newSelection = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); 4979 break; 4964 4980 4965 4981 case VK_LEFT: 4966 4967 4968 4969 4970 4971 4972 4973 4974 4982 if (prevItem->state & TVIS_EXPANDED) 4983 { 4984 TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE); 4985 } 4986 else if (prevItem->parent != infoPtr->root) 4987 { 4988 newSelection = prevItem->parent; 4989 } 4990 break; 4975 4991 4976 4992 case VK_RIGHT: 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4993 if (TREEVIEW_HasChildren(infoPtr, prevItem)) 4994 { 4995 if (!(prevItem->state & TVIS_EXPANDED)) 4996 TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE); 4997 else 4998 { 4999 newSelection = prevItem->firstChild; 5000 } 5001 } 5002 5003 break; 4988 5004 4989 5005 case VK_MULTIPLY: 4990 4991 5006 TREEVIEW_ExpandAll(infoPtr, prevItem); 5007 break; 4992 5008 4993 5009 case VK_ADD: 4994 4995 4996 5010 if (!(prevItem->state & TVIS_EXPANDED)) 5011 TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE); 5012 break; 4997 5013 4998 5014 case VK_SUBTRACT: 4999 5000 5001 5015 if (prevItem->state & TVIS_EXPANDED) 5016 TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE); 5017 break; 5002 5018 5003 5019 case VK_PRIOR: 5004 5005 5006 5007 5020 newSelection 5021 = TREEVIEW_GetListItem(infoPtr, prevItem, 5022 -TREEVIEW_GetVisibleCount(infoPtr)); 5023 break; 5008 5024 5009 5025 case VK_NEXT: 5010 5011 5012 5013 5026 newSelection 5027 = TREEVIEW_GetListItem(infoPtr, prevItem, 5028 TREEVIEW_GetVisibleCount(infoPtr)); 5029 break; 5014 5030 5015 5031 case VK_BACK: 5016 5017 5018 5019 5032 newSelection = prevItem->parent; 5033 if (newSelection == infoPtr->root) 5034 newSelection = NULL; 5035 break; 5020 5036 5021 5037 case VK_SPACE: 5022 5023 5024 5038 if (infoPtr->dwStyle & TVS_CHECKBOXES) 5039 TREEVIEW_ToggleItemState(infoPtr, prevItem); 5040 break; 5025 5041 } 5026 5042 5027 5043 if (newSelection && newSelection != prevItem) 5028 5044 { 5029 5030 5031 5032 5033 5045 if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, 5046 TVC_BYKEYBOARD)) 5047 { 5048 TREEVIEW_EnsureVisible(infoPtr, newSelection, FALSE); 5049 } 5034 5050 } 5035 5051 … … 5043 5059 5044 5060 if (lpnmh->code == PGN_CALCSIZE) { 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5061 LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam; 5062 5063 if (lppgc->dwFlag == PGF_CALCWIDTH) { 5064 lppgc->iWidth = infoPtr->treeWidth; 5065 TRACE("got PGN_CALCSIZE, returning horz size = %ld, client=%ld\n", 5066 infoPtr->treeWidth, infoPtr->clientWidth); 5067 } 5068 else { 5069 lppgc->iHeight = infoPtr->treeHeight; 5070 TRACE("got PGN_CALCSIZE, returning vert size = %ld, client=%ld\n", 5071 infoPtr->treeHeight, infoPtr->clientHeight); 5072 } 5073 return 0; 5058 5074 } 5059 5075 return DefWindowProcA(infoPtr->hwnd, WM_NOTIFY, wParam, lParam); … … 5063 5079 { 5064 5080 INT format; 5065 5081 5066 5082 TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand); 5067 5083 5068 5084 if (nCommand != NF_REQUERY) return 0; 5069 5085 5070 5086 format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY); 5071 5087 TRACE("format=%d\n", format); 5072 5088 5073 5089 if (format != NFR_ANSI && format != NFR_UNICODE) return 0; 5074 5090 5075 5091 infoPtr->bNtfUnicode = (format == NFR_UNICODE); 5076 5092 5077 5093 return format; 5078 5094 } 5079 5095 5080 5096 static LRESULT 5081 5097 TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) … … 5083 5099 if (wParam == SIZE_RESTORED) 5084 5100 { 5085 5086 5087 5088 5089 5090 5101 infoPtr->clientWidth = SLOWORD(lParam); 5102 infoPtr->clientHeight = SHIWORD(lParam); 5103 5104 TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); 5105 TREEVIEW_SetFirstVisible(infoPtr, infoPtr->firstVisible, TRUE); 5106 TREEVIEW_UpdateScrollBars(infoPtr); 5091 5107 } 5092 5108 else 5093 5109 { 5094 5110 FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam); 5095 5111 } 5096 5112 … … 5140 5156 if (!infoPtr->selectedItem) 5141 5157 { 5142 5143 5158 TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, infoPtr->firstVisible, 5159 TVC_UNKNOWN); 5144 5160 } 5145 5161 … … 5167 5183 else 5168 5184 { 5169 5170 5171 5172 5185 if (uMsg == WM_CREATE) 5186 TREEVIEW_Create(hwnd); 5187 else 5188 goto def; 5173 5189 } 5174 5190 … … 5176 5192 { 5177 5193 case TVM_CREATEDRAGIMAGE: 5178 5194 return TREEVIEW_CreateDragImage(infoPtr, wParam, lParam); 5179 5195 5180 5196 case TVM_DELETEITEM: 5181 5197 return TREEVIEW_DeleteItem(infoPtr, (HTREEITEM)lParam); 5182 5198 5183 5199 case TVM_EDITLABELA: 5184 5200 return (LRESULT)TREEVIEW_EditLabelA(infoPtr, (HTREEITEM)lParam); 5185 5201 5186 5202 case TVM_EDITLABELW: 5187 5188 5203 FIXME("Unimplemented msg TVM_EDITLABELW\n"); 5204 return 0; 5189 5205 5190 5206 case TVM_ENDEDITLABELNOW: 5191 5207 return TREEVIEW_EndEditLabelNow(infoPtr, (BOOL)wParam); 5192 5208 5193 5209 case TVM_ENSUREVISIBLE: 5194 5210 return TREEVIEW_EnsureVisible(infoPtr, (HTREEITEM)lParam, TRUE); 5195 5211 5196 5212 case TVM_EXPAND: 5197 5213 return TREEVIEW_ExpandMsg(infoPtr, (UINT)wParam, (HTREEITEM)lParam); 5198 5214 5199 5215 case TVM_GETBKCOLOR: 5200 5216 return TREEVIEW_GetBkColor(infoPtr); 5201 5217 5202 5218 case TVM_GETCOUNT: 5203 5219 return TREEVIEW_GetCount(infoPtr); 5204 5220 5205 5221 case TVM_GETEDITCONTROL: 5206 5222 return TREEVIEW_GetEditControl(infoPtr); 5207 5223 5208 5224 case TVM_GETIMAGELIST: 5209 5225 return TREEVIEW_GetImageList(infoPtr, wParam); 5210 5226 5211 5227 case TVM_GETINDENT: 5212 5228 return TREEVIEW_GetIndent(infoPtr); 5213 5229 5214 5230 case TVM_GETINSERTMARKCOLOR: 5215 5231 return TREEVIEW_GetInsertMarkColor(infoPtr); 5216 5232 5217 5233 case TVM_GETISEARCHSTRINGA: 5218 5219 5234 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n"); 5235 return 0; 5220 5236 5221 5237 case TVM_GETISEARCHSTRINGW: 5222 5223 5238 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGW\n"); 5239 return 0; 5224 5240 5225 5241 case TVM_GETITEMA: 5226 5242 return TREEVIEW_GetItemA(infoPtr, (LPTVITEMEXA)lParam); 5227 5243 5228 5244 case TVM_GETITEMW: 5229 5245 return TREEVIEW_GetItemW(infoPtr, (LPTVITEMEXW)lParam); 5230 5246 5231 5247 case TVM_GETITEMHEIGHT: 5232 5248 return TREEVIEW_GetItemHeight(infoPtr); 5233 5249 5234 5250 case TVM_GETITEMRECT: 5235 5251 return TREEVIEW_GetItemRect(infoPtr, (BOOL)wParam, (LPRECT)lParam); 5236 5252 5237 5253 case TVM_GETITEMSTATE: 5238 5254 return TREEVIEW_GetItemState(infoPtr, (HTREEITEM)wParam, (UINT)lParam); 5239 5255 5240 5256 case TVM_GETLINECOLOR: 5241 5257 return TREEVIEW_GetLineColor(infoPtr); 5242 5258 5243 5259 case TVM_GETNEXTITEM: 5244 5260 return TREEVIEW_GetNextItem(infoPtr, (UINT)wParam, (HTREEITEM)lParam); 5245 5261 5246 5262 case TVM_GETSCROLLTIME: 5247 5263 return TREEVIEW_GetScrollTime(infoPtr); 5248 5264 5249 5265 case TVM_GETTEXTCOLOR: 5250 5266 return TREEVIEW_GetTextColor(infoPtr); 5251 5267 5252 5268 case TVM_GETTOOLTIPS: 5253 5269 return TREEVIEW_GetToolTips(infoPtr); 5254 5270 5255 5271 case TVM_GETUNICODEFORMAT: 5256 5257 5272 FIXME("Unimplemented msg TVM_GETUNICODEFORMAT\n"); 5273 return 0; 5258 5274 5259 5275 case TVM_GETVISIBLECOUNT: 5260 5276 return TREEVIEW_GetVisibleCount(infoPtr); 5261 5277 5262 5278 case TVM_HITTEST: 5263 5279 return TREEVIEW_HitTest(infoPtr, (LPTVHITTESTINFO)lParam); 5264 5280 5265 5281 case TVM_INSERTITEMA: 5266 5282 return TREEVIEW_InsertItemA(infoPtr, lParam); 5267 5283 5268 5284 case TVM_INSERTITEMW: 5269 5285 return TREEVIEW_InsertItemW(infoPtr, lParam); 5270 5286 5271 5287 case TVM_SELECTITEM: 5272 5288 return TREEVIEW_SelectItem(infoPtr, (INT)wParam, (HTREEITEM)lParam); 5273 5289 5274 5290 case TVM_SETBKCOLOR: 5275 5291 return TREEVIEW_SetBkColor(infoPtr, (COLORREF)lParam); 5276 5292 5277 5293 case TVM_SETIMAGELIST: 5278 5294 return TREEVIEW_SetImageList(infoPtr, wParam, (HIMAGELIST)lParam); 5279 5295 5280 5296 case TVM_SETINDENT: 5281 5297 return TREEVIEW_SetIndent(infoPtr, (UINT)wParam); 5282 5298 5283 5299 case TVM_SETINSERTMARK: 5284 5300 return TREEVIEW_SetInsertMark(infoPtr, (BOOL)wParam, (HTREEITEM)lParam); 5285 5301 5286 5302 case TVM_SETINSERTMARKCOLOR: 5287 5303 return TREEVIEW_SetInsertMarkColor(infoPtr, (COLORREF)lParam); 5288 5304 5289 5305 case TVM_SETITEMA: 5290 5306 return TREEVIEW_SetItemA(infoPtr, (LPTVITEMEXA)lParam); 5291 5307 5292 5308 case TVM_SETITEMW: 5293 5309 return TREEVIEW_SetItemW(infoPtr, (LPTVITEMEXW)lParam); 5294 5310 return 0; 5295 5311 5296 5312 case TVM_SETLINECOLOR: 5297 5313 return TREEVIEW_SetLineColor(infoPtr, (COLORREF)lParam); 5298 5314 5299 5315 case TVM_SETITEMHEIGHT: 5300 5316 return TREEVIEW_SetItemHeight(infoPtr, (INT)(SHORT)wParam); 5301 5317 5302 5318 case TVM_SETSCROLLTIME: 5303 5319 return TREEVIEW_SetScrollTime(infoPtr, (UINT)wParam); 5304 5320 5305 5321 case TVM_SETTEXTCOLOR: 5306 5322 return TREEVIEW_SetTextColor(infoPtr, (COLORREF)lParam); 5307 5323 5308 5324 case TVM_SETTOOLTIPS: 5309 5325 return TREEVIEW_SetToolTips(infoPtr, (HWND)wParam); 5310 5326 5311 5327 case TVM_SETUNICODEFORMAT: 5312 5313 5328 FIXME("Unimplemented msg TVM_SETUNICODEFORMAT\n"); 5329 return 0; 5314 5330 5315 5331 case TVM_SORTCHILDREN: 5316 5332 return TREEVIEW_SortChildren(infoPtr, wParam, lParam); 5317 5333 5318 5334 case TVM_SORTCHILDRENCB: 5319 5335 return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam); 5320 5336 5321 5337 case WM_CHAR: … … 5323 5339 5324 5340 case WM_COMMAND: 5325 5341 return TREEVIEW_Command(infoPtr, wParam, lParam); 5326 5342 5327 5343 case WM_DESTROY: 5328 5329 5330 5344 return TREEVIEW_Destroy(infoPtr); 5345 5346 /* WM_ENABLE */ 5331 5347 5332 5348 case WM_ERASEBKGND: 5333 5349 return TREEVIEW_EraseBackground(infoPtr, (HDC)wParam); 5334 5350 5335 5351 case WM_GETDLGCODE: 5336 5352 return DLGC_WANTARROWS | DLGC_WANTCHARS; 5337 5353 5338 5354 case WM_GETFONT: 5339 5355 return TREEVIEW_GetFont(infoPtr); 5340 5356 5341 5357 case WM_HSCROLL: 5342 5358 return TREEVIEW_HScroll(infoPtr, wParam); 5343 5359 5344 5360 case WM_KEYDOWN: 5345 5361 return TREEVIEW_KeyDown(infoPtr, wParam); 5346 5362 5347 5363 case WM_KILLFOCUS: 5348 5364 return TREEVIEW_KillFocus(infoPtr); 5349 5365 5350 5366 case WM_LBUTTONDBLCLK: 5351 5367 return TREEVIEW_LButtonDoubleClick(infoPtr, lParam); 5352 5368 5353 5369 case WM_LBUTTONDOWN: 5354 5355 5356 5357 5358 5370 return TREEVIEW_LButtonDown(infoPtr, lParam); 5371 5372 /* WM_MBUTTONDOWN */ 5373 5374 /* WM_MOUSEMOVE */ 5359 5375 5360 5376 case WM_NOTIFY: 5361 5377 return TREEVIEW_Notify(infoPtr, wParam, lParam); 5362 5378 5363 5379 case WM_NOTIFYFORMAT: 5364 5380 return TREEVIEW_NotifyFormat(infoPtr, (HWND)wParam, (UINT)lParam); 5365 5381 5366 5382 case WM_PAINT: 5367 5368 5369 5383 return TREEVIEW_Paint(infoPtr, wParam); 5384 5385 /* WM_PRINTCLIENT */ 5370 5386 5371 5387 case WM_RBUTTONDOWN: 5372 5388 return TREEVIEW_RButtonDown(infoPtr, lParam); 5373 5389 5374 5390 case WM_SETFOCUS: 5375 5391 return TREEVIEW_SetFocus(infoPtr); 5376 5392 5377 5393 case WM_SETFONT: 5378 5394 return TREEVIEW_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); 5379 5395 5380 5396 case WM_SETREDRAW: … … 5382 5398 5383 5399 case WM_SIZE: 5384 5400 return TREEVIEW_Size(infoPtr, wParam, lParam); 5385 5401 5386 5402 case WM_STYLECHANGED: 5387 5388 5389 5390 5391 5403 return TREEVIEW_StyleChanged(infoPtr, wParam, lParam); 5404 5405 /* WM_SYSCOLORCHANGE */ 5406 5407 /* WM_SYSKEYDOWN */ 5392 5408 5393 5409 case WM_TIMER: 5394 5410 return TREEVIEW_HandleTimer(infoPtr, wParam); 5395 5411 5396 5412 case WM_VSCROLL: 5397 5398 5399 5413 return TREEVIEW_VScroll(infoPtr, wParam); 5414 5415 /* WM_WININICHANGE */ 5400 5416 5401 5417 case WM_MOUSEWHEEL: 5402 5403 5404 5418 if (wParam & (MK_SHIFT | MK_CONTROL)) 5419 goto def; 5420 return TREEVIEW_MouseWheel(infoPtr, wParam); 5405 5421 5406 5422 case WM_DRAWITEM: 5407 5408 5423 TRACE("drawItem\n"); 5424 goto def; 5409 5425 5410 5426 default: 5411 5412 5413 5427 /* This mostly catches MFC and Delphi messages. :( */ 5428 if ((uMsg >= WM_USER) && (uMsg < WM_APP)) 5429 TRACE("Unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); 5414 5430 def: 5415 5431 return DefWindowProcA(hwnd, uMsg, wParam, lParam); 5416 5432 } 5417 5433 return 0; … … 5456 5472 5457 5473 static inline void TREEVIEW_VerifyItemCommon(TREEVIEW_INFO *infoPtr, 5458 5474 TREEVIEW_ITEM *item) 5459 5475 { 5460 5476 assert(infoPtr != NULL); … … 5469 5485 if (item->firstChild) 5470 5486 { 5471 5472 5487 assert(item->firstChild->parent == item); 5488 assert(item->firstChild->prevSibling == NULL); 5473 5489 } 5474 5490 5475 5491 if (item->lastChild) 5476 5492 { 5477 5478 5493 assert(item->lastChild->parent == item); 5494 assert(item->lastChild->nextSibling == NULL); 5479 5495 } 5480 5496 … … 5482 5498 if (item->nextSibling) 5483 5499 { 5484 5485 5500 assert(item->nextSibling->parent == item->parent); 5501 assert(item->nextSibling->prevSibling == item); 5486 5502 } 5487 5503 … … 5489 5505 if (item->prevSibling) 5490 5506 { 5491 5492 5507 assert(item->prevSibling->parent == item->parent); 5508 assert(item->prevSibling->nextSibling == item); 5493 5509 } 5494 5510 } … … 5517 5533 5518 5534 for (child = item->firstChild; child != NULL; child = child->nextSibling) 5519 5535 TREEVIEW_VerifyItem(infoPtr, child); 5520 5536 } 5521 5537
Note:
See TracChangeset
for help on using the changeset viewer.