From 3f25bfa2ce9c41c52e6ebee4a6eb19ed10f12ea3 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 15 Mar 2015 14:13:59 +0000 Subject: [PATCH] ide: Binary files viewer (and detection) git-svn-id: svn://ultimatepp.org/upp/trunk@8270 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/HexView/HexView.cpp | 2 +- uppsrc/HexView/HexView.h | 2 +- uppsrc/HexView/HexView.lay | 1 + uppsrc/ide/Assist.cpp | 1 + uppsrc/ide/Designers/Designers.h | 60 ++++++++++++++++++++- uppsrc/ide/Designers/Designers.upp | 5 +- uppsrc/ide/Designers/HexView.icpp | 83 ++++++++++++++++++++++++++++++ uppsrc/ide/Designers/Img.h | 29 ----------- uppsrc/ide/Designers/Img.icpp | 2 +- uppsrc/ide/Designers/Png.cpp | 2 +- uppsrc/ide/Designers/Qtf.icpp | 3 +- uppsrc/ide/Designers/init | 7 ++- uppsrc/ide/Errors.cpp | 1 + uppsrc/ide/ide.h | 3 ++ uppsrc/ide/ide.key | 1 + uppsrc/ide/ide.lay | 4 +- uppsrc/ide/idebar.cpp | 2 + uppsrc/ide/idefile.cpp | 42 ++++++++++----- 18 files changed, 196 insertions(+), 54 deletions(-) create mode 100644 uppsrc/ide/Designers/HexView.icpp delete mode 100644 uppsrc/ide/Designers/Img.h diff --git a/uppsrc/HexView/HexView.cpp b/uppsrc/HexView/HexView.cpp index 71dfb1c1d..f23eef716 100644 --- a/uppsrc/HexView/HexView.cpp +++ b/uppsrc/HexView/HexView.cpp @@ -144,7 +144,7 @@ HexViewInfo::HexViewInfo() int HexView::Byte(int64 adr) { - return IsBadReadPtr((byte *)(uintptr_t)adr, 1) ? -1 : *(byte *)(unsigned)adr; + return 0; } void HexView::Paint(Draw& w) diff --git a/uppsrc/HexView/HexView.h b/uppsrc/HexView/HexView.h index 4cb034bb7..7d7e70d51 100644 --- a/uppsrc/HexView/HexView.h +++ b/uppsrc/HexView/HexView.h @@ -3,7 +3,6 @@ #include - NAMESPACE_UPP #define LAYOUTFILE @@ -88,6 +87,7 @@ public: HexView& SetFont(Font fnt); HexView& Charset(byte chrset) { charset = chrset; Refresh(); return *this; } HexView& FixedColumns(int c = 0) { fixed = c; Layout(); Refresh(); return *this; } + HexView& InfoMode(int m = 1) { info.SetMode(m); return *this; } typedef HexView CLASSNAME; diff --git a/uppsrc/HexView/HexView.lay b/uppsrc/HexView/HexView.lay index e8719393a..33ce64a61 100644 --- a/uppsrc/HexView/HexView.lay +++ b/uppsrc/HexView/HexView.lay @@ -4,3 +4,4 @@ LAYOUT(HexGotoLayout, 280, 68) ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(140, 64).TopPosZ(36, 24)) ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(208, 64).TopPosZ(36, 24)) END_LAYOUT + diff --git a/uppsrc/ide/Assist.cpp b/uppsrc/ide/Assist.cpp index 921aaaf3f..6c101ca2a 100644 --- a/uppsrc/ide/Assist.cpp +++ b/uppsrc/ide/Assist.cpp @@ -1340,6 +1340,7 @@ void Ide::JumpToDefinition(const Array& n, int q, const String& scope) const CppItem& pos = n[qimpl >= 0 ? qimpl : qcpp >= 0 ? qcpp : q]; String path = GetCppFile(pos.file); editastext.RemoveKey(path); + editashex.RemoveKey(path); if(ToLower(GetFileExt(path)) == ".lay") { AddHistory(); EditFile(path); diff --git a/uppsrc/ide/Designers/Designers.h b/uppsrc/ide/Designers/Designers.h index 15f18fee5..ffa0712bb 100644 --- a/uppsrc/ide/Designers/Designers.h +++ b/uppsrc/ide/Designers/Designers.h @@ -1,6 +1,64 @@ #ifndef _ide_Designers_Designers_h_ #define _ide_Designers_Designers_h_ -#include "Img.h" +#include +#include +#include + +struct IdeImgView : IdeDesigner, Ctrl { + Size img_sz; + Image img; + String filename; + + virtual void Paint(Draw& w); + + virtual String GetFileName() const { return filename; } + virtual void EditMenu(Bar& menu); + virtual void Save() {} + virtual Ctrl& DesignerCtrl() { return *this; } + + typedef IdeImgView CLASSNAME; +}; + +struct IdePngDes : IdeIconDes { + virtual void Save(); + + void Load(const char *filename); + void Create(const char *filename); +}; + +class FileHexView : public IdeDesigner, public HexView, private LRUCache::Maker { +public: + virtual int Byte(int64 addr); + + virtual int64 Key() const; + virtual int Make(String& object) const; + + virtual String GetFileName() const { return filename; } + virtual void Save() {} + virtual void EditMenu(Bar& menu) { StdMenu(menu); } + virtual Ctrl& DesignerCtrl() { return *this; } + +private: + String filename; + + FileIn file; + int64 blk; + + LRUCache cache; + + enum { BLKSHIFT = 14, BLKSIZE = 1 << BLKSHIFT }; + + +public: + void Serialize(Stream& s) { SerializeSettings(s); } + + void Open(const char *path); + + FileHexView(); + ~FileHexView(); +}; + +bool FileIsBinary(const char *path); #endif diff --git a/uppsrc/ide/Designers/Designers.upp b/uppsrc/ide/Designers/Designers.upp index 5674cb8a2..4ad11045f 100644 --- a/uppsrc/ide/Designers/Designers.upp +++ b/uppsrc/ide/Designers/Designers.upp @@ -1,8 +1,9 @@ description "Various small(er) designers (Image viewer, QTF editor, ...)\377B"; file - Img.h, + Designers.h, Png.cpp, Img.icpp, - Qtf.icpp; + Qtf.icpp, + HexView.icpp; diff --git a/uppsrc/ide/Designers/HexView.icpp b/uppsrc/ide/Designers/HexView.icpp new file mode 100644 index 000000000..da9f1803c --- /dev/null +++ b/uppsrc/ide/Designers/HexView.icpp @@ -0,0 +1,83 @@ +#include "Designers.h" + +bool FileIsBinary(const char *path) +{ + FileIn in(path); + if(in) { + String data = in.Get(150000); + if(*data.Last() == '\r') + data.Cat(in.Get()); + const char *end = data.End(); + int le = -1; + const char *s = data; + while(s < end) { + int c = (byte)*s; + if(c < 32) { + if(c == '\r') { + if(s[1] != '\n' || le == 0) + return true; + le = 1; + s += 2; + } + else + if(c == '\n') { + if(le == 1) + return true; + s++; + } + else + if(c == '\t') + s++; + else + return true; + } + else + s++; + } + } + return false; +} + +int64 FileHexView::Key() const +{ + return blk; +} + +int FileHexView::Make(String& object) const +{ + FileIn& in = const_cast(file); + in.Seek(blk * FileHexView::BLKSIZE); + object = in.Get(FileHexView::BLKSIZE); + return 1; +} + +int FileHexView::Byte(int64 addr) +{ + blk = addr >> BLKSHIFT; + String h = cache.Get(*this); + cache.Shrink(10); // cache only 10 blocks (~150 KB) + int ii = addr & (BLKSIZE - 1); + return ii < h.GetCount() ? (byte)h[ii] : 0; +} + +void FileHexView::Open(const char *path) +{ + filename = path; + file.Open(path); + SetTotal(file.GetSize()); +} + +FileHexView::FileHexView() +{ + InfoMode(2); + LoadFromGlobal(*this, "FileHexView"); +} + +FileHexView::~FileHexView() +{ + StoreToGlobal(*this, "FileHexView"); +} + +INITBLOCK { + RegisterGlobalConfig("FileHexView"); +} \ No newline at end of file diff --git a/uppsrc/ide/Designers/Img.h b/uppsrc/ide/Designers/Img.h deleted file mode 100644 index f5fb23302..000000000 --- a/uppsrc/ide/Designers/Img.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _ide_ImgDes_ImgDes_h_ -#define _ide_ImgDes_ImgDes_h_ - -#include -#include - -struct IdeImgView : IdeDesigner, Ctrl { - Size img_sz; - Image img; - String filename; - - virtual void Paint(Draw& w); - - virtual String GetFileName() const { return filename; } - virtual void EditMenu(Bar& menu); - virtual void Save() {} - virtual Ctrl& DesignerCtrl() { return *this; } - - typedef IdeImgView CLASSNAME; -}; - -struct IdePngDes : IdeIconDes { - virtual void Save(); - - void Load(const char *filename); - void Create(const char *filename); -}; - -#endif diff --git a/uppsrc/ide/Designers/Img.icpp b/uppsrc/ide/Designers/Img.icpp index 7be8c994e..8658d21bb 100644 --- a/uppsrc/ide/Designers/Img.icpp +++ b/uppsrc/ide/Designers/Img.icpp @@ -1,4 +1,4 @@ -#include "Img.h" +#include "Designers.h" void IdeImgView::Paint(Draw& w) { diff --git a/uppsrc/ide/Designers/Png.cpp b/uppsrc/ide/Designers/Png.cpp index 9eb36d0a5..ffad66831 100644 --- a/uppsrc/ide/Designers/Png.cpp +++ b/uppsrc/ide/Designers/Png.cpp @@ -1,4 +1,4 @@ -#include "Img.h" +#include "Designers.h" void IdePngDes::Save() { diff --git a/uppsrc/ide/Designers/Qtf.icpp b/uppsrc/ide/Designers/Qtf.icpp index 4387a8cd3..30984e22a 100644 --- a/uppsrc/ide/Designers/Qtf.icpp +++ b/uppsrc/ide/Designers/Qtf.icpp @@ -1,5 +1,4 @@ -#include -#include +#include "Designers.h" struct IdeQtfDes : IdeDesigner, RichEditWithToolBar { String filename; diff --git a/uppsrc/ide/Designers/init b/uppsrc/ide/Designers/init index 7220e079f..041b78468 100644 --- a/uppsrc/ide/Designers/init +++ b/uppsrc/ide/Designers/init @@ -1,9 +1,12 @@ #ifndef _ide_Designers_icpp_init_stub #define _ide_Designers_icpp_init_stub -#define BLITZ_INDEX__ Fadb0baddbb7b757e3ed9acaca887cd9a +#define BLITZ_INDEX__ F30af27bc27b2245be0afb8cf140e0a02 #include "Img.icpp" #undef BLITZ_INDEX__ -#define BLITZ_INDEX__ F421424bc1424dfd0a7a9d53622c87987 +#define BLITZ_INDEX__ F2b9cc9e34248ca7ce468509d67805881 #include "Qtf.icpp" #undef BLITZ_INDEX__ +#define BLITZ_INDEX__ F231a40d13d2e3c77ea055dcf401dd5dc +#include "HexView.icpp" +#undef BLITZ_INDEX__ #endif diff --git a/uppsrc/ide/Errors.cpp b/uppsrc/ide/Errors.cpp index 86761766f..05232a0e3 100644 --- a/uppsrc/ide/Errors.cpp +++ b/uppsrc/ide/Errors.cpp @@ -278,6 +278,7 @@ void Ide::GoToError(const ErrorInfo& f) return; String file = NormalizePath(f.file); editastext.FindAdd(file); + editashex.RemoveKey(file); EditFile(file); editor.SetCursor(editor.GetPos(editor.GetLineNo(f.lineno - 1), max(f.linepos - 1, 0))); editor.CenterCursor(); diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index 725a6dd8c..b2c3e27ce 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -13,6 +13,7 @@ #include #include #include +#include #define LAYOUTFILE #include @@ -497,6 +498,7 @@ public: ArrayMap filedata; Index editastext; + Index editashex; DropList mainconfiglist; String mainconfigname; @@ -753,6 +755,7 @@ public: void Edit(Bar& menu); void EditAsText(); + void EditAsHex(); void EditUsingDesigner(); void EditMakeTabs() { editor.MakeTabsOrSpaces(true); } void EditMakeSpaces() { editor.MakeTabsOrSpaces(false); } diff --git a/uppsrc/ide/ide.key b/uppsrc/ide/ide.key index 4b82bb22c..93241bdee 100644 --- a/uppsrc/ide/ide.key +++ b/uppsrc/ide/ide.key @@ -17,6 +17,7 @@ KEY(FINDINFILES, "Find in Files..", K_CTRL_F|K_SHIFT) KEY(REPLACEINFILES, "Replace in Files..", K_CTRL_H|K_SHIFT) KEY(FINDFILE, "Find file..", K_ALT_F|K_SHIFT) KEY(EDITASTEXT, "Edit as text", K_CTRL_T) +KEY(EDITASHEX, "View as binary", 0) KEY(DESIGNER, "Edit using the designer", K_CTRL_T) KEY2(CUTLINE, "Cut line", K_CTRL_Y, K_CTRL_L) KEY(DELLINE, "Delete line", 0) diff --git a/uppsrc/ide/ide.lay b/uppsrc/ide/ide.lay index 3e826a092..cccac9d08 100644 --- a/uppsrc/ide/ide.lay +++ b/uppsrc/ide/ide.lay @@ -147,9 +147,9 @@ LAYOUT(NewPackageLayout, 728, 560) END_LAYOUT LAYOUT(FileFormatLayout, 348, 108) - ITEM(Label, dv___0, SetLabel(t_("&Encoding")).LeftPosZ(8, 49).TopPosZ(8, 20)) + ITEM(Label, dv___0, SetLabel(t_("&Encoding")).LeftPosZ(8, 64).TopPosZ(8, 20)) ITEM(DropList, charset, LeftPosZ(64, 120).TopPosZ(8, 19)) - ITEM(Label, dv___2, SetLabel(t_("&Font")).LeftPosZ(8, 49).TopPosZ(32, 20)) + ITEM(Label, dv___2, SetLabel(t_("&Font")).LeftPosZ(8, 76).TopPosZ(32, 20)) ITEM(DropList, font, LeftPosZ(64, 120).TopPosZ(32, 19)) ITEM(Label, dv___4, SetLabel(t_("T&ab size")).LeftPosZ(196, 48).TopPosZ(8, 19)) ITEM(EditIntSpin, tabsize, LeftPosZ(264, 50).TopPosZ(8, 19)) diff --git a/uppsrc/ide/idebar.cpp b/uppsrc/ide/idebar.cpp index e6ec18771..69f1443fe 100644 --- a/uppsrc/ide/idebar.cpp +++ b/uppsrc/ide/idebar.cpp @@ -179,6 +179,8 @@ void Ide::SearchMenu(Bar& menu) void Ide::Edit(Bar& menu) { + if(editfile.GetCount() && editashex.Find(editfile) < 0) + menu.Add(AK_EDITASHEX, THISBACK(EditAsHex)); if(designer) { if(FileExists(designer->GetFileName())) { menu.Add(AK_EDITASTEXT, THISBACK(EditAsText)) diff --git a/uppsrc/ide/idefile.cpp b/uppsrc/ide/idefile.cpp index 0d4ac7d69..2d27e03fd 100644 --- a/uppsrc/ide/idefile.cpp +++ b/uppsrc/ide/idefile.cpp @@ -460,20 +460,26 @@ void Ide::EditFile0(const String& path, byte charset, bool astext, const String& editfile_isfolder = IsFolder(editfile); svn_dirs = SvnDirs(true).GetCount(); // Perhaps not the best place, but should be ok - if(!astext && !(debugger && (PathIsEqual(path, posfile[0]) || PathIsEqual(path, posfile[0]))) - && editastext.Find(path) < 0 && !IsNestReadOnly(editfile)) { + bool candesigner = !astext && !(debugger && (PathIsEqual(path, posfile[0]) || PathIsEqual(path, posfile[0]))) + && editastext.Find(path) < 0 && !IsNestReadOnly(editfile); + + if(candesigner) { for(int i = 0; i < GetIdeModuleCount() && !designer; i++) designer = GetIdeModule(i).CreateDesigner(this, path, charset); - if(designer) { - editpane.Add(designer->DesignerCtrl().SizePos()); - designer->RestoreEditPos(); - if(filetabs) - tabs.SetAddFile(editfile); - MakeTitle(); - SetBar(); - designer->SetFocus(); - return; - } + } + + if(!designer && editastext.Find(path) < 0 && (FileIsBinary(path) || editashex.Find(path) >= 0)) + designer.Create().Open(path); + + if(designer) { + editpane.Add(designer->DesignerCtrl().SizePos()); + designer->RestoreEditPos(); + if(filetabs) + tabs.SetAddFile(editfile); + MakeTitle(); + SetBar(); + designer->SetFocus(); + return; } tabs.SetAddFile(editfile); @@ -574,9 +580,20 @@ void Ide::TriggerAssistSync() text_updated.KillSet(1000, THISBACK(EditFileAssistSync)); } +void Ide::EditAsHex() +{ + String path = editfile; + editastext.RemoveKey(editfile); + editashex.FindPut(editfile); + byte cs = editor.GetCharset(); + FlushFile(); + EditFile0(path, cs); +} + void Ide::EditAsText() { String path = editfile; + editashex.RemoveKey(editfile); editastext.FindPut(editfile); byte cs = editor.GetCharset(); FlushFile(); @@ -586,6 +603,7 @@ void Ide::EditAsText() void Ide::EditUsingDesigner() { String path = editfile; + editashex.RemoveKey(editfile); editastext.RemoveKey(editfile); byte cs = editor.GetCharset(); FlushFile();