ultimatepp/uppsrc/ide/FindInFiles.cpp
cxl b333a94ee6 CtrlLib: FileSel::Types, Select* family of utility FileSel based functions and classes; minor ide bug fixed
git-svn-id: svn://ultimatepp.org/upp/trunk@1676 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-11-02 16:54:26 +00:00

400 lines
8.4 KiB
C++

#include "ide.h"
void Ide::SerializeFf(Stream& s) {
s % ff.find;
ff.find.SerializeList(s);
s % ff.wholeword % ff.ignorecase % ff.wildcards;
s % ff.replace;
ff.replace.SerializeList(s);
}
FileSel& sSD()
{
static bool b;
static FileSel fs;
if(!b) {
fs.AllFilesType();
b = true;
}
return fs;
}
void Ide::SerializeFindInFiles(Stream& s) {
int version = 2;
s / version;
s % ff.files;
ff.files.SerializeList(s);
s % ff.folder;
ff.folder.SerializeList(s);
if(version >= 2)
{
s % ff.replace;
ff.replace.SerializeList(s);
s % ff.style;
}
if(version >= 1)
s % sSD();
}
void SearchForFiles(Vector<String>& files, String dir, String mask, Progress& pi) {
FindFile ff(AppendFileName(dir, "*.*"));
while(ff) {
if(ff.IsFolder() && *ff.GetName() != '.')
SearchForFiles(files, AppendFileName(dir, ff.GetName()), mask, pi);
else
if(ff.IsFile() && PatternMatchMulti(mask, ff.GetName())) {
if(pi.StepCanceled()) return;
files.Add(AppendFileName(dir, ff.GetName()));
}
ff.Next();
}
}
enum {
WILDANY = 16,
WILDONE,
WILDSPACE,
WILDNUMBER,
WILDID,
};
bool Match(const char *f, const char *s, bool we, bool ignorecase) {
while(*f) {
if(*f == WILDANY) {
f++;
for(;;) {
if(Match(f, s, we, ignorecase))
return true;
if(!*s++) break;
}
return false;
}
else
if(*f == WILDONE) {
if(!*s++) return false;
}
else
if(*f == WILDSPACE) {
if(*s != ' ' && *s != '\t') return false;
s++;
while(*s == ' ' || *s == '\t')
s++;
}
else
if(*f == WILDNUMBER) {
if(*s < '0' || *s > '9') return false;
s++;
while(*s >= '0' && *s <= '9')
s++;
}
else
if(*f == WILDID) {
if(!iscib(*s)) return false;
s++;
while(iscid(*s)) s++;
}
else {
if(ignorecase ? ToUpper(*s) != ToUpper(*f) : *s != *f) return false;
s++;
}
f++;
}
return we && iscid(*s) ? false : true;
}
bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword, bool ignorecase,
int& n) {
FileIn in(fn);
if(!in) return true;
int ln = 1;
bool wb = wholeword ? iscid(*pattern) : false;
bool we = wholeword ? iscid(*pattern.Last()) : false;
int infile = 0;
while(!in.IsEof()) {
String line = in.GetLine();
bool bw = true;
for(const char *s = line; *s; s++) {
if(bw && Match(pattern, s, we, ignorecase)) {
console2 << fn << Format("(%d):", ln) << line << "\n";
console2.Sync();
infile++;
n++;
break;
}
if(wb) bw = !iscid(*s);
}
ln++;
}
in.Close();
int ffs = ~ff.style;
if(infile && ffs != STYLE_NO_REPLACE)
{
EditFile(fn);
bool doit = true;
if(ffs == STYLE_CONFIRM_REPLACE)
{
editor.SetCursor(0);
editor.Find(false, true);
switch(PromptYesNoCancel(NFormat("Replace %d lines in %s?", infile, fn)))
{
case 1: break;
case 0: doit = false; break;
case -1: return false;
}
}
if(doit)
{
editor.SelectAll();
editor.BlockReplace();
SaveFile();
console2 << NFormat("%s: %d replacements made\n", fn, infile);
console2.Sync();
}
}
return true;
}
static bool RawFileMatch(const char *pattern, const char *file, const char *& endptr)
{
for(char c; (c = *pattern++) != 0;)
if(c == '*')
{
do
if(RawFileMatch(pattern, file, endptr))
return true;
while(*file++);
endptr = pattern;
return false;
}
else if(c == '?')
{
if(*file++ == 0)
{
endptr = pattern - 1;
return false;
}
}
else if(ToLower(c) != ToLower(*file++))
{
endptr = pattern - 1;
return false;
}
endptr = file;
return true;
}
static const char *FindFileMatch(const char *pattern, const char *file, String& cont)
{
const char *endptr;
if(!RawFileMatch(pattern, file, endptr))
return endptr;
if(cont.IsVoid())
{
cont = endptr;
return NULL;
}
const char *p = cont;
while(*p && ToLower(*p) == ToLower(*endptr++))
p++;
cont.Trim(int(p - cont.Begin()));
return NULL;
}
int CharFilterFindFileMask(int c)
{
return ToUpper(ToAscii(c));
}
void Ide::FindFileName() {
const Workspace& wspc = IdeWorkspace();
WithFindFileLayout<TopWindow> ffdlg;
CtrlLayoutOKCancel(ffdlg, "Find file");
ffdlg.list.AutoHideSb();
ffdlg.list.AddColumn("Package");
ffdlg.list.AddColumn("File");
ffdlg.list.WhenLeftDouble = ffdlg.Acceptor(IDOK);
ffdlg.mask.NullText("Search");
ffdlg.mask.SetFilter(CharFilterFindFileMask);
ffdlg.mask <<= ffdlg.Breaker(IDYES);
int prev = 0;
for(;;) {
ffdlg.list.Clear();
String mask = ~ffdlg.mask;
const char *best_err = NULL;
for(int p = 0; p < wspc.GetCount(); p++) {
String packname = wspc[p];
const Package& pack = wspc.GetPackage(p);
for(int f = 0; f < pack.file.GetCount(); f++) {
String fn = pack.file[f];
if(ToUpper(packname).Find(mask) >= 0 || ToUpper(fn).Find(mask) >= 0)
ffdlg.list.Add(packname, pack.file[f]);
}
}
if(ffdlg.list.GetCount() > 0)
ffdlg.list.SetCursor(0);
switch(ffdlg.Run()) {
case IDCANCEL:
return;
case IDOK:
if(ffdlg.list.IsCursor()) {
EditFile(SourcePath(ffdlg.list.Get(0), ffdlg.list.Get(1)));
return;
}
break;
case IDYES:
break;
}
}
}
void Ide::FindInFiles() {
StringStream ss;
editor.SerializeFind(ss);
ss.Open(ss.GetResult());
SerializeFf(ss);
if(String(ff.folder).IsEmpty())
ff.folder <<= GetUppDir();
ff.style <<= STYLE_NO_REPLACE;
ff.itext = editor.GetI();
int c = ff.Execute();
ss.Create();
SerializeFf(ss);
ss.Open(ss.GetResult());
editor.SerializeFind(ss);
if(c == IDOK && !String(ff.find).IsEmpty()) {
Renumber();
ff.find.AddHistory();
ff.files.AddHistory();
ff.folder.AddHistory();
ff.replace.AddHistory();
Progress pi("Found %d files to search.");
Vector<String> files;
SearchForFiles(files, NormalizePath((String)ff.folder, GetUppDir()), ~ff.files, pi);
if(!pi.Canceled()) {
String pattern;
if(ff.wildcards) {
String q = ~ff.find;
for(const char *s = q; *s; s++)
if(*s == '\\') {
s++;
if(*s == '\0') break;
q.Cat(*s);
}
else
switch(*s) {
case '*': pattern.Cat(WILDANY); break;
case '?': pattern.Cat(WILDONE); break;
case '%': pattern.Cat(WILDSPACE); break;
case '#': pattern.Cat(WILDNUMBER); break;
case '$': pattern.Cat(WILDID); break;
default: pattern.Cat(*s);
}
}
else
pattern = ~ff.find;
pi.SetTotal(files.GetCount());
ShowConsole2();
console2.Clear();
pi.SetPos(0);
int n = 0;
for(int i = 0; i < files.GetCount(); i++) {
pi.SetText(files[i]);
if(pi.StepCanceled()) break;
if(!SearchInFile(files[i], pattern, ff.wholeword, ff.ignorecase, n))
break;
}
console2 << Format("%d occurrence(s) have been found.\n", n);
}
}
SetErrorEditor();
}
void Ide::FindString(bool back)
{
if(!editor.FindString(back))
BeepMuteExclamation();
}
void Ide::TranslateString()
{
int l, h;
if(editor.GetSelection(l, h)) {
editor.Insert(l, "t_(");
editor.Insert(h + 3, ")");
editor.SetCursor(h + 4);
FindString(false);
}
}
void Ide::InsertWildcard(int c) {
iwc = c;
}
void Ide::FindWildcard() {
int l, h;
ff.find.GetSelection(l, h);
iwc = 0;
FindWildcardMenu(THISBACK(InsertWildcard), ff.find.GetPushScreenRect().TopRight(), false);
if(iwc) {
ff.wildcards = true;
ff.find.SetFocus();
ff.find.SetSelection(l, h);
ff.find.RemoveSelection();
ff.find.Insert(iwc);
}
}
void Ide::FindSetStdDir(String n)
{
ff.folder <<= n;
}
void Ide::FindStdDir()
{
String n = GetFileFolder(editfile);
MenuBar menu;
if(!IsNull(n))
menu.Add(n, THISBACK1(FindSetStdDir, n));
Vector<String> d = GetUppDirs();
for(int i = 0; i < d.GetCount(); i++)
menu.Add(d[i], THISBACK1(FindSetStdDir, d[i]));
menu.Execute(&ff.folder, ff.folder.GetPushScreenRect().BottomLeft());
}
void Ide::FindFolder()
{
if(!sSD().ExecuteSelectDir()) return;
ff.folder <<= ~sSD();
}
void Ide::ConstructFindInFiles() {
ff.find.AddButton().SetMonoImage(CtrlImg::smallright()) <<= THISBACK(FindWildcard);
ff.files <<= String("*.cpp *.h *.hpp *.c *.C *.cxx *.cc");
ff.files.AddList((String)"*.cpp *.h *.hpp *.c *.C *.cxx *.cc *.icpp");
ff.files.AddList((String)"*.txt");
ff.files.AddList((String)"*.*");
ff.folder.AddButton().SetMonoImage(CtrlImg::smalldown()) <<= THISBACK(FindStdDir);
ff.folder.AddButton().SetMonoImage(CtrlImg::smallright()) <<= THISBACK(FindFolder);
editor.PutI(ff.find);
editor.PutI(ff.replace);
CtrlLayoutOKCancel(ff, "Find In Files");
}
bool Ide::FindInFiles::Key(dword key, int count)
{
if(key == K_CTRL_I) {
if(find.HasFocus()) {
find <<= itext;
return true;
}
if(replace.HasFocus()) {
replace <<= itext;
return true;
}
}
return TopWindow::Key(key, count);
}