1 // PanelListNotify.cpp
2
3 #include "StdAfx.h"
4
5 #include "resource.h"
6
7 #include "../../../Common/IntToString.h"
8 #include "../../../Common/StringConvert.h"
9
10 #include "../../../Windows/PropVariant.h"
11 #include "../../../Windows/PropVariantConv.h"
12
13 #include "../Common/PropIDUtils.h"
14 #include "../../PropID.h"
15
16 #include "App.h"
17 #include "Panel.h"
18 #include "FormatUtils.h"
19
20 using namespace NWindows;
21
22 /* Unicode characters for space:
23 0x009C STRING TERMINATOR
24 0x00B7 Middle dot
25 0x237D Shouldered open box
26 0x2420 Symbol for space
27 0x2422 Blank symbol
28 0x2423 Open box
29 */
30
31 #define SPACE_REPLACE_CHAR (wchar_t)(0x2423)
32 #define SPACE_TERMINATOR_CHAR (wchar_t)(0x9C)
33
34 #define INT_TO_STR_SPEC(v) \
35 while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \
36 *s++ = (unsigned char)('0' + (unsigned)v);
37
ConvertSizeToString(UInt64 val,wchar_t * s)38 static void ConvertSizeToString(UInt64 val, wchar_t *s) throw()
39 {
40 unsigned char temp[32];
41 unsigned i = 0;
42
43 if (val <= (UInt32)0xFFFFFFFF)
44 {
45 UInt32 val32 = (UInt32)val;
46 INT_TO_STR_SPEC(val32)
47 }
48 else
49 {
50 INT_TO_STR_SPEC(val)
51 }
52
53 if (i < 3)
54 {
55 if (i != 0)
56 {
57 *s++ = temp[(size_t)i - 1];
58 if (i == 2)
59 *s++ = temp[0];
60 }
61 *s = 0;
62 return;
63 }
64
65 unsigned r = i % 3;
66 if (r != 0)
67 {
68 s[0] = temp[--i];
69 if (r == 2)
70 s[1] = temp[--i];
71 s += r;
72 }
73
74 do
75 {
76 s[0] = ' ';
77 s[1] = temp[(size_t)i - 1];
78 s[2] = temp[(size_t)i - 2];
79 s[3] = temp[(size_t)i - 3];
80 s += 4;
81 }
82 while (i -= 3);
83
84 *s = 0;
85 }
86
87 UString ConvertSizeToString(UInt64 value);
ConvertSizeToString(UInt64 value)88 UString ConvertSizeToString(UInt64 value)
89 {
90 wchar_t s[32];
91 ConvertSizeToString(value, s);
92 return s;
93 }
94
GetHex_Upper(unsigned v)95 static inline unsigned GetHex_Upper(unsigned v)
96 {
97 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
98 }
99
GetHex_Lower(unsigned v)100 static inline unsigned GetHex_Lower(unsigned v)
101 {
102 return (v < 10) ? ('0' + v) : ('a' + (v - 10));
103 }
104
105 /*
106 static void HexToString(char *dest, const Byte *data, UInt32 size)
107 {
108 for (UInt32 i = 0; i < size; i++)
109 {
110 unsigned b = data[i];
111 dest[0] = GetHex((b >> 4) & 0xF);
112 dest[1] = GetHex(b & 0xF);
113 dest += 2;
114 }
115 *dest = 0;
116 }
117 */
118
119 bool IsSizeProp(UINT propID) throw();
IsSizeProp(UINT propID)120 bool IsSizeProp(UINT propID) throw()
121 {
122 switch (propID)
123 {
124 case kpidSize:
125 case kpidPackSize:
126 case kpidNumSubDirs:
127 case kpidNumSubFiles:
128 case kpidOffset:
129 case kpidLinks:
130 case kpidNumBlocks:
131 case kpidNumVolumes:
132 case kpidPhySize:
133 case kpidHeadersSize:
134 case kpidTotalSize:
135 case kpidFreeSpace:
136 case kpidClusterSize:
137 case kpidNumErrors:
138 case kpidNumStreams:
139 case kpidNumAltStreams:
140 case kpidAltStreamsSize:
141 case kpidVirtualSize:
142 case kpidUnpackSize:
143 case kpidTotalPhySize:
144 case kpidTailSize:
145 case kpidEmbeddedStubSize:
146 return true;
147 }
148 return false;
149 }
150
151
152
153 /*
154 #include <stdio.h>
155
156 UInt64 GetCpuTicks()
157 {
158 #ifdef _WIN64
159 return __rdtsc();
160 #else
161 UInt32 lowVal, highVal;
162 __asm RDTSC;
163 __asm mov lowVal, EAX;
164 __asm mov highVal, EDX;
165 return ((UInt64)highVal << 32) | lowVal;
166 #endif
167 }
168
169 UInt32 g_NumGroups;
170 UInt64 g_start_tick;
171 UInt64 g_prev_tick;
172 DWORD g_Num_SetItemText;
173 UInt32 g_NumMessages;
174 */
175
SetItemText(LVITEMW & item)176 LRESULT CPanel::SetItemText(LVITEMW &item)
177 {
178 if (_dontShowMode)
179 return 0;
180 UInt32 realIndex = GetRealIndex(item);
181
182 // g_Num_SetItemText++;
183
184 /*
185 if ((item.mask & LVIF_IMAGE) != 0)
186 {
187 bool defined = false;
188 CComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
189 _folder.QueryInterface(&folderGetSystemIconIndex);
190 if (folderGetSystemIconIndex)
191 {
192 folderGetSystemIconIndex->GetSystemIconIndex(index, &item.iImage);
193 defined = (item.iImage > 0);
194 }
195 if (!defined)
196 {
197 NCOM::CPropVariant prop;
198 _folder->GetProperty(index, kpidAttrib, &prop);
199 UINT32 attrib = 0;
200 if (prop.vt == VT_UI4)
201 attrib = prop.ulVal;
202 else if (IsItemFolder(index))
203 attrib |= FILE_ATTRIBUTE_DIRECTORY;
204 if (_currentFolderPrefix.IsEmpty())
205 throw 1;
206 else
207 item.iImage = _extToIconMap.GetIconIndex(attrib, GetSystemString(GetItemName(index)));
208 }
209 // item.iImage = 1;
210 }
211 */
212
213 if ((item.mask & LVIF_TEXT) == 0)
214 return 0;
215
216 LPWSTR text = item.pszText;
217
218 if (item.cchTextMax > 0)
219 text[0] = 0;
220
221 if (item.cchTextMax <= 1)
222 return 0;
223
224 const CPropColumn &property = _visibleColumns[item.iSubItem];
225 PROPID propID = property.ID;
226
227 if (realIndex == kParentIndex_UInt32)
228 {
229 if (propID == kpidName)
230 {
231 if (item.cchTextMax > 2)
232 {
233 text[0] = '.';
234 text[1] = '.';
235 text[2] = 0;
236 }
237 }
238 return 0;
239 }
240
241 /*
242 // List-view in report-view in Windows 10 is slow (50+ ms) for page change.
243 // that code shows the time of page reload for items
244 // if you know how to improve the speed of list view refresh, notify 7-Zip developer
245
246 // if (propID == 2000)
247 // if (propID == kpidName)
248 {
249 // debug column;
250 // DWORD dw = GetCpuTicks();
251 UInt64 dw = GetCpuTicks();
252 UInt64 deltaLast = dw - g_prev_tick;
253 #define conv_ticks(t) ((unsigned)((t) / 100000))
254 if (deltaLast > 1000u * 1000 * 1000)
255 {
256 UInt64 deltaFull = g_prev_tick - g_start_tick;
257 char s[128];
258 sprintf(s, "%d", conv_ticks(deltaFull));
259 OutputDebugStringA(s);
260 g_start_tick = dw;
261 g_NumGroups++;
262 }
263 g_prev_tick = dw;
264 UString u;
265 char s[128];
266 UInt64 deltaFull = dw - g_start_tick;
267 // for (int i = 0; i < 100000; i++)
268 sprintf(s, "%d %d %d-%d ", g_NumMessages, g_Num_SetItemText, g_NumGroups, conv_ticks(deltaFull));
269 // sprintf(s, "%d-%d ", g_NumGroups, conv_ticks(deltaFull));
270 u = s;
271 lstrcpyW(text, u.Ptr());
272 text += u.Len();
273
274 // dw = GetCpuTicks();
275 // deltaFull = dw - g_prev_tick;
276 // sprintf(s, "-%d ", conv_ticks(deltaFull));
277 // u = s;
278 // lstrcpyW(text, u.Ptr());
279 // text += u.Len();
280
281 if (propID != kpidName)
282 return 0;
283 }
284 */
285
286
287 if (property.IsRawProp)
288 {
289 const void *data;
290 UInt32 dataSize;
291 UInt32 propType;
292 RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType));
293 unsigned limit = item.cchTextMax - 1;
294 if (dataSize == 0)
295 {
296 text[0] = 0;
297 return 0;
298 }
299
300 if (propID == kpidNtReparse)
301 {
302 UString s;
303 ConvertNtReparseToString((const Byte *)data, dataSize, s);
304 if (!s.IsEmpty())
305 {
306 unsigned i;
307 for (i = 0; i < limit; i++)
308 {
309 wchar_t c = s[i];
310 if (c == 0)
311 break;
312 text[i] = c;
313 }
314 text[i] = 0;
315 return 0;
316 }
317 }
318 else if (propID == kpidNtSecure)
319 {
320 AString s;
321 ConvertNtSecureToString((const Byte *)data, dataSize, s);
322 if (!s.IsEmpty())
323 {
324 unsigned i;
325 for (i = 0; i < limit; i++)
326 {
327 wchar_t c = (Byte)s[i];
328 if (c == 0)
329 break;
330 text[i] = c;
331 }
332 text[i] = 0;
333 return 0;
334 }
335 }
336 {
337 const unsigned kMaxDataSize = 64;
338 if (dataSize > kMaxDataSize)
339 {
340 char temp[32];
341 MyStringCopy(temp, "data:");
342 ConvertUInt32ToString(dataSize, temp + 5);
343 unsigned i;
344 for (i = 0; i < limit; i++)
345 {
346 wchar_t c = (Byte)temp[i];
347 if (c == 0)
348 break;
349 text[i] = c;
350 }
351 text[i] = 0;
352 }
353 else
354 {
355 if (dataSize > limit)
356 dataSize = limit;
357 WCHAR *dest = text;
358 const bool needUpper = (dataSize <= 8)
359 && (propID == kpidCRC || propID == kpidChecksum);
360 for (UInt32 i = 0; i < dataSize; i++)
361 {
362 unsigned b = ((const Byte *)data)[i];
363 if (needUpper)
364 {
365 dest[0] = (WCHAR)GetHex_Upper((b >> 4) & 0xF);
366 dest[1] = (WCHAR)GetHex_Upper(b & 0xF);
367 }
368 else
369 {
370 dest[0] = (WCHAR)GetHex_Lower((b >> 4) & 0xF);
371 dest[1] = (WCHAR)GetHex_Lower(b & 0xF);
372 }
373 dest += 2;
374 }
375 *dest = 0;
376 }
377 }
378 return 0;
379 }
380 /*
381 {
382 NCOM::CPropVariant prop;
383 if (propID == kpidType)
384 string = GetFileType(index);
385 else
386 {
387 HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &prop);
388 if (result != S_OK)
389 {
390 // PrintMessage("GetPropertyValue error");
391 return 0;
392 }
393 string = ConvertPropertyToString(prop, propID, false);
394 }
395 }
396 */
397 // const NFind::CFileInfo &aFileInfo = m_Files[index];
398
399 NCOM::CPropVariant prop;
400 /*
401 bool needRead = true;
402 if (propID == kpidSize)
403 {
404 CComPtr<IFolderGetItemFullSize> getItemFullSize;
405 if (_folder.QueryInterface(&getItemFullSize) == S_OK)
406 {
407 if (getItemFullSize->GetItemFullSize(index, &prop) == S_OK)
408 needRead = false;
409 }
410 }
411 if (needRead)
412 */
413
414 if (item.cchTextMax < 32)
415 return 0;
416
417 if (propID == kpidName)
418 {
419 if (_folderGetItemName)
420 {
421 const wchar_t *name = NULL;
422 unsigned nameLen = 0;
423 _folderGetItemName->GetItemName(realIndex, &name, &nameLen);
424
425 if (name)
426 {
427 unsigned dest = 0;
428 unsigned limit = item.cchTextMax - 1;
429
430 for (unsigned i = 0; dest < limit;)
431 {
432 wchar_t c = name[i++];
433 if (c == 0)
434 break;
435 text[dest++] = c;
436
437 if (c != ' ')
438 {
439 if (c != 0x202E) // RLO
440 continue;
441 text[(size_t)dest - 1] = '_';
442 continue;
443 }
444
445 if (name[i] != ' ')
446 continue;
447
448 unsigned t = 1;
449 for (; name[i + t] == ' '; t++);
450
451 if (t >= 4 && dest + 4 < limit)
452 {
453 text[dest++] = '.';
454 text[dest++] = '.';
455 text[dest++] = '.';
456 text[dest++] = ' ';
457 i += t;
458 }
459 }
460
461 if (dest == 0)
462 text[dest++]= '_';
463
464 #ifdef _WIN32
465 else if (text[(size_t)dest - 1] == ' ')
466 {
467 if (dest < limit)
468 text[dest++] = SPACE_TERMINATOR_CHAR;
469 else
470 text[dest - 1] = SPACE_REPLACE_CHAR;
471 }
472 #endif
473
474 text[dest] = 0;
475 // OutputDebugStringW(text);
476 return 0;
477 }
478 }
479 }
480
481 if (propID == kpidPrefix)
482 {
483 if (_folderGetItemName)
484 {
485 const wchar_t *name = NULL;
486 unsigned nameLen = 0;
487 _folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen);
488 if (name)
489 {
490 unsigned dest = 0;
491 unsigned limit = item.cchTextMax - 1;
492 for (unsigned i = 0; dest < limit;)
493 {
494 wchar_t c = name[i++];
495 if (c == 0)
496 break;
497 text[dest++] = c;
498 }
499 text[dest] = 0;
500 return 0;
501 }
502 }
503 }
504
505 HRESULT res = _folder->GetProperty(realIndex, propID, &prop);
506
507 if (res != S_OK)
508 {
509 MyStringCopy(text, L"Error: ");
510 // s = UString("Error: ") + HResultToMessage(res);
511 }
512 else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
513 {
514 UInt64 v = 0;
515 ConvertPropVariantToUInt64(prop, v);
516 ConvertSizeToString(v, text);
517 }
518 else if (prop.vt == VT_BSTR)
519 {
520 unsigned limit = item.cchTextMax - 1;
521 const wchar_t *src = prop.bstrVal;
522 unsigned i;
523 for (i = 0; i < limit; i++)
524 {
525 wchar_t c = src[i];
526 if (c == 0) break;
527 if (c == 0xA) c = ' ';
528 if (c == 0xD) c = ' ';
529 text[i] = c;
530 }
531 text[i] = 0;
532 }
533 else
534 {
535 char temp[64];
536 ConvertPropertyToShortString2(temp, prop, propID, _timestampLevel);
537 unsigned i;
538 unsigned limit = item.cchTextMax - 1;
539 for (i = 0; i < limit; i++)
540 {
541 wchar_t c = (Byte)temp[i];
542 if (c == 0)
543 break;
544 text[i] = c;
545 }
546 text[i] = 0;
547 }
548
549 return 0;
550 }
551
552 #ifndef UNDER_CE
553 extern DWORD g_ComCtl32Version;
554 #endif
555
OnItemChanged(NMLISTVIEW * item)556 void CPanel::OnItemChanged(NMLISTVIEW *item)
557 {
558 int index = (int)item->lParam;
559 if (index == kParentIndex)
560 return;
561 bool oldSelected = (item->uOldState & LVIS_SELECTED) != 0;
562 bool newSelected = (item->uNewState & LVIS_SELECTED) != 0;
563 // Don't change this code. It works only with such check
564 if (oldSelected != newSelected)
565 _selectedStatusVector[index] = newSelected;
566 }
567
568 extern bool g_LVN_ITEMACTIVATE_Support;
569
OnNotifyActivateItems()570 void CPanel::OnNotifyActivateItems()
571 {
572 bool alt = IsKeyDown(VK_MENU);
573 bool ctrl = IsKeyDown(VK_CONTROL);
574 bool shift = IsKeyDown(VK_SHIFT);
575 if (!shift && alt && !ctrl)
576 Properties();
577 else
578 OpenSelectedItems(!shift || alt || ctrl);
579 }
580
OnNotifyList(LPNMHDR header,LRESULT & result)581 bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result)
582 {
583 switch (header->code)
584 {
585 case LVN_ITEMCHANGED:
586 {
587 if (_enableItemChangeNotify)
588 {
589 if (!_mySelectMode)
590 OnItemChanged((LPNMLISTVIEW)header);
591
592 // Post_Refresh_StatusBar();
593 /* 9.26: we don't call Post_Refresh_StatusBar.
594 it was very slow if we select big number of files
595 and then clead slection by selecting just new file.
596 probably it called slow Refresh_StatusBar for each item deselection.
597 I hope Refresh_StatusBar still will be called for each key / mouse action.
598 */
599 }
600 return false;
601 }
602 /*
603
604 case LVN_ODSTATECHANGED:
605 {
606 break;
607 }
608 */
609
610 case LVN_GETDISPINFOW:
611 {
612 LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header;
613
614 //is the sub-item information being requested?
615
616 if ((dispInfo->item.mask & LVIF_TEXT) != 0 ||
617 (dispInfo->item.mask & LVIF_IMAGE) != 0)
618 SetItemText(dispInfo->item);
619 {
620 // 20.03:
621 result = 0;
622 return true;
623 // old 7-Zip:
624 // return false;
625 }
626 }
627 case LVN_KEYDOWN:
628 {
629 LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
630 bool boolResult = OnKeyDown(keyDownInfo, result);
631 switch (keyDownInfo->wVKey)
632 {
633 case VK_CONTROL:
634 case VK_SHIFT:
635 case VK_MENU:
636 break;
637 default:
638 Post_Refresh_StatusBar();
639 }
640 return boolResult;
641 }
642
643 case LVN_COLUMNCLICK:
644 OnColumnClick(LPNMLISTVIEW(header));
645 return false;
646
647 case LVN_ITEMACTIVATE:
648 if (g_LVN_ITEMACTIVATE_Support)
649 {
650 OnNotifyActivateItems();
651 return false;
652 }
653 break;
654 case NM_DBLCLK:
655 case NM_RETURN:
656 if (!g_LVN_ITEMACTIVATE_Support)
657 {
658 OnNotifyActivateItems();
659 return false;
660 }
661 break;
662
663 case NM_RCLICK:
664 Post_Refresh_StatusBar();
665 break;
666
667 /*
668 return OnRightClick((LPNMITEMACTIVATE)header, result);
669 */
670 /*
671 case NM_CLICK:
672 SendRefreshStatusBarMessage();
673 return 0;
674
675 // TODO : Handler default action...
676 return 0;
677 case LVN_ITEMCHANGED:
678 {
679 NMLISTVIEW *pNMLV = (NMLISTVIEW *) lpnmh;
680 SelChange(pNMLV);
681 return TRUE;
682 }
683 case NM_SETFOCUS:
684 return onSetFocus(NULL);
685 case NM_KILLFOCUS:
686 return onKillFocus(NULL);
687 */
688 case NM_CLICK:
689 {
690 // we need SetFocusToList, if we drag-select items from other panel.
691 SetFocusToList();
692 Post_Refresh_StatusBar();
693 if (_mySelectMode)
694 #ifndef UNDER_CE
695 if (g_ComCtl32Version >= MAKELONG(71, 4))
696 #endif
697 OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header);
698 return false;
699 }
700 case LVN_BEGINLABELEDITW:
701 result = OnBeginLabelEdit((LV_DISPINFOW *)header);
702 return true;
703 case LVN_ENDLABELEDITW:
704 result = OnEndLabelEdit((LV_DISPINFOW *)header);
705 return true;
706
707 case NM_CUSTOMDRAW:
708 {
709 if (_mySelectMode || (_markDeletedItems && _thereAreDeletedItems))
710 return OnCustomDraw((LPNMLVCUSTOMDRAW)header, result);
711 break;
712 }
713 case LVN_BEGINDRAG:
714 {
715 OnDrag((LPNMLISTVIEW)header);
716 Post_Refresh_StatusBar();
717 break;
718 }
719 // case LVN_BEGINRDRAG:
720 }
721 return false;
722 }
723
OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd,LRESULT & result)724 bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result)
725 {
726 switch (lplvcd->nmcd.dwDrawStage)
727 {
728 case CDDS_PREPAINT :
729 result = CDRF_NOTIFYITEMDRAW;
730 return true;
731
732 case CDDS_ITEMPREPAINT:
733 /*
734 SelectObject(lplvcd->nmcd.hdc,
735 GetFontForItem(lplvcd->nmcd.dwItemSpec,
736 lplvcd->nmcd.lItemlParam) );
737 lplvcd->clrText = GetColorForItem(lplvcd->nmcd.dwItemSpec,
738 lplvcd->nmcd.lItemlParam);
739 lplvcd->clrTextBk = GetBkColorForItem(lplvcd->nmcd.dwItemSpec,
740 lplvcd->nmcd.lItemlParam);
741 */
742 int realIndex = (int)lplvcd->nmcd.lItemlParam;
743 lplvcd->clrTextBk = _listView.GetBkColor();
744 if (_mySelectMode)
745 {
746 if (realIndex != kParentIndex && _selectedStatusVector[realIndex])
747 lplvcd->clrTextBk = RGB(255, 192, 192);
748 }
749
750 if (_markDeletedItems && _thereAreDeletedItems)
751 {
752 if (IsItem_Deleted(realIndex))
753 lplvcd->clrText = RGB(255, 0, 0);
754 }
755 // lplvcd->clrText = RGB(0, 0, 0);
756 // result = CDRF_NEWFONT;
757 result = CDRF_NOTIFYITEMDRAW;
758 return true;
759
760 // return false;
761 // return true;
762 /*
763 case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
764 if (lplvcd->iSubItem == 0)
765 {
766 // lplvcd->clrText = RGB(255, 0, 0);
767 lplvcd->clrTextBk = RGB(192, 192, 192);
768 }
769 else
770 {
771 lplvcd->clrText = RGB(0, 0, 0);
772 lplvcd->clrTextBk = RGB(255, 255, 255);
773 }
774 return true;
775 */
776
777 /* At this point, you can change the background colors for the item
778 and any subitems and return CDRF_NEWFONT. If the list-view control
779 is in report mode, you can simply return CDRF_NOTIFYSUBITEMREDRAW
780 to customize the item's subitems individually */
781 }
782 return false;
783 }
784
Refresh_StatusBar()785 void CPanel::Refresh_StatusBar()
786 {
787 /*
788 g_name_cnt++;
789 char s[256];
790 sprintf(s, "g_name_cnt = %8d", g_name_cnt);
791 OutputDebugStringA(s);
792 */
793 // DWORD dw = GetTickCount();
794
795 CRecordVector<UInt32> indices;
796 GetOperatedItemIndices(indices);
797
798 wchar_t temp[32];
799 ConvertUInt32ToString(indices.Size(), temp);
800 wcscat(temp, L" / ");
801 ConvertUInt32ToString(_selectedStatusVector.Size(), temp + wcslen(temp));
802
803 // UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size()));
804 // UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size()));
805 _statusBar.SetText(0, MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp));
806 // _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size())));
807
808 wchar_t selectSizeString[32];
809 selectSizeString[0] = 0;
810
811 if (indices.Size() > 0)
812 {
813 // for (unsigned ttt = 0; ttt < 1000; ttt++) {
814 UInt64 totalSize = 0;
815 FOR_VECTOR (i, indices)
816 totalSize += GetItemSize(indices[i]);
817 ConvertSizeToString(totalSize, selectSizeString);
818 // }
819 }
820 _statusBar.SetText(1, selectSizeString);
821
822 int focusedItem = _listView.GetFocusedItem();
823 wchar_t sizeString[32];
824 sizeString[0] = 0;
825 wchar_t dateString[32];
826 dateString[0] = 0;
827 if (focusedItem >= 0 && _listView.GetSelectedCount() > 0)
828 {
829 int realIndex = GetRealItemIndex(focusedItem);
830 if (realIndex != kParentIndex)
831 {
832 ConvertSizeToString(GetItemSize(realIndex), sizeString);
833 NCOM::CPropVariant prop;
834 if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK)
835 {
836 char dateString2[32];
837 dateString2[0] = 0;
838 ConvertPropertyToShortString2(dateString2, prop, kpidMTime);
839 for (unsigned i = 0;; i++)
840 {
841 char c = dateString2[i];
842 dateString[i] = (Byte)c;
843 if (c == 0)
844 break;
845 }
846 }
847 }
848 }
849 _statusBar.SetText(2, sizeString);
850 _statusBar.SetText(3, dateString);
851
852 // _statusBar.SetText(4, nameString);
853 // _statusBar2.SetText(1, MyFormatNew(L"{0} bytes", NumberToStringW(totalSize)));
854 // }
855 /*
856 dw = GetTickCount() - dw;
857 sprintf(s, "status = %8d ms", dw);
858 OutputDebugStringA(s);
859 */
860 }
861