7 Copyright (c) 1996 Eugene Roshal
8 Copyright (c) 2000 Far Group
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 2. 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.
19 3. The name of the authors may not be used to endorse or promote products
20 derived from this software without specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "headers.hpp"
38 #include "codepage.hpp"
39 #include "macroopcode.hpp"
40 #include "keyboard.hpp"
47 #include "filepanels.hpp"
48 #include "fileview.hpp"
49 #include "savescr.hpp"
50 #include "ctrlobj.hpp"
52 #include "TPreRedrawFunc.hpp"
56 #include "message.hpp"
57 #include "clipboard.hpp"
60 #include "pathmix.hpp"
61 #include "filestr.hpp"
63 #include "execute.hpp"
64 #include "constitle.hpp"
65 #include "console.hpp"
66 #include "AnsiEsc.hpp"
67 #include "wakeful.hpp"
69 #include "UtfConvert.hpp"
71 static void PR_ViewerSearchMsg();
72 static void ViewerSearchMsg(const wchar_t *Name
,int Percent
);
74 static int InitHex
=FALSE
,SearchHex
=FALSE
;
76 static int NextViewerID
=0;
79 static int CalcByteDistance(UINT CodePage
, const wchar_t* begin
, const wchar_t* end
)
83 #if (__WCHAR_MAX__ > 0xffff)
84 if ((CodePage
== CP_UTF32LE
) || (CodePage
== CP_UTF32BE
)) {
85 return (end
- begin
) * 4;
90 if ((CodePage
== CP_UTF16LE
) || (CodePage
== CP_UTF16BE
)) {
91 distance
= UtfCalcSpace
<wchar_t, uint16_t>(begin
, end
- begin
, false);
92 distance
*= sizeof(uint16_t);
94 } else if (CodePage
== CP_UTF8
) {
95 distance
= UtfCalcSpace
<wchar_t, uint8_t>(begin
, end
- begin
, false);
97 } else {// one-byte code page?
98 distance
= end
- begin
;
102 if ((CodePage
== CP_UTF16LE
) || (CodePage
== CP_UTF16BE
)) {
103 return (end
- begin
) * 2;
108 if (CodePage
== CP_UTF8
) {
109 distance
= UtfCalcSpace
<wchar_t, uint8_t>(begin
, end
- begin
, false);
111 } else {// one-byte code page?
112 distance
= end
- begin
;
120 static int CalcCodeUnitsDistance(UINT CodePage
, const wchar_t* begin
, const wchar_t* end
)
122 int distance
= CalcByteDistance(CodePage
, begin
, end
);
123 if (distance
> 0) switch (CodePage
) {
124 case CP_UTF32LE
: case CP_UTF32BE
: distance
/= 4; break;
125 case CP_UTF16LE
: case CP_UTF16BE
: distance
/= 2; break;
131 Viewer::Viewer(bool bQuickView
, UINT aCodePage
):
133 m_bQuickView(bQuickView
)
135 _OT(SysLog(L
"[%p] Viewer::Viewer()", this));
137 for (int i
=0; i
<=MAXSCRY
; i
++)
139 Strings
[i
] = new ViewerString();
140 Strings
[i
]->lpData
[MAX_VIEWLINEB
] = 0;
143 strLastSearchStr
= strGlobalSearchString
;
144 LastSearchCase
=GlobalSearchCase
;
145 LastSearchRegexp
=Opt
.ViOpt
.SearchRegexp
;
146 LastSearchWholeWords
=GlobalSearchWholeWords
;
147 LastSearchReverse
=GlobalSearchReverse
;
148 LastSearchHex
=GlobalSearchHex
;
149 VM
.CodePage
=DefCodePage
=aCodePage
;
150 // Вспомним тип врапа
151 VM
.Wrap
=Opt
.ViOpt
.ViewerIsWrap
;
152 VM
.WordWrap
=Opt
.ViOpt
.ViewerWrap
;
161 SelectPos
=SelectSize
=0;
165 CodePageChangedByUser
=FALSE
;
166 memset(&BMSavePos
,0xff,sizeof(BMSavePos
));
167 memset(UndoData
,0xff,sizeof(UndoData
));
170 ViewerID
=::NextViewerID
++;
171 CtrlObject
->Plugins
.CurViewer
=this;
173 HostFileViewer
=nullptr;
174 bVE_READ_Sent
= false;
177 FARString
Viewer::ComposeCacheName()
179 // FARString strCacheName=strPluginData.IsEmpty()?strFileName:strPluginData+PointToName(strFileName);
180 FARString strCacheName
=strPluginData
.IsEmpty()?strFullFileName
:strPluginData
+PointToName(strFileName
);
183 strCacheName
+= L
":PROCESSED";
189 void Viewer::SavePosCache()
191 if (Opt
.ViOpt
.SavePos
&& Opt
.OnlyEditorViewerUsed
!= Options::ONLY_VIEWER_ON_CMDOUT
)
193 FARString strCacheName
=ComposeCacheName();
197 if (CodePageChangedByUser
)
199 CodePage
=VM
.CodePage
;
202 PosCache poscache
={};
203 poscache
.Param
[0]=FilePos
;
204 poscache
.Param
[1]=LeftPos
;
205 poscache
.Param
[2]=VM
.Hex
;
206 //=poscache.Param[3];
207 poscache
.Param
[4]=CodePage
;
209 if (Opt
.ViOpt
.SaveShortPos
)
211 poscache
.Position
[0]=BMSavePos
.SavePosAddr
;
212 poscache
.Position
[1]=BMSavePos
.SavePosLeft
;
213 //poscache.Position[2]=;
214 //poscache.Position[3]=;
217 CtrlObject
->ViewerPosCache
->AddPosition(strCacheName
,poscache
);
223 KeepInitParameters();
225 if (ViewFile
.Opened())
231 _tran(SysLog(L
"[%p] Viewer::~Viewer, TempViewName=[%ls]",this,TempViewName
));
233 Удаляем файл только, если нет открытых фреймов с таким именем.
236 if (!strProcessedViewName
.IsEmpty())
238 unlink(strProcessedViewName
.GetMB().c_str());
239 CutToSlash(strProcessedViewName
);
240 if (!strProcessedViewName
.IsEmpty())
242 rmdir(strProcessedViewName
.GetMB().c_str());
243 strProcessedViewName
.Clear();
247 for (int i
=0; i
<=MAXSCRY
; i
++)
252 if (!OpenFailed
&& bVE_READ_Sent
)
254 CtrlObject
->Plugins
.CurViewer
=this; //HostFileViewer;
255 CtrlObject
->Plugins
.ProcessViewerEvent(VE_CLOSE
,&ViewerID
);
260 void Viewer::KeepInitParameters()
262 strGlobalSearchString
= strLastSearchStr
;
263 GlobalSearchCase
=LastSearchCase
;
264 GlobalSearchWholeWords
=LastSearchWholeWords
;
265 GlobalSearchReverse
=LastSearchReverse
;
266 GlobalSearchHex
=LastSearchHex
;
267 Opt
.ViOpt
.ViewerIsWrap
=VM
.Wrap
;
268 Opt
.ViOpt
.ViewerWrap
=VM
.WordWrap
;
269 Opt
.ViOpt
.SearchRegexp
=LastSearchRegexp
;
274 int Viewer::OpenFile(const wchar_t *Name
,int warning
)
276 VM
.CodePage
=DefCodePage
;
277 DefCodePage
=CP_AUTODETECT
;
282 DWORD FileAttr
= apiGetFileAttributes(Name
);
283 if (FileAttr
!=INVALID_FILE_ATTRIBUTES
&& (FileAttr
&FILE_ATTRIBUTE_DEVICE
)!=0) {//avoid stuck
288 SelectSize
= 0; // Сбросим выделение
292 // Renders ANSI ESC coloring sequences
293 // For all files beside *.ansi/*.ans runs view.sh
294 // that doing 'processing' of file and writes output
295 // into temporary filename. That temporary file then
296 // viewed instead of original one's.
297 const wchar_t *ext
= wcsrchr(Name
, L
'.');
298 if (ext
&& (wcscasecmp(ext
, L
".ansi") == 0 || wcscasecmp(ext
, L
".ans") == 0))
302 if (VM
.CodePage
== CP_AUTODETECT
)
307 else if (VM
.Processed
)
309 if (strProcessedViewName
.IsEmpty())
311 if (FarMkTempEx(strProcessedViewName
, L
"view"))
313 strProcessedViewName
+= PointToName(strFileName
);
315 std::string cmd
= GetMyScriptQuoted("view.sh");
316 std::string strFile
= strFileName
.GetMB();
318 QuoteCmdArgIfNeed(strFile
);
322 strFile
= strProcessedViewName
.GetMB();
323 QuoteCmdArgIfNeed(strFile
);
326 int r
= farExecuteA(cmd
.c_str(), 0);
328 Name
= strProcessedViewName
.CPtr();
330 unlink(strProcessedViewName
.GetMB().c_str());
331 strProcessedViewName
.Clear();
335 Name
= strProcessedViewName
.CPtr();
339 ViewFile
.Open(Wide2MB(Name
));//strFileName.GetMB()
341 if (!ViewFile
.Opened())
344 + 'warning' flag processing, in QuickView it is FALSE
345 so don't show red message box */
347 Message(MSG_WARNING
|MSG_ERRORTYPE
,1,Msg::ViewerTitle
,Msg::ViewerCannotOpenFile
,strFileName
,Msg::Ok
);
353 CodePageChangedByUser
=FALSE
;
355 ConvertNameToFull(strFileName
,strFullFileName
);
356 apiGetFindDataForExactPathName(strFileName
, ViewFindData
);
357 UINT CachedCodePage
=0;
359 if (Opt
.ViOpt
.SavePos
)
361 int64_t NewLeftPos
,NewFilePos
;
362 FARString strCacheName
=ComposeCacheName();
363 memset(&BMSavePos
,0xff,sizeof(BMSavePos
)); //заполним с -1
364 PosCache poscache
={};
366 if (Opt
.ViOpt
.SaveShortPos
)
368 poscache
.Position
[0]=BMSavePos
.SavePosAddr
;
369 poscache
.Position
[1]=BMSavePos
.SavePosLeft
;
370 //poscache.Position[2]=;
371 //poscache.Position[3]=;
374 CtrlObject
->ViewerPosCache
->GetPosition(strCacheName
,poscache
);
375 NewFilePos
=poscache
.Param
[0];
376 NewLeftPos
=poscache
.Param
[1];
377 VM
.Hex
=(int)poscache
.Param
[2];
378 //=poscache.Param[3];
379 CachedCodePage
=(UINT
)poscache
.Param
[4];
381 // Проверяем поддерживается или нет загруженная из кэша кодовая страница
382 if (CachedCodePage
&& !IsCodePageSupported(CachedCodePage
))
384 LastSelPos
=FilePos
=NewFilePos
;
393 Автоопределение Unicode не должно зависеть от опции
394 "Автоопределение таблицы символов", т.к. Unicode не есть
395 _таблица символов_ для перекодировки.
397 //if(ViOpt.AutoDetectTable)
402 if (VM
.CodePage
== CP_AUTODETECT
|| IsUnicodeOrUtfCodePage(VM
.CodePage
))
404 Detect
= GetFileFormat2(strFileName
,CodePage
,nullptr,Opt
.ViOpt
.AutoDetectCodePage
!=0,true);
407 if (VM
.CodePage
==CP_AUTODETECT
)
411 VM
.CodePage
=CodePage
;
416 VM
.CodePage
=CachedCodePage
;
417 CodePageChangedByUser
=TRUE
;
420 if (VM
.CodePage
==CP_AUTODETECT
)
421 VM
.CodePage
= Opt
.ViOpt
.DefaultCodePage
;
425 CodePageChangedByUser
=TRUE
;
429 // пока что запретим переключать hex в UTF8/UTF32, ибо не работает.
430 if (VM
.Hex
&& (VM
.CodePage
==CP_UTF8
|| VM
.CodePage
==CP_UTF32LE
|| VM
.CodePage
==CP_UTF32BE
))
432 VM
.CodePage
=WINPORT(GetACP
)();
435 if (!IsUnicodeOrUtfCodePage(VM
.CodePage
))
437 ViewFile
.SetPointer(0);
442 if (FilePos
>FileSize
)
446 // if (ViOpt.AutoDetectTable && !TableChangedByUser)
451 CtrlObject
->Plugins
.CurViewer
=this; // HostFileViewer;
453 пора легализироваться */
454 CtrlObject
->Plugins
.ProcessViewerEvent(VE_READ
,nullptr);
455 bVE_READ_Sent
= true;
461 функция вычисления ширины в зависимости от наличия скроллбара
464 void Viewer::AdjustWidth()
469 if (ViOpt
.ShowScrollbar
&& !m_bQuickView
)
476 void Viewer::SetCRSym()
478 if (!ViewFile
.Opened())
482 int CRCount
=0,LFCount
=0;
485 ReadSize
=vread(Buf
,ARRAYSIZE(Buf
));
487 for (I
=0; I
<ReadSize
; I
++)
495 if (I
+1>=ReadSize
|| Buf
[I
+1]!=L
'\n')
507 void Viewer::ShowPage(int nMode
)
512 if (!ViewFile
.Opened())
514 if (!strFileName
.IsEmpty() && ((nMode
== SHOW_RELOAD
) || (nMode
== SHOW_HEX
)))
516 SetScreen(X1
,Y1
,X2
,Y2
,L
' ',COL_VIEWERTEXT
);
518 SetColor(COL_WARNDIALOGTEXT
);
519 FS
<< fmt::Cells() << fmt::Truncate(XX2
- X1
+ 1) << Msg::ViewerCannotOpenFile
;
529 vseek(FilePos
,SEEK_SET
);
537 CtrlObject
->Plugins
.CurViewer
= this; //HostFileViewer;
541 CtrlObject
->Plugins
.CurViewer
= this; //HostFileViewer;
543 for (I
=0,Y
=Y1
; Y
<=Y2
; Y
++,I
++)
545 Strings
[I
]->nFilePos
= vtell();
547 if (Y
==Y1
+1 && !ViewFile
.Eof())
550 ReadString(Strings
[I
],-1,MAX_VIEWLINEB
);
556 for (I
=Y2
-Y1
-1; I
>=0; I
--)
558 Strings
[I
+1]->nFilePos
= Strings
[I
]->nFilePos
;
559 Strings
[I
+1]->nSelStart
= Strings
[I
]->nSelStart
;
560 Strings
[I
+1]->nSelEnd
= Strings
[I
]->nSelEnd
;
561 Strings
[I
+1]->bSelection
= Strings
[I
]->bSelection
;
562 wcscpy(Strings
[I
+1]->lpData
, Strings
[I
]->lpData
);
565 Strings
[0]->nFilePos
= FilePos
;
566 SecondPos
= Strings
[1]->nFilePos
;
567 ReadString(Strings
[0],(int)(SecondPos
-FilePos
),MAX_VIEWLINEB
);
571 for (I
=0; I
<Y2
-Y1
; I
++)
573 Strings
[I
]->nFilePos
= Strings
[I
+1]->nFilePos
;
574 Strings
[I
]->nSelStart
= Strings
[I
+1]->nSelStart
;
575 Strings
[I
]->nSelEnd
= Strings
[I
+1]->nSelEnd
;
576 Strings
[I
]->bSelection
= Strings
[I
+1]->bSelection
;
577 wcscpy(Strings
[I
]->lpData
, Strings
[I
+1]->lpData
);
580 FilePos
= Strings
[0]->nFilePos
;
581 SecondPos
= Strings
[1]->nFilePos
;
582 vseek(Strings
[Y2
-Y1
]->nFilePos
, SEEK_SET
);
583 ReadString(Strings
[Y2
-Y1
],-1,MAX_VIEWLINEB
);
584 Strings
[Y2
-Y1
]->nFilePos
= vtell();
585 ReadString(Strings
[Y2
-Y1
],-1,MAX_VIEWLINEB
);
589 if (nMode
!= SHOW_HEX
)
591 std::unique_ptr
<ViewerPrinter
> printer
;
593 printer
.reset(new AnsiEsc::Printer(B_BLACK
| F_WHITE
));
595 printer
.reset(new PlainViewerPrinter(COL_VIEWERTEXT
));
596 if (IsUnicodeOrUtfCodePage(VM
.CodePage
))
597 printer
->EnableBOMSkip();
599 for (I
=0,Y
=Y1
; Y
<=Y2
; Y
++,I
++)
601 int StrLen
= printer
->Length(Strings
[I
]->lpData
);
604 printer
->Print(LeftPos
, Width
, Strings
[I
]->lpData
);
606 if (SelectSize
&& Strings
[I
]->bSelection
)
608 auto visualSelStart
= printer
->Length(Strings
[I
]->lpData
, Strings
[I
]->nSelStart
);
609 auto visualSelLength
= printer
->Length(&Strings
[I
]->lpData
[Strings
[I
]->nSelStart
],
610 Strings
[I
]->nSelEnd
- Strings
[I
]->nSelStart
);
612 if (!VM
.Wrap
&& AdjustSelPosition
&&
613 (visualSelStart
< LeftPos
|| (visualSelStart
> LeftPos
614 && visualSelStart
+ visualSelLength
> LeftPos
+ XX2
- X1
)))
616 LeftPos
= visualSelStart
> 1 ? visualSelStart
- 1 : 0;
617 AdjustSelPosition
= FALSE
;
622 int SelX1
= X1
, SelSkip
= 0;
623 if (visualSelStart
> LeftPos
)
624 SelX1
+= visualSelStart
- LeftPos
;
625 else if (visualSelStart
< LeftPos
)
626 SelSkip
= LeftPos
- visualSelStart
;
628 if (visualSelLength
> SelSkip
) {
629 GotoXY((int)SelX1
, Y
);
630 // PlainViewerPrinter selPrinter(COL_VIEWERSELECTEDTEXT);
631 // if (IsUnicodeOrUtfCodePage(VM.CodePage))
632 // selPrinter.EnableBOMSkip();
633 printer
->SetSelection(true);
634 printer
->Print(SelSkip
,
635 visualSelLength
- SelSkip
, &Strings
[I
]->lpData
[Strings
[I
]->nSelStart
]);
636 printer
->SetSelection(false);
640 if (StrLen
> LeftPos
+ Width
&& ViOpt
.ShowArrows
)
643 SetColor(COL_VIEWERARROWS
);
647 if (LeftPos
>0 && *Strings
[I
]->lpData
&& ViOpt
.ShowArrows
)
650 SetColor(COL_VIEWERARROWS
);
660 void Viewer::DisplayObject()
662 ShowPage(VM
.Hex
?SHOW_HEX
:SHOW_RELOAD
);
665 void Viewer::ShowHex()
667 wchar_t OutStr
[MAX_VIEWLINE
],TextStr
[20];
672 int SelStart
, SelEnd
;
673 bool bSelStartFound
= false, bSelEndFound
= false;
674 int64_t HexLeftPos
=((LeftPos
>80-ObjWidth
) ? Max(80-ObjWidth
,0):LeftPos
);
676 for (EndFile
=0,Y
=Y1
; Y
<=Y2
; Y
++)
678 bSelStartFound
= false;
679 bSelEndFound
= false;
681 SetColor(COL_VIEWERTEXT
);
686 FS
<< fmt::Cells() << fmt::Expand(ObjWidth
) << L
"";
690 if (Y
==Y1
+1 && !ViewFile
.Eof())
694 ViewFile
.GetPointer(Ptr
);
695 swprintf(OutStr
,ARRAYSIZE(OutStr
),L
"%010llX: ", Ptr
);
697 int HexStrStart
= (int)wcslen(OutStr
);
698 SelStart
= HexStrStart
;
700 int64_t fpos
= vtell();
702 if (fpos
> SelectPos
)
703 bSelStartFound
= true;
705 if (fpos
< SelectPos
+SelectSize
-1)
709 bSelStartFound
= bSelEndFound
= false;
711 const wchar_t BorderLine
[]={BoxSymbols
[BS_V1
],L
' ',0};
713 if (VM
.CodePage
==CP_UTF16LE
|| VM
.CodePage
==CP_UTF16BE
)
717 int64_t fpos
= vtell();
719 if (SelectSize
>0 && (SelectPos
== fpos
))
721 bSelStartFound
= true;
722 SelStart
= (int)wcslen(OutStr
);
723 // SelSize=SelectSize;
725 Внимание! Возможно, это не совсем верное решение проблемы
726 выделения из плагинов, но мне пока другого в голову не пришло.
727 Я приравниваю SelectSize нулю в Process*
732 if (SelectSize
>0 && (fpos
== (SelectPos
+SelectSize
-1)))
735 SelEnd
= (int)wcslen(OutStr
)+3;
736 // SelSize=SelectSize;
742 убираем показ пустой строки, если длина
754 TextStr
[TextPos
++]=L
' ';
760 if (VM
.CodePage
== CP_UTF16BE
) {
761 OutChar
= WideReverse(OutChar
);
765 int OutStrLen
=StrLength(OutStr
);
766 swprintf(OutStr
+OutStrLen
,ARRAYSIZE(OutStr
)-OutStrLen
,L
"%02X%02X ", (unsigned int)HIBYTE(OutChar
), (unsigned int)LOBYTE(OutChar
));
773 TextStr
[TextPos
++]=Ch
;
778 wcscat(OutStr
, BorderLine
);
785 int64_t fpos
= vtell();
787 if (SelectSize
>0 && (SelectPos
== fpos
))
789 bSelStartFound
= true;
790 SelStart
= (int)wcslen(OutStr
);
791 // SelSize=SelectSize;
793 Внимание! Возможно, это не совсем верное решение проблемы
794 выделения из плагинов, но мне пока другого в голову не пришло.
795 Я приравниваю SelectSize нулю в Process*
800 if (SelectSize
>0 && (fpos
== (SelectPos
+SelectSize
-1)))
803 SelEnd
= (int)wcslen(OutStr
)+1;
804 // SelSize=SelectSize;
810 убираем показ пустой строки, если длина
822 - вместо 5 пробелов тут надо 3 */
824 TextStr
[TextPos
++]=L
' ';
829 WINPORT(WideCharToMultiByte
)(VM
.CodePage
, 0, &Ch
,1, &NewCh
,1," ",nullptr);
830 int OutStrLen
=StrLength(OutStr
);
831 swprintf(OutStr
+OutStrLen
,ARRAYSIZE(OutStr
)-OutStrLen
,L
"%02X ", (unsigned int)(unsigned char)NewCh
);
836 TextStr
[TextPos
++]=Ch
;
841 wcscat(OutStr
,BorderLine
);
846 wcscat(TextStr
,L
" ");
848 if ((SelEnd
<= SelStart
) && bSelStartFound
)
849 SelEnd
= (int)wcslen(OutStr
)-2;
852 wcscat(OutStr
,TextStr
);
855 for (size_t I
=0; I
< wcslen(OutStr
); ++I
)
856 if (OutStr
[I
] == (wchar_t)0xFFFF)
861 if (StrLength(OutStr
)>HexLeftPos
)
863 FS
<< fmt::Cells() << fmt::LeftAlign() << fmt::Size(ObjWidth
) << OutStr
+ static_cast<size_t>(HexLeftPos
);
867 FS
<< fmt::Cells() << fmt::Expand(ObjWidth
) << L
"";
870 if (bSelStartFound
&& bSelEndFound
)
872 SetColor(COL_VIEWERSELECTEDTEXT
);
873 GotoXY((int)((int64_t)X1
+SelStart
-HexLeftPos
),Y
);
874 FS
<< fmt::Cells() << fmt::Truncate(SelEnd
- SelStart
+ 1) << OutStr
+ static_cast<size_t>(SelStart
);
881 отрисовка скроллбара - в отдельную функцию
884 void Viewer::DrawScrollbar()
886 if (ViOpt
.ShowScrollbar
)
889 SetColor(COL_PANELSCROLLBAR
);
891 SetColor(COL_VIEWERSCROLLBAR
);
895 ScrollBar(X2
+(m_bQuickView
?1:0),Y1
,Y2
-Y1
+1,(LastPage
? (!FilePos
?0:100):ToPercent64(FilePos
,FileSize
)),100);
899 UINT64 Total
=FileSize
/16+(FileSize
%16?1:0);
900 UINT64 Top
=FilePos
/16+(FilePos
%16?1:0);
901 ScrollBarEx(X2
+(m_bQuickView
?1:0),Y1
,Y2
-Y1
+1,LastPage
?Top
?Total
:0:Top
,Total
);
907 FARString
&Viewer::GetTitle(FARString
&strName
,int,int)
909 if (!strTitle
.IsEmpty())
915 if (!IsAbsolutePath(strFileName
))
918 ViewNamesList
.GetCurDir(strPath
);
919 AddEndSlash(strPath
);
920 strName
= strPath
+strFileName
;
924 strName
= strFileName
;
931 void Viewer::ShowStatus()
934 HostFileViewer
->ShowStatus();
938 void Viewer::SetStatusMode(int Mode
)
944 void Viewer::ReadString(ViewerString
*pString
, int MaxSize
, int StrSize
)
948 bool bSelStartFound
= false, bSelEndFound
= false;
949 pString
->bSelection
= false;
956 // Alter-1: ::vread accepts number of codepoint units:
957 // 4-bytes for UTF32, 2-bytes for UTF16 and 1-bytes for everything else
958 // But we always display 16 bytes
959 switch (VM
.CodePage
) {
960 case CP_UTF32LE
: case CP_UTF32BE
: len
/= 4; break;
961 case CP_UTF16LE
: case CP_UTF16BE
: len
/= 2; break;
964 OutPtr
=vread(pString
->lpData
, len
);
965 pString
->lpData
[len
] = 0;
969 bool CRSkipped
=false;
971 if (SelectSize
&& vtell() > SelectPos
)
973 pString
->nSelStart
= 0;
974 bSelStartFound
= true;
979 if (OutPtr
>=StrSize
-16)
983 ! Wrap - трехпозиционный
985 if (VM
.Wrap
&& OutPtr
>XX2
-X1
)
988 + warp are now WORD-WRAP */
989 int64_t SavePos
=vtell();
992 if (vgetc(Ch
) && Ch
!=CRSym
&& (Ch
!=L
'\r' || (vgetc(TmpChar
) && TmpChar
!=CRSym
)))
994 vseek(SavePos
,SEEK_SET
);
998 if (!IsSpace(Ch
) && !IsSpace(pString
->lpData
[(int)OutPtr
]))
1000 int64_t SavePtr
=OutPtr
;
1002 /* $ 18.07.2000 tran
1003 добавил в качестве wordwrap разделителей , ; > ) */
1006 Ch2
=pString
->lpData
[(int)OutPtr
];
1008 if (IsSpace(Ch2
) || Ch2
==L
',' || Ch2
==L
';' || Ch2
==L
'>'|| Ch2
==L
')')
1014 Ch2
=pString
->lpData
[(int)OutPtr
];
1016 if (Ch2
==L
',' || Ch2
==L
';' || Ch2
==L
')' || Ch2
==L
'>')
1019 while (IsSpace(pString
->lpData
[(int)OutPtr
]) && OutPtr
<=SavePtr
)
1022 if (OutPtr
< SavePtr
&& OutPtr
)
1024 vseek(-CalcCodeUnitsDistance(VM
.CodePage
,
1025 &pString
->lpData
[(size_t)OutPtr
],
1026 &pString
->lpData
[(size_t)SavePtr
]),
1033 /* $ 13.09.2000 tran
1034 remove space at WWrap */
1040 if (!vgetc(Ch
) || !IsSpace(Ch
)) break;
1042 vseek(lastpos
, SEEK_SET
);
1051 if (SelectSize
> 0 && SelectPos
==vtell())
1053 pString
->nSelStart
= OutPtr
+(CRSkipped
?1:0);;
1054 bSelStartFound
= true;
1069 pString
->lpData
[(int)OutPtr
++]=L
'\r';
1076 pString
->lpData
[(int)OutPtr
++]=L
' ';
1078 while ((OutPtr
% ViOpt
.TabSize
) && ((int)OutPtr
< (MAX_VIEWLINEB
-1)));
1080 if (VM
.Wrap
&& OutPtr
>XX2
-X1
)
1081 pString
->lpData
[XX2
-X1
+1]=0;
1087 Баг: не учитывали левую границу при свертке
1095 int64_t SavePos
=vtell();
1098 if (vgetc(nextCh
) && nextCh
!=CRSym
)
1103 vseek(SavePos
,SEEK_SET
);
1110 if (!Ch
|| Ch
==L
'\n')
1113 pString
->lpData
[(int)OutPtr
++]=Ch
;
1114 pString
->lpData
[(int)OutPtr
]=0;
1116 if (SelectSize
> 0 && (SelectPos
+SelectSize
)==vtell())
1118 pString
->nSelEnd
= OutPtr
;
1119 bSelEndFound
= true;
1124 pString
->lpData
[(int)OutPtr
]=0;
1126 if (!bSelEndFound
&& SelectSize
&& vtell() < SelectPos
+SelectSize
)
1128 bSelEndFound
= true;
1129 pString
->nSelEnd
= wcslen(pString
->lpData
);
1134 if (pString
->nSelStart
> (int64_t)wcslen(pString
->lpData
))
1135 bSelStartFound
= false;
1138 if (pString
->nSelStart
> pString
->nSelEnd
)
1139 bSelStartFound
= false;
1142 LastPage
=ViewFile
.Eof();
1144 if (bSelStartFound
&& bSelEndFound
)
1145 pString
->bSelection
= true;
1149 int64_t Viewer::VMProcess(int OpCode
,void *vParam
,int64_t iParam
)
1154 return (int64_t)!FileSize
;
1155 case MCODE_C_SELECTED
:
1156 return (int64_t)(SelectSize
?TRUE
:FALSE
);
1158 return (int64_t)(LastPage
|| !ViewFile
.Opened());
1160 return (int64_t)(!FilePos
|| !ViewFile
.Opened());
1161 case MCODE_V_VIEWERSTATE
:
1163 DWORD MacroViewerState
=0;
1164 MacroViewerState
|=VM
.Wrap
?0x00000008:0;
1165 MacroViewerState
|=VM
.WordWrap
?0x00000010:0;
1166 MacroViewerState
|=VM
.Hex
?0x00000020:0;
1167 MacroViewerState
|=Opt
.OnlyEditorViewerUsed
?0x08000000|0x00000800:0;
1168 MacroViewerState
|=HostFileViewer
&& !HostFileViewer
->GetCanLoseFocus()?0x00000800:0;
1169 return (int64_t)MacroViewerState
;
1171 case MCODE_V_ITEMCOUNT
: // ItemCount - число элементов в текущем объекте
1172 return (int64_t)GetViewFileSize();
1173 case MCODE_V_CURPOS
: // CurPos - текущий индекс в текущем объекте
1174 return (int64_t)(GetViewFilePos()+1);
1181 - Путем проверки ViewFile на nullptr избавляемся от падения
1183 int Viewer::ProcessKey(int Key
)
1185 // Pressing Alt together with PageDown/PageUp allows to smoothly
1186 // boost scrolling speed, releasing Alt while keeping PageDown/PageUp
1187 // will continue scrolling with selected speed. Pressing any other key
1188 // or releasing keys until KEY_IDLE event dismisses scroll speed boost.
1189 if (Key
== KEY_ALTPGUP
|| Key
== KEY_ALTPGDN
)
1191 if (iBoostPg
< 0x100000)
1194 else if (Key
!= KEY_PGUP
&& Key
!= KEY_PGDN
&& Key
!= KEY_NONE
&& iBoostPg
!= 0)
1196 fprintf(stderr
, "Dismiss iBoostPg=%u due to Key=0x%x\n", iBoostPg
, Key
);
1200 if (Key
== KEY_SHIFTLEFT
|| Key
== KEY_SHIFTRIGHT
)
1202 if (SelectSize
> 0 && (SelectPos
> 0 || Key
== KEY_SHIFTRIGHT
))
1204 int64_t NewSelectSize
= SelectSize
+ 1;
1205 int64_t NewSelectPos
= SelectPos
;
1206 if (Key
== KEY_SHIFTLEFT
)
1208 fprintf(stderr
, "SELECTIO CHANGE: [%ld +%ld)\n", (unsigned long)NewSelectPos
, NewSelectSize
);
1209 SelectText(NewSelectPos
, NewSelectSize
, SelectFlags
);
1215 Происходят какие-то манипуляции -> снимем выделение
1217 if (!ViOpt
.PersistentBlocks
&&
1218 Key
!=KEY_IDLE
&& Key
!=KEY_NONE
&& !(Key
==KEY_CTRLINS
||Key
==KEY_CTRLNUMPAD0
) && Key
!=KEY_CTRLC
)
1221 if (!InternalKey
&& !LastKeyUndo
&& (FilePos
!=UndoData
[0].UndoAddr
|| LeftPos
!=UndoData
[0].UndoLeft
))
1223 for (int i
=ARRAYSIZE(UndoData
)-1; i
>0; i
--)
1225 UndoData
[i
].UndoAddr
=UndoData
[i
-1].UndoAddr
;
1226 UndoData
[i
].UndoLeft
=UndoData
[i
-1].UndoLeft
;
1229 UndoData
[0].UndoAddr
=FilePos
;
1230 UndoData
[0].UndoLeft
=LeftPos
;
1233 if (Key
!=KEY_ALTBS
&& Key
!=KEY_CTRLZ
&& Key
!=KEY_NONE
&& Key
!=KEY_IDLE
)
1236 if (Key
>=KEY_CTRL0
&& Key
<=KEY_CTRL9
)
1238 int Pos
=Key
-KEY_CTRL0
;
1240 if (BMSavePos
.SavePosAddr
[Pos
]!=POS_NONE
)
1242 FilePos
=BMSavePos
.SavePosAddr
[Pos
];
1243 LeftPos
=BMSavePos
.SavePosLeft
[Pos
];
1244 // LastSelPos=FilePos;
1251 if (Key
>=KEY_CTRLSHIFT0
&& Key
<=KEY_CTRLSHIFT9
)
1252 Key
=Key
-KEY_CTRLSHIFT0
+KEY_RCTRL0
;
1254 if (Key
>=KEY_RCTRL0
&& Key
<=KEY_RCTRL9
)
1256 int Pos
=Key
-KEY_RCTRL0
;
1257 BMSavePos
.SavePosAddr
[Pos
]=FilePos
;
1258 BMSavePos
.SavePosLeft
[Pos
]=LeftPos
;
1266 Help
Hlp(L
"Viewer");
1279 case KEY_CTRLINS
: case KEY_CTRLNUMPAD0
:
1281 if (SelectSize
&& ViewFile
.Opened())
1284 size_t DataSize
= (size_t)SelectSize
;// + (IsFullWideCodePage(VM.CodePage) ? sizeof(wchar_t) : 1);
1285 switch (VM
.CodePage
) {
1286 case CP_UTF32LE
: case CP_UTF32BE
: DataSize
+= 4; break;
1287 case CP_UTF16LE
: case CP_UTF16BE
: DataSize
+= 2; break;
1288 default: DataSize
++;
1290 int64_t CurFilePos
=vtell();
1292 if ((SelData
=(wchar_t*)malloc(DataSize
*sizeof(wchar_t))) )
1294 wmemset(SelData
, 0, DataSize
);
1295 vseek(SelectPos
,SEEK_SET
);
1296 vread(SelData
, (int)SelectSize
);
1297 CopyToClipboard(SelData
);
1299 vseek(CurFilePos
,SEEK_SET
);
1305 // включить/выключить скролбар
1308 ViOpt
.ShowScrollbar
=!ViOpt
.ShowScrollbar
;
1309 Opt
.ViOpt
.ShowScrollbar
=ViOpt
.ShowScrollbar
;
1312 CtrlObject
->Cp()->ActivePanel
->Redraw();
1319 if (ViewFile
.Opened())
1321 // TODO: strFullFileName -> if (DriveType!=DRIVE_REMOVABLE && !IsDriveTypeCDROM(DriveType))
1323 FAR_FIND_DATA_EX NewViewFindData
;
1325 if (!apiGetFindDataForExactPathName(strFullFileName
, NewViewFindData
))
1328 ViewFile
.ActualizeFileSize();
1330 int64_t CurFileSize
=vtell();
1332 if (ViewFindData
.ftLastWriteTime
.dwLowDateTime
!=NewViewFindData
.ftLastWriteTime
.dwLowDateTime
||
1333 ViewFindData
.ftLastWriteTime
.dwHighDateTime
!=NewViewFindData
.ftLastWriteTime
.dwHighDateTime
||
1334 CurFileSize
!=FileSize
)
1336 ViewFindData
=NewViewFindData
;
1337 FileSize
=CurFileSize
;
1339 if (FilePos
>FileSize
)
1340 ProcessKey(KEY_CTRLEND
);
1343 int64_t PrevLastPage
=LastPage
;
1346 if (PrevLastPage
&& !LastPage
)
1348 ProcessKey(KEY_CTRLEND
);
1356 if (Opt
.ViewerEditorClock
&& HostFileViewer
&& HostFileViewer
->IsFullScreen() && Opt
.ViOpt
.ShowTitleBar
)
1364 for (size_t I
=1; I
<ARRAYSIZE(UndoData
); I
++)
1366 UndoData
[I
-1].UndoAddr
=UndoData
[I
].UndoAddr
;
1367 UndoData
[I
-1].UndoLeft
=UndoData
[I
].UndoLeft
;
1370 if (UndoData
[0].UndoAddr
!=-1)
1372 FilePos
=UndoData
[0].UndoAddr
;
1373 LeftPos
=UndoData
[0].UndoLeft
;
1374 UndoData
[ARRAYSIZE(UndoData
)-1].UndoAddr
=-1;
1375 UndoData
[ARRAYSIZE(UndoData
)-1].UndoLeft
=-1;
1377 // LastSelPos=FilePos;
1385 if (!FileHolder
) // if viewing observed (typically temporary) file - dont allow to switch to another file
1391 NextFileFound
=ViewNamesList
.GetNextName(strName
);
1393 NextFileFound
=ViewNamesList
.GetPrevName(strName
);
1397 if (Opt
.ViOpt
.SavePos
)
1399 FARString strCacheName
=ComposeCacheName();
1402 if (CodePageChangedByUser
)
1403 CodePage
=VM
.CodePage
;
1406 PosCache poscache
={};
1407 poscache
.Param
[0]=FilePos
;
1408 poscache
.Param
[1]=LeftPos
;
1409 poscache
.Param
[2]=VM
.Hex
;
1410 //=poscache.Param[3];
1411 poscache
.Param
[4]=CodePage
;
1413 if (Opt
.ViOpt
.SaveShortPos
)
1415 poscache
.Position
[0]=BMSavePos
.SavePosAddr
;
1416 poscache
.Position
[1]=BMSavePos
.SavePosLeft
;
1417 //poscache.Position[2]=;
1418 //poscache.Position[3]=;
1421 CtrlObject
->ViewerPosCache
->AddPosition(strCacheName
,poscache
);
1422 memset(&BMSavePos
,0xff,sizeof(BMSavePos
)); //??!!??
1426 if (PointToName(strName
) == strName
)
1428 FARString strViewDir
;
1429 ViewNamesList
.GetCurDir(strViewDir
);
1431 if (!strViewDir
.IsEmpty())
1432 FarChDir(strViewDir
);
1435 if (OpenFile(strName
, TRUE
))
1449 ProcessTypeWrapMode(!VM
.WordWrap
);
1454 ProcessWrapMode(!VM
.Wrap
);
1459 ProcessHexMode(!VM
.Hex
);
1465 VM
.Processed
= !VM
.Processed
;
1467 FARString reopenFileName
= strFileName
;
1468 if (VM
.Processed
|| !strProcessedViewName
.IsEmpty())
1470 DefCodePage
=VM
.CodePage
;
1471 OpenFile(reopenFileName
, TRUE
);
1489 SearchFlags
.Set(REVERSE_SEARCH
);
1491 SearchFlags
.Clear(REVERSE_SEARCH
);
1496 switch (VM
.CodePage
) {
1497 case CP_UTF32LE
: case CP_UTF32BE
:
1503 case CP_UTF16LE
: case CP_UTF16BE
:
1511 VM
.CodePage
= VM
.CodePage
==WINPORT(GetOEMCP
)() ? WINPORT(GetACP
)() : WINPORT(GetOEMCP
)();
1514 // LastSelPos=FilePos;
1515 CodePageChangedByUser
=TRUE
;
1520 UINT nCodePage
= SelectCodePage(VM
.CodePage
, true, true, false, true);
1521 if (nCodePage
== CP_AUTODETECT
)
1523 if (!GetFileFormat2(strFileName
,nCodePage
,nullptr,true,true))
1528 // пока что запретим переключать hex в UTF8/UTF32, ибо не работает.
1529 if (VM
.Hex
&& (nCodePage
==CP_UTF8
|| nCodePage
==CP_UTF32LE
|| nCodePage
==CP_UTF32BE
))
1534 if (nCodePage
!=(UINT
)-1)
1536 CodePageChangedByUser
=TRUE
;
1538 if (IsFullWideCodePage(VM
.CodePage
) && !IsFullWideCodePage(nCodePage
))
1540 FilePos
*= sizeof(wchar_t);
1545 else if (!IsFullWideCodePage(VM
.CodePage
) && IsFullWideCodePage(nCodePage
))
1547 FilePos
=(FilePos
+(FilePos
&3))/4; //????
1553 VM
.CodePage
=nCodePage
;
1557 // LastSelPos=FilePos;
1564 if (ViewFile
.Opened())
1571 CtrlObject
->Plugins
.CommandsMenu(MODALTYPE_VIEWER
,0,L
"Viewer");
1576 + С альтом скролим по 1 */
1577 case KEY_MSWHEEL_UP
:
1578 case(KEY_MSWHEEL_UP
| KEY_ALT
):
1580 int Roll
= Key
& KEY_ALT
?1:Opt
.MsWheelDeltaView
;
1582 for (int i
=0; i
<Roll
; i
++)
1587 case KEY_MSWHEEL_DOWN
:
1588 case(KEY_MSWHEEL_DOWN
| KEY_ALT
):
1590 int Roll
= Key
& KEY_ALT
?1:Opt
.MsWheelDeltaView
;
1592 for (int i
=0; i
<Roll
; i
++)
1593 ProcessKey(KEY_DOWN
);
1597 case KEY_MSWHEEL_LEFT
:
1598 case(KEY_MSWHEEL_LEFT
| KEY_ALT
):
1600 int Roll
= Key
& KEY_ALT
?1:Opt
.MsHWheelDeltaView
;
1602 for (int i
=0; i
<Roll
; i
++)
1603 ProcessKey(KEY_LEFT
);
1607 case KEY_MSWHEEL_RIGHT
:
1608 case(KEY_MSWHEEL_RIGHT
| KEY_ALT
):
1610 int Roll
= Key
& KEY_ALT
?1:Opt
.MsHWheelDeltaView
;
1612 for (int i
=0; i
<Roll
; i
++)
1613 ProcessKey(KEY_RIGHT
);
1617 case KEY_UP
: case KEY_NUMPAD8
: case KEY_SHIFTNUMPAD8
:
1619 if (FilePos
>0 && ViewFile
.Opened())
1626 switch (VM
.CodePage
) {
1627 case CP_UTF32LE
: case CP_UTF32BE
: len
*= 4; break;
1628 case CP_UTF16LE
: case CP_UTF16BE
: len
*= 2; break;
1630 FilePos
&=~ (len
- 1);
1637 // LastSelPos=FilePos;
1640 case KEY_DOWN
: case KEY_NUMPAD2
: case KEY_SHIFTNUMPAD2
:
1642 if (!LastPage
&& ViewFile
.Opened())
1650 ShowPage(SHOW_DOWN
);
1653 // LastSelPos=FilePos;
1657 case KEY_ALTPGUP
: case KEY_PGUP
: case KEY_NUMPAD9
: case KEY_SHIFTNUMPAD9
: case KEY_CTRLUP
:
1659 if (ViewFile
.Opened())
1661 const auto InitialFilePos
= FilePos
;
1662 for (unsigned boost
= 0; boost
<= iBoostPg
; boost
+= 4)
1664 for (int i
=Y1
; i
<Y2
; i
++)
1667 if ((FilePos
- InitialFilePos
) * 256 >= FileSize
)
1668 { // limit speed boost by FileSize/256 per keypress
1669 // fprintf(stderr, "iBoostPg limited at %u\n", boost);
1676 // LastSelPos=FilePos;
1682 case KEY_ALTPGDN
: case KEY_PGDN
: case KEY_NUMPAD3
: case KEY_SHIFTNUMPAD3
: case KEY_CTRLDOWN
:
1684 ViewerString vString
;
1685 vString
.lpData
[MAX_VIEWLINEB
] = 0;
1686 const auto InitialFilePos
= FilePos
;
1687 for (unsigned boost
= 0; boost
<= iBoostPg
; boost
+= 4)
1689 if (LastPage
|| !ViewFile
.Opened())
1694 vseek(FilePos
,SEEK_SET
);
1696 for (int i
=Y1
; i
<Y2
; i
++)
1698 ReadString(&vString
,-1, MAX_VIEWLINEB
);
1708 for (int i
=Y1
; i
<=Y2
; i
++)
1709 ReadString(&vString
,-1, MAX_VIEWLINEB
);
1712 + Старое поведение оставим на Ctrl-Down */
1715 + По PgDn листаем всегда по одной странице,
1716 даже если осталась всего одна строчка.
1717 Удобно тексты читать */
1718 if (LastPage
&& Key
== KEY_CTRLDOWN
)
1721 ProcessKey(KEY_CTRLPGDN
);
1726 if ((FilePos
- InitialFilePos
) * 256 >= FileSize
)
1727 { // limit speed boost by FileSize/256 per keypress
1728 // fprintf(stderr, "iBoostPg limited at %u\n", boost);
1735 // LastSelPos=FilePos;
1738 case KEY_LEFT
: case KEY_NUMPAD4
: case KEY_SHIFTNUMPAD4
:
1740 if (LeftPos
>0 && ViewFile
.Opened())
1742 if (VM
.Hex
&& LeftPos
>80-Width
)
1743 LeftPos
=Max(80-Width
,1);
1749 // LastSelPos=FilePos;
1752 case KEY_RIGHT
: case KEY_NUMPAD6
: case KEY_SHIFTNUMPAD6
:
1754 if (LeftPos
<MAX_VIEWLINE
&& ViewFile
.Opened() && !VM
.Hex
&& !VM
.Wrap
)
1760 // LastSelPos=FilePos;
1763 case KEY_CTRLLEFT
: case KEY_CTRLNUMPAD4
:
1765 if (ViewFile
.Opened())
1783 // LastSelPos=FilePos;
1788 case KEY_CTRLRIGHT
: case KEY_CTRLNUMPAD6
:
1790 if (ViewFile
.Opened())
1796 if (FilePos
>= FileSize
)
1797 FilePos
=FileSize
-1; //??
1803 if (LeftPos
>MAX_VIEWLINE
)
1804 LeftPos
=MAX_VIEWLINE
;
1808 // LastSelPos=FilePos;
1813 case KEY_CTRLSHIFTLEFT
: case KEY_CTRLSHIFTNUMPAD4
:
1815 // Перейти на начало строк
1816 if (ViewFile
.Opened())
1823 case KEY_CTRLSHIFTRIGHT
: case KEY_CTRLSHIFTNUMPAD6
:
1825 // Перейти на конец строк
1826 if (ViewFile
.Opened())
1828 int I
, Y
, Len
, MaxLen
= 0;
1830 for (I
=0,Y
=Y1
; Y
<=Y2
; Y
++,I
++)
1832 Len
= StrLength(Strings
[I
]->lpData
);
1839 LeftPos
= MaxLen
- Width
;
1848 case KEY_CTRLHOME
: case KEY_CTRLNUMPAD7
:
1849 case KEY_HOME
: case KEY_NUMPAD7
: case KEY_SHIFTNUMPAD7
:
1851 // Перейти на начало файла
1852 if (ViewFile
.Opened())
1855 case KEY_CTRLPGUP
: case KEY_CTRLNUMPAD9
:
1857 if (ViewFile
.Opened())
1861 // LastSelPos=FilePos;
1865 case KEY_CTRLEND
: case KEY_CTRLNUMPAD1
:
1866 case KEY_END
: case KEY_NUMPAD1
: case KEY_SHIFTNUMPAD1
:
1868 // Перейти на конец файла
1869 if (ViewFile
.Opened())
1872 case KEY_CTRLPGDN
: case KEY_CTRLNUMPAD3
:
1874 if (ViewFile
.Opened())
1877 Для обычного режима, если последняя строка не содержит перевод
1878 строки, крутанем вверх на один раз больше - иначе визуально
1879 обработка End (и подобных) на такой строке отличается от обработки
1882 unsigned int max_counter
=Y2
-Y1
;
1891 if (vgetc(LastSym
) && LastSym
!=CRSym
)
1900 sprintf(Buf,"%llX",FilePos);
1901 Message(0,1,"End",Buf,"Ok");
1904 for (int i
=0; static_cast<unsigned int>(i
)<max_counter
; i
++)
1910 sprintf(Buf,"%llX, %d",FilePos, I);
1911 Message(0,1,"Up",Buf,"Ok");
1916 switch (VM
.CodePage
) {
1917 case CP_UTF32LE
: case CP_UTF32BE
: len
*= 4; break;
1918 case CP_UTF16LE
: case CP_UTF16BE
: len
*= 2; break;
1920 FilePos
&= ~(len
- 1);
1927 sprintf(Buf,"%llX",FilePos);
1928 Message(0,1,"VM.Hex",Buf,"Ok");
1932 // LastSelPos=FilePos;
1938 if (Key
>=L
' ' && Key
<0x10000)
1948 int Viewer::ProcessMouse(MOUSE_EVENT_RECORD
*MouseEvent
)
1950 if (!(MouseEvent
->dwButtonState
& 3))
1953 // Shift + Mouse click -> adhoc quick edit
1954 if ( (MouseEvent
->dwControlKeyState
& SHIFT_PRESSED
) != 0
1955 && (MouseEvent
->dwEventFlags
& MOUSE_MOVED
) == 0
1956 && (MouseEvent
->dwButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
) != 0 ) {
1957 WINPORT(BeginConsoleAdhocQuickEdit
)();
1962 Происходят какие-то манипуляции -> снимем выделение
1967 ! Постоянный скроллинг при нажатой клавише
1968 Обыкновенный захват мыши
1971 > Если нажать в самом низу скролбара, вьюер отмотается на страницу
1972 > ниже нижней границы текста. Перед глазами будет пустой экран.
1974 if (ViOpt
.ShowScrollbar
&& MouseX
==X2
+(m_bQuickView
?1:0))
1977 Небольшая бага с тыканием в верхнюю позицию ScrollBar`а
1980 while (IsMouseButtonPressed())
1982 else if (MouseY
==Y2
)
1984 while (IsMouseButtonPressed())
1986 // _SVS(SysLog(L"Viewer/ KEY_DOWN= %i, %i",FilePos,FileSize));
1987 ProcessKey(KEY_DOWN
);
1990 else if (MouseY
== Y1
+1)
1991 ProcessKey(KEY_CTRLHOME
);
1992 else if (MouseY
== Y2
-1)
1993 ProcessKey(KEY_CTRLEND
);
1996 while (IsMouseButtonPressed())
1999 более точное позиционирование; корректная работа на больших файлах
2001 FilePos
=(FileSize
-1)/(Y2
-Y1
-1)*(MouseY
-Y1
);
2004 if (FilePos
> FileSize
)
2009 else if (FilePos
< 0)
2015 Perc
=ToPercent64(FilePos
,FileSize
);
2017 //_SVS(SysLog(L"Viewer/ ToPercent()=%i, %lld, %lld, Mouse=[%d:%d]",Perc,FilePos,FileSize,MsX,MsY));
2019 ProcessKey(KEY_CTRLEND
);
2021 ProcessKey(KEY_CTRLHOME
);
2025 не рвем строки посередине
2036 /* $ 16.12.2000 tran
2037 шелчок мышью на статус баре */
2040 угу, а только если он нсть, statusline...
2042 if (MouseY
== (Y1
-1) && (HostFileViewer
&& HostFileViewer
->IsTitleBarVisible())) // Status line
2044 int XCodePage
, XPos
, NameLength
;
2045 NameLength
=ObjWidth
-40;
2047 if (Opt
.ViewerEditorClock
&& HostFileViewer
&& HostFileViewer
->IsFullScreen())
2053 XCodePage
=NameLength
+1;
2054 XPos
=NameLength
+1+10+1+10+1;
2056 while (IsMouseButtonPressed());
2061 //_D(SysLog(L"MsX=%i, XTable=%i, XPos=%i",MsX,XTable,XPos));
2062 if (MouseX
>=XCodePage
&& MouseX
<=XCodePage
+10)
2064 ProcessKey(KEY_SHIFTF8
);
2068 if (MouseX
>=XPos
&& MouseX
<=XPos
+7+1+4+1+3)
2070 ProcessKey(KEY_ALTF8
);
2075 if (MouseX
<X1
|| MouseX
>X2
|| MouseY
<Y1
|| MouseY
>Y2
)
2079 while (IsMouseButtonPressed() && MouseX
<X1
+7)
2080 ProcessKey(KEY_LEFT
);
2081 else if (MouseX
>X2
-7)
2082 while (IsMouseButtonPressed() && MouseX
>X2
-7)
2083 ProcessKey(KEY_RIGHT
);
2084 else if (MouseY
<Y1
+(Y2
-Y1
)/2)
2085 while (IsMouseButtonPressed() && MouseY
<Y1
+(Y2
-Y1
)/2)
2088 while (IsMouseButtonPressed() && MouseY
>=Y1
+(Y2
-Y1
)/2)
2089 ProcessKey(KEY_DOWN
);
2094 void Viewer::FilePosShiftLeft(uint64_t Offset
)
2096 if (FilePos
> 0 && (uint64_t)FilePos
> Offset
) {
2104 if (!ViewFile
.Opened())
2107 wchar_t Buf
[MAX_VIEWLINE
+ 1];
2110 if (FilePos
> ((int64_t)(sizeof(Buf
)/sizeof(wchar_t))) - 1)
2111 BufSize
= (sizeof(Buf
)/sizeof(wchar_t)) - 1;
2112 else if (FilePos
!= 0)
2113 BufSize
= (int)FilePos
;
2121 // Alter-1: here we use BYTE COUNT, while in Down handler we use ::vread which may
2122 // accept either CHARACTER COUNT or w_char count.
2123 //int UpSize=IsFullWideCodePage(VM.CodePage) ? 8 : 8 * sizeof(wchar_t);
2124 int UpSize
=16; // always have 16 bytes per row
2126 if (FilePos
<(int64_t)UpSize
)
2129 FilePosShiftLeft(UpSize
);
2134 vseek(FilePos
- (int64_t)BufSize
, SEEK_SET
);
2135 I
= BufSize
= vread(Buf
, BufSize
, true);
2141 wchar_t CRSymEncoded
= (unsigned int)CRSym
;
2142 wchar_t CRRSymEncoded
= (unsigned int)'\r';
2143 switch (VM
.CodePage
)
2147 CRRSymEncoded
<<= 24;
2155 if (I
> 0 && Buf
[I
- 1] == CRSymEncoded
)
2160 if (I
> 0 && CRSym
== L
'\n' && Buf
[I
- 1] == CRRSymEncoded
)
2165 while (I
> 0 && Buf
[I
- 1] != CRSymEncoded
)
2170 int64_t WholeLineLength
= (BufSize
- I
); // in code units
2172 if (VM
.Wrap
&& Width
> 0)
2174 vseek(FilePos
- WholeLineLength
, SEEK_SET
);
2175 int WrapBufSize
= vread(Buf
, WholeLineLength
, false);
2177 // we might read more code units and could actually overflow current position
2178 // so try to find out exact substring that matches into line start and current position
2179 Buf
[WrapBufSize
] = 0;
2180 // fprintf(stderr, "WrapBufSize=%d WholeLineLength=%d LINE='%ls'\n", WrapBufSize, WholeLineLength, &Buf[0]);
2181 // fprintf(stderr, "LINE1: '%ls'\n", &Buf[0]);
2184 int distance
= CalcCodeUnitsDistance(VM
.CodePage
, &Buf
[0], &Buf
[WrapBufSize
]);
2185 if (distance
<= WholeLineLength
)
2187 while (WrapBufSize
&& distance
== CalcCodeUnitsDistance(VM
.CodePage
, &Buf
[0], &Buf
[WrapBufSize
- 1]))
2195 Buf
[WrapBufSize
] = 0;
2196 // fprintf(stderr, "Matching LINE: '%ls'\n", &Buf[0]);
2200 // khffgkjkfdg dfkghd jgfhklf |
2201 // sdflksj lfjghf fglh lf |
2202 // dfdffgljh ldgfhj |
2204 for (I
= 0; I
< WrapBufSize
;)
2206 if (!IsSpace(Buf
[I
]))
2208 for (int CurLineStart
= I
, LastFitEnd
= I
+ 1;; ++I
)
2210 if (I
== WrapBufSize
)
2212 int distance
= CalcCodeUnitsDistance(VM
.CodePage
, &Buf
[CurLineStart
], &Buf
[WrapBufSize
]);
2213 FilePosShiftLeft((distance
> 0) ? distance
: 1);
2217 if (!IsSpace(Buf
[I
]) && (I
+ 1 == WrapBufSize
|| IsSpace(Buf
[I
+ 1])))
2219 if (CalcStrSize(&Buf
[CurLineStart
], I
+ 1 - CurLineStart
) > Width
)
2235 for (int PrevSublineLength
= 0, CurLineStart
= I
= 0;; ++I
)
2237 if (I
== WrapBufSize
)
2239 int distance
= CalcCodeUnitsDistance(VM
.CodePage
, &Buf
[CurLineStart
], &Buf
[WrapBufSize
]);
2240 FilePosShiftLeft((distance
> 0) ? distance
: 1);
2244 int SublineLength
= CalcStrSize(&Buf
[CurLineStart
], I
- CurLineStart
);
2245 if (SublineLength
> PrevSublineLength
)
2247 if (SublineLength
>= Width
)
2250 PrevSublineLength
= 0;
2253 PrevSublineLength
= SublineLength
;
2259 // fprintf(stderr, "!!!!!!!!!!!!NOWRAP!!!!!!!!!!!!\n");
2260 FilePosShiftLeft( (WholeLineLength
> 0) ? WholeLineLength
: 1 );
2264 int Viewer::CalcStrSize(const wchar_t *Str
,int Length
)
2268 for (Size
=0,I
=0; I
<Length
; I
++)
2272 Size
+=ViOpt
.TabSize
-(Size
% ViOpt
.TabSize
);
2285 int Viewer::GetStrBytesNum(const wchar_t *Str
, int Length
)
2287 if (VM
.CodePage
== CP_UTF32LE
|| VM
.CodePage
== CP_UTF32BE
)
2290 int cnt
= WINPORT(WideCharToMultiByte
)(VM
.CodePage
, 0, Str
, Length
, nullptr, 0, nullptr, nullptr);
2292 return (VM
.CodePage
== CP_UTF16LE
|| VM
.CodePage
== CP_UTF16BE
) ? cnt
* 2 : cnt
;
2296 void Viewer::SetViewKeyBar(KeyBar
*ViewKeyBar
)
2298 Viewer::ViewKeyBar
=ViewKeyBar
;
2303 void Viewer::ChangeViewKeyBar()
2308 Wrap имеет 3 позиции
2311 Wrap должен показываться следующий, а не текущий
2314 VM
.Wrap
? Msg::ViewF2Unwrap
: (VM
.WordWrap
? Msg::ViewShiftF2
: Msg::ViewF2
),
2316 ViewKeyBar
->Change(KBL_SHIFT
, VM
.WordWrap
? Msg::ViewF2
: Msg::ViewShiftF2
, 1);
2319 ViewKeyBar
->Change(Msg::ViewF4Text
,3);
2321 ViewKeyBar
->Change(Msg::ViewF4
,3);
2323 if (VM
.CodePage
!= WINPORT(GetOEMCP
)())
2324 ViewKeyBar
->Change(Msg::ViewF8DOS
,7);
2326 ViewKeyBar
->Change(Msg::ViewF8
,7);
2329 ViewKeyBar
->Change(Msg::ViewF5Raw
,4);
2331 ViewKeyBar
->Change(Msg::ViewF5Processed
,4);
2333 ViewKeyBar
->Redraw();
2336 // ViewerMode vm=VM;
2337 CtrlObject
->Plugins
.CurViewer
=this; //HostFileViewer;
2338 // CtrlObject->Plugins.ProcessViewerEvent(VE_MODE,&vm);
2352 SD_CHECKBOX_REVERSE
,
2358 DM_SDSETVISIBILITY
= DM_USER
+ 1,
2361 LONG_PTR WINAPI
ViewerSearchDlgProc(HANDLE hDlg
,int Msg
,int Param1
,LONG_PTR Param2
)
2367 SendDlgMessage(hDlg
,DM_SDSETVISIBILITY
,SendDlgMessage(hDlg
,DM_GETCHECK
,SD_RADIO_HEX
,0) == BSTATE_CHECKED
,0);
2368 SendDlgMessage(hDlg
,DM_EDITUNCHANGEDFLAG
,SD_EDIT_TEXT
,1);
2369 SendDlgMessage(hDlg
,DM_EDITUNCHANGEDFLAG
,SD_EDIT_HEX
,1);
2372 case DM_SDSETVISIBILITY
:
2374 SendDlgMessage(hDlg
,DM_SHOWITEM
,SD_EDIT_TEXT
,!Param1
);
2375 SendDlgMessage(hDlg
,DM_SHOWITEM
,SD_EDIT_HEX
,Param1
);
2376 SendDlgMessage(hDlg
,DM_ENABLE
,SD_CHECKBOX_CASE
,!Param1
);
2377 SendDlgMessage(hDlg
,DM_ENABLE
,SD_CHECKBOX_WORDS
,!Param1
);
2378 //SendDlgMessage(hDlg,DM_ENABLE,SD_CHECKBOX_REGEXP,!Param1);
2383 if ((Param1
== SD_RADIO_TEXT
|| Param1
== SD_RADIO_HEX
) && Param2
)
2385 SendDlgMessage(hDlg
,DM_ENABLEREDRAW
,FALSE
,0);
2386 bool Hex
=(Param1
==SD_RADIO_HEX
);
2387 FARString strDataStr
;
2388 Transform(strDataStr
,(const wchar_t *)SendDlgMessage(hDlg
,DM_GETCONSTTEXTPTR
,Hex
?SD_EDIT_TEXT
:SD_EDIT_HEX
,0),Hex
?L
'X':L
'S');
2389 SendDlgMessage(hDlg
,DM_SETTEXTPTR
,Hex
?SD_EDIT_HEX
:SD_EDIT_TEXT
,(LONG_PTR
)strDataStr
.CPtr());
2390 SendDlgMessage(hDlg
,DM_SDSETVISIBILITY
,Hex
,0);
2392 if (!strDataStr
.IsEmpty())
2394 SendDlgMessage(hDlg
,DM_EDITUNCHANGEDFLAG
,Hex
?SD_EDIT_HEX
:SD_EDIT_TEXT
,SendDlgMessage(hDlg
,DM_EDITUNCHANGEDFLAG
,Hex
?SD_EDIT_TEXT
:SD_EDIT_HEX
,-1));
2397 SendDlgMessage(hDlg
,DM_ENABLEREDRAW
,TRUE
,0);
2403 if (Param1
==SD_TEXT_SEARCH
)
2405 SendDlgMessage(hDlg
,DM_SETFOCUS
,(SendDlgMessage(hDlg
,DM_GETCHECK
,SD_RADIO_HEX
,0) == BSTATE_CHECKED
)?SD_EDIT_HEX
:SD_EDIT_TEXT
,0);
2411 return DefDlgProc(hDlg
,Msg
,Param1
,Param2
);
2414 static void PR_ViewerSearchMsg()
2416 PreRedrawItem preRedrawItem
=PreRedraw
.Peek();
2417 ViewerSearchMsg((const wchar_t*)preRedrawItem
.Param
.Param1
,(int)(INT_PTR
)preRedrawItem
.Param
.Param2
);
2420 void ViewerSearchMsg(const wchar_t *MsgStr
,int Percent
)
2422 FARString strProgress
;
2426 FormatString strPercent
;
2427 strPercent
<<Percent
;
2429 size_t PercentLength
=Max(strPercent
.strValue().GetLength(),(size_t)3);
2430 size_t Length
=Max(Min(static_cast<int>(MAX_WIDTH_MESSAGE
-2),StrLength(MsgStr
)),40)-PercentLength
-2;
2431 wchar_t *Progress
=strProgress
.GetBuffer(Length
);
2435 size_t CurPos
=Min(Percent
,100)*Length
/100;
2436 wmemset(Progress
,BoxSymbols
[BS_X_DB
],CurPos
);
2437 wmemset(Progress
+(CurPos
),BoxSymbols
[BS_X_B0
],Length
-CurPos
);
2438 strProgress
.ReleaseBuffer(Length
);
2439 FormatString strTmp
;
2440 strTmp
<<L
" "<<fmt::Expand(PercentLength
)<<strPercent
<<L
"%";
2441 strProgress
+=strTmp
;
2446 Message(0,0,Msg::ViewSearchTitle
,(SearchHex
?Msg::ViewSearchingHex
:Msg::ViewSearchingFor
),MsgStr
,strProgress
.IsEmpty()?nullptr:strProgress
.CPtr());
2447 PreRedrawItem preRedrawItem
=PreRedraw
.Peek();
2448 preRedrawItem
.Param
.Param1
=(void*)MsgStr
;
2449 preRedrawItem
.Param
.Param2
=(LPVOID
)(INT_PTR
)Percent
;
2450 PreRedraw
.SetParam(preRedrawItem
.Param
);
2454 + Параметр Next может принимать значения:
2456 1 - Продолжить поиск со следующей позиции
2457 2 - Продолжить поиск с начала файла
2461 static inline bool CheckBufMatchesCaseInsensitive(size_t MatchLen
, const wchar_t *Buf
, const wchar_t *MatchUpperCase
, const wchar_t *MatchLowerCase
)
2463 for (size_t i
= 0; i
< MatchLen
; ++i
) {
2464 if (Buf
[i
] != MatchUpperCase
[i
] && Buf
[i
] != MatchLowerCase
[i
])
2471 static inline bool CheckBufMatchesCaseSensitive(size_t MatchLen
, const wchar_t *Buf
, const wchar_t *Match
)
2473 for (size_t i
= 0; i
< MatchLen
; ++i
) {
2474 if (Buf
[i
] != Match
[i
])
2481 void Viewer::Search(int Next
,int FirstChar
)
2483 const wchar_t *TextHistoryName
=L
"SearchText";
2484 const wchar_t *HexMask
=L
"HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH ";
2485 DialogDataEx SearchDlgData
[]=
2487 {DI_DOUBLEBOX
,3,1,72,11,{0},0,Msg::ViewSearchTitle
},
2488 {DI_TEXT
,5,2,0,2,{0},0,Msg::ViewSearchFor
},
2489 {DI_EDIT
,5,3,70,3,{(DWORD_PTR
)TextHistoryName
},DIF_FOCUS
|DIF_HISTORY
|DIF_USELASTHISTORY
,L
""},
2490 {DI_FIXEDIT
,5,3,70,3,{(DWORD_PTR
)HexMask
},DIF_MASKEDIT
,L
""},
2491 {DI_TEXT
,3,4,0,4,{0},DIF_SEPARATOR
,L
""},
2492 {DI_RADIOBUTTON
,5,5,0,5,{1},DIF_GROUP
,Msg::ViewSearchForText
},
2493 {DI_RADIOBUTTON
,5,6,0,6,{0},0,Msg::ViewSearchForHex
},
2494 {DI_CHECKBOX
,40,5,0,5,{0},0,Msg::ViewSearchCase
},
2495 {DI_CHECKBOX
,40,6,0,6,{0},0,Msg::ViewSearchWholeWords
},
2496 {DI_CHECKBOX
,40,7,0,7,{0},0,Msg::ViewSearchReverse
},
2497 {DI_CHECKBOX
,40,8,0,8,{0},DIF_DISABLE
,Msg::ViewSearchRegexp
},
2498 {DI_TEXT
,3,9,0,9,{0},DIF_SEPARATOR
,L
""},
2499 {DI_BUTTON
,0,10,0,10,{0},DIF_DEFAULT
|DIF_CENTERGROUP
,Msg::ViewSearchSearch
},
2500 {DI_BUTTON
,0,10,0,10,{0},DIF_CENTERGROUP
,Msg::ViewSearchCancel
}
2502 MakeDialogItemsEx(SearchDlgData
,SearchDlg
);
2503 FARString strSearchStr
;
2504 FARString strMsgStr
;
2506 int Case
,WholeWords
,ReverseSearch
,SearchRegexp
;
2508 if (!ViewFile
.Opened() || (Next
&& strLastSearchStr
.IsEmpty()))
2511 if (!strLastSearchStr
.IsEmpty())
2512 strSearchStr
= strLastSearchStr
;
2514 strSearchStr
.Clear();
2516 SearchDlg
[SD_RADIO_TEXT
].Selected
=!LastSearchHex
;
2517 SearchDlg
[SD_RADIO_HEX
].Selected
=LastSearchHex
;
2518 SearchDlg
[SD_CHECKBOX_CASE
].Selected
=LastSearchCase
;
2519 SearchDlg
[SD_CHECKBOX_WORDS
].Selected
=LastSearchWholeWords
;
2520 SearchDlg
[SD_CHECKBOX_REVERSE
].Selected
=LastSearchReverse
;
2521 SearchDlg
[SD_CHECKBOX_REGEXP
].Selected
=LastSearchRegexp
;
2523 if (SearchFlags
.Check(REVERSE_SEARCH
))
2524 SearchDlg
[SD_CHECKBOX_REVERSE
].Selected
=!SearchDlg
[SD_CHECKBOX_REVERSE
].Selected
;
2526 if (IsFullWideCodePage(VM
.CodePage
))
2528 SearchDlg
[SD_RADIO_TEXT
].Selected
=TRUE
;
2529 SearchDlg
[SD_RADIO_HEX
].Flags
|=DIF_DISABLE
;
2530 SearchDlg
[SD_RADIO_HEX
].Selected
=FALSE
;
2533 if (SearchDlg
[SD_RADIO_HEX
].Selected
)
2534 SearchDlg
[SD_EDIT_HEX
].strData
= strSearchStr
;
2536 SearchDlg
[SD_EDIT_TEXT
].strData
= strSearchStr
;
2540 SearchFlags
.Flags
= 0;
2541 Dialog
Dlg(SearchDlg
,ARRAYSIZE(SearchDlg
),ViewerSearchDlgProc
);
2542 Dlg
.SetPosition(-1,-1,76,13);
2543 Dlg
.SetHelp(L
"ViewerSearch");
2549 Dlg
.ProcessKey(FirstChar
);
2554 if (Dlg
.GetExitCode()!=SD_BUTTON_OK
)
2558 SearchHex
=SearchDlg
[SD_RADIO_HEX
].Selected
;
2559 Case
=SearchDlg
[SD_CHECKBOX_CASE
].Selected
;
2560 WholeWords
=SearchDlg
[SD_CHECKBOX_WORDS
].Selected
;
2561 ReverseSearch
=SearchDlg
[SD_CHECKBOX_REVERSE
].Selected
;
2562 SearchRegexp
=SearchDlg
[SD_CHECKBOX_REGEXP
].Selected
;
2566 strSearchStr
= SearchDlg
[SD_EDIT_HEX
].strData
;
2567 RemoveTrailingSpaces(strSearchStr
);
2571 strSearchStr
= SearchDlg
[SD_EDIT_TEXT
].strData
;
2574 strLastSearchStr
= strSearchStr
;
2575 LastSearchHex
=SearchHex
;
2576 LastSearchCase
=Case
;
2577 LastSearchWholeWords
=WholeWords
;
2579 if (!SearchFlags
.Check(REVERSE_SEARCH
))
2580 LastSearchReverse
=ReverseSearch
;
2582 LastSearchRegexp
=SearchRegexp
;
2584 int SearchWChars
, SearchCodeUnits
;
2587 TPreRedrawFuncGuard
preRedrawFuncGuard(PR_ViewerSearchMsg
);
2588 //SaveScreen SaveScr;
2589 SetCursorType(FALSE
,0);
2590 strMsgStr
= strSearchStr
;
2592 if (strMsgStr
.GetLength()+18 > static_cast<DWORD
>(ObjWidth
))
2593 TruncStrFromEnd(strMsgStr
, ObjWidth
-18);
2595 InsertQuote(strMsgStr
);
2599 if (!strSearchStr
.GetLength())
2602 Transform(strSearchStr
,strSearchStr
,L
'S');
2606 SearchWChars
= (int)strSearchStr
.GetLength();
2610 SearchCodeUnits
= CalcCodeUnitsDistance(VM
.CodePage
, strSearchStr
.CPtr(), strSearchStr
.CPtr() + SearchWChars
);
2611 FARString strSearchStrLowerCase
;
2613 if (!Case
&& !SearchHex
)
2615 strSearchStrLowerCase
= strSearchStr
;
2616 strSearchStr
.Upper();
2617 strSearchStrLowerCase
.Lower();
2626 SearchFlags
.Set(SEARCH_MODE2
);
2627 LastSelPos
= ReverseSearch
?FileSize
:0;
2632 LastSelPos
= SelectPos
+ (ReverseSearch
?-1:1);
2638 LastSelPos
= FilePos
;
2640 if (!LastSelPos
|| LastSelPos
== FileSize
)
2642 SearchFlags
.Set(SEARCH_MODE2
);
2643 LastSelPos
= ReverseSearch
?FileSize
:0;
2647 vseek(LastSelPos
,SEEK_SET
);
2650 if (SearchWChars
>0 && (!ReverseSearch
|| LastSelPos
>=0))
2656 INT64 StartPos
=vtell();
2657 DWORD StartTime
=WINPORT(GetTickCount
)();
2662 Изменена строка if (ReverseSearch && CurPos<0) на if (CurPos<0),
2663 так как при обычном прямом и LastSelPos=0xFFFFFFFF, поиск
2664 заканчивался так и не начавшись.
2668 //vseek(CurPos,SEEK_SET);
2669 int BufSize
= ARRAYSIZE(Buf
);
2670 int64_t CurPos
= vtell();
2674 Изменёно вычисление CurPos с учётом Whole words
2676 CurPos
-= ARRAYSIZE(Buf
) - SearchCodeUnits
- !!WholeWords
;
2678 BufSize
+= (int)CurPos
;
2681 vseek(CurPos
, SEEK_SET
);
2684 if ((ReadSize
=vread(Buf
,BufSize
,SearchHex
!=0))<=0)
2687 DWORD CurTime
=WINPORT(GetTickCount
)();
2689 if (CurTime
-StartTime
>RedrawTimeout
)
2693 if (CheckForEscSilent())
2695 if (ConfirmAbortOp())
2702 INT64 Total
=ReverseSearch
?StartPos
:FileSize
-StartPos
;
2703 INT64 Current
=_abs64(CurPos
-StartPos
);
2704 int Percent
=Total
>0?static_cast<int>(Current
*100/Total
):-1;
2705 // В случае если файл увеличивается размере, то количество
2706 // процентов может быть больше 100. Обрабатываем эту ситуацию.
2710 Total
=FileSize
-StartPos
;
2711 Percent
=Total
>0?static_cast<int>(Current
*100/Total
):-1;
2717 ViewerSearchMsg(strMsgStr
,Percent
);
2721 Убран кусок текста после приведения поисковой строки
2722 и Buf к единому регистру, если поиск не регистрозависимый
2723 или не ищется Hex-строка и в связи с этим переработан код поиска
2725 int MaxSize
=ReadSize
-SearchWChars
+1;
2726 int Increment
=ReverseSearch
? -1:+1;
2728 for (int I
=ReverseSearch
? MaxSize
-1:0; I
<MaxSize
&& I
>=0; I
+=Increment
)
2731 Обработка поиска "Whole words"
2733 bool locResultLeft
= false;
2734 bool locResultRight
= false;
2740 if (IsSpace(Buf
[I
-1]) || IsEol(Buf
[I
-1]) ||
2741 (wcschr(Opt
.strWordDiv
,Buf
[I
-1])))
2742 locResultLeft
= true;
2746 locResultLeft
= true;
2749 if (ReadSize
!=BufSize
&& I
+SearchWChars
>=ReadSize
)
2750 locResultRight
= true;
2751 else if (I
+SearchWChars
<ReadSize
&&
2752 (IsSpace(Buf
[I
+SearchWChars
]) || IsEol(Buf
[I
+SearchWChars
]) ||
2753 (wcschr(Opt
.strWordDiv
,Buf
[I
+SearchWChars
]))))
2754 locResultRight
= true;
2758 locResultLeft
= true;
2759 locResultRight
= true;
2762 if (locResultLeft
&& locResultRight
)
2764 if (!Case
&& !SearchHex
) {
2765 Match
= CheckBufMatchesCaseInsensitive(SearchWChars
, &Buf
[I
], strSearchStr
.CPtr(), strSearchStrLowerCase
.CPtr());
2767 Match
= CheckBufMatchesCaseSensitive(SearchWChars
, &Buf
[I
], strSearchStr
.CPtr());
2771 MatchPos
= CurPos
+ CalcCodeUnitsDistance(VM
.CodePage
, Buf
, Buf
+ I
);
2782 vseek(CurPos
, SEEK_SET
);
2786 if (vtell() >= FileSize
)
2789 vseek(-(SearchCodeUnits
+ !!WholeWords
), SEEK_CUR
);
2798 ! По окончании поиска отступим от верха экрана на
2799 треть отображаемой высоты.
2801 SelectText(MatchPos
, SearchCodeUnits
, ReverseSearch
? 0x2 : 0);
2803 // Покажем найденное на расстоянии трети экрана от верха.
2804 int FromTop
=(ScrY
-(Opt
.ViOpt
.ShowKeyBar
?2:1))/4;
2806 if (FromTop
<0 || FromTop
>ScrY
)
2809 for (int i
=0; i
<FromTop
; i
++)
2812 AdjustSelPosition
= TRUE
;
2814 AdjustSelPosition
= FALSE
;
2820 + После окончания поиска спросим о переходе поиска в начало/конец */
2821 if (SearchFlags
.Check(SEARCH_MODE2
))
2822 Message(MSG_WARNING
,1,Msg::ViewSearchTitle
,
2823 (SearchHex
?Msg::ViewSearchCannotFindHex
:Msg::ViewSearchCannotFind
),strMsgStr
,Msg::Ok
);
2826 if (!Message(MSG_WARNING
,2,Msg::ViewSearchTitle
,
2827 (SearchHex
?Msg::ViewSearchCannotFindHex
:Msg::ViewSearchCannotFind
),strMsgStr
,
2828 (ReverseSearch
?Msg::ViewSearchFromEnd
:Msg::ViewSearchFromBegin
),
2829 Msg::HYes
,Msg::HNo
))
2836 /*void Viewer::ConvertToHex(char *SearchStr,int &SearchLength)
2838 char OutStr[512],*SrcPtr;
2843 while (IsSpaceA(*SrcPtr))
2846 if (!SrcPtr[1] || IsSpaceA(SrcPtr[1]))
2848 N=HexToNum(SrcPtr[0]);
2853 N=16*HexToNum(SrcPtr[0])+HexToNum(SrcPtr[1]);
2861 memcpy(SearchStr,OutStr,OutPos);
2862 SearchLength=OutPos;
2866 int Viewer::HexToNum(int Hex
)
2870 if (Hex
>='0' && Hex
<='9')
2873 if (Hex
>='A' && Hex
<='F')
2880 int Viewer::GetWrapMode()
2886 void Viewer::SetWrapMode(int Wrap
)
2888 Viewer::VM
.Wrap
=Wrap
;
2891 void Viewer::EnableHideCursor(int HideCursor
)
2893 Viewer::HideCursor
=HideCursor
;
2897 int Viewer::GetWrapType()
2899 return(VM
.WordWrap
);
2903 void Viewer::SetWrapType(int TypeWrap
)
2905 Viewer::VM
.WordWrap
=TypeWrap
;
2909 void Viewer::GetFileName(FARString
&strName
)
2911 strName
= strFullFileName
;
2914 void Viewer::SetProcessed(bool Processed
)
2916 VM
.Processed
= Processed
;
2921 void Viewer::ShowConsoleTitle()
2924 strTitle
.Format(Msg::InViewer
, PointToName(strFileName
));
2925 ConsoleTitle::SetFarTitle(strTitle
);
2928 void Viewer::SetTitle(const wchar_t *Title
)
2936 void Viewer::SetFilePos(int64_t Pos
)
2941 void Viewer::SetPluginData(const wchar_t *PluginData
)
2943 Viewer::strPluginData
= NullToEmpty(PluginData
);
2947 void Viewer::SetNamesList(NamesList
*List
)
2950 List
->MoveData(ViewNamesList
);
2953 int Viewer::vread(wchar_t *Buf
,int Count
, bool Raw
)
2955 if (VM
.CodePage
== CP_WIDE_LE
|| VM
.CodePage
== CP_WIDE_BE
)
2957 DWORD ReadSize
= ViewFile
.Read((char *)Buf
, Count
* sizeof(wchar_t));
2958 DWORD ResultedCount
= ReadSize
/ sizeof(wchar_t);
2959 if ((ReadSize
% sizeof(wchar_t)) != 0 && (int)ResultedCount
< Count
) {
2960 memset(((char *)Buf
) + ReadSize
, 0, sizeof(wchar_t) - (ReadSize
% sizeof(wchar_t)));
2964 if (VM
.CodePage
== CP_WIDE_BE
&& !Raw
) {
2965 WideReverse((wchar_t *)Buf
, ResultedCount
);
2968 return ResultedCount
;
2970 else if (VM
.CodePage
== CP_UTF8
&& !Raw
)
2973 ViewFile
.GetPointer(Ptr
);
2974 int ResultedCount
= 0;
2975 for (DWORD WantViewSize
= Count
; ResultedCount
< Count
;) {
2976 DWORD ViewSize
= WantViewSize
;
2977 char *SrcView
= (char *)ViewFile
.ViewBytesAt(Ptr
, ViewSize
);
2982 size_t SourcedCount
= ViewSize
;
2983 size_t SinkedCount
= (Count
- ResultedCount
);
2985 const auto cr
= MB2Wide_Unescaped(SrcView
, SourcedCount
, &Buf
[ResultedCount
], SinkedCount
, false);
2988 ResultedCount
+= (int)SinkedCount
;
2990 if ( (cr
& CONV_NEED_MORE_SRC
) != 0 && SourcedCount
== 0) {
2991 if (ViewSize
< WantViewSize
) {
2992 if (ResultedCount
>= Count
) {
2995 Buf
[ResultedCount
] = WCHAR_REPLACEMENT
;
3000 WantViewSize
+= (4 + WantViewSize
/ 4);
3003 } else if ((cr
& CONV_NEED_MORE_DST
) != 0 || (cr
& CONV_NEED_MORE_SRC
) == 0) {
3008 ViewFile
.SetPointer(Ptr
);
3009 return ResultedCount
;
3014 ViewFile
.GetPointer(Ptr
);
3016 DWORD ReadSize
= Count
;
3017 if (VM
.CodePage
== CP_UTF16LE
|| VM
.CodePage
== CP_UTF16BE
) {
3021 LPBYTE View
= ViewFile
.ViewBytesAt(Ptr
, ReadSize
);
3023 if (Count
== 1 && ReadSize
== 2 && !Raw
&& (VM
.CodePage
==CP_UTF16LE
|| VM
.CodePage
==CP_UTF16BE
))
3025 //Если UTF16 то простой ли это символ или нет?
3026 if (*(uint16_t *)View
>= 0xd800 && *(uint16_t *)View
<= 0xdfff) {
3028 View
= ViewFile
.ViewBytesAt(Ptr
, ReadSize
);
3032 ViewFile
.SetPointer(Ptr
+ ReadSize
);
3034 if (!View
|| !ReadSize
)
3039 if (VM
.CodePage
== CP_UTF16LE
|| VM
.CodePage
== CP_UTF16BE
) {
3041 for (DWORD i
= 0; i
< ReadSize
; ++i
)
3043 Buf
[i
] = (unsigned char)View
[i
* 2 + 1];
3045 Buf
[i
]|= (unsigned char)View
[i
* 2];
3048 for (DWORD i
= 0; i
< ReadSize
; i
++)
3050 Buf
[i
] = (wchar_t)(unsigned char)View
[i
];
3056 ReadSize
= WINPORT(MultiByteToWideChar
)(VM
.CodePage
, 0, (const char *)View
, ReadSize
, Buf
, Count
);
3064 void Viewer::vseek(int64_t Offset
,int Whence
)
3066 switch (VM
.CodePage
)
3068 case CP_UTF32BE
: case CP_UTF32LE
: Offset
*= 4; break;
3069 case CP_UTF16BE
: case CP_UTF16LE
: Offset
*= 2; break;
3071 ViewFile
.SetPointer(Offset
, Whence
);
3075 int64_t Viewer::vtell()
3078 ViewFile
.GetPointer(Ptr
);
3079 switch (VM
.CodePage
)
3081 case CP_UTF32BE
: case CP_UTF32LE
: Ptr
=(Ptr
+(Ptr
&3))/4; break;
3082 case CP_UTF16BE
: case CP_UTF16LE
: Ptr
=(Ptr
+(Ptr
&1))/2; break;
3088 bool Viewer::vgetc(WCHAR
& C
)
3104 void Viewer::GoTo(int ShowDlg
,int64_t Offset
, DWORD Flags
)
3107 const wchar_t *LineHistoryName
=L
"ViewerOffset";
3108 DialogDataEx GoToDlgData
[]=
3110 {DI_DOUBLEBOX
,3,1,31,7,{0},0,Msg::ViewerGoTo
},
3111 {DI_EDIT
,5,2,29,2,{(DWORD_PTR
)LineHistoryName
},DIF_FOCUS
|DIF_DEFAULT
|DIF_HISTORY
|DIF_USELASTHISTORY
,L
""},
3112 {DI_TEXT
,3,3,0,3,{0},DIF_SEPARATOR
,L
""},
3113 {DI_RADIOBUTTON
,5,4,0,4,{0},DIF_GROUP
,Msg::GoToPercent
},
3114 {DI_RADIOBUTTON
,5,5,0,5,{0},0,Msg::GoToHex
},
3115 {DI_RADIOBUTTON
,5,6,0,6,{0},0,Msg::GoToDecimal
}
3117 MakeDialogItemsEx(GoToDlgData
,GoToDlg
);
3118 static int PrevMode
=0;
3119 GoToDlg
[3].Selected
=GoToDlg
[4].Selected
=GoToDlg
[5].Selected
=0;
3124 GoToDlg
[PrevMode
+3].Selected
=TRUE
;
3128 Dialog
Dlg(GoToDlg
,ARRAYSIZE(GoToDlg
));
3129 Dlg
.SetHelp(L
"ViewerGotoPos");
3130 Dlg
.SetPosition(-1,-1,35,9);
3133 if (Dlg
.GetExitCode()<=0)
3136 if (GoToDlg
[1].strData
.At(0)==L
'+' || GoToDlg
[1].strData
.At(0)==L
'-') // юзер хочет относительности
3138 if (GoToDlg
[1].strData
.At(0)==L
'+')
3143 GoToDlg
[1].strData
.LShift(1);
3146 if (GoToDlg
[1].strData
.Contains(L
'%')) // он хочет процентов
3148 GoToDlg
[RB_HEX
].Selected
=GoToDlg
[RB_DEC
].Selected
=0;
3149 GoToDlg
[RB_PRC
].Selected
=1;
3151 else if (!StrCmpNI(GoToDlg
[1].strData
,L
"0x",2)
3152 || GoToDlg
[1].strData
.At(0)==L
'$'
3153 || GoToDlg
[1].strData
.Contains(L
'h')
3154 || GoToDlg
[1].strData
.Contains(L
'H')) // он умный - hex код ввел!
3156 GoToDlg
[RB_PRC
].Selected
=GoToDlg
[RB_DEC
].Selected
=0;
3157 GoToDlg
[RB_HEX
].Selected
=1;
3159 if (!StrCmpNI(GoToDlg
[1].strData
,L
"0x",2))
3160 GoToDlg
[1].strData
.LShift(2);
3161 else if (GoToDlg
[1].strData
.At(0)==L
'$')
3162 GoToDlg
[1].strData
.LShift(1);
3164 //Relative=0; // при hex значении никаких относительных значений?
3167 if (GoToDlg
[RB_PRC
].Selected
)
3169 //int cPercent=ToPercent64(FilePos,FileSize);
3171 int Percent
=_wtoi(GoToDlg
[1].strData
);
3173 //if ( Relative && (cPercent+Percent*Relative<0) || (cPercent+Percent*Relative>100)) // за пределы - низя
3180 Offset
=FileSize
/100*Percent
;
3182 switch (VM
.CodePage
) {
3183 case CP_UTF32LE
: case CP_UTF32BE
: Offset
*= 4; break;
3184 case CP_UTF16LE
: case CP_UTF16BE
: Offset
*= 2; break;
3187 while (ToPercent64(Offset
,FileSize
)<Percent
)
3191 if (GoToDlg
[RB_HEX
].Selected
)
3194 swscanf(GoToDlg
[1].strData
,L
"%llx",&Offset
);
3197 if (GoToDlg
[RB_DEC
].Selected
)
3200 swscanf(GoToDlg
[1].strData
,L
"%lld",&Offset
);
3205 Relative
=(Flags
&VSP_RELATIVE
)*(Offset
<0?-1:1);
3207 if (Flags
&VSP_PERCENT
)
3209 int64_t Percent
=Offset
;
3216 Offset
=FileSize
/100*Percent
;
3218 switch (VM
.CodePage
) {
3219 case CP_UTF32LE
: case CP_UTF32BE
: Offset
*= 4; break;
3220 case CP_UTF16LE
: case CP_UTF16BE
: Offset
*= 2; break;
3223 while (ToPercent64(Offset
,FileSize
)<Percent
)
3230 if (Relative
==-1 && Offset
>FilePos
) // меньше нуля, if (FilePos<0) не пройдет - FilePos у нас uint32_t
3232 else switch (VM
.CodePage
) {
3233 case CP_UTF32LE
: case CP_UTF32BE
:
3234 FilePos
= FilePos
+Offset
*Relative
/ 4;
3237 case CP_UTF16LE
: case CP_UTF16BE
:
3238 FilePos
= FilePos
+Offset
*Relative
/ 2;
3242 FilePos
= FilePos
+Offset
*Relative
;
3247 else switch (VM
.CodePage
) {
3248 case CP_UTF32LE
: case CP_UTF32BE
:
3249 FilePos
= Offset
/ 4;
3252 case CP_UTF16LE
: case CP_UTF16BE
:
3253 FilePos
= Offset
/ 2;
3260 if (FilePos
>FileSize
|| FilePos
<0) // и куда его несет?
3261 FilePos
=FileSize
; // там все равно ничего нету
3266 // LastSelPos=FilePos;
3267 if (!(Flags
&VSP_NOREDRAW
))
3271 void Viewer::AdjustFilePos()
3276 int64_t StartLinePos
=-1,GotoLinePos
=FilePos
-(int64_t)sizeof(Buf
)/sizeof(wchar_t);
3281 vseek(GotoLinePos
,SEEK_SET
);
3282 int ReadSize
=(int)Min((int64_t)ARRAYSIZE(Buf
),(int64_t)(FilePos
-GotoLinePos
));
3283 ReadSize
=vread(Buf
,ReadSize
);
3286 for (int I
=ReadSize
-1; I
>=0; I
--)
3287 if (Buf
[I
]==(wchar_t)CRSym
)
3289 StartLinePos
=GotoLinePos
+I
;
3293 vseek(FilePos
+1,SEEK_SET
);
3297 switch (VM
.CodePage
) {
3298 case CP_UTF32LE
: case CP_UTF32BE
:
3302 case CP_UTF16LE
: case CP_UTF16BE
:
3307 FilePos
&= ~(len
- 1);
3311 if (FilePos
!=StartLinePos
)
3317 void Viewer::SetFileSize()
3319 if (!ViewFile
.Opened())
3322 UINT64 uFileSize
=0; // BUGBUG, sign
3323 ViewFile
.GetSize(uFileSize
);
3327 Везде сравниваем FilePos с FileSize, FilePos для юникодных файлов
3328 уменьшается в два раза, поэтому FileSize тоже надо уменьшать
3330 switch (VM
.CodePage
) {
3331 case CP_UTF32LE
: case CP_UTF32BE
:
3332 FileSize
=(FileSize
+(FileSize
&3)) / 4;
3335 case CP_UTF16LE
: case CP_UTF16BE
:
3336 FileSize
=(FileSize
+(FileSize
&1)) / 2;
3342 void Viewer::GetSelectedParam(int64_t &Pos
, int64_t &Length
, DWORD
&Flags
)
3350 Выделение - в качестве самостоятельной функции.
3351 Flags=0x01 - показывать (делать Show())
3352 0x02 - "обратный поиск" ?
3354 void Viewer::SelectText(const int64_t &MatchPos
,const int64_t &SearchLength
, const DWORD Flags
)
3356 if (!ViewFile
.Opened())
3359 wchar_t Buf
[MAX_VIEWLINE
];
3360 int64_t StartLinePos
=-1,SearchLinePos
=MatchPos
-sizeof(Buf
)/sizeof(wchar_t);
3362 if (SearchLinePos
<0)
3365 vseek(SearchLinePos
,SEEK_SET
);
3366 int ReadSize
=(int)Min((int64_t)ARRAYSIZE(Buf
),(int64_t)(MatchPos
-SearchLinePos
));
3367 ReadSize
=vread(Buf
,ReadSize
);
3369 for (int I
=ReadSize
-1; I
>=0; I
--)
3370 if (Buf
[I
]==(wchar_t)CRSym
)
3372 StartLinePos
=SearchLinePos
+I
;
3377 vseek(MatchPos
+1,SEEK_SET
);
3378 SelectPos
=FilePos
=MatchPos
;
3379 SelectSize
=SearchLength
;
3382 // LastSelPos=SelectPos+((Flags&0x2) ? -1:1);
3383 LastSelPos
= SelectPos
+ SearchLength
* ((Flags
& 0x2) ? -1 : 1);
3387 switch (VM
.CodePage
) {
3388 case CP_UTF32LE
: case CP_UTF32BE
:
3392 case CP_UTF16LE
: case CP_UTF16BE
:
3396 FilePos
&= ~(len
- 1);
3400 if (SelectPos
!=StartLinePos
)
3403 Show(); //update OutStr
3406 int64_t Length
=SelectPos
-StartLinePos
-1;
3409 Length
%=Width
+1; //??
3414 if (Length
-LeftPos
>Width
|| Length
<LeftPos
)
3418 if (LeftPos
>(MAX_VIEWLINE
-1) || LeftPos
<0)
3420 else if (LeftPos
>10)
3427 AdjustSelPosition
= TRUE
;
3429 AdjustSelPosition
= FALSE
;
3433 int Viewer::ViewerControl(int Command
,void *Param
)
3441 ViewerInfo
*Info
=(ViewerInfo
*)Param
;
3442 memset(&Info
->ViewerID
,0,Info
->StructSize
-sizeof(Info
->StructSize
));
3443 Info
->ViewerID
=ViewerID
;
3444 Info
->FileName
=strFullFileName
;
3445 Info
->WindowSizeX
=ObjWidth
;
3446 Info
->WindowSizeY
=Y2
-Y1
+1;
3447 Info
->FilePos
=FilePos
;
3448 Info
->FileSize
=FileSize
;
3452 if (Opt
.ViOpt
.SavePos
) Info
->Options
|=VOPT_SAVEFILEPOSITION
;
3454 if (ViOpt
.AutoDetectCodePage
) Info
->Options
|=VOPT_AUTODETECTCODEPAGE
;
3456 Info
->TabSize
=ViOpt
.TabSize
;
3457 Info
->LeftPos
=LeftPos
;
3464 Param = ViewerSetPosition
3465 сюда же будет записано новое смещение
3466 В основном совпадает с переданным
3468 case VCTL_SETPOSITION
:
3472 ViewerSetPosition
*vsp
=(ViewerSetPosition
*)Param
;
3473 bool isReShow
=vsp
->StartPos
!= FilePos
;
3475 if ((LeftPos
=vsp
->LeftPos
) < 0)
3479 Если кодировка - юникод, то оперируем числами, уменьшенными в
3480 2 раза. Поэтому увеличим StartPos в 2 раза, т.к. функция
3481 GoTo принимает смещения в _байтах_.
3484 int64_t NewPos
= vsp
->StartPos
;
3486 switch (VM
.CodePage
) {
3487 case CP_UTF32LE
: case CP_UTF32BE
:
3491 case CP_UTF16LE
: case CP_UTF16BE
:
3496 GoTo(FALSE
, NewPos
, vsp
->Flags
);
3498 if (isReShow
&& !(vsp
->Flags
&VSP_NOREDRAW
))
3501 if (!(vsp
->Flags
&VSP_NORETNEWPOS
))
3503 vsp
->StartPos
=FilePos
;
3504 vsp
->LeftPos
=LeftPos
;
3512 // Param=ViewerSelect
3517 ViewerSelect
*vs
=(ViewerSelect
*)Param
;
3518 int64_t SPos
=vs
->BlockStartPos
;
3519 int SSize
=vs
->BlockLen
;
3521 if (SPos
< FileSize
)
3523 if (SPos
+SSize
> FileSize
)
3525 SSize
=(int)(FileSize
-SPos
);
3528 SelectText(SPos
,SSize
,0x1);
3541 /* Функция установки Keybar Labels
3542 Param = nullptr - восстановить, пред. значение
3543 Param = -1 - обновить полосу (перерисовать)
3544 Param = KeyBarTitles
3546 case VCTL_SETKEYBAR
:
3548 KeyBarTitles
*Kbt
=(KeyBarTitles
*)Param
;
3551 { // восстановить пред значение!
3553 HostFileViewer
->InitKeyBar();
3557 if ((LONG_PTR
)Param
!= (LONG_PTR
)-1) // не только перерисовать?
3559 for (int i
=0; i
< 12; i
++)
3562 ViewKeyBar
->Change(KBL_MAIN
,Kbt
->Titles
[i
],i
);
3564 if (Kbt
->CtrlTitles
[i
])
3565 ViewKeyBar
->Change(KBL_CTRL
,Kbt
->CtrlTitles
[i
],i
);
3567 if (Kbt
->AltTitles
[i
])
3568 ViewKeyBar
->Change(KBL_ALT
,Kbt
->AltTitles
[i
],i
);
3570 if (Kbt
->ShiftTitles
[i
])
3571 ViewKeyBar
->Change(KBL_SHIFT
,Kbt
->ShiftTitles
[i
],i
);
3573 if (Kbt
->CtrlShiftTitles
[i
])
3574 ViewKeyBar
->Change(KBL_CTRLSHIFT
,Kbt
->CtrlShiftTitles
[i
],i
);
3576 if (Kbt
->AltShiftTitles
[i
])
3577 ViewKeyBar
->Change(KBL_ALTSHIFT
,Kbt
->AltShiftTitles
[i
],i
);
3579 if (Kbt
->CtrlAltTitles
[i
])
3580 ViewKeyBar
->Change(KBL_CTRLALT
,Kbt
->CtrlAltTitles
[i
],i
);
3584 ViewKeyBar
->Refresh(true);
3585 ScrBuf
.Flush(); //?????
3602 Разрешаем выполнение VCTL_QUIT только для вьюера, который
3603 не является панелью информации и быстрого просмотра (т.е.
3604 фактически панелей на экране не видно)
3606 if (!FrameManager
->IsPanelsActive())
3609 без этого не закрывался вьюер, а просили именно это
3611 FrameManager
->DeleteFrame(HostFileViewer
);
3614 HostFileViewer
->SetExitCode(0);
3619 /* Функция установки режимов
3620 Param = ViewerSetMode
3624 ViewerSetMode
*vsmode
=(ViewerSetMode
*)Param
;
3628 bool isRedraw
=vsmode
->Flags
&VSMFL_REDRAW
?true:false;
3630 switch (vsmode
->Type
)
3633 ProcessHexMode(vsmode
->Param
.iParam
,isRedraw
);
3636 ProcessWrapMode(vsmode
->Param
.iParam
,isRedraw
);
3639 ProcessTypeWrapMode(vsmode
->Param
.iParam
,isRedraw
);
3651 int Viewer::ProcessHexMode(int newMode
, bool isRedraw
)
3654 // До тех пор, пока не будет реализован адекватный hex-просмотр в UTF8 - будем смотреть в OEM.
3655 // Ибо сейчас это не просмотр, а генератор однотипных унылых багрепортов.
3656 if (VM
.CodePage
==CP_UTF8
&& newMode
)
3658 VM
.CodePage
=WINPORT(GetACP
)();
3670 // LastSelPos=FilePos;
3674 int Viewer::ProcessWrapMode(int newMode
, bool isRedraw
)
3676 int oldWrap
=VM
.Wrap
;
3682 if (!VM
.Wrap
&& LastPage
)
3691 Opt
.ViOpt
.ViewerIsWrap
=VM
.Wrap
;
3692 // LastSelPos=FilePos;
3696 int Viewer::ProcessTypeWrapMode(int newMode
, bool isRedraw
)
3698 int oldTypeWrap
=VM
.WordWrap
;
3699 VM
.WordWrap
=newMode
&1;
3713 Opt
.ViOpt
.ViewerWrap
=VM
.WordWrap
;
3714 //LastSelPos=FilePos;