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