root/trunk/unicode_far/filelist.cpp @ 1577

Revision 1577, 123.9 KB (checked in by drkns, 2 years ago)

 Mantis#0000004: MantisBT,  Mantis#0000080: MantisBT

Line 
1/*
2filelist.cpp
3
4Файловая панель - общие функции
5*/
6/*
7Copyright (c) 1996 Eugene Roshal
8Copyright (c) 2000 Far Group
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
141. Redistributions of source code must retain the above copyright
15   notice, this list of conditions and the following disclaimer.
162. Redistributions in binary form must reproduce the above copyright
17   notice, this list of conditions and the following disclaimer in the
18   documentation and/or other materials provided with the distribution.
193. The name of the authors may not be used to endorse or promote products
20   derived from this software without specific prior written permission.
21
22THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
34#include "headers.hpp"
35#pragma hdrstop
36
37#include "filelist.hpp"
38#include "global.hpp"
39#include "fn.hpp"
40#include "flink.hpp"
41#include "keys.hpp"
42#include "macroopcode.hpp"
43#include "lang.hpp"
44#include "ctrlobj.hpp"
45#include "filefilter.hpp"
46#include "dialog.hpp"
47#include "vmenu.hpp"
48#include "cmdline.hpp"
49#include "manager.hpp"
50#include "filepanels.hpp"
51#include "help.hpp"
52#include "fileedit.hpp"
53#include "namelist.hpp"
54#include "fileview.hpp"
55#include "copy.hpp"
56#include "history.hpp"
57#include "qview.hpp"
58#include "rdrwdsk.hpp"
59#include "plognmn.hpp"
60#include "scrbuf.hpp"
61#include "CFileMask.hpp"
62
63extern struct PanelViewSettings ViewSettingsArray[];
64
65static int _cdecl SortList(const void *el1,const void *el2);
66int _cdecl SortSearchList(const void *el1,const void *el2);
67
68static int ListSortMode,ListSortOrder,ListSortGroups,ListSelectedFirst;
69static int ListPanelMode,ListCaseSensitive,ListNumericSort;
70static HANDLE hSortPlugin;
71
72enum SELECT_MODES {SELECT_INVERT,SELECT_INVERTALL,SELECT_ADD,SELECT_REMOVE,
73    SELECT_ADDEXT,SELECT_REMOVEEXT,SELECT_ADDNAME,SELECT_REMOVENAME};
74
75FileList::FileList()
76{
77  _OT(SysLog(L"[%p] FileList::FileList()", this));
78  {
79    const wchar_t *data=UMSG(MPanelBracketsForLongName);
80    if(StrLength(data)>1)
81    {
82      *openBracket=data[0];
83      *closeBracket=data[1];
84    }
85    else
86    {
87      *openBracket=L'{';
88      *closeBracket=L'}';
89    }
90    openBracket[1]=closeBracket[1]=0;
91  }
92
93  Type=FILE_PANEL;
94  FarGetCurDir(strCurDir);
95  hPlugin=INVALID_HANDLE_VALUE;
96  Filter=NULL;
97  ListData=NULL;
98  FileCount=0;
99  UpperFolderTopFile=0;
100  CurTopFile=CurFile=0;
101  LastCurFile=-1;
102  ShowShortNames=0;
103  MouseSelection=0;
104  SortMode=BY_NAME;
105  SortOrder=1;
106  SortGroups=0;
107  SelectedFirst=0;
108  ViewMode=VIEW_3;
109  ViewSettings=ViewSettingsArray[ViewMode];
110  NumericSort=0;
111  Columns=PreparePanelView(&ViewSettings);
112  Height=0;
113  PluginsStack=NULL;
114  PluginsStackSize=0;
115  ShiftSelection=-1;
116  hListChange=INVALID_HANDLE_VALUE;
117  SelFileCount=0;
118  SelFileSize=0;
119  TotalFileCount=0;
120  TotalFileSize=0;
121  FreeDiskSize=0;
122  ReturnCurrentFile=FALSE;
123  LastUpdateTime=0;
124  PluginCommand=-1;
125  DataToDeleteCount=0;
126  PrevDataStack=NULL;
127  PrevDataStackSize=0;
128  LeftPos=0;
129  UpdateRequired=FALSE;
130  AccessTimeUpdateRequired=FALSE;
131  DizRead=FALSE;
132  InternalProcessKey=FALSE;
133  GetSelPosition = 0;
134  Is_FS_NTFS=FALSE;
135}
136
137
138FileList::~FileList()
139{
140  _OT(SysLog(L"[%p] FileList::~FileList()", this));
141  CloseChangeNotification();
142  for (int I=0;I < PrevDataStackSize; I++)
143  {
144    DeleteListData(PrevDataStack[I]->PrevListData,PrevDataStack[I]->PrevFileCount);
145    delete PrevDataStack[I];
146  }
147  if(PrevDataStack) xf_free (PrevDataStack);
148  DeleteListData(ListData,FileCount);
149  if (PanelMode==PLUGIN_PANEL)
150    while (PopPlugin(FALSE))
151      ;
152   delete Filter;
153}
154
155
156void FileList::DeleteListData(struct FileListItem **(&ListData),long &FileCount)
157{
158  if (ListData==NULL)
159    return;
160
161  struct FileListItem *CurPtr;
162  for (int I=0;I<FileCount;I++)
163  {
164    CurPtr = ListData[I];
165    if (CurPtr->CustomColumnNumber>0 && CurPtr->CustomColumnData!=NULL)
166    {
167      for (int J=0; J < CurPtr->CustomColumnNumber; J++)
168        delete[] CurPtr->CustomColumnData[J];
169      delete[] CurPtr->CustomColumnData;
170    }
171    if (CurPtr->UserFlags & PPIF_USERDATA)
172      xf_free((void *)CurPtr->UserData);
173    if (CurPtr->DizText && CurPtr->DeleteDiz)
174      delete[] CurPtr->DizText;
175
176    delete CurPtr; //!!!
177  }
178  xf_free(ListData);
179  ListData=NULL;
180  FileCount=0;
181}
182
183
184
185
186void FileList::Up(int Count)
187{
188  CurFile-=Count;
189  if(CurFile < 0)
190    CurFile=0;
191  ShowFileList(TRUE);
192}
193
194
195void FileList::Down(int Count)
196{
197  CurFile+=Count;
198  if(CurFile >= FileCount)
199    CurFile=FileCount-1;
200  ShowFileList(TRUE);
201}
202
203void FileList::Scroll(int Count)
204{
205  CurTopFile+=Count;
206  if (Count<0)
207    Up(-Count);
208  else
209    Down(Count);
210}
211
212void FileList::CorrectPosition()
213{
214  if (FileCount==0)
215  {
216    CurFile=CurTopFile=0;
217    return;
218  }
219  if (CurTopFile+Columns*Height>FileCount)
220    CurTopFile=FileCount-Columns*Height;
221  if (CurFile<0)
222    CurFile=0;
223  if (CurFile > FileCount-1)
224    CurFile=FileCount-1;
225  if (CurTopFile<0)
226    CurTopFile=0;
227  if (CurTopFile > FileCount-1)
228    CurTopFile=FileCount-1;
229  if (CurFile<CurTopFile)
230    CurTopFile=CurFile;
231  if (CurFile>CurTopFile+Columns*Height-1)
232    CurTopFile=CurFile-Columns*Height+1;
233}
234
235
236void FileList::SortFileList(int KeepPosition)
237{
238  if (FileCount>1)
239  {
240    string strCurName;
241
242    if (SortMode==BY_DIZ)
243      ReadDiz();
244
245    ListSortMode=SortMode;
246    ListSortOrder=SortOrder;
247    ListSortGroups=SortGroups;
248    ListSelectedFirst=SelectedFirst;
249    ListPanelMode=PanelMode;
250    ListCaseSensitive=ViewSettingsArray[ViewMode].CaseSensitiveSort;
251    //ListCaseSensitive=ViewSettings.CaseSensitiveSort;
252    ListNumericSort=NumericSort;
253
254
255    if (KeepPosition)
256      strCurName = ListData[CurFile]->strName;
257
258    hSortPlugin=(PanelMode==PLUGIN_PANEL) ? hPlugin:NULL;
259
260    far_qsort((void *)ListData,FileCount,sizeof(*ListData),SortList);
261    if (KeepPosition)
262      GoToFile(strCurName);
263  }
264}
265
266#if defined(__BORLANDC__)
267#pragma intrinsic strcmp
268#endif
269
270int _cdecl SortList(const void *el1,const void *el2)
271{
272  int RetCode;
273  __int64 RetCode64;
274  const wchar_t *ChPtr1,*ChPtr2;
275  struct FileListItem *SPtr1,*SPtr2;
276  SPtr1=((FileListItem **)el1)[0];
277  SPtr2=((FileListItem **)el2)[0];
278
279  const wchar_t *Name1=PointToName(SPtr1->strName);
280  const wchar_t *Name2=PointToName(SPtr2->strName);
281
282  if (Name1[0]==L'.' && Name1[1]==L'.' && Name1[2]==0)
283    return(-1);
284  if (Name2[0]==L'.' && Name2[1]==L'.' && Name2[2]==0)
285    return(1);
286
287  if (ListSortMode==UNSORTED)
288  {
289    if (ListSelectedFirst && SPtr1->Selected!=SPtr2->Selected)
290      return(SPtr1->Selected>SPtr2->Selected ? -1:1);
291    return((SPtr1->Position>SPtr2->Position) ? ListSortOrder:-ListSortOrder);
292  }
293
294  if ((SPtr1->FileAttr & FA_DIREC) < (SPtr2->FileAttr & FA_DIREC))
295    return(1);
296  if ((SPtr1->FileAttr & FA_DIREC) > (SPtr2->FileAttr & FA_DIREC))
297    return(-1);
298  if (ListSelectedFirst && SPtr1->Selected!=SPtr2->Selected)
299    return(SPtr1->Selected>SPtr2->Selected ? -1:1);
300  if (ListSortGroups && (ListSortMode==BY_NAME || ListSortMode==BY_EXT) &&
301      SPtr1->SortGroup!=SPtr2->SortGroup)
302    return(SPtr1->SortGroup<SPtr2->SortGroup ? -1:1);
303
304  if (hSortPlugin!=NULL)
305  {
306    DWORD SaveFlags1,SaveFlags2;
307    SaveFlags1=SPtr1->UserFlags;
308    SaveFlags2=SPtr2->UserFlags;
309    SPtr1->UserFlags=SPtr2->UserFlags=0;
310    PluginPanelItem pi1,pi2;
311    FileList::FileListToPluginItem(SPtr1,&pi1);
312    FileList::FileListToPluginItem(SPtr2,&pi2);
313    SPtr1->UserFlags=SaveFlags1;
314    SPtr2->UserFlags=SaveFlags2;
315    int RetCode=CtrlObject->Plugins.Compare(hSortPlugin,&pi1,&pi2,ListSortMode+(SM_UNSORTED-UNSORTED));
316    if (RetCode==-3)
317      hSortPlugin=NULL;
318    else
319      if (RetCode!=-2)
320        return(ListSortOrder*RetCode);
321  }
322
323  // НЕ СОРТИРУЕМ КАТАЛОГИ В РЕЖИМЕ "ПО РАСШИРЕНИЮ" (Опционально!)
324  if(!(ListSortMode == BY_EXT && !Opt.SortFolderExt && (SPtr1->FileAttr & FA_DIREC)))
325  {
326    switch(ListSortMode)
327    {
328      case BY_NAME:
329        break;
330
331      case BY_EXT:
332        ChPtr1=wcsrchr(*Name1 ? Name1+1:Name1,L'.');
333        ChPtr2=wcsrchr(*Name2 ? Name2+1:Name2,L'.');
334        if (ChPtr1==NULL && ChPtr2==NULL)
335          break;
336        if (ChPtr1==NULL)
337          return(-ListSortOrder);
338        if (ChPtr2==NULL)
339          return(ListSortOrder);
340        if (*(ChPtr1+1)==L'.')
341          return(-ListSortOrder);
342        if (*(ChPtr2+1)==L'.')
343          return(ListSortOrder);
344        RetCode=ListSortOrder*StrCmpI(ChPtr1+1,ChPtr2+1);
345        if(RetCode)
346          return RetCode;
347        break;
348
349      case BY_MTIME:
350        if((RetCode64=*(__int64*)&SPtr1->WriteTime - *(__int64*)&SPtr2->WriteTime) == 0)
351          break;
352        return -ListSortOrder*(RetCode64<0?-1:1);
353
354      case BY_CTIME:
355        if((RetCode64=*(__int64*)&SPtr1->CreationTime - *(__int64*)&SPtr2->CreationTime) == 0)
356          break;
357        return -ListSortOrder*(RetCode64<0?-1:1);
358
359      case BY_ATIME:
360        if((RetCode64=*(__int64*)&SPtr1->AccessTime - *(__int64*)&SPtr2->AccessTime) == 0)
361          break;
362        return -ListSortOrder*(RetCode64<0?-1:1);
363
364      case BY_SIZE:
365        return((SPtr1->UnpSize > SPtr2->UnpSize) ? -ListSortOrder : ListSortOrder);
366
367      case BY_DIZ:
368        if (SPtr1->DizText==NULL)
369          if (SPtr2->DizText==NULL)
370            break;
371          else
372            return(ListSortOrder);
373        if (SPtr2->DizText==NULL)
374          return(-ListSortOrder);
375        RetCode=ListSortOrder*StrCmpI(SPtr1->DizText,SPtr2->DizText);
376        if(RetCode)
377          return RetCode;
378        break;
379
380      case BY_OWNER:
381        RetCode=ListSortOrder*StrCmpI(SPtr1->strOwner,SPtr2->strOwner);
382        if(RetCode)
383          return RetCode;
384        break;
385
386      case BY_COMPRESSEDSIZE:
387        return((SPtr1->PackSize > SPtr2->PackSize) ? -ListSortOrder : ListSortOrder);
388
389      case BY_NUMLINKS:
390        if (SPtr1->NumberOfLinks==SPtr2->NumberOfLinks)
391          break;
392        return((SPtr1->NumberOfLinks > SPtr2->NumberOfLinks) ? -ListSortOrder : ListSortOrder);
393    }
394  }
395
396  int NameCmp;
397
398  if(!ListNumericSort)
399    NameCmp=ListCaseSensitive?StrCmp(Name1,Name2):StrCmpI(Name1,Name2);
400  else
401    NameCmp=ListCaseSensitive?NumStrCmp(Name1,Name2):NumStrCmpI(Name1,Name2);
402  NameCmp*=ListSortOrder;
403  if (NameCmp==0)
404    NameCmp=SPtr1->Position>SPtr2->Position ? ListSortOrder:-ListSortOrder;
405
406  return(NameCmp);
407}
408
409
410int _cdecl SortSearchList(const void *el1,const void *el2)
411{
412  struct FileListItem **SPtr1,**SPtr2;
413  SPtr1=(struct FileListItem **)el1;
414  SPtr2=(struct FileListItem **)el2;
415
416  return StrCmp(SPtr1[0]->strName,SPtr2[0]->strName);
417//  return NumStrcmp(SPtr1->Name,SPtr2->Name);
418}
419#if defined(__BORLANDC__)
420#pragma intrinsic -strcmp
421#endif
422
423void FileList::SetFocus()
424{
425  Panel::SetFocus();
426  /* $ 07.04.2002 KM
427    ! Рисуем заголовок консоли фара только тогда, когда
428      не идёт процесс перерисовки всех фреймов. В данном
429      случае над панелями висит диалог и незачем выводить
430      панельный заголовок.
431  */
432  if (!IsRedrawFramesInProcess)
433    SetTitle();
434}
435
436int FileList::SendKeyToPlugin(DWORD Key,BOOL Pred)
437{
438  _ALGO(CleverSysLog clv(L"FileList::SendKeyToPlugin()"));
439  _ALGO(SysLog(L"Key=%u (0x%08X) Pred=%d",Key,Key,Pred));
440  if (PanelMode==PLUGIN_PANEL &&
441      (CtrlObject->Macro.IsRecording() == MACROMODE_RECORDING_COMMON || CtrlObject->Macro.IsExecuting() == MACROMODE_EXECUTING_COMMON || CtrlObject->Macro.GetCurRecord(NULL,NULL) == MACROMODE_NOMACRO)
442     )
443  {
444    int VirtKey,ControlState;
445    if (TranslateKeyToVK(Key,VirtKey,ControlState))
446    {
447      _ALGO(SysLog(L"call Plugins.ProcessKey() {"));
448      int ProcessCode=CtrlObject->Plugins.ProcessKey(hPlugin,VirtKey|(Pred?PKF_PREPROCESS:0),ControlState);
449      _ALGO(SysLog(L"} ProcessCode=%d",ProcessCode));
450      ProcessPluginCommand();
451      if (ProcessCode)
452        return(TRUE);
453    }
454  }
455  return FALSE;
456}
457
458__int64 FileList::VMProcess(int OpCode,void *vParam,__int64 iParam)
459{
460  switch(OpCode)
461  {
462    case MCODE_C_ROOTFOLDER:
463    {
464      if (PanelMode==PLUGIN_PANEL)
465      {
466        struct OpenPluginInfo Info;
467        CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
468        return (__int64)(*NullToEmpty(Info.CurDir)==0);
469      }
470      else
471      {
472        if(!IsLocalRootPath(strCurDir))
473        {
474          string strDriveRoot;
475          GetPathRoot(strCurDir, strDriveRoot);
476          return (__int64)(!StrCmpI(strCurDir, strDriveRoot));
477        }
478        return _i64(1);
479      }
480    }
481    case MCODE_C_EOF:
482      return (__int64)(CurFile == FileCount-1);
483    case MCODE_C_BOF:
484      return (__int64)(CurFile==0);
485    case MCODE_C_SELECTED:
486      return (__int64)(GetRealSelCount()>1);
487    case MCODE_V_ITEMCOUNT:
488      return (__int64)(FileCount);
489    case MCODE_V_CURPOS:
490      return (__int64)(CurFile+1);
491  }
492
493  return _i64(0);
494}
495
496int FileList::ProcessKey(int Key)
497{
498  struct FileListItem *CurPtr=NULL;
499  int N;
500  int CmdLength=CtrlObject->CmdLine->GetLength();
501
502  if (IsVisible())
503  {
504    if(!InternalProcessKey)
505      if ((!(Key==KEY_ENTER||Key==KEY_NUMENTER) && !(Key==KEY_SHIFTENTER||Key==KEY_SHIFTNUMENTER)) || CmdLength==0)
506        if(SendKeyToPlugin(Key))
507          return TRUE;
508  }
509  else
510  {
511    // Те клавиши, которые работают при погашенных панелях:
512    switch(Key)
513    {
514      case KEY_CTRLF:
515      case KEY_CTRLALTF:
516      case KEY_CTRLENTER:
517      case KEY_CTRLNUMENTER:
518      case KEY_CTRLBRACKET:
519      case KEY_CTRLBACKBRACKET:
520      case KEY_CTRLSHIFTBRACKET:
521      case KEY_CTRLSHIFTBACKBRACKET:
522      case KEY_CTRL|KEY_SEMICOLON:
523      case KEY_CTRL|KEY_ALT|KEY_SEMICOLON:
524      case KEY_CTRLALTBRACKET:
525      case KEY_CTRLALTBACKBRACKET:
526      case KEY_ALTSHIFTBRACKET:
527      case KEY_ALTSHIFTBACKBRACKET:
528        break;
529
530      case KEY_CTRLG:
531      case KEY_SHIFTF4:
532      case KEY_F7:
533      case KEY_CTRLH:
534      case KEY_ALTSHIFTF9:
535      case KEY_CTRLN:
536        break;
537
538      // эти спорные, хотя, если Ctrl-F работает, то и эти должны :-)
539/*
540      case KEY_CTRLINS:
541      case KEY_CTRLSHIFTINS:
542      case KEY_CTRLALTINS:
543      case KEY_ALTSHIFTINS:
544        break;
545*/
546      default:
547        return(FALSE);
548    }
549  }
550
551  if (!ShiftPressed && ShiftSelection!=-1)
552  {
553    if (SelectedFirst)
554    {
555      SortFileList(TRUE);
556      ShowFileList(TRUE);
557    }
558    ShiftSelection=-1;
559  }
560
561  if (!InternalProcessKey && (Key>=KEY_RCTRL0 && Key<=KEY_RCTRL9 ||
562      Key>=KEY_CTRLSHIFT0 && Key<=KEY_CTRLSHIFT9))
563  {
564
565    string strShortcutFolder;
566    int SizeFolderNameShortcut=GetShortcutFolderSize(Key);
567    //char *ShortcutFolder=NULL;
568    string strPluginModule,strPluginFile,strPluginData;
569    if (PanelMode==PLUGIN_PANEL)
570    {
571      PluginHandle *ph = (PluginHandle*)hPlugin;
572      strPluginModule = ph->pPlugin->GetModuleName();
573
574      struct OpenPluginInfo Info;
575      CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
576
577      strPluginFile = NullToEmpty(Info.HostFile);
578      strShortcutFolder = NullToEmpty(Info.CurDir);
579      strPluginData = NullToEmpty(Info.ShortcutData);
580    }
581    else
582    {
583      strPluginModule=strPluginFile=strPluginData=L"";
584      strShortcutFolder = strCurDir;
585    }
586    if (SaveFolderShortcut(Key,&strShortcutFolder,&strPluginModule,&strPluginFile,&strPluginData))
587    {
588      return(TRUE);
589    }
590
591      if (GetShortcutFolder(Key,&strShortcutFolder,&strPluginModule,&strPluginFile,&strPluginData))
592      {
593        if( !strPluginModule.IsEmpty() )
594        {
595          if( !strPluginFile.IsEmpty() )
596          {
597            switch(CheckShortcutFolder(&strPluginFile,0,TRUE))
598            {
599              case 0:
600  //              return FALSE;
601              case -1:
602                return TRUE;
603            }
604            /* Своеобразное решение BugZ#50 */
605            string strRealDir;
606
607            strRealDir = strPluginFile;
608
609            if(CutToSlash(strRealDir))
610            {
611              SetCurDir(strRealDir,TRUE);
612              GoToFile(PointToName(strPluginFile));
613              // удалим пред.значение.
614              if(PrevDataStackSize>0)
615              {
616                for(--PrevDataStackSize;PrevDataStackSize > 0;PrevDataStackSize--)
617                  DeleteListData(PrevDataStack[PrevDataStackSize]->PrevListData,PrevDataStack[PrevDataStackSize]->PrevFileCount);
618              }
619            }
620            /**/
621
622            OpenFilePlugin(strPluginFile,FALSE);
623            if ( !strShortcutFolder.IsEmpty() )
624              SetCurDir(strShortcutFolder,FALSE);
625            Show();
626          }
627          else
628          {
629            switch(CheckShortcutFolder(NULL,0,TRUE))
630            {
631              case 0:
632  //              return FALSE;
633              case -1:
634                return TRUE;
635            }
636            for (int I=0;I<CtrlObject->Plugins.PluginsCount;I++)
637            {
638              Plugin *pPlugin = CtrlObject->Plugins.PluginsData[I];
639
640              if ( StrCmpI(pPlugin->GetModuleName(),strPluginModule)==0)
641              {
642                if (pPlugin->HasOpenPlugin())
643                {
644                  HANDLE hNewPlugin=CtrlObject->Plugins.OpenPlugin(pPlugin,OPEN_SHORTCUT,(INT_PTR)(const wchar_t *)strPluginData);
645                  if (hNewPlugin!=INVALID_HANDLE_VALUE)
646                  {
647                    int CurFocus=GetFocus();
648                    Panel *NewPanel=CtrlObject->Cp()->ChangePanel(this,FILE_PANEL,TRUE,TRUE);
649                    NewPanel->SetPluginMode(hNewPlugin,L"",CurFocus || !CtrlObject->Cp()->GetAnotherPanel(NewPanel)->IsVisible());
650
651                    if (!strShortcutFolder.IsEmpty())
652                      CtrlObject->Plugins.SetDirectory(hNewPlugin,strShortcutFolder,0);
653                    NewPanel->Update(0);
654                    NewPanel->Show();
655                  }
656                }
657                break;
658              }
659            }
660            /*
661            if(I == CtrlObject->Plugins.PluginsCount)
662            {
663              char Target[NM*2];
664              xstrncpy(Target, PluginModule, sizeof(Target)-1);
665              TruncPathStr(Target, ScrX-16);
666              Message (MSG_WARNING | MSG_ERRORTYPE, 1, MSG(MError), Target, MSG (MNeedNearPath), MSG(MOk))
667            }
668            */
669          }
670          return(TRUE);
671        }
672        switch(CheckShortcutFolder(&strShortcutFolder,SizeFolderNameShortcut,FALSE))
673        {
674          case 0:
675  //          return FALSE;
676          case -1:
677            return TRUE;
678        }
679        SetCurDir(strShortcutFolder,TRUE);
680        Show();
681        return(TRUE);
682      }
683  }
684
685  /* $ 27.08.2002 SVS
686      [*] В панели с одной колонкой Shift-Left/Right аналогично нажатию
687          Shift-PgUp/PgDn.
688  */
689  if(Columns==1 && CmdLength==0)
690  {
691    if(Key == KEY_SHIFTLEFT || Key == KEY_SHIFTNUMPAD4)
692      Key=KEY_SHIFTPGUP;
693    else if(Key == KEY_SHIFTRIGHT || Key == KEY_SHIFTNUMPAD6)
694      Key=KEY_SHIFTPGDN;
695  }
696
697  switch(Key)
698  {
699    case KEY_F1:
700    {
701      _ALGO(CleverSysLog clv(L"F1"));
702      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
703      if (PanelMode==PLUGIN_PANEL && PluginPanelHelp(hPlugin))
704        return(TRUE);
705      return(FALSE);
706    }
707
708    case KEY_ALTSHIFTF9:
709    {
710      PluginHandle *ph = (PluginHandle*)hPlugin;
711
712      if (PanelMode==PLUGIN_PANEL)
713        CtrlObject->Plugins.ConfigureCurrent(ph->pPlugin, 0);
714      else
715        CtrlObject->Plugins.Configure();
716      return TRUE;
717    }
718
719    case KEY_SHIFTSUBTRACT:
720    {
721      SaveSelection();
722      ClearSelection();
723      Redraw();
724      return(TRUE);
725    }
726
727    case KEY_SHIFTADD:
728    {
729      SaveSelection();
730      {
731        struct FileListItem *CurPtr;
732        for (int I=0; I < FileCount; I++)
733        {
734          CurPtr = ListData[I];
735          if ((CurPtr->FileAttr & FA_DIREC)==0 || Opt.SelectFolders)
736            Select(CurPtr,1);
737        }
738      }
739      if (SelectedFirst)
740        SortFileList(TRUE);
741      Redraw();
742      return(TRUE);
743    }
744
745    case KEY_ADD:
746      SelectFiles(SELECT_ADD);
747      return(TRUE);
748
749    case KEY_SUBTRACT:
750      SelectFiles(SELECT_REMOVE);
751      return(TRUE);
752
753    case KEY_CTRLADD:
754      SelectFiles(SELECT_ADDEXT);
755      return(TRUE);
756
757    case KEY_CTRLSUBTRACT:
758      SelectFiles(SELECT_REMOVEEXT);
759      return(TRUE);
760
761    case KEY_ALTADD:
762      SelectFiles(SELECT_ADDNAME);
763      return(TRUE);
764
765    case KEY_ALTSUBTRACT:
766      SelectFiles(SELECT_REMOVENAME);
767      return(TRUE);
768
769    case KEY_MULTIPLY:
770      SelectFiles(SELECT_INVERT);
771      return(TRUE);
772
773    case KEY_CTRLMULTIPLY:
774      SelectFiles(SELECT_INVERTALL);
775      return(TRUE);
776
777    case KEY_ALTLEFT:     // Прокрутка длинных имен и описаний
778    case KEY_ALTHOME:     // Прокрутка длинных имен и описаний - в начало
779      LeftPos=(Key == KEY_ALTHOME)?-0x7fff:LeftPos-1;
780      Redraw();
781      return(TRUE);
782
783    case KEY_ALTRIGHT:    // Прокрутка длинных имен и описаний
784    case KEY_ALTEND:     // Прокрутка длинных имен и описаний - в конец
785      LeftPos=(Key == KEY_ALTEND)?0x7fff:LeftPos+1;
786      Redraw();
787      return(TRUE);
788
789    case KEY_CTRLINS:      case KEY_CTRLNUMPAD0:
790      if (CmdLength>0)
791        return(FALSE);
792    case KEY_CTRLSHIFTINS: case KEY_CTRLSHIFTNUMPAD0:  // копировать имена
793    case KEY_CTRLALTINS:   case KEY_CTRLALTNUMPAD0:    // копировать UNC-имена
794    case KEY_ALTSHIFTINS:                              // копировать полные имена
795
796      //if (FileCount>0 && SetCurPath()) // ?????
797      SetCurPath ();
798
799      CopyNames(Key == KEY_CTRLALTINS || Key == KEY_ALTSHIFTINS || Key == KEY_CTRLALTNUMPAD0,
800                (Key&(KEY_CTRL|KEY_ALT))==(KEY_CTRL|KEY_ALT));
801      return(TRUE);
802
803    /* $ 14.02.2001 VVM
804      + Ctrl: вставляет имя файла с пассивной панели.
805      + CtrlAlt: вставляет UNC-имя файла с пассивной панели */
806    case KEY_CTRL|KEY_SEMICOLON:
807    case KEY_CTRL|KEY_ALT|KEY_SEMICOLON:
808    {
809      int NewKey = KEY_CTRLF;
810      if (Key & KEY_ALT)
811        NewKey|=KEY_ALT;
812
813      Panel *SrcPanel = CtrlObject->Cp()->GetAnotherPanel(CtrlObject->Cp()->ActivePanel);
814      int OldState = SrcPanel->IsVisible();
815      SrcPanel->SetVisible(1);
816      SrcPanel->ProcessKey(NewKey);
817      SrcPanel->SetVisible(OldState);
818
819      SetCurPath();
820      return(TRUE);
821    }
822
823    case KEY_CTRLNUMENTER:
824    case KEY_CTRLSHIFTNUMENTER:
825    case KEY_CTRLENTER:
826    case KEY_CTRLSHIFTENTER:
827    case KEY_CTRLJ:
828    case KEY_CTRLF:
829    case KEY_CTRLALTF:  // 29.01.2001 VVM + По CTRL+ALT+F в командную строку сбрасывается UNC-имя текущего файла.
830    {
831      if (FileCount>0 && SetCurPath())
832      {
833        string strFileName;
834        if(Key==KEY_CTRLSHIFTENTER || Key==KEY_CTRLSHIFTNUMENTER)
835          _MakePath1(Key,strFileName, L" ");
836        else
837        {
838          int CurrentPath=FALSE;
839          CurPtr=ListData[CurFile];
840
841          if ( ShowShortNames && !CurPtr->strShortName.IsEmpty() )
842            strFileName = CurPtr->strShortName;
843          else
844            strFileName = CurPtr->strName;
845
846          if (TestParentFolderName(strFileName))
847          {
848            if (PanelMode==PLUGIN_PANEL)
849              strFileName=L"";
850            else
851              strFileName.SetLength(1); // "."
852
853            if(Key!=KEY_CTRLALTF)
854              Key=KEY_CTRLF;
855            CurrentPath=TRUE;
856          }
857          if (Key==KEY_CTRLF || Key==KEY_CTRLALTF)
858          {
859            struct OpenPluginInfo Info={0};
860            if (PanelMode==PLUGIN_PANEL)
861            {
862              CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
863            }
864            if (PanelMode!=PLUGIN_PANEL || (Info.Flags & OPIF_REALNAMES))
865              CreateFullPathName(CurPtr->strName,CurPtr->strShortName,CurPtr->FileAttr, strFileName, Key==KEY_CTRLALTF);
866            else
867            {
868              string strFullName = NullToEmpty(Info.CurDir);
869
870              if (Opt.PanelCtrlFRule && ViewSettings.FolderUpperCase)
871                strFullName.Upper ();
872
873              if ( !strFullName.IsEmpty() )
874                AddEndSlash(strFullName,0);
875
876              if(Opt.PanelCtrlFRule)
877              {
878                /* $ 13.10.2000 tran
879                  по Ctrl-f имя должно отвечать условиям на панели */
880                if ( ViewSettings.FileLowerCase && !(CurPtr->FileAttr & FA_DIREC))
881                  strFileName.Lower ();
882                if (ViewSettings.FileUpperToLowerCase)
883                  if (!(CurPtr->FileAttr & FA_DIREC) && !IsCaseMixed(strFileName))
884                     strFileName.Lower();
885              }
886              strFullName += strFileName;
887              strFileName = strFullName;
888            }
889          }
890          if (CurrentPath)
891            AddEndSlash(strFileName);
892
893          // добавим первый префикс!
894          if(PanelMode==PLUGIN_PANEL && Opt.SubstPluginPrefix && !(Key == KEY_CTRLENTER || Key == KEY_CTRLNUMENTER || Key == KEY_CTRLJ))
895          {
896            string strPrefix;
897            /* $ 19.11.2001 IS оптимизация по скорости :) */
898            if(*AddPluginPrefix((FileList *)CtrlObject->Cp()->ActivePanel,strPrefix))
899            {
900                strPrefix += strFileName;
901                strFileName = strPrefix;
902            }
903          }
904          if(Opt.QuotedName&QUOTEDNAME_INSERT)
905            QuoteSpace(strFileName);
906          strFileName += L" ";
907        }
908        CtrlObject->CmdLine->InsertString(strFileName);
909      }
910      return(TRUE);
911    }
912
913    case KEY_CTRLALTBRACKET:       // Вставить сетевое (UNC) путь из левой панели
914    case KEY_CTRLALTBACKBRACKET:   // Вставить сетевое (UNC) путь из правой панели
915    case KEY_ALTSHIFTBRACKET:      // Вставить сетевое (UNC) путь из активной панели
916    case KEY_ALTSHIFTBACKBRACKET:  // Вставить сетевое (UNC) путь из пассивной панели
917    case KEY_CTRLBRACKET:          // Вставить путь из левой панели
918    case KEY_CTRLBACKBRACKET:      // Вставить путь из правой панели
919    case KEY_CTRLSHIFTBRACKET:     // Вставить путь из активной панели
920    case KEY_CTRLSHIFTBACKBRACKET: // Вставить путь из пассивной панели
921    {
922      string strPanelDir;
923      if(_MakePath1(Key,strPanelDir, L""))
924        CtrlObject->CmdLine->InsertString(strPanelDir);
925      return(TRUE);
926    }
927
928    case KEY_CTRLA:
929    {
930      _ALGO(CleverSysLog clv(L"Ctrl-A"));
931      if (FileCount>0 && SetCurPath())
932      {
933        ShellSetFileAttributes(this);
934        Show();
935      }
936      return(TRUE);
937    }
938
939    case KEY_CTRLG:
940    {
941      _ALGO(CleverSysLog clv(L"Ctrl-G"));
942      if (PanelMode!=PLUGIN_PANEL ||
943          CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FAROTHER))
944        if (FileCount>0 && ApplyCommand())
945        {
946          Update(UPDATE_KEEP_SELECTION);
947          Redraw();
948          Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
949          AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
950          AnotherPanel->Redraw();
951        }
952      return(TRUE);
953    }
954
955    case KEY_CTRLZ:
956      if (FileCount>0 && PanelMode==NORMAL_PANEL && SetCurPath())
957        DescribeFiles();
958      return(TRUE);
959
960    case KEY_CTRLH:
961    {
962      Opt.ShowHidden=!Opt.ShowHidden;
963      Update(UPDATE_KEEP_SELECTION);
964      Redraw();
965      Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
966      AnotherPanel->Update(UPDATE_KEEP_SELECTION);//|UPDATE_SECONDARY);
967      AnotherPanel->Redraw();
968      return(TRUE);
969    }
970
971    case KEY_CTRLM:
972    {
973      RestoreSelection();
974      return(TRUE);
975    }
976
977    case KEY_CTRLR:
978    {
979      Update(UPDATE_KEEP_SELECTION);
980      Redraw();
981      {
982        Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
983        if (AnotherPanel->GetType()!=FILE_PANEL)
984        {
985          AnotherPanel->SetCurDir(strCurDir,FALSE);
986          AnotherPanel->Redraw();
987        }
988      }
989      break;
990    }
991
992    case KEY_CTRLN:
993    {
994      ShowShortNames=!ShowShortNames;
995      Redraw();
996      return(TRUE);
997    }
998
999    case KEY_NUMENTER:
1000    case KEY_SHIFTNUMENTER:
1001    case KEY_ENTER:
1002    case KEY_SHIFTENTER:
1003    {
1004      _ALGO(CleverSysLog clv(L"Enter/Shift-Enter"));
1005      _ALGO(SysLog(L"%s, FileCount=%d Key=%s",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount,_FARKEY_ToName(Key)));
1006      if (CmdLength>0 || FileCount==0)
1007      {
1008        // Для средней клавиши мыши и не пустой строке... исполним эту строку
1009        if(MButtonPressed && CmdLength>0)
1010        {
1011          CtrlObject->CmdLine->ProcessKey(Key);
1012          return(TRUE);
1013        }
1014        break;
1015      }
1016      ProcessEnter(1,Key==KEY_SHIFTENTER||Key==KEY_SHIFTNUMENTER);
1017      return(TRUE);
1018    }
1019
1020    case KEY_CTRLBACKSLASH:
1021    {
1022      _ALGO(CleverSysLog clv(L"Ctrl-\\"));
1023      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1024      BOOL NeedChangeDir=TRUE;
1025      if (PanelMode==PLUGIN_PANEL)// && *PluginsStack[PluginsStackSize-1].HostFile)
1026      {
1027        int CheckFullScreen=IsFullScreen();
1028        struct OpenPluginInfo Info;
1029        CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
1030        if (!Info.CurDir || *Info.CurDir == 0)
1031        {
1032          ChangeDir(L"..");
1033          NeedChangeDir=FALSE;
1034          if(CheckFullScreen)
1035            CtrlObject->Cp()->GetAnotherPanel(this)->Show();
1036        }
1037      }
1038      if(NeedChangeDir)
1039        ChangeDir(L"\\");
1040      Show();
1041      return(TRUE);
1042    }
1043
1044    case KEY_SHIFTF1:
1045    {
1046      _ALGO(CleverSysLog clv(L"Shift-F1"));
1047      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1048      if (FileCount>0 && PanelMode!=PLUGIN_PANEL && SetCurPath())
1049        PluginPutFilesToNew();
1050      return(TRUE);
1051    }
1052
1053    case KEY_SHIFTF2:
1054    {
1055      _ALGO(CleverSysLog clv(L"Shift-F2"));
1056      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1057      if (FileCount>0 && SetCurPath())
1058      {
1059        if (PanelMode==PLUGIN_PANEL)
1060        {
1061          struct OpenPluginInfo Info;
1062          CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
1063          if (Info.HostFile!=NULL && *Info.HostFile!=0)
1064            ProcessKey(KEY_F5);
1065          else
1066            if ( (Info.Flags & OPIF_REALNAMES) == OPIF_REALNAMES )
1067              PluginHostGetFiles();
1068
1069          return(TRUE);
1070        }
1071        PluginHostGetFiles();
1072      }
1073      return(TRUE);
1074    }
1075
1076    case KEY_SHIFTF3:
1077    {
1078      _ALGO(CleverSysLog clv(L"Shift-F3"));
1079      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1080      ProcessHostFile();
1081      return(TRUE);
1082    }
1083
1084    case KEY_F3:
1085    case KEY_NUMPAD5:      case KEY_SHIFTNUMPAD5:
1086    case KEY_ALTF3:
1087    case KEY_CTRLSHIFTF3:
1088    case KEY_F4:
1089    case KEY_ALTF4:
1090    case KEY_SHIFTF4:
1091    case KEY_CTRLSHIFTF4:
1092    {
1093      _ALGO(CleverSysLog clv(L"Edit/View"));
1094      _ALGO(SysLog(L"%s, FileCount=%d Key=%s",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount,_FARKEY_ToName(Key)));
1095
1096      struct OpenPluginInfo Info;
1097      BOOL RefreshedPanel=TRUE;
1098
1099      if(PanelMode==PLUGIN_PANEL)
1100        CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
1101      else
1102        memset(&Info,0,sizeof(Info));
1103
1104
1105      if (Key == KEY_NUMPAD5 || Key == KEY_SHIFTNUMPAD5)
1106        Key=KEY_F3;
1107      if ((Key==KEY_SHIFTF4 || FileCount>0) && SetCurPath())
1108      {
1109        int Edit=(Key==KEY_F4 || Key==KEY_ALTF4 || Key==KEY_SHIFTF4 || Key==KEY_CTRLSHIFTF4);
1110        BOOL Modaling=FALSE; ///
1111        int UploadFile=TRUE;
1112        string strPluginData;
1113        string strFileName;
1114        string strShortFileName;
1115
1116        int PluginMode=PanelMode==PLUGIN_PANEL &&
1117            !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILE);
1118
1119        if (PluginMode)
1120        {
1121          if(Info.Flags & OPIF_REALNAMES)
1122            PluginMode=FALSE;
1123          else
1124            strPluginData.Format (L"<%s:%s>",NullToEmpty(Info.HostFile),NullToEmpty(Info.CurDir));
1125        }
1126
1127        if(!PluginMode)
1128          strPluginData=L"";
1129
1130        int codepage = CP_AUTODETECT;
1131
1132        if (Key==KEY_SHIFTF4)
1133        {
1134          static string strLastFileName=L"";
1135
1136          do{
1137
1138            if ( !dlgOpenEditor (strLastFileName, codepage) )
1139                return FALSE;
1140
1141            /*if (!GetString(UMSG(MEditTitle),
1142                           UMSG(MFileToEdit),
1143                           L"NewEdit",
1144                           strLastFileName,
1145                           strLastFileName,
1146                           512, //BUGBUG
1147                           L"Editor",
1148                           FIB_BUTTONS|FIB_EXPANDENV|FIB_EDITPATH|FIB_ENABLEEMPTY))
1149              return(FALSE);*/
1150
1151            if( !strLastFileName.IsEmpty() )
1152            {
1153              strFileName = strLastFileName;
1154
1155              RemoveTrailingSpaces(strFileName);
1156              Unquote(strFileName);
1157              ConvertNameToShort(strFileName,strShortFileName);
1158
1159              if (PathMayBeAbsolute(strFileName))
1160              {
1161                PluginMode=FALSE;
1162              }
1163
1164              {
1165                // проверим путь к файлу
1166                wchar_t *lpwszStart=strFileName.GetBuffer ();
1167
1168                wchar_t *Ptr = wcsrchr(lpwszStart, L'\\');
1169                if(Ptr && Ptr != lpwszStart)
1170                {
1171                  wchar_t wChr=Ptr[1];
1172                  Ptr[1]=0;
1173                  DWORD CheckFAttr=GetFileAttributesW(lpwszStart);
1174                  if(CheckFAttr == (DWORD)-1)
1175                  {
1176                    SetMessageHelp(L"WarnEditorPath");
1177                    if (Message(MSG_WARNING,2,UMSG(MWarning),
1178                                UMSG(MEditNewPath1),
1179                                UMSG(MEditNewPath2),
1180                                UMSG(MEditNewPath3),
1181                                UMSG(MHYes),UMSG(MHNo))!=0)
1182
1183                      return(FALSE);
1184                  }
1185                  Ptr[1]=wChr;
1186                }
1187
1188                strFileName.ReleaseBuffer ();
1189              }
1190            }
1191            else if(PluginMode) // пустое имя файла в панели плагина не разрешается!
1192            {
1193              SetMessageHelp(L"WarnEditorPluginName");
1194              if (Message(MSG_WARNING,2,UMSG(MWarning),
1195                          UMSG(MEditNewPlugin1),
1196                          UMSG(MEditNewPath3),UMSG(MCancel))!=0)
1197
1198                return(FALSE);
1199            }
1200            else
1201              strFileName = UMSG(MNewFileName);
1202
1203          } while(strFileName.IsEmpty());
1204
1205        }
1206        else
1207        {
1208          CurPtr=ListData[CurFile];
1209
1210          if (CurPtr->FileAttr & FA_DIREC)
1211          {
1212            if (Edit)
1213              return ProcessKey(KEY_CTRLA);
1214
1215            CountDirSize(Info.Flags);
1216            return(TRUE);
1217          }
1218
1219          strFileName = CurPtr->strName;
1220
1221          if ( !CurPtr->strShortName.IsEmpty () )
1222            strShortFileName = CurPtr->strShortName;
1223          else
1224            strShortFileName = CurPtr->strName;
1225        }
1226
1227        string strTempDir, strTempName;
1228
1229        int UploadFailed=FALSE, NewFile=FALSE;
1230
1231        if (PluginMode)
1232        {
1233          if(!FarMkTempEx(strTempDir))
1234            return(TRUE);
1235
1236          CreateDirectoryW(strTempDir,NULL);
1237          strTempName.Format (L"%s\\%s",(const wchar_t*)strTempDir,(const wchar_t*)PointToName(strFileName));
1238          if (Key==KEY_SHIFTF4)
1239          {
1240            int Pos=FindFile(strFileName);
1241            if (Pos!=-1)
1242              CurPtr=ListData[Pos];
1243            else
1244            {
1245              NewFile=TRUE;
1246              strFileName = strTempName;
1247            }
1248          }
1249
1250          if (!NewFile)
1251          {
1252            struct PluginPanelItem PanelItem;
1253            FileListToPluginItem(CurPtr,&PanelItem);
1254            if (!CtrlObject->Plugins.GetFile(hPlugin,&PanelItem,strTempDir,strFileName,OPM_SILENT|(Edit ? OPM_EDIT:OPM_VIEW)))
1255            {
1256              apiRemoveDirectory(strTempDir);
1257              return(TRUE);
1258            }
1259          }
1260
1261          ConvertNameToShort(strFileName,strShortFileName);
1262        }
1263
1264        /* $ 08.04.2002 IS
1265           Флаг, говорящий о том, что нужно удалить файл, который открывали во
1266           вьюере. Если файл открыли во внутреннем вьюере, то DeleteViewedFile
1267           должно быт равно false, т.к. внутренний вьюер сам все удалит.
1268        */
1269        bool DeleteViewedFile=PluginMode && !Edit;
1270        if ( !strFileName.IsEmpty () )
1271          if (Edit)
1272          {
1273            int EnableExternal=((Key==KEY_F4 || Key==KEY_SHIFTF4) && Opt.EdOpt.UseExternalEditor ||
1274                Key==KEY_ALTF4 && !Opt.EdOpt.UseExternalEditor) && !Opt.strExternalEditor.IsEmpty();
1275            /* $ 02.08.2001 IS обработаем ассоциации для alt-f4 */
1276            BOOL Processed=FALSE;
1277            if(Key==KEY_ALTF4 &&
1278               ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_ALTEDIT,
1279               PluginMode))
1280               Processed=TRUE;
1281            else if(Key==KEY_F4 &&
1282               ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_EDIT,
1283               PluginMode))
1284               Processed=TRUE;
1285
1286            if (!Processed || Key==KEY_CTRLSHIFTF4)
1287            {
1288              if (EnableExternal)
1289                ProcessExternal(Opt.strExternalEditor,strFileName,strShortFileName,PluginMode);
1290              else if (PluginMode)
1291              {
1292                RefreshedPanel=FrameManager->GetCurrentFrame()->GetType()==MODALTYPE_EDITOR?FALSE:TRUE;
1293
1294                FileEditor ShellEditor (strFileName,codepage,(Key==KEY_SHIFTF4?FFILEEDIT_CANNEWFILE:0)|FFILEEDIT_DISABLEHISTORY,-1,-1,strPluginData);
1295                ShellEditor.SetDynamicallyBorn(false);
1296                FrameManager->EnterModalEV();
1297                FrameManager->ExecuteModal();//OT
1298                FrameManager->ExitModalEV();
1299                /* $ 24.11.2001 IS
1300                     Если мы создали новый файл, то не важно, изменялся он
1301                     или нет, все равно добавим его на панель плагина.
1302                */
1303                UploadFile=ShellEditor.IsFileChanged() || NewFile;
1304                Modaling=TRUE;///
1305              }
1306              else
1307              {
1308                NamesList EditList;
1309                if (!PluginMode)
1310                {
1311                  for (int I=0;I<FileCount;I++)
1312                    if ((ListData[I]->FileAttr & FA_DIREC)==0)
1313                      EditList.AddName(ListData[I]->strName, ListData[I]->strShortName);
1314
1315                  EditList.SetCurDir(strCurDir);
1316                  EditList.SetCurName(strFileName);
1317                }
1318
1319                FileEditor *ShellEditor=new FileEditor(strFileName,codepage,(Key==KEY_SHIFTF4?FFILEEDIT_CANNEWFILE:0)|FFILEEDIT_ENABLEF6);
1320                /* TODO: BUG BUG BUG!!! проблема в том, что если...
1321                если была ошибка - то ShellEditor в список манагера не попадает, получается утечка памяти
1322                */
1323#if 0
1324
1325                if(ShellEditor->GetExitCode() == XC_OPEN_ERROR) // и прочие коды с ошибками!!!
1326                  delete ShellEditor;
1327                else
1328                {
1329                  ShellEditor->SetNamesList (&EditList);
1330                  FrameManager->ExecuteModal();//OT
1331                }
1332#else
1333                ShellEditor->SetNamesList (&EditList);
1334                FrameManager->ExecuteModal();//OT
1335#endif
1336              }
1337            }
1338
1339            if (PluginMode && UploadFile)
1340            {
1341              struct PluginPanelItem PanelItem;
1342              string strSaveDir;
1343
1344              FarGetCurDir(strSaveDir);
1345
1346              if (GetFileAttributesW(strTempName)==0xffffffff)
1347              {
1348                string strFindName;
1349                string strPath;
1350
1351                strPath = strTempName;
1352
1353                CutToSlash(strPath, false);
1354
1355                strFindName = strPath+L"*";
1356
1357                HANDLE FindHandle;
1358                FAR_FIND_DATA_EX FindData;
1359
1360                bool Done=((FindHandle=apiFindFirstFile(strFindName,&FindData))==INVALID_HANDLE_VALUE);
1361                while (!Done)
1362                {
1363                  if ((FindData.dwFileAttributes & FA_DIREC)==0)
1364                  {
1365                    strTempName = strPath+FindData.strFileName;
1366                    break;
1367                  }
1368                  Done=!apiFindNextFile(FindHandle,&FindData);
1369                }
1370                FindClose(FindHandle);
1371              }
1372
1373              if (FileNameToPluginItem(strTempName,&PanelItem))
1374              {
1375                int PutCode=CtrlObject->Plugins.PutFiles(hPlugin,&PanelItem,1,FALSE,OPM_EDIT);
1376                if (PutCode==1 || PutCode==2)
1377                  SetPluginModified();
1378                if (PutCode==0)
1379                  UploadFailed=TRUE;
1380              }
1381
1382              FarChDir(strSaveDir);
1383            }
1384          }
1385          else
1386          {
1387            int EnableExternal=(Key==KEY_F3 && Opt.ViOpt.UseExternalViewer ||
1388                                Key==KEY_ALTF3 && !Opt.ViOpt.UseExternalViewer) &&
1389                                !Opt.strExternalViewer.IsEmpty();
1390            /* $ 02.08.2001 IS обработаем ассоциации для alt-f3 */
1391            BOOL Processed=FALSE;
1392            if(Key==KEY_ALTF3 &&
1393               ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_ALTVIEW,PluginMode))
1394               Processed=TRUE;
1395            else if(Key==KEY_F3 &&
1396               ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_VIEW,PluginMode))
1397               Processed=TRUE;
1398
1399            if (!Processed || Key==KEY_CTRLSHIFTF3)
1400              if (EnableExternal)
1401                ProcessExternal(Opt.strExternalViewer,strFileName,strShortFileName,PluginMode);
1402              else
1403              {
1404                NamesList ViewList;
1405                if (!PluginMode)
1406                {
1407                  for (int I=0;I<FileCount;I++)
1408                    if ((ListData[I]->FileAttr & FA_DIREC)==0)
1409                      ViewList.AddName(ListData[I]->strName,ListData[I]->strShortName);
1410
1411                  ViewList.SetCurDir(strCurDir);
1412                  ViewList.SetCurName(strFileName);
1413                }
1414                FileViewer *ShellViewer=new FileViewer(strFileName, TRUE,PluginMode,PluginMode,-1,strPluginData,&ViewList);
1415
1416                /* $ 08.04.2002 IS
1417                   Сбросим DeleteViewedFile, т.к. внутренний вьюер сам все удалит
1418                */
1419                if (PluginMode)
1420                {
1421                  ShellViewer->SetTempViewName(strFileName);
1422                  DeleteViewedFile=false;
1423                }
1424                Modaling=FALSE;
1425              }
1426          }
1427        /* $ 08.04.2002 IS
1428             для файла, который открывался во внутреннем вьюере, ничего не
1429             предпринимаем, т.к. вьюер об этом позаботится сам
1430        */
1431        if (PluginMode)
1432        {
1433          if (UploadFailed)
1434            Message(MSG_WARNING,1,UMSG(MError),UMSG(MCannotSaveFile),
1435                    UMSG(MTextSavedToTemp),strFileName,UMSG(MOk));
1436          else if(Edit || DeleteViewedFile)
1437            // удаляем файл только для случая окрытия его в редакторе или во
1438            // внешнем вьюере, т.к. внутренний вьюер удаляет файл сам
1439            DeleteFileWithFolder(strFileName);
1440        }
1441        if (Modaling && (Edit || IsColumnDisplayed(ADATE_COLUMN)) && RefreshedPanel)
1442        {
1443          //if (!PluginMode || UploadFile)
1444          {
1445            Update(UPDATE_KEEP_SELECTION);
1446            Redraw();
1447            Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
1448            if (AnotherPanel->GetMode()==NORMAL_PANEL)
1449            {
1450              AnotherPanel->Update(UPDATE_KEEP_SELECTION);
1451              AnotherPanel->Redraw();
1452            }
1453          }
1454//          else
1455//            SetTitle();
1456        }
1457        else
1458          if (PanelMode==NORMAL_PANEL)
1459            AccessTimeUpdateRequired=TRUE;
1460      }
1461      /* $ 15.07.2000 tran
1462         а тут мы вызываем перерисовку панелей
1463         потому что этот viewer, editor могут нам неверно восстановить
1464         */
1465//      CtrlObject->Cp()->Redraw();
1466      return(TRUE);
1467    }
1468
1469    case KEY_F5:
1470    case KEY_F6:
1471    case KEY_ALTF6:
1472    case KEY_DRAGCOPY:
1473    case KEY_DRAGMOVE:
1474    {
1475      _ALGO(CleverSysLog clv(L"F5/F6/Alt-F6/DragCopy/DragMove"));
1476      _ALGO(SysLog(L"%s, FileCount=%d Key=%s",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount,_FARKEY_ToName(Key)));
1477      if (FileCount>0 && SetCurPath())
1478        ProcessCopyKeys(Key);
1479      return(TRUE);
1480    }
1481
1482    case KEY_ALTF5:  // Печать текущего/выбранных файла/ов
1483    {
1484      _ALGO(CleverSysLog clv(L"Alt-F5"));
1485      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1486      // $ 11.03.2001 VVM - Печать через pman только из файловых панелей.
1487      if ((PanelMode!=PLUGIN_PANEL) && (Opt.UsePrintManager && CtrlObject->Plugins.FindPlugin(SYSID_PRINTMANAGER)))
1488         CtrlObject->Plugins.CallPlugin(SYSID_PRINTMANAGER,OPEN_FILEPANEL,0); // printman
1489      else
1490        if (FileCount>0 && SetCurPath())
1491          PrintFiles(this);
1492      return(TRUE);
1493    }
1494
1495    case KEY_SHIFTF5:
1496    case KEY_SHIFTF6:
1497    {
1498      _ALGO(CleverSysLog clv(L"Shift-F5/Shift-F6"));
1499      _ALGO(SysLog(L"%s, FileCount=%d Key=%s",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount,_FARKEY_ToName(Key)));
1500      if (FileCount>0 && SetCurPath())
1501      {
1502        int OldFileCount=FileCount,OldCurFile=CurFile;
1503        int OldSelection=ListData[CurFile]->Selected;
1504        int ToPlugin=0;
1505        int RealName=PanelMode!=PLUGIN_PANEL;
1506        ReturnCurrentFile=TRUE;
1507
1508        if (PanelMode==PLUGIN_PANEL)
1509        {
1510          struct OpenPluginInfo Info;
1511          CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
1512          RealName=Info.Flags&OPIF_REALNAMES;
1513        }
1514
1515        if (RealName)
1516        {
1517          ShellCopy ShCopy(this,Key==KEY_SHIFTF6,FALSE,TRUE,TRUE,ToPlugin,NULL);
1518        }
1519        else
1520        {
1521          ProcessCopyKeys(Key==KEY_SHIFTF5 ? KEY_F5:KEY_F6);
1522        }
1523        ReturnCurrentFile=FALSE;
1524        if (Key!=KEY_SHIFTF5 && FileCount==OldFileCount &&
1525            CurFile==OldCurFile && OldSelection!=ListData[CurFile]->Selected)
1526        {
1527          Select(ListData[CurFile],OldSelection);
1528          Redraw();
1529        }
1530      }
1531      return(TRUE);
1532    }
1533
1534    case KEY_F7:
1535    {
1536      _ALGO(CleverSysLog clv(L"F7"));
1537      _ALGO(SysLog(L"%s, FileCount=%d",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount));
1538      if (SetCurPath())
1539      {
1540        if (PanelMode==PLUGIN_PANEL && !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARMAKEDIRECTORY))
1541        {
1542          string strDirName;
1543          int MakeCode=CtrlObject->Plugins.MakeDirectory(hPlugin,strDirName,0);
1544          if (!MakeCode)
1545            Message(MSG_DOWN|MSG_WARNING|MSG_ERRORTYPE,1,UMSG(MError),UMSG(MCannotCreateFolder),strDirName,UMSG(MOk));
1546          Update(UPDATE_KEEP_SELECTION);
1547          if (MakeCode==1)
1548            GoToFile(PointToName(strDirName));
1549          Redraw();
1550          Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
1551          /* $ 07.09.2001 VVM
1552            ! Обновить соседнюю панель с установкой на новый каталог */
1553//          AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
1554//          AnotherPanel->Redraw();
1555
1556          if (AnotherPanel->GetType()!=FILE_PANEL)
1557          {
1558            AnotherPanel->SetCurDir(strCurDir,FALSE);
1559            AnotherPanel->Redraw();
1560          }
1561        }
1562        else
1563          ShellMakeDir(this);
1564      }
1565      return(TRUE);
1566    }
1567
1568    case KEY_F8:
1569    case KEY_SHIFTDEL:
1570    case KEY_SHIFTF8:
1571    case KEY_SHIFTNUMDEL:
1572    case KEY_SHIFTDECIMAL:
1573    case KEY_ALTNUMDEL:
1574    case KEY_ALTDECIMAL:
1575    case KEY_ALTDEL:
1576    {
1577      _ALGO(CleverSysLog clv(L"F8/Shift-F8/Shift-Del/Alt-Del"));
1578      _ALGO(SysLog(L"%s, FileCount=%d, Key=%s",(PanelMode==PLUGIN_PANEL?"PluginPanel":"FilePanel"),FileCount,_FARKEY_ToName(Key)));
1579      if (FileCount>0 && SetCurPath())
1580      {
1581        if (Key==KEY_SHIFTF8)
1582          ReturnCurrentFile=TRUE;
1583        if (PanelMode==PLUGIN_PANEL &&
1584            !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARDELETEFILES))
1585          PluginDelete();
1586        else
1587        {
1588          int SaveOpt=Opt.DeleteToRecycleBin;
1589          if (Key==KEY_SHIFTDEL || Key==KEY_SHIFTNUMDEL || Key==KEY_SHIFTDECIMAL)
1590            Opt.DeleteToRecycleBin=0;
1591          ShellDelete(this,Key==KEY_ALTDEL||Key==KEY_ALTNUMDEL||Key==KEY_ALTDECIMAL);
1592          Opt.DeleteToRecycleBin=SaveOpt;
1593        }
1594        if (Key==KEY_SHIFTF8)
1595          ReturnCurrentFile=FALSE;
1596      }
1597      return(TRUE);
1598    }
1599
1600    // $ 26.07.2001 VVM  С альтом скролим всегда по 1
1601    case KEY_MSWHEEL_UP:
1602    case (KEY_MSWHEEL_UP | KEY_ALT):
1603      Scroll(Key & KEY_ALT?-1:-Opt.MsWheelDelta);
1604      return(TRUE);
1605
1606    case KEY_MSWHEEL_DOWN:
1607    case (KEY_MSWHEEL_DOWN | KEY_ALT):
1608      Scroll(Key & KEY_ALT?1:Opt.MsWheelDelta);
1609      return(TRUE);
1610
1611    case KEY_MSWHEEL_LEFT:
1612    case (KEY_MSWHEEL_LEFT | KEY_ALT):
1613    {
1614      int Roll = Key & KEY_ALT?1:Opt.MsHWheelDelta;
1615      for (int i=0; i<Roll; i++)
1616        ProcessKey(KEY_LEFT);
1617      return TRUE;
1618    }
1619
1620    case KEY_MSWHEEL_RIGHT:
1621    case (KEY_MSWHEEL_RIGHT | KEY_ALT):
1622    {
1623      int Roll = Key & KEY_ALT?1:Opt.MsHWheelDelta;
1624      for (int i=0; i<Roll; i++)
1625        ProcessKey(KEY_RIGHT);
1626      return TRUE;
1627    }
1628
1629    case KEY_HOME:         case KEY_NUMPAD7:
1630      Up(0x7fffff);
1631      return(TRUE);
1632
1633    case KEY_END:          case KEY_NUMPAD1:
1634      Down(0x7fffff);
1635      return(TRUE);
1636
1637    case KEY_UP:           case KEY_NUMPAD8:
1638      Up(1);
1639      return(TRUE);
1640
1641    case KEY_DOWN:         case KEY_NUMPAD2:
1642      Down(1);
1643      return(TRUE);
1644
1645    case KEY_PGUP:         case KEY_NUMPAD9:
1646      N=Columns*Height-1;
1647      CurTopFile-=N;
1648      Up(N);
1649      return(TRUE);
1650
1651    case KEY_PGDN:         case KEY_NUMPAD3:
1652      N=Columns*Height-1;
1653      CurTopFile+=N;
1654      Down(N);
1655      return(TRUE);
1656
1657    case KEY_LEFT:         case KEY_NUMPAD4:
1658      if ( (Columns==1 && Opt.ShellRightLeftArrowsRule == 1) || Columns>1 || CmdLength==0 )
1659      {
1660        if (CurTopFile>=Height && CurFile-CurTopFile<Height)
1661          CurTopFile-=Height;
1662        Up(Height);
1663        return(TRUE);
1664      }
1665      return(FALSE);
1666
1667    case KEY_RIGHT:        case KEY_NUMPAD6:
1668      if ( (Columns==1 && Opt.ShellRightLeftArrowsRule == 1) || Columns>1 || CmdLength==0 )
1669      {
1670        if (CurFile+Height<FileCount && CurFile-CurTopFile>=(Columns-1)*(Height))
1671          CurTopFile+=Height;
1672        Down(Height);
1673        return(TRUE);
1674      }
1675      return(FALSE);
1676    /* $ 25.04.2001 DJ
1677       оптимизация Shift-стрелок для Selected files first: делаем сортировку
1678       один раз
1679    */
1680    case KEY_SHIFTHOME:    case KEY_SHIFTNUMPAD7:
1681    {
1682      InternalProcessKey++;
1683      Lock ();
1684      while (CurFile>0)
1685        ProcessKey(KEY_SHIFTUP);
1686      ProcessKey(KEY_SHIFTUP);
1687      InternalProcessKey--;
1688      Unlock ();
1689      if (SelectedFirst)
1690        SortFileList(TRUE);
1691      ShowFileList(TRUE);
1692      return(TRUE);
1693    }
1694
1695    case KEY_SHIFTEND:     case KEY_SHIFTNUMPAD1:
1696    {
1697      InternalProcessKey++;
1698      Lock ();
1699      while (CurFile<FileCount-1)
1700        ProcessKey(KEY_SHIFTDOWN);
1701      ProcessKey(KEY_SHIFTDOWN);
1702      InternalProcessKey--;
1703      Unlock ();
1704      if (SelectedFirst)
1705        SortFileList(TRUE);
1706      ShowFileList(TRUE);
1707      return(TRUE);
1708    }
1709
1710    case KEY_SHIFTPGUP:    case KEY_SHIFTNUMPAD9:
1711    case KEY_SHIFTPGDN:    case KEY_SHIFTNUMPAD3:
1712    {
1713      N=Columns*Height-1;
1714      InternalProcessKey++;
1715      Lock ();
1716      while (N--)
1717        ProcessKey(Key==KEY_SHIFTPGUP||Key==KEY_SHIFTNUMPAD9? KEY_SHIFTUP:KEY_SHIFTDOWN);
1718      InternalProcessKey--;
1719      Unlock ();
1720      if (SelectedFirst)
1721        SortFileList(TRUE);
1722      ShowFileList(TRUE);
1723      return(TRUE);
1724    }
1725
1726    case KEY_SHIFTLEFT:    case KEY_SHIFTNUMPAD4:
1727    case KEY_SHIFTRIGHT:   case KEY_SHIFTNUMPAD6:
1728    {
1729      if (FileCount==0)
1730        return(TRUE);
1731      if (Columns>1)
1732      {
1733        int N=Height;
1734        InternalProcessKey++;
1735        Lock ();
1736        while (N--)
1737          ProcessKey(Key==KEY_SHIFTLEFT || Key==KEY_SHIFTNUMPAD4? KEY_SHIFTUP:KEY_SHIFTDOWN);
1738        Select(ListData[CurFile],ShiftSelection);
1739        if (SelectedFirst)
1740          SortFileList(TRUE);
1741        InternalProcessKey--;
1742        Unlock ();
1743        if (SelectedFirst)
1744          SortFileList(TRUE);
1745        ShowFileList(TRUE);
1746        return(TRUE);
1747      }
1748      return(FALSE);
1749    }
1750
1751    case KEY_SHIFTUP:      case KEY_SHIFTNUMPAD8:
1752    case KEY_SHIFTDOWN:    case KEY_SHIFTNUMPAD2:
1753    {
1754      if (FileCount==0)
1755        return(TRUE);
1756      CurPtr=ListData[CurFile];
1757      if (ShiftSelection==-1)
1758      {
1759        // .. is never selected
1760        if (CurFile < FileCount-1 && TestParentFolderName(CurPtr->strName))
1761          ShiftSelection = !ListData [CurFile+1]->Selected;
1762        else
1763          ShiftSelection=!CurPtr->Selected;
1764      }
1765      Select(CurPtr,ShiftSelection);
1766      if (Key==KEY_SHIFTUP || Key == KEY_SHIFTNUMPAD8)
1767        Up(1);
1768      else
1769        Down(1);
1770      if (SelectedFirst && !InternalProcessKey)
1771        SortFileList(TRUE);
1772      ShowFileList(TRUE);
1773      return(TRUE);
1774    }
1775
1776    case KEY_INS:          case KEY_NUMPAD0:
1777    {
1778      if (FileCount==0)
1779        return(TRUE);
1780      CurPtr=ListData[CurFile];
1781      Select(CurPtr,!CurPtr->Selected);
1782      Down(1);
1783      if (SelectedFirst)
1784        SortFileList(TRUE);
1785      ShowFileList(TRUE);
1786      return(TRUE);
1787    }
1788
1789    case KEY_CTRLF3:
1790      SetSortMode(BY_NAME);
1791      return(TRUE);
1792
1793    case KEY_CTRLF4:
1794      SetSortMode(BY_EXT);
1795      return(TRUE);
1796
1797    case KEY_CTRLF5:
1798      SetSortMode(BY_MTIME);
1799      return(TRUE);
1800
1801    case KEY_CTRLF6:
1802      SetSortMode(BY_SIZE);
1803      return(TRUE);
1804
1805    case KEY_CTRLF7:
1806      SetSortMode(UNSORTED);
1807      return(TRUE);
1808
1809    case KEY_CTRLF8:
1810      SetSortMode(BY_CTIME);
1811      return(TRUE);
1812
1813    case KEY_CTRLF9:
1814      SetSortMode(BY_ATIME);
1815      return(TRUE);
1816
1817    case KEY_CTRLF10:
1818      SetSortMode(BY_DIZ);
1819      return(TRUE);
1820
1821    case KEY_CTRLF11:
1822      SetSortMode(BY_OWNER);
1823      return(TRUE);
1824
1825    case KEY_CTRLF12:
1826      SelectSortMode();
1827      return(TRUE);
1828
1829    case KEY_SHIFTF11:
1830      SortGroups=!SortGroups;
1831      if (SortGroups)
1832        ReadSortGroups();
1833      SortFileList(TRUE);
1834      Show();
1835      return(TRUE);
1836
1837    case KEY_SHIFTF12:
1838      SelectedFirst=!SelectedFirst;
1839      SortFileList(TRUE);
1840      Show();
1841      return(TRUE);
1842
1843    case KEY_CTRLPGUP:     case KEY_CTRLNUMPAD9:
1844      /* $ 25.12.2001 DJ
1845         И кого мы будем перерисовывать, если ChangeDir() вызвал деструктор
1846         панели? Правильно, не this, а активную панель. Потому что this
1847         уже уничтожен!
1848      */
1849      ChangeDir(L"..");
1850      /* $ 24.04.2001 IS
1851           Проинициализируем заново режим панели.
1852      */
1853      {
1854        Panel *NewActivePanel = CtrlObject->Cp()->ActivePanel;
1855        NewActivePanel->SetViewMode(NewActivePanel->GetViewMode());
1856        NewActivePanel->Show();
1857      }
1858      return(TRUE);
1859
1860    case KEY_CTRLPGDN:     case KEY_CTRLNUMPAD3:
1861      ProcessEnter(0,0);
1862      return(TRUE);
1863
1864    default:
1865      if((Key>=KEY_ALT_BASE+0x01 && Key<=KEY_ALT_BASE+65535 ||
1866          Key>=KEY_ALTSHIFT_BASE+0x01 && Key<=KEY_ALTSHIFT_BASE+65535) &&
1867         Key != KEY_ALTBS && Key != (KEY_ALTBS|KEY_SHIFT)
1868        )
1869      {
1870        //_SVS(SysLog(L">FastFind: Key=%s",_FARKEY_ToName(Key)));
1871        // Скорректирем уже здесь нужные клавиши, т.к. WaitInFastFind
1872        // в это время еще равно нулю.
1873        static const char Code[]=")!@#$%^&*(";
1874        if(Key >= KEY_ALTSHIFT0 && Key <= KEY_ALTSHIFT9)
1875          Key=(DWORD)Code[Key-KEY_ALTSHIFT0];
1876        else if((Key&(~(KEY_ALT+KEY_SHIFT))) == '/')
1877          Key='?';
1878        else if(Key == KEY_ALTSHIFT+'-')
1879          Key='_';
1880        else if(Key == KEY_ALTSHIFT+'=')
1881          Key='+';
1882        //_SVS(SysLog(L"<FastFind: Key=%s",_FARKEY_ToName(Key)));
1883        FastFind(Key);
1884      }
1885      else
1886        break;
1887      return(TRUE);
1888  }
1889  return(FALSE);
1890}
1891
1892
1893void FileList::Select(struct FileListItem *SelPtr,int Selection)
1894{
1895  if (!TestParentFolderName(SelPtr->strName) && SelPtr->Selected!=Selection)
1896    if ((SelPtr->Selected=Selection)!=0)
1897    {
1898      SelFileCount++;
1899      SelFileSize += SelPtr->UnpSize;
1900    }
1901    else
1902    {
1903       SelFileCount--;
1904       SelFileSize -= SelPtr->UnpSize;
1905    }
1906}
1907
1908
1909void FileList::ProcessEnter(int EnableExec,int SeparateWindow)
1910{
1911  struct FileListItem *CurPtr;
1912  string strFileName, strShortFileName;
1913  const wchar_t *ExtPtr;
1914  if (CurFile>=FileCount)
1915    return;
1916
1917  CurPtr=ListData[CurFile];
1918
1919  strFileName = CurPtr->strName;
1920
1921  if ( !CurPtr->strShortName.IsEmpty () )
1922    strShortFileName = CurPtr->strShortName;
1923  else
1924    strShortFileName = CurPtr->strName;
1925
1926  if (CurPtr->FileAttr & FA_DIREC)
1927  {
1928    BOOL IsRealName=FALSE;
1929    if(PanelMode==PLUGIN_PANEL)
1930    {
1931      struct OpenPluginInfo Info;
1932      CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
1933      IsRealName=Info.Flags&OPIF_REALNAMES;
1934    }
1935
1936    // Shift-Enter на каталоге вызывает проводник
1937    if((PanelMode!=PLUGIN_PANEL || IsRealName) && SeparateWindow)
1938    {
1939      string strFullPath;
1940      if(!PathMayBeAbsolute(CurPtr->strName))
1941      {
1942        strFullPath = strCurDir;
1943        AddEndSlash(strFullPath);
1944        /* 23.08.2001 VVM
1945          ! SHIFT+ENTER на ".." срабатывает для текущего каталога, а не родительского */
1946        if (!TestParentFolderName(CurPtr->strName))
1947          strFullPath += CurPtr->strName;
1948      }
1949      else
1950      {
1951        strFullPath = CurPtr->strName;
1952      }
1953      QuoteSpace(strFullPath);
1954
1955      Execute(strFullPath,FALSE,SeparateWindow?2:0,TRUE,CurPtr->FileAttr&FA_DIREC);
1956    }
1957    else
1958    {
1959      /* $ 09.04.2001 SVS
1960         Не перерисовываем, если ChangeDir закрыла панель
1961      */
1962      BOOL res=FALSE;
1963      int CheckFullScreen=IsFullScreen();
1964      if (PanelMode==PLUGIN_PANEL || wcschr(CurPtr->strName,L'?')==NULL ||
1965          CurPtr->strShortName.IsEmpty() )
1966      {
1967        res=ChangeDir(CurPtr->strName);
1968      }
1969      else
1970        res=ChangeDir(CurPtr->strShortName);
1971//      if(res)
1972      if(CheckFullScreen)
1973      {
1974        CtrlObject->Cp()->GetAnotherPanel(this)->Show();
1975      }
1976      CtrlObject->Cp()->ActivePanel->Show();
1977    }
1978  }
1979  else
1980  {
1981    int PluginMode=PanelMode==PLUGIN_PANEL &&
1982        !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILE);
1983    if (PluginMode)
1984    {
1985      string strTempDir;
1986      if(!FarMkTempEx(strTempDir))
1987        return;
1988      CreateDirectoryW(strTempDir,NULL);
1989      struct PluginPanelItem PanelItem;
1990      FileListToPluginItem(CurPtr,&PanelItem);
1991
1992      if (!CtrlObject->Plugins.GetFile(hPlugin,&PanelItem,strTempDir,strFileName,OPM_SILENT|OPM_VIEW))
1993      {
1994        apiRemoveDirectory(strTempDir);
1995        return;
1996      }
1997
1998      ConvertNameToShort(strFileName,strShortFileName);
1999    }
2000
2001    if (EnableExec && SetCurPath() && !SeparateWindow &&
2002        ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_EXEC,PluginMode)) //?? is was var!
2003    {
2004      if (PluginMode)
2005        DeleteFileWithFolder(strFileName);
2006      return;
2007    }
2008
2009    ExtPtr=wcsrchr(strFileName,L'.');
2010    int ExeType=FALSE,BatType=FALSE;
2011    if (ExtPtr!=NULL)
2012    {
2013      ExeType=StrCmpI(ExtPtr,L".exe")==0 || StrCmpI(ExtPtr,L".com")==0;
2014      BatType=IsBatchExtType(ExtPtr);
2015    }
2016    if (EnableExec && (ExeType || BatType))
2017    {
2018      QuoteSpace(strFileName);
2019      if (!(Opt.ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTPANEL) && !PluginMode) //AN
2020        CtrlObject->CmdHistory->AddToHistory(strFileName);
2021
2022      int DirectRun=(strCurDir.At(0)==L'\\' && strCurDir.At(1)==L'\\' && ExeType);
2023
2024      CtrlObject->CmdLine->ExecString(strFileName,PluginMode,SeparateWindow,DirectRun);
2025      if (PluginMode)
2026        DeleteFileWithFolder(strFileName);
2027    }
2028    else
2029      if (SetCurPath())
2030      {
2031        HANDLE hOpen=NULL;
2032        /* $ 02.08.2001 IS обработаем ассоциации для ctrl-pgdn */
2033
2034        if(!EnableExec &&     // не запускаем и не в отдельном окне,
2035           !SeparateWindow && // следовательно это Ctrl-PgDn
2036           ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_ALTEXEC,
2037           PluginMode)
2038          )
2039        {
2040          if (PluginMode)
2041          {
2042            DeleteFileWithFolder(strFileName);
2043          }
2044          return;
2045        }
2046        if (SeparateWindow || (hOpen=OpenFilePlugin(strFileName,TRUE))==INVALID_HANDLE_VALUE ||
2047            hOpen==(HANDLE)-2)
2048        {
2049          if (EnableExec && hOpen!=(HANDLE)-2)
2050            if (SeparateWindow || Opt.UseRegisteredTypes)
2051              ProcessGlobalFileTypes(strFileName,PluginMode);
2052          if (PluginMode)
2053          {
2054            DeleteFileWithFolder(strFileName);
2055          }
2056        }
2057        return;
2058      }
2059  }
2060}
2061
2062
2063void FileList::SetCurDir(const wchar_t *NewDir,int ClosePlugin)
2064{
2065  if (ClosePlugin && PanelMode==PLUGIN_PANEL)
2066  {
2067    while (1)
2068    {
2069      if (ProcessPluginEvent(FE_CLOSE,NULL))
2070        return;
2071      if (!PopPlugin(TRUE))
2072        break;
2073    }
2074    CtrlObject->Cp()->RedrawKeyBar();
2075  }
2076  /* $ 20.07.2001 VVM
2077    ! Проверить на непустую строку */
2078  if ((NewDir) && (*NewDir))
2079  {
2080    ChangeDir(NewDir);
2081  }
2082}
2083
2084BOOL FileList::ChangeDir(const wchar_t *NewDir,BOOL IsUpdated)
2085{
2086  Panel *AnotherPanel;
2087  string strFindDir, strSetDir;
2088
2089  strSetDir = NewDir;
2090    /* $ 28.08.2007 YJH
2091      + У форточек сносит крышу на GetFileAttributes("..") при нахождении в
2092        корне UNC пути. Приходится обходить в ручную */
2093  if (PanelMode!=PLUGIN_PANEL && !StrCmp(strSetDir, L"..") &&
2094      !StrCmpN(strCurDir, L"\\\\?\\", 4) && strCurDir.At(4) &&
2095      !StrCmp(&strCurDir[5], L":\\"))
2096  {
2097    strSetDir = (const wchar_t*)strCurDir+4;
2098  }
2099  PrepareDiskPath(strSetDir);
2100
2101  if ( !TestParentFolderName(strSetDir) && StrCmp(strSetDir,L"\\")!=0)
2102    UpperFolderTopFile=CurTopFile;
2103
2104  if (SelFileCount>0)
2105    ClearSelection();
2106
2107  int PluginClosed=FALSE,GoToPanelFile=FALSE;
2108  if (PanelMode==PLUGIN_PANEL)
2109  {
2110    struct OpenPluginInfo Info;
2111    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
2112
2113    /* $ 16.01.2002 VVM
2114      + Если у плагина нет OPIF_REALNAMES, то история папок не пишется в реестр */
2115
2116    string strInfoCurDir;
2117    string strInfoFormat;
2118
2119    strInfoCurDir = NullToEmpty(Info.CurDir);
2120    strInfoFormat = NullToEmpty(Info.Format);
2121
2122    CtrlObject->FolderHistory->AddToHistory(strInfoCurDir,strInfoFormat,1,
2123                               (Info.Flags & OPIF_REALNAMES)?0:(Opt.SavePluginFoldersHistory?0:1));
2124
2125    /* $ 25.04.01 DJ
2126       при неудаче SetDirectory не сбрасываем выделение
2127    */
2128    BOOL SetDirectorySuccess = TRUE;
2129    int UpperFolder=TestParentFolderName(strSetDir);
2130    if (UpperFolder && *NullToEmpty(Info.CurDir)==0)
2131    {
2132      if (ProcessPluginEvent(FE_CLOSE,NULL))
2133        return(TRUE);
2134      PluginClosed=TRUE;
2135
2136      strFindDir = NullToEmpty(Info.HostFile);
2137      if ( strFindDir.IsEmpty() && (Info.Flags & OPIF_REALNAMES) && CurFile<FileCount)
2138      {
2139        strFindDir = ListData[CurFile]->strName;
2140        GoToPanelFile=TRUE;
2141      }
2142      PopPlugin(TRUE);
2143      Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
2144      if (AnotherPanel->GetType()==INFO_PANEL)
2145        AnotherPanel->Redraw();
2146    }
2147    else
2148    {
2149      strFindDir = NullToEmpty(Info.CurDir);
2150      SetDirectorySuccess=CtrlObject->Plugins.SetDirectory(hPlugin,strSetDir,0);
2151    }
2152    ProcessPluginCommand();
2153    if (SetDirectorySuccess)
2154      Update(0);
2155    else
2156      Update(UPDATE_KEEP_SELECTION);
2157    if (PluginClosed && PrevDataStackSize>0)
2158    {
2159      PrevDataStackSize--;
2160      if (PrevDataStack[PrevDataStackSize]->PrevFileCount>0)
2161      {
2162        MoveSelection(ListData,FileCount,PrevDataStack[PrevDataStackSize]->PrevListData,PrevDataStack[PrevDataStackSize]->PrevFileCount);
2163        UpperFolderTopFile = PrevDataStack[PrevDataStackSize]->PrevTopFile;
2164        if (!GoToPanelFile)
2165          strFindDir = PrevDataStack[PrevDataStackSize]->strPrevName;
2166
2167        DeleteListData(PrevDataStack[PrevDataStackSize]->PrevListData,PrevDataStack[PrevDataStackSize]->PrevFileCount);
2168        if (ListSelectedFirst)
2169          SortFileList(FALSE);
2170        else if (FileCount>0)
2171          SortFileList(TRUE);
2172      }
2173    }
2174
2175    if (UpperFolder)
2176    {
2177      long Pos=FindFile(PointToName(strFindDir));
2178      if (Pos!=-1)
2179        CurFile=Pos;
2180      else
2181        GoToFile(strFindDir);
2182      CurTopFile=UpperFolderTopFile;
2183      UpperFolderTopFile=0;
2184      CorrectPosition();
2185    }
2186    /* $ 26.04.2001 DJ
2187       доделка про несброс выделения при неудаче SetDirectory
2188    */
2189    else if (SetDirectorySuccess)
2190      CurFile=CurTopFile=0;
2191    return(TRUE);
2192  }
2193  else
2194  {
2195    string strFullNewDir;
2196
2197    ConvertNameToFull(strSetDir, strFullNewDir);
2198
2199    if ( StrCmpI(strFullNewDir, strCurDir)!=0)
2200      CtrlObject->FolderHistory->AddToHistory(strCurDir,NULL,0);
2201
2202    if(TestParentFolderName(strSetDir))
2203    {
2204      string strRootDir, strTempDir;
2205
2206      strTempDir = strCurDir;
2207
2208      AddEndSlash(strTempDir);
2209      GetPathRoot(strTempDir, strRootDir);
2210
2211      if((strCurDir.At(0) == L'\\' && strCurDir.At(1) == L'\\' && StrCmp(strTempDir,strRootDir)==0) ||
2212         (strCurDir.At(1) == L':'  && strCurDir[2] == L'\\' && strCurDir.At(3)==0))
2213      {
2214        string strDirName;
2215        strDirName = strCurDir;
2216
2217        AddEndSlash(strDirName);
2218
2219        if(Opt.PgUpChangeDisk &&
2220          (FAR_GetDriveType(strDirName) != DRIVE_REMOTE ||
2221           !CtrlObject->Plugins.FindPlugin(SYSID_NETWORK)))
2222        {
2223          CtrlObject->Cp()->ActivePanel->ChangeDisk();
2224          return TRUE;
2225        }
2226
2227        string strNewCurDir;
2228
2229        strNewCurDir = strCurDir;
2230        if(strNewCurDir.At(1) == L':')
2231        {
2232          wchar_t Letter=strNewCurDir.At(0);
2233          DriveLocalToRemoteName(DRIVE_REMOTE,Letter,strNewCurDir);
2234        }
2235
2236        if( !strNewCurDir.IsEmpty() ) // проверим - может не удалось определить RemoteName
2237        {
2238          const wchar_t *PtrS1=wcschr((const wchar_t*)strNewCurDir+2,L'\\');
2239          if(PtrS1 && !wcschr(PtrS1+1,L'\\'))
2240          {
2241            if(CtrlObject->Plugins.CallPlugin(SYSID_NETWORK,OPEN_FILEPANEL,(void*)(const wchar_t *)strNewCurDir)) // NetWork Plugin :-)
2242              return(FALSE);
2243          }
2244        }
2245      }
2246    }
2247  }
2248
2249  strFindDir = PointToName(strCurDir);
2250
2251  if ( strSetDir.IsEmpty() || strSetDir.At(1) != L':' || strSetDir.At(2) != L'\\')
2252    FarChDir(strCurDir);
2253
2254  /* $ 26.04.2001 DJ
2255     проверяем, удалось ли сменить каталог, и обновляем с KEEP_SELECTION,
2256     если не удалось
2257  */
2258  int UpdateFlags = 0;
2259
2260  // ...когда ввели в масдае cd //host/share
2261  if(WinVer.dwPlatformId != VER_PLATFORM_WIN32_NT &&
2262    strSetDir.At(0) == L'/' && strSetDir.At(1) == L'/')
2263  {
2264    wchar_t *Ptr=strSetDir.GetBuffer();
2265    while(*Ptr)
2266    {
2267      if(*Ptr == L'/')
2268        *Ptr=L'\\';
2269      ++Ptr;
2270    }
2271
2272    strSetDir.ReleaseBuffer ();
2273  }
2274
2275  if(PanelMode!=PLUGIN_PANEL && !StrCmp(strSetDir,L"\\"))
2276  {
2277#if 1    // если поставить 0, то ФАР будет выкидыват в корень того диска, который подмаплен на файловую систему
2278    GetPathRootOne(strCurDir,strSetDir);
2279#else
2280    GetPathRoot(strCurDir,strSetDir);
2281    if(!StrCmpN(SetDir,L"\\\\?\\Volume{",11)) // случай, когда том прилинкован на NTFS в качестве каталога, но буквы не имеет.
2282      GetPathRootOne(CurDir,SetDir);
2283#endif
2284  }
2285
2286  if (!FarChDir(strSetDir))
2287  {
2288    /* $ 03.11.2001 IS
2289         Укажем имя неудачного каталога
2290    */
2291    Message(MSG_WARNING | MSG_ERRORTYPE, 1, UMSG (MError), strSetDir, UMSG (MOk));
2292    UpdateFlags = UPDATE_KEEP_SELECTION;
2293  }
2294  /* $ 28.04.2001 IS
2295       Закомментарим "до лучших времен".
2296       Я не знаю, почему глюк проявлялся только у меня, но зато знаю, почему он
2297       был просто-таки обязан проявится. Желающие могут немного RTFM. Тема для
2298       изучения: chdir, setdisk, SetCurrentDirectory и переменные окружения
2299
2300  */
2301  /*else {
2302    if (isalpha(SetDir[0]) && SetDir[1]==':')
2303    {
2304      int CurDisk=toupper(SetDir[0])-'A';
2305      setdisk(CurDisk);
2306    }
2307  }*/
2308  FarGetCurDir(strCurDir);
2309
2310  if(!IsUpdated)
2311    return(TRUE);
2312
2313  Update(UpdateFlags);
2314
2315  if (TestParentFolderName(strSetDir))
2316  {
2317    GoToFile(strFindDir);
2318    CurTopFile=UpperFolderTopFile;
2319    UpperFolderTopFile=0;
2320    CorrectPosition();
2321  }
2322  else if (UpdateFlags != UPDATE_KEEP_SELECTION)
2323    CurFile=CurTopFile=0;
2324
2325  if (GetFocus())
2326  {
2327    CtrlObject->CmdLine->SetCurDir(strCurDir);
2328    CtrlObject->CmdLine->Show();
2329  }
2330  AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
2331  if (AnotherPanel->GetType()!=FILE_PANEL)
2332  {
2333    AnotherPanel->SetCurDir(strCurDir,FALSE);
2334    AnotherPanel->Redraw();
2335  }
2336  if (PanelMode==PLUGIN_PANEL)
2337    CtrlObject->Cp()->RedrawKeyBar();
2338  return(TRUE);
2339
2340}
2341
2342
2343int FileList::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
2344{
2345  struct FileListItem *CurPtr;
2346  int RetCode;
2347
2348  if (IsVisible() && Opt.ShowColumnTitles && MouseEvent->dwEventFlags==0 &&
2349      MouseEvent->dwMousePosition.Y==Y1+1 &&
2350      MouseEvent->dwMousePosition.X>X1 && MouseEvent->dwMousePosition.X<X1+3)
2351  {
2352    if (MouseEvent->dwButtonState)
2353      if (MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
2354        ChangeDisk();
2355      else
2356        SelectSortMode();
2357    return(TRUE);
2358  }
2359
2360  if (IsVisible() && Opt.ShowPanelScrollbar && MouseX==X2 &&
2361      (MouseEvent->dwButtonState & 1) && !IsDragging())
2362  {
2363    int ScrollY=Y1+1+Opt.ShowColumnTitles;
2364    if (MouseY==ScrollY)
2365    {
2366      while (IsMouseButtonPressed())
2367        ProcessKey(KEY_UP);
2368      SetFocus();
2369      return(TRUE);
2370    }
2371    if (MouseY==ScrollY+Height-1)
2372    {
2373      while (IsMouseButtonPressed())
2374        ProcessKey(KEY_DOWN);
2375      SetFocus();
2376      return(TRUE);
2377    }
2378    if (MouseY>ScrollY && MouseY<ScrollY+Height-1 && Height>2)
2379    {
2380      CurFile=(FileCount-1)*(MouseY-ScrollY)/(Height-2);
2381      ShowFileList(TRUE);
2382      SetFocus();
2383      return(TRUE);
2384    }
2385  }
2386
2387  /* $ 21.08.2001 VVM
2388    + Считать нажатие средней кнопки за ЕНТЕР */
2389  /* $ 17.12.2001 IS
2390    ! новшество от Василия - опционально
2391  */
2392  if ((MouseEvent->dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
2393      && (MouseEvent->dwEventFlags != MOUSE_MOVED)
2394      && Opt.PanelMiddleClickRule)
2395  {
2396    int Key = KEY_ENTER;
2397    if (MouseEvent->dwControlKeyState & SHIFT_PRESSED)
2398      Key |= KEY_SHIFT;
2399    if (MouseEvent->dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
2400      Key |= KEY_CTRL;
2401    if (MouseEvent->dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
2402      Key |= KEY_ALT;
2403    ProcessKey(Key);
2404    return(TRUE);
2405  }
2406
2407  if (Panel::PanelProcessMouse(MouseEvent,RetCode))
2408    return(RetCode);
2409
2410  if (MouseEvent->dwMousePosition.Y>Y1+Opt.ShowColumnTitles &&
2411      MouseEvent->dwMousePosition.Y<Y2-2*Opt.ShowPanelStatus)
2412  {
2413    SetFocus();
2414    if (FileCount==0)
2415      return(TRUE);
2416    MoveToMouse(MouseEvent);
2417    CurPtr=ListData[CurFile];
2418
2419    if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) &&
2420        MouseEvent->dwEventFlags==DOUBLE_CLICK)
2421    {
2422      if (PanelMode==PLUGIN_PANEL)
2423      {
2424        FlushInputBuffer(); // !!!
2425        int ProcessCode=CtrlObject->Plugins.ProcessKey(hPlugin,VK_RETURN,ShiftPressed ? PKF_SHIFT:0);
2426        ProcessPluginCommand();
2427        if (ProcessCode)
2428          return(TRUE);
2429      }
2430      /*$ 21.02.2001 SKV
2431        Если пришел DOUBLE_CLICK без предшевствующего ему
2432        простого клика, то курсор не перерисовывается.
2433        Перересуем его.
2434        По идее при нормальном DOUBLE_CLICK, будет
2435        двойная перерисовка...
2436        Но мы же вызываем Fast=TRUE...
2437        Вроде всё должно быть ок.
2438      */
2439      ShowFileList(TRUE);
2440      FlushInputBuffer();
2441      ProcessEnter(1,ShiftPressed!=0);
2442      return(TRUE);
2443    }
2444    else
2445    {
2446      /* $ 11.09.2000 SVS
2447         Bug #17: Выделяем при условии, что колонка ПОЛНОСТЬЮ пуста.
2448      */
2449      if ((MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) && !IsEmpty)
2450      {
2451        if (MouseEvent->dwEventFlags==0)
2452          MouseSelection=!CurPtr->Selected;
2453        Select(CurPtr,MouseSelection);
2454        if (SelectedFirst)
2455          SortFileList(TRUE);
2456      }
2457    }
2458    ShowFileList(TRUE);
2459    return(TRUE);
2460  }
2461  if (MouseEvent->dwMousePosition.Y<=Y1+1)
2462  {
2463    SetFocus();
2464    if (FileCount==0)
2465      return(TRUE);
2466    while (IsMouseButtonPressed() && MouseY<=Y1+1)
2467    {
2468      Up(1);
2469      if (RButtonPressed)
2470      {
2471        CurPtr=ListData[CurFile];
2472        Select(CurPtr,MouseSelection);
2473      }
2474    }
2475    if (SelectedFirst)
2476      SortFileList(TRUE);
2477    return(TRUE);
2478  }
2479  if (MouseEvent->dwMousePosition.Y>=Y2-2)
2480  {
2481    SetFocus();
2482    if (FileCount==0)
2483      return(TRUE);
2484    while (IsMouseButtonPressed() && MouseY>=Y2-2)
2485    {
2486      Down(1);
2487      if (RButtonPressed)
2488      {
2489        CurPtr=ListData[CurFile];
2490        Select(CurPtr,MouseSelection);
2491      }
2492    }
2493    if (SelectedFirst)
2494      SortFileList(TRUE);
2495    return(TRUE);
2496  }
2497  return(FALSE);
2498}
2499
2500
2501/* $ 12.09.2000 SVS
2502  + Опциональное поведение для правой клавиши мыши на пустой панели
2503*/
2504void FileList::MoveToMouse(MOUSE_EVENT_RECORD *MouseEvent)
2505{
2506  int CurColumn=1,ColumnsWidth,I;
2507  int PanelX=MouseEvent->dwMousePosition.X-X1-1;
2508
2509  int Level = 0;
2510
2511  for (ColumnsWidth=I=0;I<ViewSettings.ColumnCount;I++)
2512  {
2513    if ( Level == ColumnsInGlobal )
2514    {
2515      CurColumn++;
2516      Level = 0;
2517    }
2518    ColumnsWidth+=ViewSettings.ColumnWidth[I];
2519    if (ColumnsWidth>=PanelX)
2520      break;
2521    ColumnsWidth++;
2522    Level++;
2523  }
2524//  if (CurColumn==0)
2525//    CurColumn=1;
2526  int OldCurFile=CurFile;
2527  CurFile=CurTopFile+MouseEvent->dwMousePosition.Y-Y1-1-Opt.ShowColumnTitles;
2528  if (CurColumn>1)
2529    CurFile+=(CurColumn-1)*Height;
2530  CorrectPosition();
2531  /* $ 11.09.2000 SVS
2532     Bug #17: Проверим на ПОЛНОСТЬЮ пустую колонку.
2533  */
2534  if(Opt.PanelRightClickRule == 1)
2535    IsEmpty=((CurColumn-1)*Height > FileCount);
2536  else if(Opt.PanelRightClickRule == 2 &&
2537          (MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) &&
2538          ((CurColumn-1)*Height > FileCount))
2539  {
2540    CurFile=OldCurFile;
2541    IsEmpty=TRUE;
2542  }
2543  else
2544    IsEmpty=FALSE;
2545}
2546
2547void FileList::SetViewMode(int ViewMode)
2548{
2549  int CurFullScreen=IsFullScreen();
2550  int OldOwner=IsColumnDisplayed(OWNER_COLUMN);
2551  int OldPacked=IsColumnDisplayed(PACKED_COLUMN);
2552  int OldNumLink=IsColumnDisplayed(NUMLINK_COLUMN);
2553  int OldDiz=IsColumnDisplayed(DIZ_COLUMN);
2554  int OldCaseSensitiveSort=ViewSettings.CaseSensitiveSort;
2555  int OldNumericSort=NumericSort;
2556  PrepareViewSettings(ViewMode,NULL);
2557  int NewOwner=IsColumnDisplayed(OWNER_COLUMN);
2558  int NewPacked=IsColumnDisplayed(PACKED_COLUMN);
2559  int NewNumLink=IsColumnDisplayed(NUMLINK_COLUMN);
2560  int NewDiz=IsColumnDisplayed(DIZ_COLUMN);
2561  int NewAccessTime=IsColumnDisplayed(ADATE_COLUMN);
2562  int NewCaseSensitiveSort=ViewSettings.CaseSensitiveSort;
2563  int NewNumericSort=NumericSort;
2564  int ResortRequired=FALSE;
2565
2566  string strDriveRoot;
2567  DWORD FileSystemFlags;
2568  GetPathRoot(strCurDir,strDriveRoot);
2569  if (NewPacked && apiGetVolumeInformation (strDriveRoot,NULL,NULL,NULL,&FileSystemFlags,NULL))
2570    if ((FileSystemFlags & FS_FILE_COMPRESSION)==0)
2571      NewPacked=FALSE;
2572
2573  if (FileCount>0 && PanelMode!=PLUGIN_PANEL &&
2574      (!OldOwner && NewOwner || !OldPacked && NewPacked ||
2575       !OldNumLink && NewNumLink ||
2576       AccessTimeUpdateRequired && NewAccessTime))
2577    Update(UPDATE_KEEP_SELECTION);
2578  else
2579    if (OldCaseSensitiveSort!=NewCaseSensitiveSort || OldNumericSort!=NewNumericSort) //????
2580      ResortRequired=TRUE;
2581
2582  if (!OldDiz && NewDiz)
2583    ReadDiz();
2584
2585  if (ViewSettings.FullScreen && !CurFullScreen)
2586  {
2587    if (Y2>0)
2588      SetPosition(0,Y1,ScrX,Y2);
2589    FileList::ViewMode=ViewMode;
2590  }
2591  else
2592    if (!ViewSettings.FullScreen && CurFullScreen)
2593    {
2594      if (Y2>0)
2595        if (this==CtrlObject->Cp()->LeftPanel)
2596          SetPosition(0,Y1,ScrX/2-Opt.WidthDecrement,Y2);
2597        else
2598          SetPosition(ScrX/2+1-Opt.WidthDecrement,Y1,ScrX,Y2);
2599      FileList::ViewMode=ViewMode;
2600    }
2601    else
2602    {
2603      FileList::ViewMode=ViewMode;
2604      FrameManager->RefreshFrame();
2605    }
2606
2607  if (PanelMode==PLUGIN_PANEL)
2608  {
2609    string strColumnTypes,strColumnWidths;
2610
2611//    SetScreenPosition();
2612    ViewSettingsToText(ViewSettings.ColumnType,ViewSettings.ColumnWidth,
2613        ViewSettings.ColumnCount,strColumnTypes,strColumnWidths);
2614    ProcessPluginEvent(FE_CHANGEVIEWMODE,(void*)(const wchar_t*)strColumnTypes);
2615  }
2616
2617  if (ResortRequired)
2618  {
2619    SortFileList(TRUE);
2620    ShowFileList(TRUE);
2621    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
2622    if (AnotherPanel->GetType()==TREE_PANEL)
2623      AnotherPanel->Redraw();
2624  }
2625}
2626
2627
2628void FileList::SetSortMode(int SortMode)
2629{
2630  if (SortMode==FileList::SortMode && Opt.ReverseSort)
2631    SortOrder=-SortOrder;
2632  else
2633    SortOrder=1;
2634  FileList::SortMode=SortMode;
2635  if (FileCount>0)
2636    SortFileList(TRUE);
2637  FrameManager->RefreshFrame();
2638}
2639
2640int FileList::GoToFile(long idxItem)
2641{
2642  if ((DWORD)idxItem < (DWORD)FileCount)
2643  {
2644    CurFile=idxItem;
2645    CorrectPosition();
2646    return TRUE;
2647  }
2648  return FALSE;
2649}
2650
2651int FileList::GoToFile(const wchar_t *Name,BOOL OnlyPartName)
2652{
2653  return GoToFile(FindFile(Name,OnlyPartName));
2654}
2655
2656
2657long FileList::FindFile(const wchar_t *Name,BOOL OnlyPartName)
2658{
2659  long I;
2660  struct FileListItem *CurPtr;
2661
2662  for (I=0; I < FileCount; I++)
2663  {
2664    CurPtr = ListData[I];
2665    const wchar_t *CurPtrName=CurPtr->strName;
2666
2667    if(OnlyPartName)
2668      CurPtrName=PointToName(CurPtr->strName);
2669
2670    if (StrCmp(Name,CurPtrName)==0)
2671      return I;
2672    if (StrCmpI(Name,CurPtrName)==0)
2673      return I;
2674  }
2675  return -1;
2676}
2677
2678long FileList::FindFirst(const wchar_t *Name)
2679{
2680  return FindNext(0,Name);
2681}
2682
2683long FileList::FindNext(int StartPos, const wchar_t *Name)
2684{
2685  int I;
2686  struct FileListItem *CurPtr;
2687
2688  if((DWORD)StartPos < (DWORD)FileCount)
2689    for(I=StartPos; I < FileCount; I++)
2690    {
2691      CurPtr = ListData[I];
2692      const wchar_t *CurPtrName=CurPtr->strName;
2693      if (CmpName(Name,CurPtrName,TRUE))
2694        if (!TestParentFolderName(CurPtrName))
2695          return I;
2696    }
2697  return -1;
2698}
2699
2700
2701int FileList::IsSelected(const wchar_t *Name)
2702{
2703  long Pos=FindFile(Name);
2704  return(Pos!=-1 && (ListData[Pos]->Selected || SelFileCount==0 && Pos==CurFile));
2705}
2706
2707
2708// $ 02.08.2000 IG  Wish.Mix #21 - при нажатии '/' или '\' в QuickSerach переходим на директорию
2709int FileList::FindPartName(const wchar_t *Name,int Next,int Direct,int ExcludeSets)
2710{
2711  int I;
2712  struct FileListItem *CurPtr;
2713
2714  int DirFind = 0;
2715  int Length = StrLength(Name);
2716
2717  string strMask;
2718
2719  strMask = Name;
2720
2721  if ( Length > 0 && (Name[Length-1] == L'/' || Name[Length-1] == L'\\') )
2722  {
2723    DirFind = 1;
2724    strMask.SetLength(strMask.GetLength ()-1);
2725  }
2726
2727  strMask += L"*";
2728
2729  if(ExcludeSets)
2730  {
2731    ReplaceStrings(strMask,L"[",L"<[%>",-1,1);
2732    ReplaceStrings(strMask,L"]",L"[]]",-1,1);
2733    ReplaceStrings(strMask,L"<[%>",L"[[]",-1,1);
2734  }
2735
2736  for (I=CurFile+(Next?Direct:0); I >= 0 && I < FileCount; I+=Direct)
2737  {
2738    CurPtr = ListData[I];
2739    CmpNameSearchMode=(I==CurFile);
2740    if (CmpName(strMask,CurPtr->strName,TRUE))
2741      if (!TestParentFolderName(CurPtr->strName))
2742        if (!DirFind || (CurPtr->FileAttr & FA_DIREC))
2743        {
2744          CmpNameSearchMode=FALSE;
2745          CurFile=I;
2746          CurTopFile=CurFile-(Y2-Y1)/2;
2747          ShowFileList(TRUE);
2748          return(TRUE);
2749        }
2750  }
2751
2752  CmpNameSearchMode=FALSE;
2753
2754  for(I=(Direct > 0)?0:FileCount-1; (Direct > 0) ? I < CurFile:I > CurFile; I+=Direct)
2755  {
2756    CurPtr = ListData[I];
2757    if (CmpName(strMask,CurPtr->strName,TRUE))
2758      if (!TestParentFolderName(CurPtr->strName))
2759        if (!DirFind || (CurPtr->FileAttr & FA_DIREC))
2760        {
2761          CurFile=I;
2762          CurTopFile=CurFile-(Y2-Y1)/2;
2763          ShowFileList(TRUE);
2764          return(TRUE);
2765        }
2766  }
2767
2768  return(FALSE);
2769}
2770
2771
2772int FileList::GetSelCount()
2773{
2774  if (FileCount==0)
2775    return(0);
2776  if (SelFileCount==0 || ReturnCurrentFile)
2777    return(1);
2778  return(SelFileCount);
2779}
2780
2781int FileList::GetRealSelCount()
2782{
2783  if (FileCount==0)
2784    return(0);
2785  return(SelFileCount);
2786}
2787
2788
2789int FileList::GetSelName(string *strName,int &FileAttr,string *strShortName,FAR_FIND_DATA_EX *fd)
2790{
2791  if ( strName==NULL )
2792  {
2793    GetSelPosition=0;
2794    LastSelPosition=-1;
2795    return(TRUE);
2796  }
2797
2798
2799  if (SelFileCount==0 || ReturnCurrentFile)
2800  {
2801    if (GetSelPosition==0 && CurFile<FileCount)
2802    {
2803      GetSelPosition=1;
2804
2805      *strName = ListData[CurFile]->strName;
2806      if ( strShortName!=NULL )
2807      {
2808        *strShortName = ListData[CurFile]->strShortName;
2809
2810        if ( strShortName->IsEmpty() )
2811          *strShortName = *strName;
2812      }
2813      FileAttr=ListData[CurFile]->FileAttr;
2814      LastSelPosition=CurFile;
2815
2816      if (fd)
2817      {
2818        fd->dwFileAttributes=ListData[CurFile]->FileAttr;
2819        fd->ftCreationTime=ListData[CurFile]->CreationTime;
2820        fd->ftLastAccessTime=ListData[CurFile]->AccessTime;
2821        fd->ftLastWriteTime=ListData[CurFile]->WriteTime;
2822        fd->nFileSize=ListData[CurFile]->UnpSize;
2823        fd->nPackSize=ListData[CurFile]->PackSize;
2824
2825        fd->strFileName = ListData[CurFile]->strName;
2826        fd->strAlternateFileName = ListData[CurFile]->strShortName;
2827      }
2828
2829      return(TRUE);
2830    }
2831    else
2832      return(FALSE);
2833  }
2834
2835  while (GetSelPosition<FileCount)
2836    if (ListData[GetSelPosition++]->Selected)
2837    {
2838      *strName = ListData[GetSelPosition-1]->strName;
2839      if ( strShortName!=NULL )
2840      {
2841        *strShortName = ListData[GetSelPosition-1]->strShortName;
2842        if ( strShortName->IsEmpty() )
2843          *strShortName = *strName;
2844      }
2845      FileAttr=ListData[GetSelPosition-1]->FileAttr;
2846      LastSelPosition=GetSelPosition-1;
2847
2848      if (fd)
2849      {
2850        fd->dwFileAttributes=ListData[GetSelPosition-1]->FileAttr;
2851        fd->ftCreationTime=ListData[GetSelPosition-1]->CreationTime;
2852        fd->ftLastAccessTime=ListData[GetSelPosition-1]->AccessTime;
2853        fd->ftLastWriteTime=ListData[GetSelPosition-1]->WriteTime;
2854        fd->nFileSize=ListData[GetSelPosition-1]->UnpSize;
2855        fd->nPackSize=ListData[GetSelPosition-1]->PackSize;
2856        fd->strFileName = ListData[GetSelPosition-1]->strName;
2857        fd->strAlternateFileName = ListData[GetSelPosition-1]->strShortName;
2858      }
2859
2860      return(TRUE);
2861    }
2862  return(FALSE);
2863}
2864
2865
2866void FileList::ClearLastGetSelection()
2867{
2868  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2869    Select(ListData[LastSelPosition],0);
2870}
2871
2872
2873void FileList::UngetSelName()
2874{
2875  GetSelPosition=LastSelPosition;
2876}
2877
2878
2879unsigned __int64 FileList::GetLastSelectedSize ()
2880{
2881  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2882    return ListData[LastSelPosition]->UnpSize;
2883
2884  return (unsigned __int64)(-1);
2885}
2886
2887
2888int FileList::GetLastSelectedItem(struct FileListItem *LastItem)
2889{
2890  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2891  {
2892    *LastItem=*ListData[LastSelPosition];
2893    return(TRUE);
2894  }
2895  return(FALSE);
2896}
2897
2898
2899/*int FileList::GetCurName(char *Name,char *ShortName)
2900{
2901  if (FileCount==0)
2902  {
2903    *Name=*ShortName=0;
2904    return(FALSE);
2905  }
2906  strcpy(Name,ListData[CurFile]->Name);
2907  strcpy(ShortName,ListData[CurFile]->ShortName);
2908  if (*ShortName==0)
2909    strcpy(ShortName,Name);
2910  return(TRUE);
2911}
2912*/
2913int FileList::GetCurName(string &strName, string &strShortName)
2914{
2915  if (FileCount==0)
2916  {
2917    strName = L"";
2918    strShortName = L"";
2919    return(FALSE);
2920  }
2921
2922  strName = ListData[CurFile]->strName;
2923  strShortName = ListData[CurFile]->strShortName;
2924
2925  if ( strShortName.IsEmpty() )
2926    strShortName = strName;
2927  return(TRUE);
2928}
2929
2930
2931/*int FileList::GetCurBaseName(char *Name,char *ShortName)
2932{
2933  *Name=*ShortName=0;
2934  if (FileCount==0)
2935    return(FALSE);
2936  if(PanelMode==PLUGIN_PANEL && PluginsStack) // для плагинов
2937  {
2938    // берем самую основу (при вложенных)
2939    strcpy(Name,PointToName(NullToEmpty(PluginsStack->HostFile)));
2940  }
2941  else if(PanelMode==NORMAL_PANEL)
2942  {
2943    strcpy(Name,ListData[CurFile].Name);
2944    strcpy(ShortName,ListData[CurFile].ShortName);
2945  }
2946
2947  if (*ShortName==0)
2948    strcpy(ShortName,Name);
2949  return(TRUE);
2950}*/
2951
2952int FileList::GetCurBaseName(string &strName, string &strShortName)
2953{
2954  if (FileCount==0)
2955  {
2956    strName = L"";
2957    strShortName = L"";
2958    return(FALSE);
2959  }
2960
2961  if(PanelMode==PLUGIN_PANEL && PluginsStack) // для плагинов
2962  {
2963    strName = PointToName(PluginsStack[0]->strHostFile);
2964  }
2965  else if(PanelMode==NORMAL_PANEL)
2966  {
2967    strName = ListData[CurFile]->strName;
2968    strShortName = ListData[CurFile]->strShortName;
2969  }
2970
2971  if ( strShortName.IsEmpty() )
2972    strShortName = strName;
2973  return(TRUE);
2974}
2975
2976extern void add_char (string &str, wchar_t c); //BUGBUG
2977
2978void FileList::SelectFiles(int Mode)
2979{
2980  CFileMask FileMask; // Класс для работы с масками
2981  const wchar_t *HistoryName=L"Masks";
2982  static struct DialogDataEx SelectDlgData[]=
2983  {
2984    DI_DOUBLEBOX,3,1,51,5,0,0,0,0,L"",
2985    DI_EDIT,5,2,49,2,1,(DWORD_PTR)HistoryName,DIF_HISTORY,0,L"",
2986    DI_TEXT,0,3,0,3,0,0,DIF_SEPARATOR,0,L"",
2987    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,1,(const wchar_t *)MOk,
2988    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MSelectFilter,
2989    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MCancel,
2990  };
2991  MakeDialogItemsEx(SelectDlgData,SelectDlg);
2992
2993  FileFilter Filter(this,FFT_SELECT);
2994  bool bUseFilter = false;
2995
2996  struct FileListItem *CurPtr;
2997  static string strPrevMask=L"*.*";
2998  /* $ 20.05.2002 IS
2999     При обработке маски, если работаем с именем файла на панели,
3000     берем каждую квадратную скобку в имени при образовании маски в скобки,
3001     чтобы подобные имена захватывались полученной маской - это специфика,
3002     диктуемая CmpName.
3003  */
3004  string strMask=L"*.*", strRawMask;
3005  int Selection=0,I;
3006  bool WrapBrackets=false; // говорит о том, что нужно взять кв.скобки в скобки
3007
3008  if (CurFile>=FileCount)
3009    return;
3010
3011  int RawSelection=FALSE;
3012  if (PanelMode==PLUGIN_PANEL)
3013  {
3014    struct OpenPluginInfo Info;
3015    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3016    RawSelection=(Info.Flags & OPIF_RAWSELECTION);
3017  }
3018
3019  CurPtr=ListData[CurFile];
3020  string strCurName=(ShowShortNames && !CurPtr->strShortName.IsEmpty() ? CurPtr->strShortName:CurPtr->strName);
3021
3022  if (Mode==SELECT_ADDEXT || Mode==SELECT_REMOVEEXT)
3023  {
3024    const wchar_t *DotPtr=wcsrchr(strCurName,L'.');
3025    if (DotPtr!=NULL)
3026    {
3027      // Учтем тот момент, что расширение может содержать символы-разделители
3028      strRawMask.Format (L"\"*.%s\"", DotPtr+1);
3029      WrapBrackets=true;
3030    }
3031    else
3032      strMask = L"*.";
3033    Mode=(Mode==SELECT_ADDEXT) ? SELECT_ADD:SELECT_REMOVE;
3034  }
3035  else
3036  {
3037    if (Mode==SELECT_ADDNAME || Mode==SELECT_REMOVENAME)
3038    {
3039      // Учтем тот момент, что имя может содержать символы-разделители
3040      strRawMask.Format (L"\"%s", (const wchar_t*)strCurName);
3041
3042      wchar_t *DotPtr = strRawMask.GetBuffer ((int)strRawMask.GetLength()+4);
3043
3044      DotPtr=wcsrchr(DotPtr,L'.');
3045
3046      if (DotPtr!=NULL)
3047      {
3048        wcscpy(DotPtr,L".*\"");
3049        strRawMask.ReleaseBuffer ();
3050      }
3051      else
3052      {
3053        strRawMask.ReleaseBuffer ();
3054        strRawMask += ".*\"";
3055      }
3056      WrapBrackets=true;
3057      Mode=(Mode==SELECT_ADDNAME) ? SELECT_ADD:SELECT_REMOVE;
3058    }
3059    else
3060    {
3061      if (Mode==SELECT_ADD || Mode==SELECT_REMOVE)
3062      {
3063        SelectDlg[1].strData = strPrevMask;
3064        if (Mode==SELECT_ADD)
3065          SelectDlg[0].strData = UMSG(MSelectTitle);
3066        else
3067          SelectDlg[0].strData = UMSG(MUnselectTitle);
3068        {
3069          Dialog Dlg(SelectDlg,sizeof(SelectDlg)/sizeof(SelectDlg[0]));
3070          Dlg.SetHelp(L"SelectFiles");
3071          Dlg.SetPosition(-1,-1,55,7);
3072          for(;;)
3073          {
3074            Dlg.ClearDone();
3075            Dlg.Process();
3076            if (Dlg.GetExitCode()==4 && Filter.FilterEdit())
3077            {
3078              bUseFilter = true;
3079              break;
3080            }
3081            if (Dlg.GetExitCode()!=3)
3082              return;
3083            strMask = SelectDlg[1].strData;
3084            if(FileMask.Set(strMask, 0)) // Проверим вводимые пользователем маски на ошибки
3085            {
3086              strPrevMask = strMask;
3087              break;
3088            }
3089          }
3090        }
3091      }
3092    }
3093  }
3094  SaveSelection();
3095
3096  if(!bUseFilter && WrapBrackets) // возьмем кв.скобки в скобки, чтобы получить
3097  {                               // работоспособную маску
3098    const wchar_t *src=(const wchar_t*)strRawMask;
3099    strMask=(const wchar_t*)L"";
3100    while ( *src )
3101    {
3102      if(*src==L']' || *src==L'[')
3103      {
3104        add_char (strMask, L'[');
3105        add_char (strMask, *src);
3106        add_char (strMask, L']');
3107      }
3108      else
3109        add_char (strMask, *src);
3110
3111      src++;
3112    }
3113  }
3114
3115  if(bUseFilter || FileMask.Set(strMask, FMF_SILENT)) // Скомпилируем маски файлов и работаем
3116  {                                                // дальше в зависимости от успеха компиляции
3117    for (I=0; I < FileCount; I++)
3118    {
3119      CurPtr=ListData[I];
3120      int Match=FALSE;
3121      if (Mode==SELECT_INVERT || Mode==SELECT_INVERTALL)
3122        Match=TRUE;
3123      else
3124      {
3125        if (bUseFilter)
3126          Match=Filter.FileInFilter(CurPtr);
3127        else
3128          Match=FileMask.Compare((ShowShortNames && !CurPtr->strShortName.IsEmpty() ? CurPtr->strShortName:CurPtr->strName));
3129      }
3130
3131      if (Match)
3132      {
3133        switch(Mode)
3134        {
3135          case SELECT_ADD:
3136            Selection=1;
3137            break;
3138          case SELECT_REMOVE:
3139            Selection=0;
3140            break;
3141          case SELECT_INVERT:
3142          case SELECT_INVERTALL:
3143            Selection=!CurPtr->Selected;
3144            break;
3145        }
3146        if (bUseFilter || (CurPtr->FileAttr & FA_DIREC)==0 || Opt.SelectFolders ||
3147            Selection==0 || RawSelection || Mode==SELECT_INVERTALL)
3148          Select(CurPtr,Selection);
3149      }
3150    }
3151  }
3152
3153  if (SelectedFirst)
3154    SortFileList(TRUE);
3155  ShowFileList(TRUE);
3156}
3157
3158void FileList::UpdateViewPanel()
3159{
3160  Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3161  if (FileCount>0 && AnotherPanel->IsVisible() &&
3162      AnotherPanel->GetType()==QVIEW_PANEL && SetCurPath())
3163  {
3164    QuickView *ViewPanel=(QuickView *)AnotherPanel;
3165    struct FileListItem *CurPtr=ListData[CurFile];
3166    if (PanelMode!=PLUGIN_PANEL ||
3167        CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILE))
3168    {
3169      if (TestParentFolderName(CurPtr->strName))
3170        ViewPanel->ShowFile(strCurDir,FALSE,NULL);
3171      else
3172        ViewPanel->ShowFile(CurPtr->strName,FALSE,NULL);
3173    }
3174    else
3175      if ((CurPtr->FileAttr & FA_DIREC)==0)
3176      {
3177        string strTempDir,strFileName;
3178        strFileName = CurPtr->strName;
3179        if(!FarMkTempEx(strTempDir))
3180          return;
3181        CreateDirectoryW(strTempDir,NULL);
3182        struct PluginPanelItem PanelItem;
3183        FileListToPluginItem(CurPtr,&PanelItem);
3184        if (!CtrlObject->Plugins.GetFile(hPlugin,&PanelItem,strTempDir,strFileName,OPM_SILENT|OPM_VIEW|OPM_QUICKVIEW))
3185        {
3186          ViewPanel->ShowFile(NULL,FALSE,NULL);
3187          apiRemoveDirectory(strTempDir);
3188          return;
3189        }
3190        ViewPanel->ShowFile(strFileName,TRUE,NULL);
3191      }
3192      else
3193        if (!TestParentFolderName(CurPtr->strName))
3194          ViewPanel->ShowFile(CurPtr->strName,FALSE,hPlugin);
3195        else
3196          ViewPanel->ShowFile(NULL,FALSE,NULL);
3197
3198    SetTitle();
3199  }
3200}
3201
3202
3203void FileList::CompareDir()
3204{
3205  FileList *Another=(FileList *)CtrlObject->Cp()->GetAnotherPanel(this);
3206  int I,J;
3207  if (Another->GetType()!=FILE_PANEL || !Another->IsVisible())
3208  {
3209    Message(MSG_WARNING,1,UMSG(MCompareTitle),UMSG(MCompareFilePanelsRequired1),
3210            UMSG(MCompareFilePanelsRequired2),UMSG(MOk));
3211    return;
3212  }
3213
3214  ScrBuf.Flush();
3215
3216  // полностью снимаем выделение с обоих панелей
3217  ClearSelection();
3218  Another->ClearSelection();
3219
3220  struct FileListItem *CurPtr, *AnotherCurPtr;
3221  string strTempName1, strTempName2;
3222
3223  const wchar_t *PtrTempName1, *PtrTempName2;
3224  BOOL OpifRealnames1=FALSE, OpifRealnames2=FALSE;
3225
3226  // помечаем ВСЕ, кроме каталогов на активной панели
3227  for (I=0; I < FileCount; I++)
3228  {
3229    CurPtr = ListData[I];
3230    if((CurPtr->FileAttr & FA_DIREC)==0)
3231      Select(CurPtr,TRUE);
3232  }
3233
3234  // помечаем ВСЕ, кроме каталогов на пассивной панели
3235  for (J=0; J < Another->FileCount; J++)
3236  {
3237    AnotherCurPtr = Another->ListData[J];
3238    if((AnotherCurPtr->FileAttr & FA_DIREC)==0)
3239      Another->Select(AnotherCurPtr,TRUE);
3240  }
3241
3242  int CompareFatTime=FALSE;
3243  if (PanelMode==PLUGIN_PANEL)
3244  {
3245    struct OpenPluginInfo Info;
3246    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3247    if (Info.Flags & OPIF_COMPAREFATTIME)
3248      CompareFatTime=TRUE;
3249    OpifRealnames1=Info.Flags & OPIF_REALNAMES;
3250  }
3251  if (Another->PanelMode==PLUGIN_PANEL && !CompareFatTime)
3252  {
3253    struct OpenPluginInfo Info;
3254    CtrlObject->Plugins.GetOpenPluginInfo(Another->hPlugin,&Info);
3255    if (Info.Flags & OPIF_COMPAREFATTIME)
3256      CompareFatTime=TRUE;
3257    OpifRealnames2=Info.Flags & OPIF_REALNAMES;
3258  }
3259
3260  if (PanelMode==NORMAL_PANEL && Another->PanelMode==NORMAL_PANEL)
3261  {
3262    string strFileSystemName1, strFileSystemName2;
3263    string strRoot1, strRoot2;
3264
3265    GetPathRoot(strCurDir, strRoot1);
3266    GetPathRoot(Another->strCurDir, strRoot2);
3267
3268    if (apiGetVolumeInformation (strRoot1,NULL,NULL,NULL,NULL,&strFileSystemName1) &&
3269        apiGetVolumeInformation (strRoot2,NULL,NULL,NULL,NULL,&strFileSystemName2))
3270      if (StrCmpI(strFileSystemName1,strFileSystemName2)!=0)
3271        CompareFatTime=TRUE;
3272  }
3273
3274  // теперь начнем цикл по снятию выделений
3275  // каждый элемент активной панели...
3276  for (I=0; I < FileCount; I++)
3277  {
3278    CurPtr = ListData[I];
3279    // ...сравниваем с элементом пассивной панели...
3280    for (J=0; J < Another->FileCount; J++)
3281    {
3282      AnotherCurPtr = Another->ListData[J];
3283      int Cmp=0;
3284#if 0
3285      PtrTempName1=CurPtr->Name;
3286      PtrTempName2=AnotherCurPtr->Name;
3287
3288      int fp1=strpbrk(CurPtr->Name,":\\/")!=NULL;
3289      int fp2=strpbrk(AnotherCurPtr->Name,":\\/")!=NULL;
3290
3291      if(fp1 && !fp2 && strcmp(PtrTempName2,".."))
3292      {
3293        UnicodeToAnsi (Another->strCurDir, TempName2); //BUGBUG
3294        AddEndSlash(TempName2);
3295        strncat(TempName2,AnotherCurPtr->Name,sizeof(TempName2)-1);
3296        PtrTempName2=TempName2;
3297      }
3298      else if(!fp1 && fp2 && strcmp(PtrTempName1,".."))
3299      {
3300        strcpy(TempName1,CurDir);
3301        AddEndSlash(TempName1);
3302        strncat(TempName1,CurPtr->Name,sizeof(TempName1)-1);
3303        PtrTempName1=TempName1;
3304      }
3305
3306      if(OpifRealnames1 || OpifRealnames2)
3307      {
3308        PtrTempName1=PointToName(CurPtr->Name);
3309        PtrTempName2=PointToName(AnotherCurPtr->Name);
3310      }
3311#else
3312      PtrTempName1=PointToName(CurPtr->strName);
3313      PtrTempName2=PointToName(AnotherCurPtr->strName);
3314#endif
3315
3316      if (StrCmpI(PtrTempName1,PtrTempName2)==0)
3317      //if (LocalStricmp(CurPtr->Name,AnotherCurPtr->Name)==0)
3318      {
3319        if (CompareFatTime)
3320        {
3321          WORD DosDate,DosTime,AnotherDosDate,AnotherDosTime;
3322          FileTimeToDosDateTime(&CurPtr->WriteTime,&DosDate,&DosTime);
3323          FileTimeToDosDateTime(&AnotherCurPtr->WriteTime,&AnotherDosDate,&AnotherDosTime);
3324          DWORD FullDosTime,AnotherFullDosTime;
3325          FullDosTime=((DWORD)DosDate<<16)+DosTime;
3326          AnotherFullDosTime=((DWORD)AnotherDosDate<<16)+AnotherDosTime;
3327          int D=FullDosTime-AnotherFullDosTime;
3328          if (D>=-1 && D<=1)
3329            Cmp=0;
3330          else
3331            Cmp=(FullDosTime<AnotherFullDosTime) ? -1:1;
3332        }
3333        else
3334        {
3335          __int64 RetCompare=*(__int64*)&CurPtr->WriteTime - *(__int64*)&AnotherCurPtr->WriteTime;
3336          Cmp=!RetCompare?0:(RetCompare > 0?1:-1);
3337        }
3338
3339        if (Cmp==0 && (CurPtr->UnpSize != AnotherCurPtr->UnpSize) )
3340          continue;
3341
3342        if (Cmp < 1 && CurPtr->Selected)
3343          Select(CurPtr,0);
3344
3345        if (Cmp > -1 && AnotherCurPtr->Selected)
3346          Another->Select(AnotherCurPtr,0);
3347
3348        if (Another->PanelMode!=PLUGIN_PANEL)
3349          break;
3350      }
3351    }
3352  }
3353
3354  if (SelectedFirst)
3355    SortFileList(TRUE);
3356
3357  Redraw();
3358  Another->Redraw();
3359  if (SelFileCount==0 && Another->SelFileCount==0)
3360    Message(0,1,UMSG(MCompareTitle),UMSG(MCompareSameFolders1),UMSG(MCompareSameFolders2),UMSG(MOk));
3361}
3362
3363void FileList::CopyNames(int FillPathName,int UNC)
3364{
3365  struct OpenPluginInfo Info;
3366  wchar_t *CopyData=NULL;
3367  long DataSize=0;
3368  string strSelName, strSelShortName, strQuotedName;
3369  int FileAttr;
3370
3371  if (PanelMode==PLUGIN_PANEL)
3372  {
3373    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3374  }
3375
3376  GetSelName(NULL,FileAttr);
3377  while (GetSelName(&strSelName,FileAttr,&strSelShortName))
3378  {
3379    if (DataSize>0)
3380    {
3381      wcscat(CopyData+DataSize,L"\r\n");
3382      DataSize+=2;
3383    }
3384    strQuotedName = (ShowShortNames && !strSelShortName.IsEmpty()) ? strSelShortName:strSelName;
3385    if(FillPathName)
3386    {
3387
3388      if (PanelMode!=PLUGIN_PANEL || (Info.Flags & OPIF_REALNAMES))
3389      {
3390        /* $ 14.02.2002 IS
3391           ".." в текущем каталоге обработаем как имя текущего каталога
3392        */
3393        if(TestParentFolderName(strQuotedName) && TestParentFolderName(strSelShortName))
3394        {
3395                                        strQuotedName.SetLength(1);
3396                                        strSelShortName.SetLength(1);
3397        }
3398        if(!CreateFullPathName(strQuotedName,strSelShortName,FileAttr,strQuotedName,UNC))
3399        {
3400          if (CopyData)
3401          {
3402            xf_free(CopyData);
3403            CopyData=NULL;
3404          }
3405          break;
3406        }
3407      }
3408      else
3409      {
3410        string strFullName = NullToEmpty(Info.CurDir);
3411
3412        if (Opt.PanelCtrlFRule && ViewSettings.FolderUpperCase)
3413          strFullName.Upper();
3414
3415        if ( !strFullName.IsEmpty() )
3416          AddEndSlash(strFullName);
3417
3418        if(Opt.PanelCtrlFRule)
3419        {
3420          // имя должно отвечать условиям на панели
3421          if (ViewSettings.FileLowerCase && !(FileAttr & FA_DIREC))
3422            strQuotedName.Lower();
3423          if (ViewSettings.FileUpperToLowerCase)
3424            if (!(FileAttr & FA_DIREC) && !IsCaseMixed(strQuotedName))
3425               strQuotedName.Lower();
3426        }
3427        strFullName += strQuotedName;
3428        strQuotedName = strFullName;
3429        // добавим первый префикс!
3430        if(PanelMode==PLUGIN_PANEL && Opt.SubstPluginPrefix)
3431        {
3432          string strPrefix;
3433          /* $ 19.11.2001 IS оптимизация по скорости :) */
3434          if(*AddPluginPrefix((FileList *)CtrlObject->Cp()->ActivePanel,strPrefix))
3435          {
3436            strPrefix += strQuotedName;
3437            strQuotedName = strPrefix;
3438          }
3439        }
3440      }
3441    }
3442    if(Opt.QuotedName&QUOTEDNAME_CLIPBOARD)
3443      QuoteSpace(strQuotedName);
3444    int Length=(int)strQuotedName.GetLength();
3445    wchar_t *NewPtr=(wchar_t *)xf_realloc(CopyData, (DataSize+Length+3)*sizeof (wchar_t));
3446    if (NewPtr==NULL)
3447    {
3448        if (CopyData)
3449        {
3450        xf_free(CopyData);
3451        CopyData=NULL;
3452      }
3453      break;
3454    }
3455    CopyData=NewPtr;
3456    CopyData[DataSize]=0;
3457
3458    wcscpy (CopyData+DataSize, strQuotedName);
3459    DataSize+=Length;
3460  }
3461
3462  CopyToClipboard(CopyData);
3463  xf_free(CopyData);
3464}
3465
3466string &FileList::CreateFullPathName(const wchar_t *Name, const wchar_t *ShortName,DWORD FileAttr, string &strDest, int UNC,int ShortNameAsIs)
3467{
3468  //wchar_t *NamePtr;
3469  wchar_t Chr=0;
3470
3471  string strFileName;
3472  string strTemp;
3473
3474  strFileName = strDest;
3475
3476  const wchar_t *ShortNameLastSlash=wcsrchr(ShortName, L'\\'), *NameLastSlash=wcsrchr(Name, L'\\');
3477
3478  if (NULL==ShortNameLastSlash && NULL==NameLastSlash)
3479    ConvertNameToFull(strFileName, strFileName);
3480  else
3481
3482  if(ShowShortNames)
3483  {
3484    strTemp = Name;
3485
3486    wchar_t *lpwszTemp = strTemp.GetBuffer ();
3487
3488    if(NameLastSlash)
3489      lpwszTemp[1+NameLastSlash-Name]=0;
3490
3491    strTemp.ReleaseBuffer();
3492
3493    const wchar_t *NamePtr = wcsrchr(strFileName, L'\\');
3494
3495    if(NamePtr != NULL)
3496      NamePtr++;
3497    else
3498      NamePtr=strFileName;
3499
3500    strTemp += NameLastSlash?NameLastSlash+1:Name; //??? NamePtr??? BUGBUG
3501    strFileName = strTemp;
3502  }
3503  if (ShowShortNames && ShortNameAsIs)
3504    ConvertNameToShort(strFileName,strFileName);
3505
3506  /* $ 29.01.2001 VVM
3507    + По CTRL+ALT+F в командную строку сбрасывается UNC-имя текущего файла. */
3508  if (UNC)
3509  {
3510    // Посмотрим на тип файловой системы
3511    string strFileSystemName;
3512    GetPathRoot(strFileName,strTemp);
3513
3514    if(!apiGetVolumeInformation (strTemp,NULL,NULL,NULL,NULL,&strFileSystemName))
3515      strFileSystemName=L"";
3516
3517
3518    UNIVERSAL_NAME_INFOW uni;
3519    DWORD uniSize = sizeof(uni);
3520    // применяем WNetGetUniversalName для чего угодно, только не для Novell`а
3521    if (StrCmpI(strFileSystemName,L"NWFS") != 0 &&
3522        WNetGetUniversalNameW(strFileName, UNIVERSAL_NAME_INFO_LEVEL,&uni, &uniSize) == NOERROR)
3523    {
3524        strFileName = uni.lpUniversalName;
3525    }
3526    else if(strFileName.At(1) == L':')
3527    {
3528      // BugZ#449 - Неверная работа CtrlAltF с ресурсами Novell DS
3529      // Здесь, если не получилось получить UniversalName и если это
3530      // мапленный диск - получаем как для меню выбора дисков
3531
3532
3533      /*if(*DriveLocalToRemoteName(DRIVE_UNKNOWN,*FileName,Temp) != 0)
3534      {
3535        if((NamePtr=wcschr(strFileName, L'/')) == NULL)
3536          NamePtr=wcschr(strFileName, L'\\');
3537        if(NamePtr != NULL)
3538        {
3539          AddEndSlashW(strTemp);
3540
3541          NamePtr++;
3542          strTemp += NamePtr;
3543        }
3544
3545        strFileName = strTemp;
3546      }*/ //BUGBUG
3547    }
3548
3549    ConvertNameToReal(strFileName,strFileName);
3550  } /* if */
3551
3552  // $ 20.10.2000 SVS Сделаем фичу Ctrl-F опциональной!
3553  if(Opt.PanelCtrlFRule)
3554  {
3555    /* $ 13.10.2000 tran
3556      по Ctrl-f имя должно отвечать условиям на панели */
3557    if (ViewSettings.FolderUpperCase)
3558    {
3559      if ( FileAttr & FA_DIREC )
3560        strFileName.Upper();
3561      else
3562      {
3563          wchar_t *lpwszFileName = strFileName.GetBuffer();
3564          wchar_t *NamePtr=(wchar_t *)wcsrchr(lpwszFileName,L'\\');
3565
3566          if(NamePtr != NULL)
3567          {
3568            Chr=*NamePtr;
3569            *NamePtr=0;
3570          }
3571
3572          CharUpperW (lpwszFileName);
3573
3574          if(NamePtr)
3575            *NamePtr=Chr;
3576
3577          strFileName.ReleaseBuffer();
3578      }
3579    }
3580    if (ViewSettings.FileUpperToLowerCase)
3581      if (!(FileAttr & FA_DIREC) && wcsrchr(strFileName,L'\\') && !IsCaseMixed(wcsrchr(strFileName,L'\\')))
3582      {
3583          wchar_t *lpwszFileName = strFileName.GetBuffer();
3584
3585          lpwszFileName = wcsrchr (lpwszFileName, L'\\');
3586          CharLowerW (lpwszFileName);
3587
3588          strFileName.ReleaseBuffer();
3589      }
3590    if ( ViewSettings.FileLowerCase && wcsrchr(strFileName,L'\\') && !(FileAttr & FA_DIREC))
3591    {
3592        wchar_t *lpwszFileName = strFileName.GetBuffer();
3593
3594        lpwszFileName = wcsrchr (lpwszFileName, L'\\');
3595        CharLowerW (lpwszFileName);
3596
3597        strFileName.ReleaseBuffer();
3598    }
3599  }
3600
3601  strDest = strFileName;
3602
3603  return strDest;
3604}
3605
3606
3607void FileList::SetTitle()
3608{
3609  if (GetFocus() || CtrlObject->Cp()->GetAnotherPanel(this)->GetType()!=FILE_PANEL)
3610  {
3611    string strTitleDir = L"{";
3612    if (PanelMode==PLUGIN_PANEL)
3613    {
3614      struct OpenPluginInfo Info;
3615
3616      CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3617
3618      string strPluginTitle = NullToEmpty(Info.PanelTitle);
3619
3620      RemoveExternalSpaces(strPluginTitle);
3621
3622      strTitleDir += strPluginTitle;
3623    }
3624    else
3625      strTitleDir += strCurDir;
3626
3627    strTitleDir += L"}";
3628
3629    strLastFarTitle = strTitleDir; //BUGBUG;
3630    SetFarTitle(strTitleDir);
3631  }
3632}
3633
3634
3635void FileList::ClearSelection()
3636{
3637  struct FileListItem *CurPtr;
3638  for (int I=0; I < FileCount; I++)
3639  {
3640    CurPtr = ListData[I];
3641    Select(CurPtr,0);
3642  }
3643
3644  if (SelectedFirst)
3645    SortFileList(TRUE);
3646}
3647
3648
3649void FileList::SaveSelection()
3650{
3651  struct FileListItem *CurPtr;
3652  for (int I=0; I < FileCount; I++)
3653  {
3654    CurPtr = ListData[I];
3655    CurPtr->PrevSelected=CurPtr->Selected;
3656  }
3657}
3658
3659
3660void FileList::RestoreSelection()
3661{
3662  struct FileListItem *CurPtr;
3663  for (int I=0; I < FileCount; I++)
3664  {
3665    CurPtr = ListData[I];
3666    int NewSelection=CurPtr->PrevSelected;
3667    CurPtr->PrevSelected=CurPtr->Selected;
3668    Select(CurPtr,NewSelection);
3669  }
3670  if (SelectedFirst)
3671    SortFileList(TRUE);
3672  Redraw();
3673}
3674
3675
3676
3677int FileList::GetFileName(string &strName,int Pos,int &FileAttr)
3678{
3679  if (Pos>=FileCount)
3680    return(FALSE);
3681
3682  strName = ListData[Pos]->strName;
3683
3684  FileAttr=ListData[Pos]->FileAttr;
3685  return(TRUE);
3686}
3687
3688
3689int FileList::GetCurrentPos()
3690{
3691  return(CurFile);
3692}
3693
3694
3695void FileList::EditFilter()
3696{
3697  if (Filter==NULL)
3698    Filter=new FileFilter(this,FFT_PANEL);
3699  Filter->FilterEdit();
3700}
3701
3702
3703void FileList::SelectSortMode()
3704{
3705  struct MenuDataEx SortMenu[]=
3706  {
3707   /* 00 */(const wchar_t *)MMenuSortByName,LIF_SELECTED,KEY_CTRLF3,
3708   /* 01 */(const wchar_t *)MMenuSortByExt,0,KEY_CTRLF4,
3709   /* 02 */(const wchar_t *)MMenuSortByModification,0,KEY_CTRLF5,
3710   /* 03 */(const wchar_t *)MMenuSortBySize,0,KEY_CTRLF6,
3711   /* 04 */(const wchar_t *)MMenuUnsorted,0,KEY_CTRLF7,
3712   /* 05 */(const wchar_t *)MMenuSortByCreation,0,KEY_CTRLF8,
3713   /* 06 */(const wchar_t *)MMenuSortByAccess,0,KEY_CTRLF9,
3714   /* 07 */(const wchar_t *)MMenuSortByDiz,0,KEY_CTRLF10,
3715   /* 08 */(const wchar_t *)MMenuSortByOwner,0,KEY_CTRLF11,
3716   /* 09 */(const wchar_t *)MMenuSortByCompressedSize,0,0,
3717   /* 10 */(const wchar_t *)MMenuSortByNumLinks,0,0,
3718   /* 11 */L"",LIF_SEPARATOR,0,
3719   /* 12 */(const wchar_t *)MMenuSortUseNumeric,0,0,
3720   /* 13 */(const wchar_t *)MMenuSortUseGroups,0,KEY_SHIFTF11,
3721   /* 14 */(const wchar_t *)MMenuSortSelectedFirst,0,KEY_SHIFTF12,
3722  };
3723
3724  static int SortModes[]={BY_NAME,   BY_EXT,    BY_MTIME,
3725                          BY_SIZE,   UNSORTED,  BY_CTIME,
3726                          BY_ATIME,  BY_DIZ,    BY_OWNER,
3727                          BY_COMPRESSEDSIZE,BY_NUMLINKS};
3728
3729  for (int I=0;I<sizeof(SortModes)/sizeof(SortModes[0]);I++)
3730    if (SortMode==SortModes[I])
3731    {
3732      SortMenu[I].SetCheck(SortOrder==1 ? L'+':L'-');
3733      break;
3734    }
3735
3736  int SG=GetSortGroups();
3737  SortMenu[12].SetCheck(NumericSort);
3738  SortMenu[13].SetCheck(SG);
3739  SortMenu[14].SetCheck(SelectedFirst);
3740
3741  int SortCode;
3742  {
3743    VMenu SortModeMenu(UMSG(MMenuSortTitle),SortMenu,sizeof(SortMenu)/sizeof(SortMenu[0]),0);
3744
3745    SortModeMenu.SetHelp(L"PanelCmdSort");
3746    SortModeMenu.SetPosition(X1+4,-1,0,0);
3747    SortModeMenu.SetFlags(VMENU_WRAPMODE);
3748    SortModeMenu.Process();
3749    if ((SortCode=SortModeMenu.Modal::GetExitCode())<0)
3750      return;
3751  }
3752  if (SortCode<sizeof(SortModes)/sizeof(SortModes[0]))
3753    SetSortMode(SortModes[SortCode]);
3754  else
3755    switch(SortCode)
3756    {
3757      case 13:
3758        ProcessKey(KEY_SHIFTF11);
3759        break;
3760      case 14:
3761        ProcessKey(KEY_SHIFTF12);
3762        break;
3763      case 12:
3764        NumericSort=NumericSort?0:1;
3765        Update(UPDATE_KEEP_SELECTION);
3766        Redraw();
3767        Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3768        AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
3769        AnotherPanel->Redraw();
3770        break;
3771    }
3772}
3773
3774
3775void FileList::DeleteDiz(const wchar_t *Name, const wchar_t *ShortName)
3776{
3777  if (PanelMode==NORMAL_PANEL)
3778    Diz.DeleteDiz(Name,ShortName);
3779}
3780
3781
3782void FileList::FlushDiz()
3783{
3784  if (PanelMode==NORMAL_PANEL)
3785    Diz.Flush(strCurDir);
3786}
3787
3788
3789void FileList::GetDizName(string &strDizName)
3790{
3791  if (PanelMode==NORMAL_PANEL)
3792    Diz.GetDizName(strDizName);
3793}
3794
3795
3796void FileList::CopyDiz(const wchar_t *Name, const wchar_t *ShortName,const wchar_t *DestName,
3797                       const wchar_t *DestShortName,DizList *DestDiz)
3798{
3799  Diz.CopyDiz(Name,ShortName,DestName,DestShortName,DestDiz);
3800}
3801
3802
3803void FileList::DescribeFiles()
3804{
3805  string strSelName, strSelShortName;
3806  int FileAttr,DizCount=0;
3807
3808  ReadDiz();
3809
3810  SaveSelection();
3811  GetSelName(NULL,FileAttr);
3812  Panel* AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3813  int AnotherType=AnotherPanel->GetType();
3814
3815  while (GetSelName(&strSelName,FileAttr,&strSelShortName))
3816  {
3817    string strDizText, strMsg, strTruncMsg, strQuotedName;
3818    const wchar_t *PrevText;
3819    PrevText=Diz.GetDizTextAddr(strSelName,strSelShortName,GetLastSelectedSize());
3820    strQuotedName = strSelName;
3821    QuoteSpaceOnly(strQuotedName);
3822    strMsg.Format (UMSG(MEnterDescription),(const wchar_t*)strQuotedName);
3823    strTruncMsg.Format (L"%.65s",(const wchar_t*)strMsg);
3824    /* $ 09.08.2000 SVS
3825       Для Ctrl-Z ненужно брать предыдущее значение!
3826    */
3827    if (!GetString(UMSG(MDescribeFiles),strTruncMsg,L"DizText",
3828                   PrevText!=NULL ? PrevText:L"",strDizText,1024,
3829                   L"FileDiz",FIB_ENABLEEMPTY|(!DizCount?FIB_NOUSELASTHISTORY:0)|FIB_BUTTONS))
3830      break;
3831
3832    DizCount++;
3833    if ( strDizText.IsEmpty() )
3834      Diz.DeleteDiz(strSelName,strSelShortName);
3835    else
3836    {
3837      string strDizLine;
3838      strDizLine.Format (L"%-*s %s",Opt.Diz.StartPos>1 ? Opt.Diz.StartPos-2:0, (const wchar_t*)strQuotedName, (const wchar_t*)strDizText);
3839      Diz.AddDiz(strSelName,strSelShortName,strDizLine);
3840    }
3841    ClearLastGetSelection();
3842    // BugZ#442 - Deselection is late when making file descriptions
3843    FlushDiz();
3844    // BugZ#863 - При редактировании группы дескрипшенов они не обновляются на ходу
3845    //if (AnotherType==QVIEW_PANEL) continue; //TODO ???
3846    if (AnotherType==INFO_PANEL) AnotherPanel->Update(UIC_UPDATE_NORMAL);
3847    Update(UPDATE_KEEP_SELECTION);
3848    Redraw();
3849  }
3850  /*if (DizCount>0)
3851  {
3852    FlushDiz();
3853    Update(UPDATE_KEEP_SELECTION);
3854    Redraw();
3855    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3856    AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
3857    AnotherPanel->Redraw();
3858  }*/
3859}
3860
3861
3862void FileList::SetReturnCurrentFile(int Mode)
3863{
3864  ReturnCurrentFile=Mode;
3865}
3866
3867
3868bool FileList::ApplyCommand()
3869{
3870  static string strPrevCommand;
3871  string strCommand;
3872
3873  if (!GetString(UMSG(MAskApplyCommandTitle),UMSG(MAskApplyCommand),L"ApplyCmd",strPrevCommand,strCommand,260, L"ApplyCmd",FIB_BUTTONS) || !SetCurPath())
3874    return false;
3875
3876  strPrevCommand = strCommand;
3877  string strSelName, strSelShortName;
3878  int FileAttr;
3879  int RdrwDskt=CtrlObject->MainKeyBar->IsVisible();
3880
3881  RedrawDesktop Redraw(TRUE);
3882  SaveSelection();
3883
3884  GetSelName(NULL,FileAttr);
3885  while (GetSelName(&strSelName,FileAttr,&strSelShortName) && !CheckForEsc())
3886  {
3887    string strConvertedCommand;
3888    string strListName, strAnotherListName;
3889    string strShortListName, strAnotherShortListName;
3890
3891    strConvertedCommand = strCommand;
3892
3893    {
3894      int PreserveLFN=SubstFileName(strConvertedCommand,strSelName,strSelShortName,&strListName,&strAnotherListName,&strShortListName, &strAnotherShortListName);
3895      PreserveLongName PreserveName(strSelShortName,PreserveLFN);
3896
3897      Execute(strConvertedCommand,FALSE,FALSE);
3898
3899      ClearLastGetSelection();
3900    }
3901  }
3902  /*$ 23.07.2001 SKV
3903    что бы не затирать последнюю строку вывода.
3904  */
3905  if(RdrwDskt)
3906  {
3907    ScrBuf.Scroll(1);
3908    ScrBuf.Flush();
3909  }
3910  return true;
3911}
3912
3913
3914void FileList::CountDirSize(DWORD PluginFlags)
3915{
3916  unsigned long DirCount,DirFileCount,ClusterSize;;
3917  unsigned __int64 FileSize,CompressedFileSize,RealFileSize;
3918  unsigned long SelDirCount=0;
3919  struct FileListItem *CurPtr;
3920  int I;
3921
3922  /* $ 09.11.2000 OT
3923    F3 на ".." в плагинах
3924  */
3925  if ( PanelMode==PLUGIN_PANEL && !CurFile && TestParentFolderName(ListData[0]->strName))
3926  {
3927    struct FileListItem *DoubleDotDir = NULL;
3928    if (SelFileCount)
3929    {
3930      DoubleDotDir = ListData[0];
3931      for (I=0; I < FileCount; I++)
3932      {
3933        CurPtr = ListData[I];
3934        if (CurPtr->Selected && (CurPtr->FileAttr & FA_DIREC))
3935        {
3936          DoubleDotDir = NULL;
3937          break;
3938        }
3939      }
3940    }
3941    else
3942    {
3943      DoubleDotDir = ListData[0];
3944    }
3945
3946    if (DoubleDotDir)
3947    {
3948      DoubleDotDir->ShowFolderSize=1;
3949      DoubleDotDir->UnpSize     = 0;
3950      DoubleDotDir->PackSize    = 0;
3951      for (I=1; I < FileCount; I++)
3952      {
3953        CurPtr = ListData[I];
3954        if (CurPtr->FileAttr & FA_DIREC)
3955        {
3956          if (GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize))
3957          {
3958            DoubleDotDir->UnpSize += FileSize;
3959            DoubleDotDir->PackSize += CompressedFileSize;
3960          }
3961        }
3962        else
3963        {
3964          DoubleDotDir->UnpSize     += CurPtr->UnpSize;
3965          DoubleDotDir->PackSize    += CurPtr->PackSize;
3966        }
3967      }
3968    }
3969  }
3970
3971  for (I=0; I < FileCount; I++)
3972  {
3973    CurPtr = ListData[I];
3974    if (CurPtr->Selected && (CurPtr->FileAttr & FA_DIREC))
3975    {
3976      SelDirCount++;
3977      if (PanelMode==PLUGIN_PANEL && !(PluginFlags & OPIF_REALNAMES) &&
3978          GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize)
3979        ||
3980          (PanelMode!=PLUGIN_PANEL || (PluginFlags & OPIF_REALNAMES)) &&
3981          GetDirInfo(UMSG(MDirInfoViewTitle),
3982                     CurPtr->strName,
3983                     DirCount,DirFileCount,FileSize,
3984                     CompressedFileSize,RealFileSize, ClusterSize,0,Filter,GETDIRINFO_DONTREDRAWFRAME|GETDIRINFO_SCANSYMLINKDEF)==1)
3985      {
3986        SelFileSize -= CurPtr->UnpSize;
3987        SelFileSize += FileSize;
3988        CurPtr->UnpSize = FileSize;
3989        CurPtr->PackSize = CompressedFileSize;
3990        CurPtr->ShowFolderSize=1;
3991      }
3992      else
3993        break;
3994    }
3995  }
3996
3997  CurPtr=ListData[CurFile];
3998
3999  if (SelDirCount==0)
4000  {
4001    if (PanelMode==PLUGIN_PANEL && !(PluginFlags & OPIF_REALNAMES) &&
4002        GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize)
4003      ||
4004        (PanelMode!=PLUGIN_PANEL || (PluginFlags & OPIF_REALNAMES)) &&
4005        GetDirInfo(UMSG(MDirInfoViewTitle),
4006                   TestParentFolderName(CurPtr->strName) ? L".":CurPtr->strName,
4007                   DirCount,
4008                   DirFileCount,FileSize,CompressedFileSize,RealFileSize,ClusterSize,0,Filter,GETDIRINFO_DONTREDRAWFRAME|GETDIRINFO_SCANSYMLINKDEF)==1)
4009    {
4010      CurPtr->UnpSize = FileSize;
4011      CurPtr->PackSize = CompressedFileSize;
4012      CurPtr->ShowFolderSize=1;
4013    }
4014  }
4015
4016  SortFileList(TRUE);
4017  ShowFileList(TRUE);
4018  CtrlObject->Cp()->Redraw();
4019  CreateChangeNotification(TRUE);
4020}
4021
4022
4023int FileList::GetPrevViewMode()
4024{
4025  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4026    return(PluginsStack[0]->PrevViewMode);
4027  else
4028    return(ViewMode);
4029}
4030
4031
4032int FileList::GetPrevSortMode()
4033{
4034  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4035    return(PluginsStack[0]->PrevSortMode);
4036  else
4037    return(SortMode);
4038}
4039
4040
4041int FileList::GetPrevSortOrder()
4042{
4043  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4044    return(PluginsStack[0]->PrevSortOrder);
4045  else
4046    return(SortOrder);
4047}
4048
4049int FileList::GetPrevNumericSort()
4050{
4051  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4052    return(PluginsStack[0]->PrevNumericSort);
4053  else
4054    return(NumericSort);
4055}
4056
4057
4058HANDLE FileList::OpenFilePlugin(const wchar_t *FileName,int PushPrev)
4059{
4060  if (!PushPrev && PanelMode==PLUGIN_PANEL)
4061    while (1)
4062    {
4063      if (ProcessPluginEvent(FE_CLOSE,NULL))
4064        return((HANDLE)-2);
4065      if (!PopPlugin(TRUE))
4066        break;
4067    }
4068  HANDLE hNewPlugin=OpenPluginForFile(FileName);
4069  if (hNewPlugin!=INVALID_HANDLE_VALUE && hNewPlugin!=(HANDLE)-2)
4070  {
4071    if (PushPrev)
4072    {
4073
4074      PrevDataStack=(PrevDataItem **)xf_realloc(PrevDataStack,(PrevDataStackSize+1)*sizeof(PrevDataItem*));
4075
4076      PrevDataStack[PrevDataStackSize] = new PrevDataItem;
4077
4078      PrevDataStack[PrevDataStackSize]->PrevListData=ListData;
4079      PrevDataStack[PrevDataStackSize]->PrevFileCount=FileCount;
4080      PrevDataStack[PrevDataStackSize]->PrevTopFile = CurTopFile;
4081      PrevDataStack[PrevDataStackSize]->strPrevName = FileName;
4082      PrevDataStackSize++;
4083      ListData=NULL;
4084      FileCount=0;
4085    }
4086
4087    BOOL WasFullscreen = IsFullScreen();
4088
4089    SetPluginMode(hNewPlugin,FileName);  // SendOnFocus??? true???
4090    PanelMode=PLUGIN_PANEL;
4091    UpperFolderTopFile=CurTopFile;
4092    CurFile=0;
4093    Update(0);
4094    Redraw();
4095    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
4096    if ( (AnotherPanel->GetType()==INFO_PANEL) || WasFullscreen )
4097      AnotherPanel->Redraw();
4098  }
4099  return(hNewPlugin);
4100}
4101
4102
4103void FileList::ProcessCopyKeys(int Key)
4104{
4105  if (FileCount>0)
4106  {
4107    int Drag=Key==KEY_DRAGCOPY || Key==KEY_DRAGMOVE;
4108    int Ask=!Drag || Opt.Confirm.Drag;
4109    int Move=(Key==KEY_F6 || Key==KEY_DRAGMOVE);
4110    int AnotherDir=FALSE;
4111    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
4112    if (AnotherPanel->GetType()==FILE_PANEL)
4113    {
4114      FileList *AnotherFilePanel=(FileList *)AnotherPanel;
4115      if (AnotherFilePanel->FileCount>0 &&
4116          (AnotherFilePanel->ListData[AnotherFilePanel->CurFile]->FileAttr & FA_DIREC) &&
4117          !TestParentFolderName(AnotherFilePanel->ListData[AnotherFilePanel->CurFile]->strName))
4118      {
4119        AnotherDir=TRUE;
4120        if (Drag)
4121        {
4122          AnotherPanel->ProcessKey(KEY_ENTER);
4123          SetCurPath();
4124        }
4125      }
4126    }
4127    if (PanelMode==PLUGIN_PANEL && !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILES))
4128    {
4129      if (Key!=KEY_ALTF6)
4130      {
4131        string strPluginDestPath;
4132        int ToPlugin=FALSE;
4133        if (AnotherPanel->GetMode()==PLUGIN_PANEL && AnotherPanel->IsVisible() &&
4134            !CtrlObject->Plugins.UseFarCommand(AnotherPanel->GetPluginHandle(),PLUGIN_FARPUTFILES))
4135        {
4136          ToPlugin=2;
4137          ShellCopy ShCopy(this,Move,FALSE,FALSE,Ask,ToPlugin,strPluginDestPath);
4138        }
4139        if (ToPlugin!=-1)
4140          if (ToPlugin)
4141            PluginToPluginFiles(Move);
4142          else
4143          {
4144            string strDestPath;
4145            if ( !strPluginDestPath.IsEmpty() )
4146              strDestPath = strPluginDestPath;
4147            else
4148            {
4149              AnotherPanel->GetCurDir(strDestPath);
4150              if(!AnotherPanel->IsVisible())
4151              {
4152                struct OpenPluginInfo Info;
4153                CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
4154                if (Info.HostFile!=NULL && *Info.HostFile!=0)
4155                {
4156                  wchar_t *ExtPtr;
4157                  strDestPath = PointToName(Info.HostFile);
4158
4159                  ExtPtr = strDestPath.GetBuffer();
4160
4161                  if ( (ExtPtr=wcsrchr(ExtPtr, L'.')) != NULL )
4162                      *ExtPtr = 0;
4163
4164                  strDestPath.ReleaseBuffer();
4165                }
4166              }
4167            }
4168
4169            PluginGetFiles(strDestPath,Move);
4170          }
4171      }
4172    }
4173    else
4174    {
4175      int ToPlugin=AnotherPanel->GetMode()==PLUGIN_PANEL &&
4176                    AnotherPanel->IsVisible() && Key!=KEY_ALTF6 &&
4177                    !CtrlObject->Plugins.UseFarCommand(AnotherPanel->GetPluginHandle(),PLUGIN_FARPUTFILES);
4178
4179      if(Key != KEY_ALTF6 ||
4180        (Key == KEY_ALTF6 && WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT))
4181      {
4182         ShellCopy ShCopy(this,Move,Key==KEY_ALTF6,FALSE,Ask,ToPlugin,NULL);
4183      }
4184
4185      if (ToPlugin==1)
4186        PluginPutFilesToAnother(Move,AnotherPanel);
4187    }
4188    if (AnotherDir && Drag)
4189      AnotherPanel->ProcessKey(KEY_ENTER);
4190  }
4191}
4192
4193void FileList::SetSelectedFirstMode(int Mode)
4194{
4195  SelectedFirst=Mode;
4196  SortFileList(TRUE);
4197}
4198
4199void FileList::ChangeSortOrder(int NewOrder)
4200{
4201  Panel::ChangeSortOrder(NewOrder);
4202  SortFileList(TRUE);
4203  Show();
4204}
4205
4206BOOL FileList::UpdateKeyBar()
4207{
4208  KeyBar *KB=CtrlObject->MainKeyBar;
4209
4210  KB->SetAllGroup (KBL_MAIN, MF1, 12);
4211  KB->SetAllGroup (KBL_SHIFT, MShiftF1, 12);
4212  KB->SetAllGroup (KBL_ALT, MAltF1, 12);
4213  KB->SetAllGroup (KBL_CTRL, MCtrlF1, 12);
4214  KB->SetAllGroup (KBL_CTRLSHIFT, MCtrlShiftF1, 12);
4215  KB->SetAllGroup (KBL_CTRLALT, MCtrlAltF1, 12);
4216  KB->SetAllGroup (KBL_ALTSHIFT, MAltShiftF1, 12);
4217
4218  if(WinVer.dwPlatformId != VER_PLATFORM_WIN32_NT)
4219    KB->Change(KBL_ALT,L"",6-1);
4220
4221  KB->ReadRegGroup(L"Shell",Opt.strLanguage);
4222  KB->SetAllRegGroup();
4223
4224  if (GetMode() == PLUGIN_PANEL)
4225  {
4226    struct OpenPluginInfo Info;
4227    GetOpenPluginInfo(&Info);
4228    if (Info.KeyBar)
4229    {
4230      KB->Set((const wchar_t **)Info.KeyBar->Titles,12);
4231      KB->SetShift((const wchar_t **)Info.KeyBar->ShiftTitles,12);
4232      KB->SetAlt((const wchar_t **)Info.KeyBar->AltTitles,12);
4233      KB->SetCtrl((const wchar_t **)Info.KeyBar->CtrlTitles,12);
4234      if(Info.StructSize >= sizeof(struct OpenPluginInfo))
4235      {
4236        KB->SetCtrlShift((const wchar_t **)Info.KeyBar->CtrlShiftTitles,12);
4237        KB->SetAltShift((const wchar_t **)Info.KeyBar->AltShiftTitles,12);
4238        KB->SetCtrlAlt((const wchar_t **)Info.KeyBar->CtrlAltTitles,12);
4239      }
4240    }
4241  }
4242
4243  return TRUE;
4244}
4245
4246int FileList::PluginPanelHelp(HANDLE hPlugin)
4247{
4248  string strPath, strFileName, strStartTopic;
4249
4250  PluginHandle *ph = (PluginHandle*)hPlugin;
4251
4252  strPath = ph->pPlugin->GetModuleName();
4253
4254  CutToSlash(strPath);
4255
4256  int nCodePage = CP_OEMCP;
4257
4258  FILE *HelpFile=Language::OpenLangFile(strPath,HelpFileMask,Opt.strHelpLanguage,strFileName, nCodePage);
4259  if (HelpFile==NULL)
4260    return(FALSE);
4261  fclose(HelpFile);
4262  strStartTopic.Format(HelpFormatLink,(const wchar_t*)strPath,L"Contents");
4263  Help PanelHelp(strStartTopic);
4264  return(TRUE);
4265}
4266
4267/* $ 19.11.2001 IS
4268     для файловых панелей с реальными файлами никакого префикса не добавляем
4269*/
4270string &FileList::AddPluginPrefix(FileList *SrcPanel,string &strPrefix)
4271{
4272        strPrefix = L"";
4273        if(Opt.SubstPluginPrefix && SrcPanel->GetMode()==PLUGIN_PANEL)
4274        {
4275                OpenPluginInfo Info;
4276                PluginHandle *ph = (PluginHandle*)SrcPanel->hPlugin;
4277
4278                CtrlObject->Plugins.GetOpenPluginInfo(ph,&Info);
4279
4280                if(!(Info.Flags & OPIF_REALNAMES))
4281                {
4282                        PluginInfo PInfo;
4283
4284                        CtrlObject->Plugins.GetPluginInfo(ph->pPlugin, &PInfo);
4285
4286                        if(PInfo.CommandPrefix && *PInfo.CommandPrefix)
4287                        {
4288                                strPrefix = PInfo.CommandPrefix;
4289
4290                                wchar_t *Ptr=strPrefix.GetBuffer ();
4291
4292                                Ptr = wcschr(Ptr, L':');
4293
4294                                if(Ptr)
4295                                {
4296                                        *++Ptr=0;
4297                                        strPrefix.ReleaseBuffer();
4298                                }
4299                                else
4300                                {
4301                                        strPrefix.ReleaseBuffer();
4302                                        strPrefix += L":";
4303                                }
4304                        }
4305                }
4306        }
4307        return strPrefix;
4308}
4309
4310
4311void FileList::IfGoHome(wchar_t Drive)
4312{
4313        string strTmpCurDir;
4314        string strFName;
4315
4316        if (apiGetModuleFileName (NULL, strFName))
4317        {
4318                strFName.SetLength(3);
4319
4320                // СНАЧАЛА ПАССИВНАЯ ПАНЕЛЬ!!!
4321                /*
4322                        Почему? - Просто - если активная широкая (или пассивная
4323                        широкая) - получаем багу с прорисовкой!
4324                */
4325                Panel *Another=CtrlObject->Cp()->GetAnotherPanel (this);
4326                if (Another->GetMode() != PLUGIN_PANEL)
4327                {
4328                        Another->GetCurDir(strTmpCurDir);
4329                        if (strTmpCurDir.At(0) == Drive && strTmpCurDir.At(1) == L':')
4330                                Another->SetCurDir(strFName, FALSE);
4331                }
4332
4333                if (GetMode() != PLUGIN_PANEL)
4334                {
4335                        GetCurDir(strTmpCurDir);
4336                        if (strTmpCurDir.At(0) == Drive && strTmpCurDir.At(1) == L':')
4337                                SetCurDir(strFName, FALSE); // переходим в корень диска с far.exe
4338                }
4339        }
4340}
4341
4342
4343BOOL FileList::GetItem(int Index,void *Dest)
4344{
4345  if(Index == -1 || Index == -2)
4346    Index=GetCurrentPos();
4347  if((DWORD)Index >= (DWORD)FileCount)
4348    return FALSE;
4349  *((FileListItem *)Dest)=*ListData[Index];
4350  return TRUE;
4351}
Note: See TracBrowser for help on using the browser.