~ubuntu-installer/wubi/trunk

« back to all changes in this revision

Viewing changes to src/7z/CPP/7zip/UI/FileManager/App.cpp

  • Committer: Agostino Russo
  • Date: 2008-12-04 00:37:30 UTC
  • Revision ID: agostino.russo@gmail.com-20081204003730-3o051yp78d6ujckl
* Bumped version to 9.04
* Added required binaries (will be compiled at a later stage)
* Added uninstallation page
* Added BitTorrent source
* Added documentation and licenses
* Connected download managers
* Fixed download status updates
* Added more information to the README
* Made the tasklist thread daemonic so that it does not prevent the
  main application from quitting

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// App.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
#include "resource.h"
 
6
 
 
7
#include "Common/StringConvert.h"
 
8
#include "Windows/FileDir.h"
 
9
#include "Windows/Error.h"
 
10
#include "Windows/COM.h"
 
11
#include "Windows/Thread.h"
 
12
#include "IFolder.h"
 
13
 
 
14
#include "App.h"
 
15
 
 
16
#include "CopyDialog.h"
 
17
 
 
18
#include "ExtractCallback.h"
 
19
#include "ViewSettings.h"
 
20
#include "RegistryUtils.h"
 
21
#include "LangUtils.h"
 
22
 
 
23
using namespace NWindows;
 
24
using namespace NFile;
 
25
using namespace NFind;
 
26
 
 
27
extern DWORD g_ComCtl32Version;
 
28
extern HINSTANCE g_hInstance;
 
29
 
 
30
static LPCWSTR kTempDirPrefix = L"7zE"; 
 
31
 
 
32
void CPanelCallbackImp::OnTab()
 
33
{
 
34
  if (g_App.NumPanels != 1)
 
35
    _app->Panels[1 - _index].SetFocusToList();  
 
36
  _app->RefreshTitle();
 
37
}
 
38
 
 
39
void CPanelCallbackImp::SetFocusToPath(int index)
 
40
 
41
  int newPanelIndex = index;
 
42
  if (g_App.NumPanels == 1)
 
43
    newPanelIndex = g_App.LastFocusedPanel;
 
44
  _app->Panels[newPanelIndex]._headerComboBox.SetFocus();
 
45
  _app->RefreshTitle();
 
46
}
 
47
 
 
48
 
 
49
void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }
 
50
void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }
 
51
void CPanelCallbackImp::OnSetSubFolder()  { _app->OnSetSubFolder(_index); }
 
52
void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); }
 
53
void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }
 
54
void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }
 
55
void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); }
 
56
 
 
57
void CApp::SetListSettings()
 
58
{
 
59
  bool showDots = ReadShowDots();
 
60
  bool showRealFileIcons = ReadShowRealFileIcons();
 
61
 
 
62
  DWORD extendedStyle = LVS_EX_HEADERDRAGDROP;
 
63
  if (ReadFullRow())
 
64
    extendedStyle |= LVS_EX_FULLROWSELECT;
 
65
  if (ReadShowGrid())
 
66
    extendedStyle |= LVS_EX_GRIDLINES;
 
67
  bool mySelectionMode = ReadAlternativeSelection();
 
68
  
 
69
  /*
 
70
  if (ReadSingleClick())
 
71
  {
 
72
    extendedStyle |= LVS_EX_ONECLICKACTIVATE 
 
73
      | LVS_EX_TRACKSELECT;
 
74
    if (ReadUnderline())
 
75
      extendedStyle |= LVS_EX_UNDERLINEHOT;
 
76
  }
 
77
  */
 
78
 
 
79
  for (int i = 0; i < kNumPanelsMax; i++)
 
80
  {
 
81
    CPanel &panel = Panels[i];
 
82
    panel._mySelectMode = mySelectionMode;
 
83
    panel._showDots = showDots;
 
84
    panel._showRealFileIcons = showRealFileIcons;
 
85
    panel._exStyle = extendedStyle;
 
86
 
 
87
    DWORD style = (DWORD)panel._listView.GetStyle();
 
88
    if (mySelectionMode)
 
89
      style |= LVS_SINGLESEL;
 
90
    else
 
91
      style &= ~LVS_SINGLESEL;
 
92
    panel._listView.SetStyle(style);
 
93
    panel.SetExtendedStyle();
 
94
  }
 
95
}
 
96
 
 
97
void CApp::SetShowSystemMenu()
 
98
{
 
99
  ShowSystemMenu = ReadShowSystemMenu();
 
100
}
 
101
 
 
102
void CApp::CreateOnePanel(int panelIndex, const UString &mainPath, bool &archiveIsOpened, bool &encrypted)
 
103
{
 
104
  if (PanelsCreated[panelIndex])
 
105
    return;
 
106
  m_PanelCallbackImp[panelIndex].Init(this, panelIndex);
 
107
  UString path;
 
108
  if (mainPath.IsEmpty())
 
109
  {
 
110
    if (!::ReadPanelPath(panelIndex, path))
 
111
      path.Empty();
 
112
  }
 
113
  else
 
114
    path = mainPath;
 
115
  int id = 1000 + 100 * panelIndex;
 
116
  Panels[panelIndex].Create(_window, _window, 
 
117
      id, path, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted);
 
118
  PanelsCreated[panelIndex] = true;
 
119
}
 
120
 
 
121
static void CreateToolbar(
 
122
    HWND parent,
 
123
    NWindows::NControl::CImageList &imageList,
 
124
    NWindows::NControl::CToolBar &toolBar,
 
125
    bool LargeButtons)
 
126
{
 
127
  toolBar.Attach(::CreateWindowEx(0, 
 
128
      TOOLBARCLASSNAME,
 
129
      NULL, 0
 
130
      | WS_VISIBLE
 
131
      | TBSTYLE_FLAT
 
132
      | TBSTYLE_TOOLTIPS 
 
133
      | WS_CHILD
 
134
      | CCS_NOPARENTALIGN
 
135
      | CCS_NORESIZE 
 
136
      | CCS_NODIVIDER
 
137
      // | TBSTYLE_AUTOSIZE
 
138
      // | CCS_ADJUSTABLE 
 
139
      ,0,0,0,0, parent, NULL, g_hInstance, NULL));
 
140
 
 
141
  // TB_BUTTONSTRUCTSIZE message, which is required for 
 
142
  // backward compatibility.
 
143
  toolBar.ButtonStructSize();
 
144
 
 
145
  imageList.Create(
 
146
      LargeButtons ? 48: 24, 
 
147
      LargeButtons ? 36: 24, 
 
148
      ILC_MASK, 0, 0);
 
149
  toolBar.SetImageList(0, imageList);
 
150
}
 
151
 
 
152
struct CButtonInfo
 
153
{
 
154
  UINT commandID;
 
155
  UINT BitmapResID;
 
156
  UINT Bitmap2ResID;
 
157
  UINT StringResID; 
 
158
  UINT32 LangID;
 
159
  UString GetText()const { return LangString(StringResID, LangID); };
 
160
};
 
161
 
 
162
static CButtonInfo g_StandardButtons[] = 
 
163
{
 
164
  { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY, 0x03020420},
 
165
  { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE, 0x03020421},
 
166
  { IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE, 0x03020422} ,
 
167
  { IDM_FILE_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO, 0x03020423} 
 
168
};
 
169
 
 
170
static CButtonInfo g_ArchiveButtons[] = 
 
171
{
 
172
  { kAddCommand, IDB_ADD, IDB_ADD2, IDS_ADD, 0x03020400},
 
173
  { kExtractCommand, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT, 0x03020401},
 
174
  { kTestCommand , IDB_TEST, IDB_TEST2, IDS_TEST, 0x03020402}
 
175
};
 
176
 
 
177
bool SetButtonText(UINT32 commandID, CButtonInfo *buttons, int numButtons, UString &s)
 
178
{
 
179
  for (int i = 0; i < numButtons; i++)
 
180
  {
 
181
    const CButtonInfo &b = buttons[i];
 
182
    if (b.commandID == commandID)
 
183
    {
 
184
      s = b.GetText();
 
185
      return true;
 
186
    }
 
187
  }
 
188
  return false;
 
189
}
 
190
 
 
191
void SetButtonText(UINT32 commandID, UString &s)
 
192
{
 
193
  if (SetButtonText(commandID, g_StandardButtons, 
 
194
      sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s))
 
195
    return;
 
196
  SetButtonText(commandID, g_ArchiveButtons, 
 
197
      sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]), s);
 
198
}
 
199
 
 
200
static void AddButton(
 
201
    NControl::CImageList &imageList,
 
202
    NControl::CToolBar &toolBar, 
 
203
    CButtonInfo &butInfo,
 
204
    bool showText,
 
205
    bool large)
 
206
{
 
207
  TBBUTTON but; 
 
208
  but.iBitmap = 0; 
 
209
  but.idCommand = butInfo.commandID; 
 
210
  but.fsState = TBSTATE_ENABLED; 
 
211
  but.fsStyle = BTNS_BUTTON
 
212
    // | BTNS_AUTOSIZE 
 
213
    ;
 
214
  but.dwData = 0;
 
215
 
 
216
  UString s = butInfo.GetText();
 
217
  but.iString = 0;
 
218
  if (showText)
 
219
    but.iString = (INT_PTR)(LPCWSTR)s; 
 
220
 
 
221
  but.iBitmap = imageList.GetImageCount();
 
222
  HBITMAP b = ::LoadBitmap(g_hInstance, 
 
223
      large ? 
 
224
      MAKEINTRESOURCE(butInfo.BitmapResID):
 
225
      MAKEINTRESOURCE(butInfo.Bitmap2ResID));
 
226
  if (b != 0)
 
227
  {
 
228
    imageList.AddMasked(b, RGB(255, 0, 255));
 
229
    ::DeleteObject(b);
 
230
  }
 
231
  #ifdef _UNICODE
 
232
  toolBar.AddButton(1, &but);
 
233
  #else
 
234
  toolBar.AddButtonW(1, &but);
 
235
  #endif
 
236
}
 
237
 
 
238
static void AddBand(NControl::CReBar &reBar, NControl::CToolBar &toolBar)
 
239
{
 
240
  SIZE size;
 
241
  toolBar.GetMaxSize(&size);
 
242
 
 
243
  RECT rect;
 
244
  toolBar.GetWindowRect(&rect);
 
245
  
 
246
  REBARBANDINFO rbBand;
 
247
  rbBand.cbSize = sizeof(REBARBANDINFO);  // Required
 
248
  rbBand.fMask  = RBBIM_STYLE 
 
249
    | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
 
250
  rbBand.fStyle = RBBS_CHILDEDGE; // RBBS_NOGRIPPER;
 
251
  rbBand.cxMinChild = size.cx; // rect.right - rect.left;
 
252
  rbBand.cyMinChild = size.cy; // rect.bottom - rect.top;
 
253
  rbBand.cyChild = rbBand.cyMinChild;
 
254
  rbBand.cx = rbBand.cxMinChild;
 
255
  rbBand.cxIdeal = rbBand.cxMinChild;
 
256
  rbBand.hwndChild = toolBar;
 
257
  reBar.InsertBand(-1, &rbBand);
 
258
}
 
259
 
 
260
void CApp::ReloadToolbars()
 
261
 
262
  if (!_rebar)
 
263
    return;
 
264
  HWND parent = _rebar;
 
265
 
 
266
  while(_rebar.GetBandCount() > 0)
 
267
    _rebar.DeleteBand(0);
 
268
 
 
269
  _archiveToolBar.Destroy();
 
270
  _archiveButtonsImageList.Destroy();
 
271
 
 
272
  _standardButtonsImageList.Destroy();
 
273
  _standardToolBar.Destroy();
 
274
 
 
275
  if (ShowArchiveToolbar)
 
276
  {
 
277
    CreateToolbar(parent, _archiveButtonsImageList, _archiveToolBar, LargeButtons);
 
278
    for (int i = 0; i < sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]); i++)
 
279
      AddButton(_archiveButtonsImageList, _archiveToolBar, g_ArchiveButtons[i], 
 
280
          ShowButtonsLables, LargeButtons);
 
281
    AddBand(_rebar, _archiveToolBar);
 
282
  }
 
283
 
 
284
  if (ShowStandardToolbar)
 
285
  {
 
286
    CreateToolbar(parent, _standardButtonsImageList, _standardToolBar, LargeButtons);
 
287
    for (int i = 0; i < sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]); i++)
 
288
      AddButton(_standardButtonsImageList, _standardToolBar, g_StandardButtons[i], 
 
289
          ShowButtonsLables, LargeButtons);
 
290
    AddBand(_rebar, _standardToolBar);
 
291
  }
 
292
}
 
293
 
 
294
void CApp::ReloadRebar(HWND hwnd)
 
295
{
 
296
  _rebar.Destroy();
 
297
  if (!ShowArchiveToolbar && !ShowStandardToolbar)
 
298
    return;
 
299
  if (g_ComCtl32Version >= MAKELONG(71, 4))
 
300
  {
 
301
    INITCOMMONCONTROLSEX icex;
 
302
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
 
303
    icex.dwICC  = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
 
304
    InitCommonControlsEx(&icex);
 
305
    
 
306
    _rebar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW,
 
307
      REBARCLASSNAME,
 
308
      NULL, 
 
309
      WS_VISIBLE 
 
310
      | WS_BORDER 
 
311
      | WS_CHILD 
 
312
      | WS_CLIPCHILDREN 
 
313
      | WS_CLIPSIBLINGS 
 
314
      // | CCS_NODIVIDER  
 
315
      // | CCS_NOPARENTALIGN  // it's bead for moveing of two bands
 
316
      // | CCS_TOP
 
317
      | RBS_VARHEIGHT 
 
318
      | RBS_BANDBORDERS
 
319
      // | RBS_AUTOSIZE
 
320
      ,0,0,0,0, hwnd, NULL, g_hInstance, NULL));
 
321
  }
 
322
  if (_rebar == 0)
 
323
    return;
 
324
  REBARINFO rbi;
 
325
  rbi.cbSize = sizeof(REBARINFO);  // Required when using this struct.
 
326
  rbi.fMask = 0;
 
327
  rbi.himl = (HIMAGELIST)NULL;
 
328
  _rebar.SetBarInfo(&rbi);
 
329
  ReloadToolbars();
 
330
}
 
331
 
 
332
void CApp::Create(HWND hwnd, const UString &mainPath, int xSizes[2], bool &archiveIsOpened, bool &encrypted)
 
333
{
 
334
  ReadToolbar();
 
335
  ReloadRebar(hwnd);
 
336
 
 
337
  int i;
 
338
  for (i = 0; i < kNumPanelsMax; i++)
 
339
    PanelsCreated[i] = false;
 
340
 
 
341
  _window.Attach(hwnd);
 
342
  AppState.Read();
 
343
  SetListSettings();
 
344
  SetShowSystemMenu();
 
345
  if (LastFocusedPanel >= kNumPanelsMax)
 
346
    LastFocusedPanel = 0;
 
347
 
 
348
  CListMode listMode;
 
349
  ReadListMode(listMode);
 
350
  for (i = 0; i < kNumPanelsMax; i++)
 
351
  {
 
352
    Panels[i]._ListViewMode = listMode.Panels[i];
 
353
    Panels[i]._xSize = xSizes[i];
 
354
  }
 
355
  for (i = 0; i < kNumPanelsMax; i++)
 
356
    if (NumPanels > 1 || i == LastFocusedPanel)
 
357
    {
 
358
      if (NumPanels == 1)
 
359
        Panels[i]._xSize = xSizes[0] + xSizes[1];
 
360
      bool archiveIsOpened2 = false;
 
361
      bool encrypted2 = false;
 
362
      bool mainPanel = (i == LastFocusedPanel);
 
363
      CreateOnePanel(i, mainPanel ? mainPath : L"", archiveIsOpened2, encrypted2);
 
364
      if (mainPanel)
 
365
      {
 
366
        archiveIsOpened = archiveIsOpened2;
 
367
        encrypted = encrypted2;
 
368
      }
 
369
    }
 
370
  SetFocusedPanel(LastFocusedPanel);
 
371
  Panels[LastFocusedPanel].SetFocusToList();
 
372
}
 
373
 
 
374
extern void MoveSubWindows(HWND hWnd);
 
375
 
 
376
void CApp::SwitchOnOffOnePanel()
 
377
{
 
378
  if (NumPanels == 1)
 
379
  {
 
380
    NumPanels++;
 
381
    bool archiveIsOpened, encrypted;
 
382
    CreateOnePanel(1 - LastFocusedPanel, UString(), archiveIsOpened, encrypted);
 
383
    Panels[1 - LastFocusedPanel].Enable(true);
 
384
    Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
 
385
  }
 
386
  else
 
387
  {
 
388
    NumPanels--;
 
389
    Panels[1 - LastFocusedPanel].Enable(false);
 
390
    Panels[1 - LastFocusedPanel].Show(SW_HIDE);
 
391
  }
 
392
  MoveSubWindows(_window);
 
393
}
 
394
 
 
395
void CApp::Save()
 
396
{
 
397
  AppState.Save();
 
398
  CListMode listMode;
 
399
  for (int i = 0; i < kNumPanelsMax; i++)
 
400
  {
 
401
    const CPanel &panel = Panels[i];
 
402
    UString path;
 
403
    if (panel._parentFolders.IsEmpty())
 
404
      path = panel._currentFolderPrefix;
 
405
    else
 
406
      path = GetFolderPath(panel._parentFolders[0].ParentFolder);
 
407
    SavePanelPath(i, path);
 
408
    listMode.Panels[i] = panel.GetListViewMode();
 
409
  }
 
410
  SaveListMode(listMode);
 
411
}
 
412
 
 
413
void CApp::Release()
 
414
{
 
415
  // It's for unloading COM dll's: don't change it. 
 
416
  for (int i = 0; i < kNumPanelsMax; i++)
 
417
    Panels[i].Release();
 
418
}
 
419
 
 
420
static bool IsThereFolderOfPath(const UString &path)
 
421
{
 
422
  CFileInfoW fileInfo;
 
423
  if (!FindFile(path, fileInfo))
 
424
    return false;
 
425
  return fileInfo.IsDirectory();
 
426
}
 
427
 
 
428
// reduces path to part that exists on disk
 
429
static void ReducePathToRealFileSystemPath(UString &path)
 
430
{
 
431
  while(!path.IsEmpty())
 
432
  {
 
433
    if (IsThereFolderOfPath(path))
 
434
    {
 
435
      NName::NormalizeDirPathPrefix(path);
 
436
      break;
 
437
    }
 
438
    int pos = path.ReverseFind('\\');
 
439
    if (pos < 0)
 
440
      path.Empty();
 
441
    else
 
442
    {
 
443
      path = path.Left(pos + 1);
 
444
      if (path.Length() == 3 && path[1] == L':')
 
445
        break;
 
446
      path = path.Left(pos);
 
447
    }
 
448
  }
 
449
}
 
450
 
 
451
// return true for dir\, if dir exist
 
452
static bool CheckFolderPath(const UString &path)
 
453
{
 
454
  UString pathReduced = path;
 
455
  ReducePathToRealFileSystemPath(pathReduced);
 
456
  return (pathReduced == path);
 
457
}
 
458
 
 
459
static bool IsPathAbsolute(const UString &path)
 
460
{
 
461
  if ((path.Length() >= 1 && path[0] == L'\\') ||
 
462
      (path.Length() >= 3 && path[1] == L':' && path[2] == L'\\'))
 
463
    return true;
 
464
  return false;
 
465
}
 
466
 
 
467
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
 
468
{
 
469
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
 
470
  CPanel &srcPanel = Panels[srcPanelIndex];
 
471
  CPanel &destPanel = Panels[destPanelIndex];
 
472
 
 
473
  CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
 
474
  CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
 
475
 
 
476
  if (!srcPanel.DoesItSupportOperations())
 
477
  {
 
478
    srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
 
479
    return;
 
480
  }
 
481
 
 
482
  CRecordVector<UInt32> indices;
 
483
  UString destPath;
 
484
  bool useDestPanel = false;
 
485
 
 
486
  {
 
487
    if (copyToSame)
 
488
    {
 
489
      int focusedItem = srcPanel._listView.GetFocusedItem();
 
490
      if (focusedItem < 0)
 
491
        return;
 
492
      int realIndex = srcPanel.GetRealItemIndex(focusedItem);
 
493
      if (realIndex == kParentIndex)
 
494
        return;
 
495
      indices.Add(realIndex);
 
496
      destPath = srcPanel.GetItemName(realIndex);
 
497
    }
 
498
    else
 
499
    {
 
500
      srcPanel.GetOperatedItemIndices(indices);
 
501
      if (indices.Size() == 0)
 
502
        return;
 
503
      destPath = destPanel._currentFolderPrefix;
 
504
      if (NumPanels == 1)
 
505
        ReducePathToRealFileSystemPath(destPath);
 
506
    }
 
507
 
 
508
    CCopyDialog copyDialog;
 
509
    UStringVector copyFolders;
 
510
    ReadCopyHistory(copyFolders);
 
511
 
 
512
    copyDialog.Strings = copyFolders;
 
513
    copyDialog.Value = destPath;
 
514
    
 
515
    copyDialog.Title = move ? 
 
516
        LangString(IDS_MOVE, 0x03020202):
 
517
        LangString(IDS_COPY, 0x03020201);
 
518
    copyDialog.Static = move ? 
 
519
        LangString(IDS_MOVE_TO, 0x03020204):
 
520
        LangString(IDS_COPY_TO, 0x03020203);
 
521
 
 
522
    if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)
 
523
      return;
 
524
 
 
525
    destPath = copyDialog.Value;
 
526
 
 
527
    if (!IsPathAbsolute(destPath))
 
528
    {
 
529
      if (!srcPanel.IsFSFolder())
 
530
      {
 
531
        srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
 
532
        return;
 
533
      }
 
534
      destPath = srcPanel._currentFolderPrefix + destPath;
 
535
    }
 
536
 
 
537
    if (indices.Size() > 1 || (destPath.Length() > 0 && destPath.ReverseFind('\\') == destPath.Length() - 1) || 
 
538
        IsThereFolderOfPath(destPath))
 
539
    {
 
540
      NDirectory::CreateComplexDirectory(destPath);
 
541
      NName::NormalizeDirPathPrefix(destPath);
 
542
      if (!CheckFolderPath(destPath))
 
543
      {
 
544
        if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations())
 
545
        {
 
546
          srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
 
547
          return;
 
548
        }
 
549
        useDestPanel = true;
 
550
      }
 
551
    }
 
552
    else
 
553
    {
 
554
      int pos = destPath.ReverseFind('\\');
 
555
      if (pos >= 0)
 
556
      {
 
557
        UString prefix = destPath.Left(pos + 1);
 
558
        NDirectory::CreateComplexDirectory(prefix);
 
559
        if (!CheckFolderPath(prefix))
 
560
        {
 
561
          srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
 
562
          return;
 
563
        }
 
564
      }
 
565
    }
 
566
 
 
567
    AddUniqueStringToHeadOfList(copyFolders, destPath);
 
568
    while (copyFolders.Size() > 20)
 
569
      copyFolders.DeleteBack();
 
570
    SaveCopyHistory(copyFolders);
 
571
  }
 
572
 
 
573
  bool useSrcPanel = (!useDestPanel || !srcPanel.IsFSFolder() || destPanel.IsFSFolder());
 
574
  bool useTemp = useSrcPanel && useDestPanel;
 
575
  NFile::NDirectory::CTempDirectoryW tempDirectory;
 
576
  UString tempDirPrefix;
 
577
  if (useTemp)
 
578
  {
 
579
    tempDirectory.Create(kTempDirPrefix);
 
580
    tempDirPrefix = tempDirectory.GetPath();
 
581
    NFile::NName::NormalizeDirPathPrefix(tempDirPrefix);
 
582
  }
 
583
 
 
584
  CSelectedState srcSelState;
 
585
  CSelectedState destSelState;
 
586
  srcPanel.SaveSelectedState(srcSelState);
 
587
  destPanel.SaveSelectedState(destSelState);
 
588
 
 
589
  HRESULT result;
 
590
  if (useSrcPanel)
 
591
  {
 
592
    UString folder = useTemp ? tempDirPrefix : destPath;
 
593
    result = srcPanel.CopyTo(indices, folder, move, true, 0);
 
594
    if (result != S_OK)
 
595
    {
 
596
      disableTimerProcessing1.Restore();
 
597
      disableTimerProcessing2.Restore();
 
598
      // For Password:
 
599
      srcPanel.SetFocusToList();
 
600
      if (result != E_ABORT)
 
601
        srcPanel.MessageBoxError(result, L"Error");
 
602
      return;
 
603
    }
 
604
  }
 
605
  
 
606
  if (useDestPanel)
 
607
  {
 
608
    UStringVector filePaths;
 
609
    UString folderPrefix;
 
610
    if (useTemp)
 
611
      folderPrefix = tempDirPrefix;
 
612
    else
 
613
      folderPrefix = srcPanel._currentFolderPrefix;
 
614
    filePaths.Reserve(indices.Size());
 
615
    for(int i = 0; i < indices.Size(); i++)
 
616
      filePaths.Add(srcPanel.GetItemRelPath(indices[i]));
 
617
 
 
618
    result = destPanel.CopyFrom(folderPrefix, filePaths, true, 0);
 
619
 
 
620
    if (result != S_OK)
 
621
    {
 
622
      disableTimerProcessing1.Restore();
 
623
      disableTimerProcessing2.Restore();
 
624
      // For Password:
 
625
      srcPanel.SetFocusToList();
 
626
      if (result != E_ABORT)
 
627
        srcPanel.MessageBoxError(result, L"Error");
 
628
      return;
 
629
    }
 
630
  }
 
631
 
 
632
  RefreshTitleAlways();
 
633
  if (copyToSame || move)
 
634
  {
 
635
    srcPanel.RefreshListCtrl(srcSelState);
 
636
  }
 
637
  if (!copyToSame)
 
638
  {
 
639
    destPanel.RefreshListCtrl(destSelState);
 
640
    srcPanel.KillSelection();
 
641
  }
 
642
  disableTimerProcessing1.Restore();
 
643
  disableTimerProcessing2.Restore();
 
644
  srcPanel.SetFocusToList();
 
645
}
 
646
 
 
647
void CApp::OnSetSameFolder(int srcPanelIndex)
 
648
{
 
649
  if (NumPanels <= 1)
 
650
    return;
 
651
  const CPanel &srcPanel = Panels[srcPanelIndex];
 
652
  CPanel &destPanel = Panels[1 - srcPanelIndex];
 
653
  destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix);
 
654
}
 
655
 
 
656
void CApp::OnSetSubFolder(int srcPanelIndex)
 
657
{
 
658
  if (NumPanels <= 1)
 
659
    return;
 
660
  const CPanel &srcPanel = Panels[srcPanelIndex];
 
661
  CPanel &destPanel = Panels[1 - srcPanelIndex];
 
662
 
 
663
  int focusedItem = srcPanel._listView.GetFocusedItem();
 
664
  if (focusedItem < 0)
 
665
    return;
 
666
  int realIndex = srcPanel.GetRealItemIndex(focusedItem);
 
667
  if (!srcPanel.IsItemFolder(realIndex))
 
668
    return;
 
669
 
 
670
 
 
671
  /*
 
672
  UString string = srcPanel._currentFolderPrefix + 
 
673
      srcPanel.GetItemName(realIndex) + L'\\';
 
674
  destPanel.BindToFolder(string);
 
675
  */
 
676
  CMyComPtr<IFolderFolder> newFolder;
 
677
  if (realIndex == kParentIndex)
 
678
  {
 
679
    if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK)
 
680
      return;
 
681
  }
 
682
  else
 
683
  {
 
684
    if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)
 
685
      return;
 
686
  }
 
687
  destPanel.CloseOpenFolders();
 
688
  destPanel._folder = newFolder;
 
689
  destPanel.RefreshListCtrl();
 
690
}
 
691
 
 
692
/*
 
693
int CApp::GetFocusedPanelIndex() const
 
694
{
 
695
  return LastFocusedPanel;
 
696
  HWND hwnd = ::GetFocus();
 
697
  for (;;)
 
698
  {
 
699
    if (hwnd == 0)
 
700
      return 0;
 
701
    for (int i = 0; i < kNumPanelsMax; i++)
 
702
    {
 
703
      if (PanelsCreated[i] && 
 
704
          ((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))
 
705
        return i;
 
706
    }
 
707
    hwnd = GetParent(hwnd);
 
708
  }
 
709
}
 
710
  */
 
711
 
 
712
static UString g_ToolTipBuffer;
 
713
static CSysString g_ToolTipBufferSys;
 
714
 
 
715
void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh)
 
716
{
 
717
  if (pnmh->hwndFrom == _rebar)
 
718
  {
 
719
    switch(pnmh->code)
 
720
    {
 
721
      case RBN_HEIGHTCHANGE:
 
722
      {
 
723
        MoveSubWindows(g_HWND);
 
724
        return;
 
725
      }
 
726
    }
 
727
    return ;
 
728
  }
 
729
  else 
 
730
  {
 
731
    if (pnmh->code == TTN_GETDISPINFO)
 
732
    {
 
733
      LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh;
 
734
      info->hinst = 0;
 
735
      g_ToolTipBuffer.Empty();
 
736
      SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer);
 
737
      g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer);
 
738
      info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys;
 
739
      return;
 
740
    }
 
741
    #ifndef _UNICODE
 
742
    if (pnmh->code == TTN_GETDISPINFOW)
 
743
    {
 
744
      LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh;
 
745
      info->hinst = 0;
 
746
      g_ToolTipBuffer.Empty();
 
747
      SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer);
 
748
      info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer;
 
749
      return;
 
750
    }
 
751
    #endif
 
752
  }
 
753
}
 
754
 
 
755
void CApp::RefreshTitle(bool always)
 
756
 
757
  UString path = GetFocusedPanel()._currentFolderPrefix;
 
758
  if (path.IsEmpty())
 
759
    path += LangString(IDS_APP_TITLE, 0x03000000);
 
760
  if (!always && path == PrevTitle)
 
761
    return;
 
762
  PrevTitle = path;
 
763
  NWindows::MySetWindowText(_window, path);
 
764
}
 
765
 
 
766
void CApp::RefreshTitle(int panelIndex, bool always)
 
767
 
768
  if (panelIndex != GetFocusedPanelIndex())
 
769
    return;
 
770
  RefreshTitle(always);
 
771
}
 
772