root/trunk/unicode_far/filelist.cpp @ 1579

Revision 1579, 123.9 KB (checked in by skirda, 2 years ago)

macro mix

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