root/trunk/unicode_far/filelist.cpp @ 1549

Revision 1549, 124.0 KB (checked in by drkns, 2 years ago)

 Mantis#0000222: 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    string strTarget;
2292    strTarget = strSetDir;
2293    TruncPathStr(strTarget, ScrX-16);
2294    Message(MSG_WARNING | MSG_ERRORTYPE, 1, UMSG (MError), strTarget, UMSG (MOk));
2295    UpdateFlags = UPDATE_KEEP_SELECTION;
2296  }
2297  /* $ 28.04.2001 IS
2298       Закомментарим "до лучших времен".
2299       Я не знаю, почему глюк проявлялся только у меня, но зато знаю, почему он
2300       был просто-таки обязан проявится. Желающие могут немного RTFM. Тема для
2301       изучения: chdir, setdisk, SetCurrentDirectory и переменные окружения
2302
2303  */
2304  /*else {
2305    if (isalpha(SetDir[0]) && SetDir[1]==':')
2306    {
2307      int CurDisk=toupper(SetDir[0])-'A';
2308      setdisk(CurDisk);
2309    }
2310  }*/
2311  FarGetCurDir(strCurDir);
2312
2313  if(!IsUpdated)
2314    return(TRUE);
2315
2316  Update(UpdateFlags);
2317
2318  if (TestParentFolderName(strSetDir))
2319  {
2320    GoToFile(strFindDir);
2321    CurTopFile=UpperFolderTopFile;
2322    UpperFolderTopFile=0;
2323    CorrectPosition();
2324  }
2325  else if (UpdateFlags != UPDATE_KEEP_SELECTION)
2326    CurFile=CurTopFile=0;
2327
2328  if (GetFocus())
2329  {
2330    CtrlObject->CmdLine->SetCurDir(strCurDir);
2331    CtrlObject->CmdLine->Show();
2332  }
2333  AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
2334  if (AnotherPanel->GetType()!=FILE_PANEL)
2335  {
2336    AnotherPanel->SetCurDir(strCurDir,FALSE);
2337    AnotherPanel->Redraw();
2338  }
2339  if (PanelMode==PLUGIN_PANEL)
2340    CtrlObject->Cp()->RedrawKeyBar();
2341  return(TRUE);
2342
2343}
2344
2345
2346int FileList::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
2347{
2348  struct FileListItem *CurPtr;
2349  int RetCode;
2350
2351  if (IsVisible() && Opt.ShowColumnTitles && MouseEvent->dwEventFlags==0 &&
2352      MouseEvent->dwMousePosition.Y==Y1+1 &&
2353      MouseEvent->dwMousePosition.X>X1 && MouseEvent->dwMousePosition.X<X1+3)
2354  {
2355    if (MouseEvent->dwButtonState)
2356      if (MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
2357        ChangeDisk();
2358      else
2359        SelectSortMode();
2360    return(TRUE);
2361  }
2362
2363  if (IsVisible() && Opt.ShowPanelScrollbar && MouseX==X2 &&
2364      (MouseEvent->dwButtonState & 1) && !IsDragging())
2365  {
2366    int ScrollY=Y1+1+Opt.ShowColumnTitles;
2367    if (MouseY==ScrollY)
2368    {
2369      while (IsMouseButtonPressed())
2370        ProcessKey(KEY_UP);
2371      SetFocus();
2372      return(TRUE);
2373    }
2374    if (MouseY==ScrollY+Height-1)
2375    {
2376      while (IsMouseButtonPressed())
2377        ProcessKey(KEY_DOWN);
2378      SetFocus();
2379      return(TRUE);
2380    }
2381    if (MouseY>ScrollY && MouseY<ScrollY+Height-1 && Height>2)
2382    {
2383      CurFile=(FileCount-1)*(MouseY-ScrollY)/(Height-2);
2384      ShowFileList(TRUE);
2385      SetFocus();
2386      return(TRUE);
2387    }
2388  }
2389
2390  /* $ 21.08.2001 VVM
2391    + Считать нажатие средней кнопки за ЕНТЕР */
2392  /* $ 17.12.2001 IS
2393    ! новшество от Василия - опционально
2394  */
2395  if ((MouseEvent->dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
2396      && (MouseEvent->dwEventFlags != MOUSE_MOVED)
2397      && Opt.PanelMiddleClickRule)
2398  {
2399    int Key = KEY_ENTER;
2400    if (MouseEvent->dwControlKeyState & SHIFT_PRESSED)
2401      Key |= KEY_SHIFT;
2402    if (MouseEvent->dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
2403      Key |= KEY_CTRL;
2404    if (MouseEvent->dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
2405      Key |= KEY_ALT;
2406    ProcessKey(Key);
2407    return(TRUE);
2408  }
2409
2410  if (Panel::PanelProcessMouse(MouseEvent,RetCode))
2411    return(RetCode);
2412
2413  if (MouseEvent->dwMousePosition.Y>Y1+Opt.ShowColumnTitles &&
2414      MouseEvent->dwMousePosition.Y<Y2-2*Opt.ShowPanelStatus)
2415  {
2416    SetFocus();
2417    if (FileCount==0)
2418      return(TRUE);
2419    MoveToMouse(MouseEvent);
2420    CurPtr=ListData[CurFile];
2421
2422    if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) &&
2423        MouseEvent->dwEventFlags==DOUBLE_CLICK)
2424    {
2425      if (PanelMode==PLUGIN_PANEL)
2426      {
2427        FlushInputBuffer(); // !!!
2428        int ProcessCode=CtrlObject->Plugins.ProcessKey(hPlugin,VK_RETURN,ShiftPressed ? PKF_SHIFT:0);
2429        ProcessPluginCommand();
2430        if (ProcessCode)
2431          return(TRUE);
2432      }
2433      /*$ 21.02.2001 SKV
2434        Если пришел DOUBLE_CLICK без предшевствующего ему
2435        простого клика, то курсор не перерисовывается.
2436        Перересуем его.
2437        По идее при нормальном DOUBLE_CLICK, будет
2438        двойная перерисовка...
2439        Но мы же вызываем Fast=TRUE...
2440        Вроде всё должно быть ок.
2441      */
2442      ShowFileList(TRUE);
2443      FlushInputBuffer();
2444      ProcessEnter(1,ShiftPressed!=0);
2445      return(TRUE);
2446    }
2447    else
2448    {
2449      /* $ 11.09.2000 SVS
2450         Bug #17: Выделяем при условии, что колонка ПОЛНОСТЬЮ пуста.
2451      */
2452      if ((MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) && !IsEmpty)
2453      {
2454        if (MouseEvent->dwEventFlags==0)
2455          MouseSelection=!CurPtr->Selected;
2456        Select(CurPtr,MouseSelection);
2457        if (SelectedFirst)
2458          SortFileList(TRUE);
2459      }
2460    }
2461    ShowFileList(TRUE);
2462    return(TRUE);
2463  }
2464  if (MouseEvent->dwMousePosition.Y<=Y1+1)
2465  {
2466    SetFocus();
2467    if (FileCount==0)
2468      return(TRUE);
2469    while (IsMouseButtonPressed() && MouseY<=Y1+1)
2470    {
2471      Up(1);
2472      if (RButtonPressed)
2473      {
2474        CurPtr=ListData[CurFile];
2475        Select(CurPtr,MouseSelection);
2476      }
2477    }
2478    if (SelectedFirst)
2479      SortFileList(TRUE);
2480    return(TRUE);
2481  }
2482  if (MouseEvent->dwMousePosition.Y>=Y2-2)
2483  {
2484    SetFocus();
2485    if (FileCount==0)
2486      return(TRUE);
2487    while (IsMouseButtonPressed() && MouseY>=Y2-2)
2488    {
2489      Down(1);
2490      if (RButtonPressed)
2491      {
2492        CurPtr=ListData[CurFile];
2493        Select(CurPtr,MouseSelection);
2494      }
2495    }
2496    if (SelectedFirst)
2497      SortFileList(TRUE);
2498    return(TRUE);
2499  }
2500  return(FALSE);
2501}
2502
2503
2504/* $ 12.09.2000 SVS
2505  + Опциональное поведение для правой клавиши мыши на пустой панели
2506*/
2507void FileList::MoveToMouse(MOUSE_EVENT_RECORD *MouseEvent)
2508{
2509  int CurColumn=1,ColumnsWidth,I;
2510  int PanelX=MouseEvent->dwMousePosition.X-X1-1;
2511
2512  int Level = 0;
2513
2514  for (ColumnsWidth=I=0;I<ViewSettings.ColumnCount;I++)
2515  {
2516    if ( Level == ColumnsInGlobal )
2517    {
2518      CurColumn++;
2519      Level = 0;
2520    }
2521    ColumnsWidth+=ViewSettings.ColumnWidth[I];
2522    if (ColumnsWidth>=PanelX)
2523      break;
2524    ColumnsWidth++;
2525    Level++;
2526  }
2527//  if (CurColumn==0)
2528//    CurColumn=1;
2529  int OldCurFile=CurFile;
2530  CurFile=CurTopFile+MouseEvent->dwMousePosition.Y-Y1-1-Opt.ShowColumnTitles;
2531  if (CurColumn>1)
2532    CurFile+=(CurColumn-1)*Height;
2533  CorrectPosition();
2534  /* $ 11.09.2000 SVS
2535     Bug #17: Проверим на ПОЛНОСТЬЮ пустую колонку.
2536  */
2537  if(Opt.PanelRightClickRule == 1)
2538    IsEmpty=((CurColumn-1)*Height > FileCount);
2539  else if(Opt.PanelRightClickRule == 2 &&
2540          (MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) &&
2541          ((CurColumn-1)*Height > FileCount))
2542  {
2543    CurFile=OldCurFile;
2544    IsEmpty=TRUE;
2545  }
2546  else
2547    IsEmpty=FALSE;
2548}
2549
2550void FileList::SetViewMode(int ViewMode)
2551{
2552  int CurFullScreen=IsFullScreen();
2553  int OldOwner=IsColumnDisplayed(OWNER_COLUMN);
2554  int OldPacked=IsColumnDisplayed(PACKED_COLUMN);
2555  int OldNumLink=IsColumnDisplayed(NUMLINK_COLUMN);
2556  int OldDiz=IsColumnDisplayed(DIZ_COLUMN);
2557  int OldCaseSensitiveSort=ViewSettings.CaseSensitiveSort;
2558  int OldNumericSort=NumericSort;
2559  PrepareViewSettings(ViewMode,NULL);
2560  int NewOwner=IsColumnDisplayed(OWNER_COLUMN);
2561  int NewPacked=IsColumnDisplayed(PACKED_COLUMN);
2562  int NewNumLink=IsColumnDisplayed(NUMLINK_COLUMN);
2563  int NewDiz=IsColumnDisplayed(DIZ_COLUMN);
2564  int NewAccessTime=IsColumnDisplayed(ADATE_COLUMN);
2565  int NewCaseSensitiveSort=ViewSettings.CaseSensitiveSort;
2566  int NewNumericSort=NumericSort;
2567  int ResortRequired=FALSE;
2568
2569  string strDriveRoot;
2570  DWORD FileSystemFlags;
2571  GetPathRoot(strCurDir,strDriveRoot);
2572  if (NewPacked && apiGetVolumeInformation (strDriveRoot,NULL,NULL,NULL,&FileSystemFlags,NULL))
2573    if ((FileSystemFlags & FS_FILE_COMPRESSION)==0)
2574      NewPacked=FALSE;
2575
2576  if (FileCount>0 && PanelMode!=PLUGIN_PANEL &&
2577      (!OldOwner && NewOwner || !OldPacked && NewPacked ||
2578       !OldNumLink && NewNumLink ||
2579       AccessTimeUpdateRequired && NewAccessTime))
2580    Update(UPDATE_KEEP_SELECTION);
2581  else
2582    if (OldCaseSensitiveSort!=NewCaseSensitiveSort || OldNumericSort!=NewNumericSort) //????
2583      ResortRequired=TRUE;
2584
2585  if (!OldDiz && NewDiz)
2586    ReadDiz();
2587
2588  if (ViewSettings.FullScreen && !CurFullScreen)
2589  {
2590    if (Y2>0)
2591      SetPosition(0,Y1,ScrX,Y2);
2592    FileList::ViewMode=ViewMode;
2593  }
2594  else
2595    if (!ViewSettings.FullScreen && CurFullScreen)
2596    {
2597      if (Y2>0)
2598        if (this==CtrlObject->Cp()->LeftPanel)
2599          SetPosition(0,Y1,ScrX/2-Opt.WidthDecrement,Y2);
2600        else
2601          SetPosition(ScrX/2+1-Opt.WidthDecrement,Y1,ScrX,Y2);
2602      FileList::ViewMode=ViewMode;
2603    }
2604    else
2605    {
2606      FileList::ViewMode=ViewMode;
2607      FrameManager->RefreshFrame();
2608    }
2609
2610  if (PanelMode==PLUGIN_PANEL)
2611  {
2612    string strColumnTypes,strColumnWidths;
2613
2614//    SetScreenPosition();
2615    ViewSettingsToText(ViewSettings.ColumnType,ViewSettings.ColumnWidth,
2616        ViewSettings.ColumnCount,strColumnTypes,strColumnWidths);
2617    ProcessPluginEvent(FE_CHANGEVIEWMODE,(void*)(const wchar_t*)strColumnTypes);
2618  }
2619
2620  if (ResortRequired)
2621  {
2622    SortFileList(TRUE);
2623    ShowFileList(TRUE);
2624    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
2625    if (AnotherPanel->GetType()==TREE_PANEL)
2626      AnotherPanel->Redraw();
2627  }
2628}
2629
2630
2631void FileList::SetSortMode(int SortMode)
2632{
2633  if (SortMode==FileList::SortMode && Opt.ReverseSort)
2634    SortOrder=-SortOrder;
2635  else
2636    SortOrder=1;
2637  FileList::SortMode=SortMode;
2638  if (FileCount>0)
2639    SortFileList(TRUE);
2640  FrameManager->RefreshFrame();
2641}
2642
2643int FileList::GoToFile(long idxItem)
2644{
2645  if ((DWORD)idxItem < (DWORD)FileCount)
2646  {
2647    CurFile=idxItem;
2648    CorrectPosition();
2649    return TRUE;
2650  }
2651  return FALSE;
2652}
2653
2654int FileList::GoToFile(const wchar_t *Name,BOOL OnlyPartName)
2655{
2656  return GoToFile(FindFile(Name,OnlyPartName));
2657}
2658
2659
2660long FileList::FindFile(const wchar_t *Name,BOOL OnlyPartName)
2661{
2662  long I;
2663  struct FileListItem *CurPtr;
2664
2665  for (I=0; I < FileCount; I++)
2666  {
2667    CurPtr = ListData[I];
2668    const wchar_t *CurPtrName=CurPtr->strName;
2669
2670    if(OnlyPartName)
2671      CurPtrName=PointToName(CurPtr->strName);
2672
2673    if (StrCmp(Name,CurPtrName)==0)
2674      return I;
2675    if (StrCmpI(Name,CurPtrName)==0)
2676      return I;
2677  }
2678  return -1;
2679}
2680
2681long FileList::FindFirst(const wchar_t *Name)
2682{
2683  return FindNext(0,Name);
2684}
2685
2686long FileList::FindNext(int StartPos, const wchar_t *Name)
2687{
2688  int I;
2689  struct FileListItem *CurPtr;
2690
2691  if((DWORD)StartPos < (DWORD)FileCount)
2692    for(I=StartPos; I < FileCount; I++)
2693    {
2694      CurPtr = ListData[I];
2695      const wchar_t *CurPtrName=CurPtr->strName;
2696      if (CmpName(Name,CurPtrName,TRUE))
2697        if (!TestParentFolderName(CurPtrName))
2698          return I;
2699    }
2700  return -1;
2701}
2702
2703
2704int FileList::IsSelected(const wchar_t *Name)
2705{
2706  long Pos=FindFile(Name);
2707  return(Pos!=-1 && (ListData[Pos]->Selected || SelFileCount==0 && Pos==CurFile));
2708}
2709
2710
2711// $ 02.08.2000 IG  Wish.Mix #21 - при нажатии '/' или '\' в QuickSerach переходим на директорию
2712int FileList::FindPartName(const wchar_t *Name,int Next,int Direct,int ExcludeSets)
2713{
2714  int I;
2715  struct FileListItem *CurPtr;
2716
2717  int DirFind = 0;
2718  int Length = StrLength(Name);
2719
2720  string strMask;
2721
2722  strMask = Name;
2723
2724  if ( Length > 0 && (Name[Length-1] == L'/' || Name[Length-1] == L'\\') )
2725  {
2726    DirFind = 1;
2727    strMask.SetLength(strMask.GetLength ()-1);
2728  }
2729
2730  strMask += L"*";
2731
2732  if(ExcludeSets)
2733  {
2734    ReplaceStrings(strMask,L"[",L"<[%>",-1,1);
2735    ReplaceStrings(strMask,L"]",L"[]]",-1,1);
2736    ReplaceStrings(strMask,L"<[%>",L"[[]",-1,1);
2737  }
2738
2739  for (I=CurFile+(Next?Direct:0); I >= 0 && I < FileCount; I+=Direct)
2740  {
2741    CurPtr = ListData[I];
2742    CmpNameSearchMode=(I==CurFile);
2743    if (CmpName(strMask,CurPtr->strName,TRUE))
2744      if (!TestParentFolderName(CurPtr->strName))
2745        if (!DirFind || (CurPtr->FileAttr & FA_DIREC))
2746        {
2747          CmpNameSearchMode=FALSE;
2748          CurFile=I;
2749          CurTopFile=CurFile-(Y2-Y1)/2;
2750          ShowFileList(TRUE);
2751          return(TRUE);
2752        }
2753  }
2754
2755  CmpNameSearchMode=FALSE;
2756
2757  for(I=(Direct > 0)?0:FileCount-1; (Direct > 0) ? I < CurFile:I > CurFile; I+=Direct)
2758  {
2759    CurPtr = ListData[I];
2760    if (CmpName(strMask,CurPtr->strName,TRUE))
2761      if (!TestParentFolderName(CurPtr->strName))
2762        if (!DirFind || (CurPtr->FileAttr & FA_DIREC))
2763        {
2764          CurFile=I;
2765          CurTopFile=CurFile-(Y2-Y1)/2;
2766          ShowFileList(TRUE);
2767          return(TRUE);
2768        }
2769  }
2770
2771  return(FALSE);
2772}
2773
2774
2775int FileList::GetSelCount()
2776{
2777  if (FileCount==0)
2778    return(0);
2779  if (SelFileCount==0 || ReturnCurrentFile)
2780    return(1);
2781  return(SelFileCount);
2782}
2783
2784int FileList::GetRealSelCount()
2785{
2786  if (FileCount==0)
2787    return(0);
2788  return(SelFileCount);
2789}
2790
2791
2792int FileList::GetSelName(string *strName,int &FileAttr,string *strShortName,FAR_FIND_DATA_EX *fd)
2793{
2794  if ( strName==NULL )
2795  {
2796    GetSelPosition=0;
2797    LastSelPosition=-1;
2798    return(TRUE);
2799  }
2800
2801
2802  if (SelFileCount==0 || ReturnCurrentFile)
2803  {
2804    if (GetSelPosition==0 && CurFile<FileCount)
2805    {
2806      GetSelPosition=1;
2807
2808      *strName = ListData[CurFile]->strName;
2809      if ( strShortName!=NULL )
2810      {
2811        *strShortName = ListData[CurFile]->strShortName;
2812
2813        if ( strShortName->IsEmpty() )
2814          *strShortName = *strName;
2815      }
2816      FileAttr=ListData[CurFile]->FileAttr;
2817      LastSelPosition=CurFile;
2818
2819      if (fd)
2820      {
2821        fd->dwFileAttributes=ListData[CurFile]->FileAttr;
2822        fd->ftCreationTime=ListData[CurFile]->CreationTime;
2823        fd->ftLastAccessTime=ListData[CurFile]->AccessTime;
2824        fd->ftLastWriteTime=ListData[CurFile]->WriteTime;
2825        fd->nFileSize=ListData[CurFile]->UnpSize;
2826        fd->nPackSize=ListData[CurFile]->PackSize;
2827
2828        fd->strFileName = ListData[CurFile]->strName;
2829        fd->strAlternateFileName = ListData[CurFile]->strShortName;
2830      }
2831
2832      return(TRUE);
2833    }
2834    else
2835      return(FALSE);
2836  }
2837
2838  while (GetSelPosition<FileCount)
2839    if (ListData[GetSelPosition++]->Selected)
2840    {
2841      *strName = ListData[GetSelPosition-1]->strName;
2842      if ( strShortName!=NULL )
2843      {
2844        *strShortName = ListData[GetSelPosition-1]->strShortName;
2845        if ( strShortName->IsEmpty() )
2846          *strShortName = *strName;
2847      }
2848      FileAttr=ListData[GetSelPosition-1]->FileAttr;
2849      LastSelPosition=GetSelPosition-1;
2850
2851      if (fd)
2852      {
2853        fd->dwFileAttributes=ListData[GetSelPosition-1]->FileAttr;
2854        fd->ftCreationTime=ListData[GetSelPosition-1]->CreationTime;
2855        fd->ftLastAccessTime=ListData[GetSelPosition-1]->AccessTime;
2856        fd->ftLastWriteTime=ListData[GetSelPosition-1]->WriteTime;
2857        fd->nFileSize=ListData[GetSelPosition-1]->UnpSize;
2858        fd->nPackSize=ListData[GetSelPosition-1]->PackSize;
2859        fd->strFileName = ListData[GetSelPosition-1]->strName;
2860        fd->strAlternateFileName = ListData[GetSelPosition-1]->strShortName;
2861      }
2862
2863      return(TRUE);
2864    }
2865  return(FALSE);
2866}
2867
2868
2869void FileList::ClearLastGetSelection()
2870{
2871  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2872    Select(ListData[LastSelPosition],0);
2873}
2874
2875
2876void FileList::UngetSelName()
2877{
2878  GetSelPosition=LastSelPosition;
2879}
2880
2881
2882unsigned __int64 FileList::GetLastSelectedSize ()
2883{
2884  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2885    return ListData[LastSelPosition]->UnpSize;
2886
2887  return (unsigned __int64)(-1);
2888}
2889
2890
2891int FileList::GetLastSelectedItem(struct FileListItem *LastItem)
2892{
2893  if (LastSelPosition>=0 && LastSelPosition<FileCount)
2894  {
2895    *LastItem=*ListData[LastSelPosition];
2896    return(TRUE);
2897  }
2898  return(FALSE);
2899}
2900
2901
2902/*int FileList::GetCurName(char *Name,char *ShortName)
2903{
2904  if (FileCount==0)
2905  {
2906    *Name=*ShortName=0;
2907    return(FALSE);
2908  }
2909  strcpy(Name,ListData[CurFile]->Name);
2910  strcpy(ShortName,ListData[CurFile]->ShortName);
2911  if (*ShortName==0)
2912    strcpy(ShortName,Name);
2913  return(TRUE);
2914}
2915*/
2916int FileList::GetCurName(string &strName, string &strShortName)
2917{
2918  if (FileCount==0)
2919  {
2920    strName = L"";
2921    strShortName = L"";
2922    return(FALSE);
2923  }
2924
2925  strName = ListData[CurFile]->strName;
2926  strShortName = ListData[CurFile]->strShortName;
2927
2928  if ( strShortName.IsEmpty() )
2929    strShortName = strName;
2930  return(TRUE);
2931}
2932
2933
2934/*int FileList::GetCurBaseName(char *Name,char *ShortName)
2935{
2936  *Name=*ShortName=0;
2937  if (FileCount==0)
2938    return(FALSE);
2939  if(PanelMode==PLUGIN_PANEL && PluginsStack) // для плагинов
2940  {
2941    // берем самую основу (при вложенных)
2942    strcpy(Name,PointToName(NullToEmpty(PluginsStack->HostFile)));
2943  }
2944  else if(PanelMode==NORMAL_PANEL)
2945  {
2946    strcpy(Name,ListData[CurFile].Name);
2947    strcpy(ShortName,ListData[CurFile].ShortName);
2948  }
2949
2950  if (*ShortName==0)
2951    strcpy(ShortName,Name);
2952  return(TRUE);
2953}*/
2954
2955int FileList::GetCurBaseName(string &strName, string &strShortName)
2956{
2957  if (FileCount==0)
2958  {
2959    strName = L"";
2960    strShortName = L"";
2961    return(FALSE);
2962  }
2963
2964  if(PanelMode==PLUGIN_PANEL && PluginsStack) // для плагинов
2965  {
2966    strName = PointToName(PluginsStack[0]->strHostFile);
2967  }
2968  else if(PanelMode==NORMAL_PANEL)
2969  {
2970    strName = ListData[CurFile]->strName;
2971    strShortName = ListData[CurFile]->strShortName;
2972  }
2973
2974  if ( strShortName.IsEmpty() )
2975    strShortName = strName;
2976  return(TRUE);
2977}
2978
2979extern void add_char (string &str, wchar_t c); //BUGBUG
2980
2981void FileList::SelectFiles(int Mode)
2982{
2983  CFileMask FileMask; // Класс для работы с масками
2984  const wchar_t *HistoryName=L"Masks";
2985  static struct DialogDataEx SelectDlgData[]=
2986  {
2987    DI_DOUBLEBOX,3,1,51,5,0,0,0,0,L"",
2988    DI_EDIT,5,2,49,2,1,(DWORD_PTR)HistoryName,DIF_HISTORY,0,L"",
2989    DI_TEXT,0,3,0,3,0,0,DIF_SEPARATOR,0,L"",
2990    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,1,(const wchar_t *)MOk,
2991    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MSelectFilter,
2992    DI_BUTTON,0,4,0,4,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MCancel,
2993  };
2994  MakeDialogItemsEx(SelectDlgData,SelectDlg);
2995
2996  FileFilter Filter(this,FFT_SELECT);
2997  bool bUseFilter = false;
2998
2999  struct FileListItem *CurPtr;
3000  static string strPrevMask=L"*.*";
3001  /* $ 20.05.2002 IS
3002     При обработке маски, если работаем с именем файла на панели,
3003     берем каждую квадратную скобку в имени при образовании маски в скобки,
3004     чтобы подобные имена захватывались полученной маской - это специфика,
3005     диктуемая CmpName.
3006  */
3007  string strMask=L"*.*", strRawMask;
3008  int Selection=0,I;
3009  bool WrapBrackets=false; // говорит о том, что нужно взять кв.скобки в скобки
3010
3011  if (CurFile>=FileCount)
3012    return;
3013
3014  int RawSelection=FALSE;
3015  if (PanelMode==PLUGIN_PANEL)
3016  {
3017    struct OpenPluginInfo Info;
3018    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3019    RawSelection=(Info.Flags & OPIF_RAWSELECTION);
3020  }
3021
3022  CurPtr=ListData[CurFile];
3023  string strCurName=(ShowShortNames && !CurPtr->strShortName.IsEmpty() ? CurPtr->strShortName:CurPtr->strName);
3024
3025  if (Mode==SELECT_ADDEXT || Mode==SELECT_REMOVEEXT)
3026  {
3027    const wchar_t *DotPtr=wcsrchr(strCurName,L'.');
3028    if (DotPtr!=NULL)
3029    {
3030      // Учтем тот момент, что расширение может содержать символы-разделители
3031      strRawMask.Format (L"\"*.%s\"", DotPtr+1);
3032      WrapBrackets=true;
3033    }
3034    else
3035      strMask = L"*.";
3036    Mode=(Mode==SELECT_ADDEXT) ? SELECT_ADD:SELECT_REMOVE;
3037  }
3038  else
3039  {
3040    if (Mode==SELECT_ADDNAME || Mode==SELECT_REMOVENAME)
3041    {
3042      // Учтем тот момент, что имя может содержать символы-разделители
3043      strRawMask.Format (L"\"%s", (const wchar_t*)strCurName);
3044
3045      wchar_t *DotPtr = strRawMask.GetBuffer ((int)strRawMask.GetLength()+4);
3046
3047      DotPtr=wcsrchr(DotPtr,L'.');
3048
3049      if (DotPtr!=NULL)
3050      {
3051        wcscpy(DotPtr,L".*\"");
3052        strRawMask.ReleaseBuffer ();
3053      }
3054      else
3055      {
3056        strRawMask.ReleaseBuffer ();
3057        strRawMask += ".*\"";
3058      }
3059      WrapBrackets=true;
3060      Mode=(Mode==SELECT_ADDNAME) ? SELECT_ADD:SELECT_REMOVE;
3061    }
3062    else
3063    {
3064      if (Mode==SELECT_ADD || Mode==SELECT_REMOVE)
3065      {
3066        SelectDlg[1].strData = strPrevMask;
3067        if (Mode==SELECT_ADD)
3068          SelectDlg[0].strData = UMSG(MSelectTitle);
3069        else
3070          SelectDlg[0].strData = UMSG(MUnselectTitle);
3071        {
3072          Dialog Dlg(SelectDlg,sizeof(SelectDlg)/sizeof(SelectDlg[0]));
3073          Dlg.SetHelp(L"SelectFiles");
3074          Dlg.SetPosition(-1,-1,55,7);
3075          for(;;)
3076          {
3077            Dlg.ClearDone();
3078            Dlg.Process();
3079            if (Dlg.GetExitCode()==4 && Filter.FilterEdit())
3080            {
3081              bUseFilter = true;
3082              break;
3083            }
3084            if (Dlg.GetExitCode()!=3)
3085              return;
3086            strMask = SelectDlg[1].strData;
3087            if(FileMask.Set(strMask, 0)) // Проверим вводимые пользователем маски на ошибки
3088            {
3089              strPrevMask = strMask;
3090              break;
3091            }
3092          }
3093        }
3094      }
3095    }
3096  }
3097  SaveSelection();
3098
3099  if(!bUseFilter && WrapBrackets) // возьмем кв.скобки в скобки, чтобы получить
3100  {                               // работоспособную маску
3101    const wchar_t *src=(const wchar_t*)strRawMask;
3102    strMask=(const wchar_t*)L"";
3103    while ( *src )
3104    {
3105      if(*src==L']' || *src==L'[')
3106      {
3107        add_char (strMask, L'[');
3108        add_char (strMask, *src);
3109        add_char (strMask, L']');
3110      }
3111      else
3112        add_char (strMask, *src);
3113
3114      src++;
3115    }
3116  }
3117
3118  if(bUseFilter || FileMask.Set(strMask, FMF_SILENT)) // Скомпилируем маски файлов и работаем
3119  {                                                // дальше в зависимости от успеха компиляции
3120    for (I=0; I < FileCount; I++)
3121    {
3122      CurPtr=ListData[I];
3123      int Match=FALSE;
3124      if (Mode==SELECT_INVERT || Mode==SELECT_INVERTALL)
3125        Match=TRUE;
3126      else
3127      {
3128        if (bUseFilter)
3129          Match=Filter.FileInFilter(CurPtr);
3130        else
3131          Match=FileMask.Compare((ShowShortNames && !CurPtr->strShortName.IsEmpty() ? CurPtr->strShortName:CurPtr->strName));
3132      }
3133
3134      if (Match)
3135      {
3136        switch(Mode)
3137        {
3138          case SELECT_ADD:
3139            Selection=1;
3140            break;
3141          case SELECT_REMOVE:
3142            Selection=0;
3143            break;
3144          case SELECT_INVERT:
3145          case SELECT_INVERTALL:
3146            Selection=!CurPtr->Selected;
3147            break;
3148        }
3149        if (bUseFilter || (CurPtr->FileAttr & FA_DIREC)==0 || Opt.SelectFolders ||
3150            Selection==0 || RawSelection || Mode==SELECT_INVERTALL)
3151          Select(CurPtr,Selection);
3152      }
3153    }
3154  }
3155
3156  if (SelectedFirst)
3157    SortFileList(TRUE);
3158  ShowFileList(TRUE);
3159}
3160
3161void FileList::UpdateViewPanel()
3162{
3163  Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3164  if (FileCount>0 && AnotherPanel->IsVisible() &&
3165      AnotherPanel->GetType()==QVIEW_PANEL && SetCurPath())
3166  {
3167    QuickView *ViewPanel=(QuickView *)AnotherPanel;
3168    struct FileListItem *CurPtr=ListData[CurFile];
3169    if (PanelMode!=PLUGIN_PANEL ||
3170        CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILE))
3171    {
3172      if (TestParentFolderName(CurPtr->strName))
3173        ViewPanel->ShowFile(strCurDir,FALSE,NULL);
3174      else
3175        ViewPanel->ShowFile(CurPtr->strName,FALSE,NULL);
3176    }
3177    else
3178      if ((CurPtr->FileAttr & FA_DIREC)==0)
3179      {
3180        string strTempDir,strFileName;
3181        strFileName = CurPtr->strName;
3182        if(!FarMkTempEx(strTempDir))
3183          return;
3184        CreateDirectoryW(strTempDir,NULL);
3185        struct PluginPanelItem PanelItem;
3186        FileListToPluginItem(CurPtr,&PanelItem);
3187        if (!CtrlObject->Plugins.GetFile(hPlugin,&PanelItem,strTempDir,strFileName,OPM_SILENT|OPM_VIEW|OPM_QUICKVIEW))
3188        {
3189          ViewPanel->ShowFile(NULL,FALSE,NULL);
3190          apiRemoveDirectory(strTempDir);
3191          return;
3192        }
3193        ViewPanel->ShowFile(strFileName,TRUE,NULL);
3194      }
3195      else
3196        if (!TestParentFolderName(CurPtr->strName))
3197          ViewPanel->ShowFile(CurPtr->strName,FALSE,hPlugin);
3198        else
3199          ViewPanel->ShowFile(NULL,FALSE,NULL);
3200
3201    SetTitle();
3202  }
3203}
3204
3205
3206void FileList::CompareDir()
3207{
3208  FileList *Another=(FileList *)CtrlObject->Cp()->GetAnotherPanel(this);
3209  int I,J;
3210  if (Another->GetType()!=FILE_PANEL || !Another->IsVisible())
3211  {
3212    Message(MSG_WARNING,1,UMSG(MCompareTitle),UMSG(MCompareFilePanelsRequired1),
3213            UMSG(MCompareFilePanelsRequired2),UMSG(MOk));
3214    return;
3215  }
3216
3217  ScrBuf.Flush();
3218
3219  // полностью снимаем выделение с обоих панелей
3220  ClearSelection();
3221  Another->ClearSelection();
3222
3223  struct FileListItem *CurPtr, *AnotherCurPtr;
3224  string strTempName1, strTempName2;
3225
3226  const wchar_t *PtrTempName1, *PtrTempName2;
3227  BOOL OpifRealnames1=FALSE, OpifRealnames2=FALSE;
3228
3229  // помечаем ВСЕ, кроме каталогов на активной панели
3230  for (I=0; I < FileCount; I++)
3231  {
3232    CurPtr = ListData[I];
3233    if((CurPtr->FileAttr & FA_DIREC)==0)
3234      Select(CurPtr,TRUE);
3235  }
3236
3237  // помечаем ВСЕ, кроме каталогов на пассивной панели
3238  for (J=0; J < Another->FileCount; J++)
3239  {
3240    AnotherCurPtr = Another->ListData[J];
3241    if((AnotherCurPtr->FileAttr & FA_DIREC)==0)
3242      Another->Select(AnotherCurPtr,TRUE);
3243  }
3244
3245  int CompareFatTime=FALSE;
3246  if (PanelMode==PLUGIN_PANEL)
3247  {
3248    struct OpenPluginInfo Info;
3249    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3250    if (Info.Flags & OPIF_COMPAREFATTIME)
3251      CompareFatTime=TRUE;
3252    OpifRealnames1=Info.Flags & OPIF_REALNAMES;
3253  }
3254  if (Another->PanelMode==PLUGIN_PANEL && !CompareFatTime)
3255  {
3256    struct OpenPluginInfo Info;
3257    CtrlObject->Plugins.GetOpenPluginInfo(Another->hPlugin,&Info);
3258    if (Info.Flags & OPIF_COMPAREFATTIME)
3259      CompareFatTime=TRUE;
3260    OpifRealnames2=Info.Flags & OPIF_REALNAMES;
3261  }
3262
3263  if (PanelMode==NORMAL_PANEL && Another->PanelMode==NORMAL_PANEL)
3264  {
3265    string strFileSystemName1, strFileSystemName2;
3266    string strRoot1, strRoot2;
3267
3268    GetPathRoot(strCurDir, strRoot1);
3269    GetPathRoot(Another->strCurDir, strRoot2);
3270
3271    if (apiGetVolumeInformation (strRoot1,NULL,NULL,NULL,NULL,&strFileSystemName1) &&
3272        apiGetVolumeInformation (strRoot2,NULL,NULL,NULL,NULL,&strFileSystemName2))
3273      if (StrCmpI(strFileSystemName1,strFileSystemName2)!=0)
3274        CompareFatTime=TRUE;
3275  }
3276
3277  // теперь начнем цикл по снятию выделений
3278  // каждый элемент активной панели...
3279  for (I=0; I < FileCount; I++)
3280  {
3281    CurPtr = ListData[I];
3282    // ...сравниваем с элементом пассивной панели...
3283    for (J=0; J < Another->FileCount; J++)
3284    {
3285      AnotherCurPtr = Another->ListData[J];
3286      int Cmp=0;
3287#if 0
3288      PtrTempName1=CurPtr->Name;
3289      PtrTempName2=AnotherCurPtr->Name;
3290
3291      int fp1=strpbrk(CurPtr->Name,":\\/")!=NULL;
3292      int fp2=strpbrk(AnotherCurPtr->Name,":\\/")!=NULL;
3293
3294      if(fp1 && !fp2 && strcmp(PtrTempName2,".."))
3295      {
3296        UnicodeToAnsi (Another->strCurDir, TempName2); //BUGBUG
3297        AddEndSlash(TempName2);
3298        strncat(TempName2,AnotherCurPtr->Name,sizeof(TempName2)-1);
3299        PtrTempName2=TempName2;
3300      }
3301      else if(!fp1 && fp2 && strcmp(PtrTempName1,".."))
3302      {
3303        strcpy(TempName1,CurDir);
3304        AddEndSlash(TempName1);
3305        strncat(TempName1,CurPtr->Name,sizeof(TempName1)-1);
3306        PtrTempName1=TempName1;
3307      }
3308
3309      if(OpifRealnames1 || OpifRealnames2)
3310      {
3311        PtrTempName1=PointToName(CurPtr->Name);
3312        PtrTempName2=PointToName(AnotherCurPtr->Name);
3313      }
3314#else
3315      PtrTempName1=PointToName(CurPtr->strName);
3316      PtrTempName2=PointToName(AnotherCurPtr->strName);
3317#endif
3318
3319      if (StrCmpI(PtrTempName1,PtrTempName2)==0)
3320      //if (LocalStricmp(CurPtr->Name,AnotherCurPtr->Name)==0)
3321      {
3322        if (CompareFatTime)
3323        {
3324          WORD DosDate,DosTime,AnotherDosDate,AnotherDosTime;
3325          FileTimeToDosDateTime(&CurPtr->WriteTime,&DosDate,&DosTime);
3326          FileTimeToDosDateTime(&AnotherCurPtr->WriteTime,&AnotherDosDate,&AnotherDosTime);
3327          DWORD FullDosTime,AnotherFullDosTime;
3328          FullDosTime=((DWORD)DosDate<<16)+DosTime;
3329          AnotherFullDosTime=((DWORD)AnotherDosDate<<16)+AnotherDosTime;
3330          int D=FullDosTime-AnotherFullDosTime;
3331          if (D>=-1 && D<=1)
3332            Cmp=0;
3333          else
3334            Cmp=(FullDosTime<AnotherFullDosTime) ? -1:1;
3335        }
3336        else
3337        {
3338          __int64 RetCompare=*(__int64*)&CurPtr->WriteTime - *(__int64*)&AnotherCurPtr->WriteTime;
3339          Cmp=!RetCompare?0:(RetCompare > 0?1:-1);
3340        }
3341
3342        if (Cmp==0 && (CurPtr->UnpSize != AnotherCurPtr->UnpSize) )
3343          continue;
3344
3345        if (Cmp < 1 && CurPtr->Selected)
3346          Select(CurPtr,0);
3347
3348        if (Cmp > -1 && AnotherCurPtr->Selected)
3349          Another->Select(AnotherCurPtr,0);
3350
3351        if (Another->PanelMode!=PLUGIN_PANEL)
3352          break;
3353      }
3354    }
3355  }
3356
3357  if (SelectedFirst)
3358    SortFileList(TRUE);
3359
3360  Redraw();
3361  Another->Redraw();
3362  if (SelFileCount==0 && Another->SelFileCount==0)
3363    Message(0,1,UMSG(MCompareTitle),UMSG(MCompareSameFolders1),UMSG(MCompareSameFolders2),UMSG(MOk));
3364}
3365
3366void FileList::CopyNames(int FillPathName,int UNC)
3367{
3368  struct OpenPluginInfo Info;
3369  wchar_t *CopyData=NULL;
3370  long DataSize=0;
3371  string strSelName, strSelShortName, strQuotedName;
3372  int FileAttr;
3373
3374  if (PanelMode==PLUGIN_PANEL)
3375  {
3376    CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3377  }
3378
3379  GetSelName(NULL,FileAttr);
3380  while (GetSelName(&strSelName,FileAttr,&strSelShortName))
3381  {
3382    if (DataSize>0)
3383    {
3384      wcscat(CopyData+DataSize,L"\r\n");
3385      DataSize+=2;
3386    }
3387    strQuotedName = (ShowShortNames && !strSelShortName.IsEmpty()) ? strSelShortName:strSelName;
3388    if(FillPathName)
3389    {
3390
3391      if (PanelMode!=PLUGIN_PANEL || (Info.Flags & OPIF_REALNAMES))
3392      {
3393        /* $ 14.02.2002 IS
3394           ".." в текущем каталоге обработаем как имя текущего каталога
3395        */
3396        if(TestParentFolderName(strQuotedName) && TestParentFolderName(strSelShortName))
3397        {
3398                                        strQuotedName.SetLength(1);
3399                                        strSelShortName.SetLength(1);
3400        }
3401        if(!CreateFullPathName(strQuotedName,strSelShortName,FileAttr,strQuotedName,UNC))
3402        {
3403          if (CopyData)
3404          {
3405            xf_free(CopyData);
3406            CopyData=NULL;
3407          }
3408          break;
3409        }
3410      }
3411      else
3412      {
3413        string strFullName = NullToEmpty(Info.CurDir);
3414
3415        if (Opt.PanelCtrlFRule && ViewSettings.FolderUpperCase)
3416          strFullName.Upper();
3417
3418        if ( !strFullName.IsEmpty() )
3419          AddEndSlash(strFullName);
3420
3421        if(Opt.PanelCtrlFRule)
3422        {
3423          // имя должно отвечать условиям на панели
3424          if (ViewSettings.FileLowerCase && !(FileAttr & FA_DIREC))
3425            strQuotedName.Lower();
3426          if (ViewSettings.FileUpperToLowerCase)
3427            if (!(FileAttr & FA_DIREC) && !IsCaseMixed(strQuotedName))
3428               strQuotedName.Lower();
3429        }
3430        strFullName += strQuotedName;
3431        strQuotedName = strFullName;
3432        // добавим первый префикс!
3433        if(PanelMode==PLUGIN_PANEL && Opt.SubstPluginPrefix)
3434        {
3435          string strPrefix;
3436          /* $ 19.11.2001 IS оптимизация по скорости :) */
3437          if(*AddPluginPrefix((FileList *)CtrlObject->Cp()->ActivePanel,strPrefix))
3438          {
3439            strPrefix += strQuotedName;
3440            strQuotedName = strPrefix;
3441          }
3442        }
3443      }
3444    }
3445    if(Opt.QuotedName&QUOTEDNAME_CLIPBOARD)
3446      QuoteSpace(strQuotedName);
3447    int Length=(int)strQuotedName.GetLength();
3448    wchar_t *NewPtr=(wchar_t *)xf_realloc(CopyData, (DataSize+Length+3)*sizeof (wchar_t));
3449    if (NewPtr==NULL)
3450    {
3451        if (CopyData)
3452        {
3453        xf_free(CopyData);
3454        CopyData=NULL;
3455      }
3456      break;
3457    }
3458    CopyData=NewPtr;
3459    CopyData[DataSize]=0;
3460
3461    wcscpy (CopyData+DataSize, strQuotedName);
3462    DataSize+=Length;
3463  }
3464
3465  CopyToClipboard(CopyData);
3466  xf_free(CopyData);
3467}
3468
3469string &FileList::CreateFullPathName(const wchar_t *Name, const wchar_t *ShortName,DWORD FileAttr, string &strDest, int UNC,int ShortNameAsIs)
3470{
3471  //wchar_t *NamePtr;
3472  wchar_t Chr=0;
3473
3474  string strFileName;
3475  string strTemp;
3476
3477  strFileName = strDest;
3478
3479  const wchar_t *ShortNameLastSlash=wcsrchr(ShortName, L'\\'), *NameLastSlash=wcsrchr(Name, L'\\');
3480
3481  if (NULL==ShortNameLastSlash && NULL==NameLastSlash)
3482    ConvertNameToFull(strFileName, strFileName);
3483  else
3484
3485  if(ShowShortNames)
3486  {
3487    strTemp = Name;
3488
3489    wchar_t *lpwszTemp = strTemp.GetBuffer ();
3490
3491    if(NameLastSlash)
3492      lpwszTemp[1+NameLastSlash-Name]=0;
3493
3494    strTemp.ReleaseBuffer();
3495
3496    const wchar_t *NamePtr = wcsrchr(strFileName, L'\\');
3497
3498    if(NamePtr != NULL)
3499      NamePtr++;
3500    else
3501      NamePtr=strFileName;
3502
3503    strTemp += NameLastSlash?NameLastSlash+1:Name; //??? NamePtr??? BUGBUG
3504    strFileName = strTemp;
3505  }
3506  if (ShowShortNames && ShortNameAsIs)
3507    ConvertNameToShort(strFileName,strFileName);
3508
3509  /* $ 29.01.2001 VVM
3510    + По CTRL+ALT+F в командную строку сбрасывается UNC-имя текущего файла. */
3511  if (UNC)
3512  {
3513    // Посмотрим на тип файловой системы
3514    string strFileSystemName;
3515    GetPathRoot(strFileName,strTemp);
3516
3517    if(!apiGetVolumeInformation (strTemp,NULL,NULL,NULL,NULL,&strFileSystemName))
3518      strFileSystemName=L"";
3519
3520
3521    UNIVERSAL_NAME_INFOW uni;
3522    DWORD uniSize = sizeof(uni);
3523    // применяем WNetGetUniversalName для чего угодно, только не для Novell`а
3524    if (StrCmpI(strFileSystemName,L"NWFS") != 0 &&
3525        WNetGetUniversalNameW(strFileName, UNIVERSAL_NAME_INFO_LEVEL,&uni, &uniSize) == NOERROR)
3526    {
3527        strFileName = uni.lpUniversalName;
3528    }
3529    else if(strFileName.At(1) == L':')
3530    {
3531      // BugZ#449 - Неверная работа CtrlAltF с ресурсами Novell DS
3532      // Здесь, если не получилось получить UniversalName и если это
3533      // мапленный диск - получаем как для меню выбора дисков
3534
3535
3536      /*if(*DriveLocalToRemoteName(DRIVE_UNKNOWN,*FileName,Temp) != 0)
3537      {
3538        if((NamePtr=wcschr(strFileName, L'/')) == NULL)
3539          NamePtr=wcschr(strFileName, L'\\');
3540        if(NamePtr != NULL)
3541        {
3542          AddEndSlashW(strTemp);
3543
3544          NamePtr++;
3545          strTemp += NamePtr;
3546        }
3547
3548        strFileName = strTemp;
3549      }*/ //BUGBUG
3550    }
3551
3552    ConvertNameToReal(strFileName,strFileName);
3553  } /* if */
3554
3555  // $ 20.10.2000 SVS Сделаем фичу Ctrl-F опциональной!
3556  if(Opt.PanelCtrlFRule)
3557  {
3558    /* $ 13.10.2000 tran
3559      по Ctrl-f имя должно отвечать условиям на панели */
3560    if (ViewSettings.FolderUpperCase)
3561    {
3562      if ( FileAttr & FA_DIREC )
3563        strFileName.Upper();
3564      else
3565      {
3566          wchar_t *lpwszFileName = strFileName.GetBuffer();
3567          wchar_t *NamePtr=(wchar_t *)wcsrchr(lpwszFileName,L'\\');
3568
3569          if(NamePtr != NULL)
3570          {
3571            Chr=*NamePtr;
3572            *NamePtr=0;
3573          }
3574
3575          CharUpperW (lpwszFileName);
3576
3577          if(NamePtr)
3578            *NamePtr=Chr;
3579
3580          strFileName.ReleaseBuffer();
3581      }
3582    }
3583    if (ViewSettings.FileUpperToLowerCase)
3584      if (!(FileAttr & FA_DIREC) && wcsrchr(strFileName,L'\\') && !IsCaseMixed(wcsrchr(strFileName,L'\\')))
3585      {
3586          wchar_t *lpwszFileName = strFileName.GetBuffer();
3587
3588          lpwszFileName = wcsrchr (lpwszFileName, L'\\');
3589          CharLowerW (lpwszFileName);
3590
3591          strFileName.ReleaseBuffer();
3592      }
3593    if ( ViewSettings.FileLowerCase && wcsrchr(strFileName,L'\\') && !(FileAttr & FA_DIREC))
3594    {
3595        wchar_t *lpwszFileName = strFileName.GetBuffer();
3596
3597        lpwszFileName = wcsrchr (lpwszFileName, L'\\');
3598        CharLowerW (lpwszFileName);
3599
3600        strFileName.ReleaseBuffer();
3601    }
3602  }
3603
3604  strDest = strFileName;
3605
3606  return strDest;
3607}
3608
3609
3610void FileList::SetTitle()
3611{
3612  if (GetFocus() || CtrlObject->Cp()->GetAnotherPanel(this)->GetType()!=FILE_PANEL)
3613  {
3614    string strTitleDir = L"{";
3615    if (PanelMode==PLUGIN_PANEL)
3616    {
3617      struct OpenPluginInfo Info;
3618
3619      CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
3620
3621      string strPluginTitle = NullToEmpty(Info.PanelTitle);
3622
3623      RemoveExternalSpaces(strPluginTitle);
3624
3625      strTitleDir += strPluginTitle;
3626    }
3627    else
3628      strTitleDir += strCurDir;
3629
3630    strTitleDir += L"}";
3631
3632    strLastFarTitle = strTitleDir; //BUGBUG;
3633    SetFarTitle(strTitleDir);
3634  }
3635}
3636
3637
3638void FileList::ClearSelection()
3639{
3640  struct FileListItem *CurPtr;
3641  for (int I=0; I < FileCount; I++)
3642  {
3643    CurPtr = ListData[I];
3644    Select(CurPtr,0);
3645  }
3646
3647  if (SelectedFirst)
3648    SortFileList(TRUE);
3649}
3650
3651
3652void FileList::SaveSelection()
3653{
3654  struct FileListItem *CurPtr;
3655  for (int I=0; I < FileCount; I++)
3656  {
3657    CurPtr = ListData[I];
3658    CurPtr->PrevSelected=CurPtr->Selected;
3659  }
3660}
3661
3662
3663void FileList::RestoreSelection()
3664{
3665  struct FileListItem *CurPtr;
3666  for (int I=0; I < FileCount; I++)
3667  {
3668    CurPtr = ListData[I];
3669    int NewSelection=CurPtr->PrevSelected;
3670    CurPtr->PrevSelected=CurPtr->Selected;
3671    Select(CurPtr,NewSelection);
3672  }
3673  if (SelectedFirst)
3674    SortFileList(TRUE);
3675  Redraw();
3676}
3677
3678
3679
3680int FileList::GetFileName(string &strName,int Pos,int &FileAttr)
3681{
3682  if (Pos>=FileCount)
3683    return(FALSE);
3684
3685  strName = ListData[Pos]->strName;
3686
3687  FileAttr=ListData[Pos]->FileAttr;
3688  return(TRUE);
3689}
3690
3691
3692int FileList::GetCurrentPos()
3693{
3694  return(CurFile);
3695}
3696
3697
3698void FileList::EditFilter()
3699{
3700  if (Filter==NULL)
3701    Filter=new FileFilter(this,FFT_PANEL);
3702  Filter->FilterEdit();
3703}
3704
3705
3706void FileList::SelectSortMode()
3707{
3708  struct MenuDataEx SortMenu[]=
3709  {
3710   /* 00 */(const wchar_t *)MMenuSortByName,LIF_SELECTED,KEY_CTRLF3,
3711   /* 01 */(const wchar_t *)MMenuSortByExt,0,KEY_CTRLF4,
3712   /* 02 */(const wchar_t *)MMenuSortByModification,0,KEY_CTRLF5,
3713   /* 03 */(const wchar_t *)MMenuSortBySize,0,KEY_CTRLF6,
3714   /* 04 */(const wchar_t *)MMenuUnsorted,0,KEY_CTRLF7,
3715   /* 05 */(const wchar_t *)MMenuSortByCreation,0,KEY_CTRLF8,
3716   /* 06 */(const wchar_t *)MMenuSortByAccess,0,KEY_CTRLF9,
3717   /* 07 */(const wchar_t *)MMenuSortByDiz,0,KEY_CTRLF10,
3718   /* 08 */(const wchar_t *)MMenuSortByOwner,0,KEY_CTRLF11,
3719   /* 09 */(const wchar_t *)MMenuSortByCompressedSize,0,0,
3720   /* 10 */(const wchar_t *)MMenuSortByNumLinks,0,0,
3721   /* 11 */L"",LIF_SEPARATOR,0,
3722   /* 12 */(const wchar_t *)MMenuSortUseNumeric,0,0,
3723   /* 13 */(const wchar_t *)MMenuSortUseGroups,0,KEY_SHIFTF11,
3724   /* 14 */(const wchar_t *)MMenuSortSelectedFirst,0,KEY_SHIFTF12,
3725  };
3726
3727  static int SortModes[]={BY_NAME,   BY_EXT,    BY_MTIME,
3728                          BY_SIZE,   UNSORTED,  BY_CTIME,
3729                          BY_ATIME,  BY_DIZ,    BY_OWNER,
3730                          BY_COMPRESSEDSIZE,BY_NUMLINKS};
3731
3732  for (int I=0;I<sizeof(SortModes)/sizeof(SortModes[0]);I++)
3733    if (SortMode==SortModes[I])
3734    {
3735      SortMenu[I].SetCheck(SortOrder==1 ? L'+':L'-');
3736      break;
3737    }
3738
3739  int SG=GetSortGroups();
3740  SortMenu[12].SetCheck(NumericSort);
3741  SortMenu[13].SetCheck(SG);
3742  SortMenu[14].SetCheck(SelectedFirst);
3743
3744  int SortCode;
3745  {
3746    VMenu SortModeMenu(UMSG(MMenuSortTitle),SortMenu,sizeof(SortMenu)/sizeof(SortMenu[0]),0);
3747
3748    SortModeMenu.SetHelp(L"PanelCmdSort");
3749    SortModeMenu.SetPosition(X1+4,-1,0,0);
3750    SortModeMenu.SetFlags(VMENU_WRAPMODE);
3751    SortModeMenu.Process();
3752    if ((SortCode=SortModeMenu.Modal::GetExitCode())<0)
3753      return;
3754  }
3755  if (SortCode<sizeof(SortModes)/sizeof(SortModes[0]))
3756    SetSortMode(SortModes[SortCode]);
3757  else
3758    switch(SortCode)
3759    {
3760      case 13:
3761        ProcessKey(KEY_SHIFTF11);
3762        break;
3763      case 14:
3764        ProcessKey(KEY_SHIFTF12);
3765        break;
3766      case 12:
3767        NumericSort=NumericSort?0:1;
3768        Update(UPDATE_KEEP_SELECTION);
3769        Redraw();
3770        Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3771        AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
3772        AnotherPanel->Redraw();
3773        break;
3774    }
3775}
3776
3777
3778void FileList::DeleteDiz(const wchar_t *Name, const wchar_t *ShortName)
3779{
3780  if (PanelMode==NORMAL_PANEL)
3781    Diz.DeleteDiz(Name,ShortName);
3782}
3783
3784
3785void FileList::FlushDiz()
3786{
3787  if (PanelMode==NORMAL_PANEL)
3788    Diz.Flush(strCurDir);
3789}
3790
3791
3792void FileList::GetDizName(string &strDizName)
3793{
3794  if (PanelMode==NORMAL_PANEL)
3795    Diz.GetDizName(strDizName);
3796}
3797
3798
3799void FileList::CopyDiz(const wchar_t *Name, const wchar_t *ShortName,const wchar_t *DestName,
3800                       const wchar_t *DestShortName,DizList *DestDiz)
3801{
3802  Diz.CopyDiz(Name,ShortName,DestName,DestShortName,DestDiz);
3803}
3804
3805
3806void FileList::DescribeFiles()
3807{
3808  string strSelName, strSelShortName;
3809  int FileAttr,DizCount=0;
3810
3811  ReadDiz();
3812
3813  SaveSelection();
3814  GetSelName(NULL,FileAttr);
3815  Panel* AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3816  int AnotherType=AnotherPanel->GetType();
3817
3818  while (GetSelName(&strSelName,FileAttr,&strSelShortName))
3819  {
3820    string strDizText, strMsg, strTruncMsg, strQuotedName;
3821    const wchar_t *PrevText;
3822    PrevText=Diz.GetDizTextAddr(strSelName,strSelShortName,GetLastSelectedSize());
3823    strQuotedName = strSelName;
3824    QuoteSpaceOnly(strQuotedName);
3825    strMsg.Format (UMSG(MEnterDescription),(const wchar_t*)strQuotedName);
3826    strTruncMsg.Format (L"%.65s",(const wchar_t*)strMsg);
3827    /* $ 09.08.2000 SVS
3828       Для Ctrl-Z ненужно брать предыдущее значение!
3829    */
3830    if (!GetString(UMSG(MDescribeFiles),strTruncMsg,L"DizText",
3831                   PrevText!=NULL ? PrevText:L"",strDizText,1024,
3832                   L"FileDiz",FIB_ENABLEEMPTY|(!DizCount?FIB_NOUSELASTHISTORY:0)|FIB_BUTTONS))
3833      break;
3834
3835    DizCount++;
3836    if ( strDizText.IsEmpty() )
3837      Diz.DeleteDiz(strSelName,strSelShortName);
3838    else
3839    {
3840      string strDizLine;
3841      strDizLine.Format (L"%-*s %s",Opt.Diz.StartPos>1 ? Opt.Diz.StartPos-2:0, (const wchar_t*)strQuotedName, (const wchar_t*)strDizText);
3842      Diz.AddDiz(strSelName,strSelShortName,strDizLine);
3843    }
3844    ClearLastGetSelection();
3845    // BugZ#442 - Deselection is late when making file descriptions
3846    FlushDiz();
3847    // BugZ#863 - При редактировании группы дескрипшенов они не обновляются на ходу
3848    //if (AnotherType==QVIEW_PANEL) continue; //TODO ???
3849    if (AnotherType==INFO_PANEL) AnotherPanel->Update(UIC_UPDATE_NORMAL);
3850    Update(UPDATE_KEEP_SELECTION);
3851    Redraw();
3852  }
3853  /*if (DizCount>0)
3854  {
3855    FlushDiz();
3856    Update(UPDATE_KEEP_SELECTION);
3857    Redraw();
3858    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
3859    AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
3860    AnotherPanel->Redraw();
3861  }*/
3862}
3863
3864
3865void FileList::SetReturnCurrentFile(int Mode)
3866{
3867  ReturnCurrentFile=Mode;
3868}
3869
3870
3871bool FileList::ApplyCommand()
3872{
3873  static string strPrevCommand;
3874  string strCommand;
3875
3876  if (!GetString(UMSG(MAskApplyCommandTitle),UMSG(MAskApplyCommand),L"ApplyCmd",strPrevCommand,strCommand,260, L"ApplyCmd",FIB_BUTTONS) || !SetCurPath())
3877    return false;
3878
3879  strPrevCommand = strCommand;
3880  string strSelName, strSelShortName;
3881  int FileAttr;
3882  int RdrwDskt=CtrlObject->MainKeyBar->IsVisible();
3883
3884  RedrawDesktop Redraw(TRUE);
3885  SaveSelection();
3886
3887  GetSelName(NULL,FileAttr);
3888  while (GetSelName(&strSelName,FileAttr,&strSelShortName) && !CheckForEsc())
3889  {
3890    string strConvertedCommand;
3891    string strListName, strAnotherListName;
3892    string strShortListName, strAnotherShortListName;
3893
3894    strConvertedCommand = strCommand;
3895
3896    {
3897      int PreserveLFN=SubstFileName(strConvertedCommand,strSelName,strSelShortName,&strListName,&strAnotherListName,&strShortListName, &strAnotherShortListName);
3898      PreserveLongName PreserveName(strSelShortName,PreserveLFN);
3899
3900      Execute(strConvertedCommand,FALSE,FALSE);
3901
3902      ClearLastGetSelection();
3903    }
3904  }
3905  /*$ 23.07.2001 SKV
3906    что бы не затирать последнюю строку вывода.
3907  */
3908  if(RdrwDskt)
3909  {
3910    ScrBuf.Scroll(1);
3911    ScrBuf.Flush();
3912  }
3913  return true;
3914}
3915
3916
3917void FileList::CountDirSize(DWORD PluginFlags)
3918{
3919  unsigned long DirCount,DirFileCount,ClusterSize;;
3920  unsigned __int64 FileSize,CompressedFileSize,RealFileSize;
3921  unsigned long SelDirCount=0;
3922  struct FileListItem *CurPtr;
3923  int I;
3924
3925  /* $ 09.11.2000 OT
3926    F3 на ".." в плагинах
3927  */
3928  if ( PanelMode==PLUGIN_PANEL && !CurFile && TestParentFolderName(ListData[0]->strName))
3929  {
3930    struct FileListItem *DoubleDotDir = NULL;
3931    if (SelFileCount)
3932    {
3933      DoubleDotDir = ListData[0];
3934      for (I=0; I < FileCount; I++)
3935      {
3936        CurPtr = ListData[I];
3937        if (CurPtr->Selected && (CurPtr->FileAttr & FA_DIREC))
3938        {
3939          DoubleDotDir = NULL;
3940          break;
3941        }
3942      }
3943    }
3944    else
3945    {
3946      DoubleDotDir = ListData[0];
3947    }
3948
3949    if (DoubleDotDir)
3950    {
3951      DoubleDotDir->ShowFolderSize=1;
3952      DoubleDotDir->UnpSize     = 0;
3953      DoubleDotDir->PackSize    = 0;
3954      for (I=1; I < FileCount; I++)
3955      {
3956        CurPtr = ListData[I];
3957        if (CurPtr->FileAttr & FA_DIREC)
3958        {
3959          if (GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize))
3960          {
3961            DoubleDotDir->UnpSize += FileSize;
3962            DoubleDotDir->PackSize += CompressedFileSize;
3963          }
3964        }
3965        else
3966        {
3967          DoubleDotDir->UnpSize     += CurPtr->UnpSize;
3968          DoubleDotDir->PackSize    += CurPtr->PackSize;
3969        }
3970      }
3971    }
3972  }
3973
3974  for (I=0; I < FileCount; I++)
3975  {
3976    CurPtr = ListData[I];
3977    if (CurPtr->Selected && (CurPtr->FileAttr & FA_DIREC))
3978    {
3979      SelDirCount++;
3980      if (PanelMode==PLUGIN_PANEL && !(PluginFlags & OPIF_REALNAMES) &&
3981          GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize)
3982        ||
3983          (PanelMode!=PLUGIN_PANEL || (PluginFlags & OPIF_REALNAMES)) &&
3984          GetDirInfo(UMSG(MDirInfoViewTitle),
3985                     CurPtr->strName,
3986                     DirCount,DirFileCount,FileSize,
3987                     CompressedFileSize,RealFileSize, ClusterSize,0,Filter,GETDIRINFO_DONTREDRAWFRAME|GETDIRINFO_SCANSYMLINKDEF)==1)
3988      {
3989        SelFileSize -= CurPtr->UnpSize;
3990        SelFileSize += FileSize;
3991        CurPtr->UnpSize = FileSize;
3992        CurPtr->PackSize = CompressedFileSize;
3993        CurPtr->ShowFolderSize=1;
3994      }
3995      else
3996        break;
3997    }
3998  }
3999
4000  CurPtr=ListData[CurFile];
4001
4002  if (SelDirCount==0)
4003  {
4004    if (PanelMode==PLUGIN_PANEL && !(PluginFlags & OPIF_REALNAMES) &&
4005        GetPluginDirInfo(hPlugin,CurPtr->strName,DirCount,DirFileCount,FileSize,CompressedFileSize)
4006      ||
4007        (PanelMode!=PLUGIN_PANEL || (PluginFlags & OPIF_REALNAMES)) &&
4008        GetDirInfo(UMSG(MDirInfoViewTitle),
4009                   TestParentFolderName(CurPtr->strName) ? L".":CurPtr->strName,
4010                   DirCount,
4011                   DirFileCount,FileSize,CompressedFileSize,RealFileSize,ClusterSize,0,Filter,GETDIRINFO_DONTREDRAWFRAME|GETDIRINFO_SCANSYMLINKDEF)==1)
4012    {
4013      CurPtr->UnpSize = FileSize;
4014      CurPtr->PackSize = CompressedFileSize;
4015      CurPtr->ShowFolderSize=1;
4016    }
4017  }
4018
4019  SortFileList(TRUE);
4020  ShowFileList(TRUE);
4021  CtrlObject->Cp()->Redraw();
4022  CreateChangeNotification(TRUE);
4023}
4024
4025
4026int FileList::GetPrevViewMode()
4027{
4028  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4029    return(PluginsStack[0]->PrevViewMode);
4030  else
4031    return(ViewMode);
4032}
4033
4034
4035int FileList::GetPrevSortMode()
4036{
4037  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4038    return(PluginsStack[0]->PrevSortMode);
4039  else
4040    return(SortMode);
4041}
4042
4043
4044int FileList::GetPrevSortOrder()
4045{
4046  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4047    return(PluginsStack[0]->PrevSortOrder);
4048  else
4049    return(SortOrder);
4050}
4051
4052int FileList::GetPrevNumericSort()
4053{
4054  if (PanelMode==PLUGIN_PANEL && PluginsStackSize>0)
4055    return(PluginsStack[0]->PrevNumericSort);
4056  else
4057    return(NumericSort);
4058}
4059
4060
4061HANDLE FileList::OpenFilePlugin(const wchar_t *FileName,int PushPrev)
4062{
4063  if (!PushPrev && PanelMode==PLUGIN_PANEL)
4064    while (1)
4065    {
4066      if (ProcessPluginEvent(FE_CLOSE,NULL))
4067        return((HANDLE)-2);
4068      if (!PopPlugin(TRUE))
4069        break;
4070    }
4071  HANDLE hNewPlugin=OpenPluginForFile(FileName);
4072  if (hNewPlugin!=INVALID_HANDLE_VALUE && hNewPlugin!=(HANDLE)-2)
4073  {
4074    if (PushPrev)
4075    {
4076
4077      PrevDataStack=(PrevDataItem **)xf_realloc(PrevDataStack,(PrevDataStackSize+1)*sizeof(PrevDataItem*));
4078
4079      PrevDataStack[PrevDataStackSize] = new PrevDataItem;
4080
4081      PrevDataStack[PrevDataStackSize]->PrevListData=ListData;
4082      PrevDataStack[PrevDataStackSize]->PrevFileCount=FileCount;
4083      PrevDataStack[PrevDataStackSize]->PrevTopFile = CurTopFile;
4084      PrevDataStack[PrevDataStackSize]->strPrevName = FileName;
4085      PrevDataStackSize++;
4086      ListData=NULL;
4087      FileCount=0;
4088    }
4089
4090    BOOL WasFullscreen = IsFullScreen();
4091
4092    SetPluginMode(hNewPlugin,FileName);  // SendOnFocus??? true???
4093    PanelMode=PLUGIN_PANEL;
4094    UpperFolderTopFile=CurTopFile;
4095    CurFile=0;
4096    Update(0);
4097    Redraw();
4098    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
4099    if ( (AnotherPanel->GetType()==INFO_PANEL) || WasFullscreen )
4100      AnotherPanel->Redraw();
4101  }
4102  return(hNewPlugin);
4103}
4104
4105
4106void FileList::ProcessCopyKeys(int Key)
4107{
4108  if (FileCount>0)
4109  {
4110    int Drag=Key==KEY_DRAGCOPY || Key==KEY_DRAGMOVE;
4111    int Ask=!Drag || Opt.Confirm.Drag;
4112    int Move=(Key==KEY_F6 || Key==KEY_DRAGMOVE);
4113    int AnotherDir=FALSE;
4114    Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(this);
4115    if (AnotherPanel->GetType()==FILE_PANEL)
4116    {
4117      FileList *AnotherFilePanel=(FileList *)AnotherPanel;
4118      if (AnotherFilePanel->FileCount>0 &&
4119          (AnotherFilePanel->ListData[AnotherFilePanel->CurFile]->FileAttr & FA_DIREC) &&
4120          !TestParentFolderName(AnotherFilePanel->ListData[AnotherFilePanel->CurFile]->strName))
4121      {
4122        AnotherDir=TRUE;
4123        if (Drag)
4124        {
4125          AnotherPanel->ProcessKey(KEY_ENTER);
4126          SetCurPath();
4127        }
4128      }
4129    }
4130    if (PanelMode==PLUGIN_PANEL && !CtrlObject->Plugins.UseFarCommand(hPlugin,PLUGIN_FARGETFILES))
4131    {
4132      if (Key!=KEY_ALTF6)
4133      {
4134        string strPluginDestPath;
4135        int ToPlugin=FALSE;
4136        if (AnotherPanel->GetMode()==PLUGIN_PANEL && AnotherPanel->IsVisible() &&
4137            !CtrlObject->Plugins.UseFarCommand(AnotherPanel->GetPluginHandle(),PLUGIN_FARPUTFILES))
4138        {
4139          ToPlugin=2;
4140          ShellCopy ShCopy(this,Move,FALSE,FALSE,Ask,ToPlugin,strPluginDestPath);
4141        }
4142        if (ToPlugin!=-1)
4143          if (ToPlugin)
4144            PluginToPluginFiles(Move);
4145          else
4146          {
4147            string strDestPath;
4148            if ( !strPluginDestPath.IsEmpty() )
4149              strDestPath = strPluginDestPath;
4150            else
4151            {
4152              AnotherPanel->GetCurDir(strDestPath);
4153              if(!AnotherPanel->IsVisible())
4154              {
4155                struct OpenPluginInfo Info;
4156                CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info);
4157                if (Info.HostFile!=NULL && *Info.HostFile!=0)
4158                {
4159                  wchar_t *ExtPtr;
4160                  strDestPath = PointToName(Info.HostFile);
4161
4162                  ExtPtr = strDestPath.GetBuffer();
4163
4164                  if ( (ExtPtr=wcsrchr(ExtPtr, L'.')) != NULL )
4165                      *ExtPtr = 0;
4166
4167                  strDestPath.ReleaseBuffer();
4168                }
4169              }
4170            }
4171
4172            PluginGetFiles(strDestPath,Move);
4173          }
4174      }
4175    }
4176    else
4177    {
4178      int ToPlugin=AnotherPanel->GetMode()==PLUGIN_PANEL &&
4179                    AnotherPanel->IsVisible() && Key!=KEY_ALTF6 &&
4180                    !CtrlObject->Plugins.UseFarCommand(AnotherPanel->GetPluginHandle(),PLUGIN_FARPUTFILES);
4181
4182      if(Key != KEY_ALTF6 ||
4183        (Key == KEY_ALTF6 && WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT))
4184      {
4185         ShellCopy ShCopy(this,Move,Key==KEY_ALTF6,FALSE,Ask,ToPlugin,NULL);
4186      }
4187
4188      if (ToPlugin==1)
4189        PluginPutFilesToAnother(Move,AnotherPanel);
4190    }
4191    if (AnotherDir && Drag)
4192      AnotherPanel->ProcessKey(KEY_ENTER);
4193  }
4194}
4195
4196void FileList::SetSelectedFirstMode(int Mode)
4197{
4198  SelectedFirst=Mode;
4199  SortFileList(TRUE);
4200}
4201
4202void FileList::ChangeSortOrder(int NewOrder)
4203{
4204  Panel::ChangeSortOrder(NewOrder);
4205  SortFileList(TRUE);
4206  Show();
4207}
4208
4209BOOL FileList::UpdateKeyBar()
4210{
4211  KeyBar *KB=CtrlObject->MainKeyBar;
4212
4213  KB->SetAllGroup (KBL_MAIN, MF1, 12);
4214  KB->SetAllGroup (KBL_SHIFT, MShiftF1, 12);
4215  KB->SetAllGroup (KBL_ALT, MAltF1, 12);
4216  KB->SetAllGroup (KBL_CTRL, MCtrlF1, 12);
4217  KB->SetAllGroup (KBL_CTRLSHIFT, MCtrlShiftF1, 12);
4218  KB->SetAllGroup (KBL_CTRLALT, MCtrlAltF1, 12);
4219  KB->SetAllGroup (KBL_ALTSHIFT, MAltShiftF1, 12);
4220
4221  if(WinVer.dwPlatformId != VER_PLATFORM_WIN32_NT)
4222    KB->Change(KBL_ALT,L"",6-1);
4223
4224  KB->ReadRegGroup(L"Shell",Opt.strLanguage);
4225  KB->SetAllRegGroup();
4226
4227  if (GetMode() == PLUGIN_PANEL)
4228  {
4229    struct OpenPluginInfo Info;
4230    GetOpenPluginInfo(&Info);
4231    if (Info.KeyBar)
4232    {
4233      KB->Set((const wchar_t **)Info.KeyBar->Titles,12);
4234      KB->SetShift((const wchar_t **)Info.KeyBar->ShiftTitles,12);
4235      KB->SetAlt((const wchar_t **)Info.KeyBar->AltTitles,12);
4236      KB->SetCtrl((const wchar_t **)Info.KeyBar->CtrlTitles,12);
4237      if(Info.StructSize >= sizeof(struct OpenPluginInfo))
4238      {
4239        KB->SetCtrlShift((const wchar_t **)Info.KeyBar->CtrlShiftTitles,12);
4240        KB->SetAltShift((const wchar_t **)Info.KeyBar->AltShiftTitles,12);
4241        KB->SetCtrlAlt((const wchar_t **)Info.KeyBar->CtrlAltTitles,12);
4242      }
4243    }
4244  }
4245
4246  return TRUE;
4247}
4248
4249int FileList::PluginPanelHelp(HANDLE hPlugin)
4250{
4251  string strPath, strFileName, strStartTopic;
4252
4253  PluginHandle *ph = (PluginHandle*)hPlugin;
4254
4255  strPath = ph->pPlugin->GetModuleName();
4256
4257  CutToSlash(strPath);
4258
4259  int nCodePage = CP_OEMCP;
4260
4261  FILE *HelpFile=Language::OpenLangFile(strPath,HelpFileMask,Opt.strHelpLanguage,strFileName, nCodePage);
4262  if (HelpFile==NULL)
4263    return(FALSE);
4264  fclose(HelpFile);
4265  strStartTopic.Format(HelpFormatLink,(const wchar_t*)strPath,L"Contents");
4266  Help PanelHelp(strStartTopic);
4267  return(TRUE);
4268}
4269
4270/* $ 19.11.2001 IS
4271     для файловых панелей с реальными файлами никакого префикса не добавляем
4272*/
4273string &FileList::AddPluginPrefix(FileList *SrcPanel,string &strPrefix)
4274{
4275        strPrefix = L"";
4276        if(Opt.SubstPluginPrefix && SrcPanel->GetMode()==PLUGIN_PANEL)
4277        {
4278                OpenPluginInfo Info;
4279                PluginHandle *ph = (PluginHandle*)SrcPanel->hPlugin;
4280
4281                CtrlObject->Plugins.GetOpenPluginInfo(ph,&Info);
4282
4283                if(!(Info.Flags & OPIF_REALNAMES))
4284                {
4285                        PluginInfo PInfo;
4286
4287                        CtrlObject->Plugins.GetPluginInfo(ph->pPlugin, &PInfo);
4288
4289                        if(PInfo.CommandPrefix && *PInfo.CommandPrefix)
4290                        {
4291                                strPrefix = PInfo.CommandPrefix;
4292
4293                                wchar_t *Ptr=strPrefix.GetBuffer ();
4294
4295                                Ptr = wcschr(Ptr, L':');
4296
4297                                if(Ptr)
4298                                {
4299                                        *++Ptr=0;
4300                                        strPrefix.ReleaseBuffer();
4301                                }
4302                                else
4303                                {
4304                                        strPrefix.ReleaseBuffer();
4305                                        strPrefix += L":";
4306                                }
4307                        }
4308                }
4309        }
4310        return strPrefix;
4311}
4312
4313
4314void FileList::IfGoHome(wchar_t Drive)
4315{
4316        string strTmpCurDir;
4317        string strFName;
4318
4319        if (apiGetModuleFileName (NULL, strFName))
4320        {
4321                strFName.SetLength(3);
4322
4323                // СНАЧАЛА ПАССИВНАЯ ПАНЕЛЬ!!!
4324                /*
4325                        Почему? - Просто - если активная широкая (или пассивная
4326                        широкая) - получаем багу с прорисовкой!
4327                */
4328                Panel *Another=CtrlObject->Cp()->GetAnotherPanel (this);
4329                if (Another->GetMode() != PLUGIN_PANEL)
4330                {
4331                        Another->GetCurDir(strTmpCurDir);
4332                        if (strTmpCurDir.At(0) == Drive && strTmpCurDir.At(1) == L':')
4333                                Another->SetCurDir(strFName, FALSE);
4334                }
4335
4336                if (GetMode() != PLUGIN_PANEL)
4337                {
4338                        GetCurDir(strTmpCurDir);
4339                        if (strTmpCurDir.At(0) == Drive && strTmpCurDir.At(1) == L':')
4340                                SetCurDir(strFName, FALSE); // переходим в корень диска с far.exe
4341                }
4342        }
4343}
4344
4345
4346BOOL FileList::GetItem(int Index,void *Dest)
4347{
4348  if(Index == -1 || Index == -2)
4349    Index=GetCurrentPos();
4350  if((DWORD)Index >= (DWORD)FileCount)
4351    return FALSE;
4352  *((FileListItem *)Dest)=*ListData[Index];
4353  return TRUE;
4354}
Note: See TracBrowser for help on using the browser.