home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1999 February
/
VPR9902A.BIN
/
APUPDATE
/
VC
/
Tx300d
/
TX300D.LZH
/
GREP.C
< prev
next >
Wrap
Text File
|
1997-10-17
|
37KB
|
1,382 lines
// WZ Grep
// Copyright 1995-97 TY
// Thanks to: y.mikomeさん/M.Ishidaさん (古株順??)
//1.00D Grepでログファイルなど、
// コントロールコード(例えば^H)が含まれるファイルが検索できなかったので、
// "バイナリファイルも検索"オプションを追加した
//1.00H2 ロングファイル名対応のため、マスク表示をやめるなど全面改良
//2.92 全面改良
//2.92 Grep置換機能を新設
//2.94 970121 高速オープン対応
//2.99F 970404 Grep置換機能は、UNIX/MACファイル確認動作が不安定だったのを修正したあおりで、動作しなくなり、やむなく削除。
//3.00A 970428 Grep置換機能実装
//{###検索・置換}
#pragma TXE
#include <windows.h>
#include <windowsx.h>
#include "dialog.h"
#include "search.txh"
#include "_filer.h"
#include "prof.h"
#define IDM_CMDLINE 100
#define IDM_UIGREP 101
#define IDD_SZPATH 101
#define IDD_SEARCHINFO 102
#define IDD_TOREPLACE 103
// search.cと同じ
#define IDD_SZFIND 3000
#define IDD_SZREPLACE 3001
#define IDD_REFERSEARCHLIST 3002
extern "search" BOOL dlgprocSearch(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
// for cmdline指定を優先させる
static txstr _cmdline_szpath(500); //
static txstr _cmdline_szsearch(CCHWORD); //1.00F 文字列選択状態でWZ Grepを起動すると検索文字列に取り込みます。
static BOOL _cmdline_fSearchDirectory; //
//
static SEARCHOPT _searchopt; //1.96 検索オプション
static BOOL _fReplace = FALSE; //2.92 置換?
static TX* _textGrep; //2.94 970121 grep text
// preview
#define DEFAULT_PREVIEW_RATE 70
static HWND _hwndPreview; //2.99 970317 preview dialog
static HWND _hwndPreviewPartition; //2.99 970318 partition grep,preview
permanent BOOL p_fPreview = TRUE; //2.99 970318
permanent int p_ratePreview = DEFAULT_PREVIEW_RATE;//2.99 970318 プレビュー時のMainWindowの比率
typedef struct {
BOOL fEcho; // 付属情報も出力?
int nfind; // 見つけた数
BBOOL modeDisp; // 見つけた内容の表示モード
} GREPCONTEXT;
static GREPCONTEXT _context;
static HWND _hdlg; // Grep中ダイアログボックス
static mchar *szworking = " Grep:検索中...";
//3.00B1 970613 Grepの検索ボックスのフォントもテキストと同じにできるようにした
static BOOL _fsetfontSearch;
static BOOL _fsetfontReplace;
//##ユーザアボート
static BOOL _fUserAbort;
static BOOL AbortProc(void)
{
MSG msg;
while(!_fUserAbort && _hdlg && PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (!IsDialogMessage(_hdlg,&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return !_fUserAbort;
}
//##grep main
static void grepafile(mchar *szfilename,mchar *szfind,DWORD searchmode,GREPCONTEXT* context,mchar* szReplace)
{
TX* text = _textGrep;//2.96 970205 grep置換のバグ修正
//
if (!(searchmode & GREP_BACKUP)) {//2.92
mchar* sz = pathGetFileName(szfilename);
if (sz[0] == '$' && sz[1] == '~') return;
sz = pathGetExt(szfilename);
if (sz[0] == '~') return;
}
TX _textBody2;//2.96 970205
TX* text2 = &_textBody2;
txInitText(text2);
txSetFileName(text2,szfilename);
if (!(searchmode & GREP_BINARY) && txIsBinary(text2)) return; // 開く前にファイル名でチェック
text2->fSilent = TRUE; // 不要なattentionを出さない
//
text2->fLineD = FALSE; // 論理行モード
text2->fViewMode = TRUE;
text2->fNoCursor = TRUE; //3.00C 971013 マウスカーソルのちらつきを改善
searchmode |= SEARCH_CUR; // 最初は、カーソル位置(ファイル先頭)から検索
//
BOOL fFirstFind = TRUE;
#if 1//3.00B1 970612 Grepで漢字コードの自動判別効いてなかった
text2->fKcAuto = text->share->config.fKcAuto;//1.97
#else
text->fKcAuto = text->share->config.fKcAuto;//1.97
#endif
text2->fBinary = TRUE; //3.00C 971013 バイナリファイルを検索しても無限ループにならないように
txOpenText(text2);
if ((searchmode & GREP_BINARY) || !txIsBinary(text2)) {
IFILE adr0 = -1;
txstr szfindstr(200);
txstr szpara(2048);//2.92
SetDlgItemText(_hdlg,IDD_SEARCHINFO,pathGetFileName(szfilename));
//3.00A 970428
REPLACECONTEXT rc;
if (szReplace) {
structClear(rc);
rc.text = text2;
sstrcpy(rc.szReplace,szReplace);
rc.lchReplace = strlen(rc.szReplace);
rc.fGrepReplace = TRUE;
text2->rc = &rc;
}
//
while(1) {
int retFind;
if (!AbortProc()) break;
if (retFind = txSearchEx(text2,szfind,searchmode)) {
WORD sizex = txGetAddress(text2) - txGetParaTop(text2);
{//1.00C 無限に同じ所にマッチすることがあった
IFILE adr = txGetAddress(text2);
if (adr == adr0) break;
adr0 = adr;
}
{
if (context->fEcho) {
if (fFirstFind) {
txInsertLine(text,"%s\"%s\"",text->tsztitle[0],szfilename);
}
if (szReplace) {
mchar* szReplace1 = szReplace;
if (rc.fGrepReplaceTag) {
szReplace1 = rc.rarg.szReplace;
}
szfindstr = "";
if (retFind) txGetBuff(text2,retFind-1,szfindstr,cchtxstr(szfindstr));
txInsertf(text,"・a%-10d: (%d,%d,%d)%s -> ",txGetAddress(text2),retFind,strlen(szfindstr),strlen(szReplace1),szfindstr);
txInsert(text,szReplace1);
} else {
switch(context->modeDisp) {
case 0:txGetLine(text2,szfindstr);break;
case 1:txGetLineRear(text2,szfindstr);break;
case 2:szfindstr = "";break;
}
txInsertf(text,"・%5d,%-4d: %s",text2->npara,sizex,szfindstr);
if (context->modeDisp == 2) {
txGetPara(text2,szpara);
txInsert(text,szpara);
}
}
txInsertReturn(text);
} else {
// 古い形式を使う
// ファイル名を""でくくってロングファイル対応はする
txInsertLine(text,"\"%s\" %5d,%4d:",szfilename,text2->npara,sizex);
}
context->nfind++;
fFirstFind = FALSE;
}
searchmode &= ~SEARCH_CUR;
// 次からは、カーソル位置の次の文字から検索
} else {
break;
}
}
//3.00A 970428
text2->rc = NULL;
}
txClose(text2);
}
static void greppath(mchar *szpath,mchar *szfind,DWORD searchmode,GREPCONTEXT* context,mchar* szReplace)
{
#ifdef __FLAT__
WIN32_FIND_DATA ffd;
#else
FILEFIND filefind;
#endif
mchar szfilename[CCHPATHNAME];
// 通常ファイル
strcpy(szfilename,szpath);
#ifdef __FLAT__
{
HANDLE hfind = FindFirstFile(szpath,&ffd);
if (hfind != INVALID_HANDLE_VALUE) {
do {
if (!AbortProc()) break;
if (context->fEcho) statprintf(szworking);
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
pathSetFileName(szfilename,ffd.cFileName);
grepafile(szfilename,szfind,searchmode,context,szReplace);
} while(FindNextFile(hfind,&ffd));
FindClose(hfind);
}
}
#else
if (!fileFindFirst(szpath,FA_NORMAL,&filefind)) {
do {
if (!AbortProc()) break;
if (context->fEcho) statprintf(szworking);
pathSetFileName(szfilename,filefind.name);
grepafile(szfilename,szfind,searchmode,context,szReplace);
} while (!fileFindNext(&filefind));
}
#endif
// サブディレクトリ
if (searchmode & GREP_DIRECTORY) {
strcpy(szfilename,szpath);
pathSetFileName(szfilename,"*.*");
#ifdef __FLAT__
{
HANDLE hfind = FindFirstFile(szfilename,&ffd);
if (hfind != INVALID_HANDLE_VALUE) {
do {
if (!AbortProc()) break;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (ffd.cFileName[0] != '.') {
txstr szsubpath(CCHPATHNAME);
szsubpath = szpath;
pathSetFileName(szsubpath,ffd.cFileName + "\\" + pathGetFileName(szsubpath));
// information("[%s]",szsubpath);
greppath(szsubpath,szfind,searchmode,context,szReplace);
}
}
} while(FindNextFile(hfind,&ffd));
FindClose(hfind);
}
}
#else
if (!fileFindFirst(szfilename,FA_DIREC,&filefind)) {
do {
if (!AbortProc()) break;
if (filefind.attrib & FA_DIREC) {
if (filefind.name[0] != '.') {
txstr szsubpath(CCHPATHNAME);
szsubpath = szpath;
pathSetFileName(szsubpath,filefind.name + "\\" + pathGetFileName(szsubpath));
// information("[%s]",szsubpath);
greppath(szsubpath,szfind,searchmode,context,szReplace);
}
}
} while (!fileFindNext(&filefind));
}
#endif
}
}
BOOL dlgprocGreping(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message) {
case WM_INITDIALOG: {
_fUserAbort = FALSE;
//2.92 "検索中"の表示位置改善
// 中途半端な位置に表示されていて、Grepの動作が重くなっていた
RECT r;
GetClientRect(hwnd,&r);
int cx = r.right;
GetWindowRect(_textGrep->hwndtext,&r);
SetWindowPos(hwnd,NULL,r.left+(rectCx(&r)-cx)/2,r.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
break;
}
case WM_COMMAND: {
if (LOWORD(wParam) == IDCANCEL) {
_fUserAbort = TRUE;
return TRUE;
}
break;
}
}
return FALSE;
}
permanent BOOL p_fNoGrepReplaceMsg;//3.00A3 970507
static int _grep(TX *text,mchar *szpathBase,mchar *szfind,DWORD searchmode,GREPCONTEXT* context,mchar* szReplace)
{
//1.00H4 空白を含むパス内の検索ができなかったので修正
// textをクリア
text->fNomoveBase = TRUE;//2.94 970121
context->nfind = 0;
txDeleteText(text);
txJumpFileTop(text);
if (context->fEcho) statprintf(szworking);
//1.00C grepを中止できるようにした
HDIALOG hd = dialog("検索中");
dialogSetHookEx(hd,"\m.dlgprocGreping");
//1.00H4 検索中のファイル名を表示するようにした。
dialogControlStyle(hd,WS_CHILD|WS_VISIBLE|SS_CENTER);
dialogControlID(hd,IDD_SEARCHINFO);
dialogCaptionDynamic(hd,"",30);
dialogControlStyle(hd,0);
//
dialogSetPosLX(hd,10);
dialogCancel(hd,10);
//
_hdlg = dialogCreate(hd);
EnableWindow(text->hwndbase,FALSE);
// text->txmode |= TXMODE_SCROLLHIGH;//1.00F スクロールを真面目にやってると遅い
//
{
mchar *p = szpathBase;
while(*p) {
p = strGetWordTop(p);
int len = strGetWordLen(p);
mchar szitem[CCHPATHNAME];
if (len == 0) break;//1.01A "*.* "の様に最後にスペースを開けると\から検索してしまっていた
strcpylen(szitem,p,len);
p += len;
// パスを正規化
pathFormLong(szitem);
pathSetFull(szitem);
if (!pathIsWild(szitem) && pathDirExist(szitem)) {
// "a:\wz"のような指定がされた場合...
strcat(szitem,\"\*.*");
}
{//1.00C 検索パスを"a:\wz\*.c;*.h"の様に指定することができるようにした
mchar szpath[CCHPATHNAME];
mchar *szfile = pathGetFileName(szitem);
strcpy(szpath,szitem);
while(1) {
if (!AbortProc()) break;
mchar *p;
if (p = strchr(szfile,';')) {
*p = 0;
}
pathSetFileName(szpath,szfile);
greppath(szpath,szfind,searchmode,context,szReplace);
if (p) {
*p = ';';
szfile = p + 1;
} else {
break;
}
}
}
}
}
//1.00C
EnableWindow(text->hwndbase,TRUE);
if (_hdlg) {
dialogFree(_hdlg);
_hdlg = NULL;
}
// text->txmode &= ~TXMODE_SCROLLHIGH;//1.00F
//
txSetUndispSilent(text); //3.00C 971013 Silent
if (context->fEcho) {
txInsertReturn(text);
if (_fUserAbort) {
txInsertLine(text,"検索を中止しました。");
} else {
txInsertLine(text,"検索が終了しました。");
}
if (context->nfind) {
txInsertf(text," %d個 見つけました。",context->nfind);
if (szReplace) {//3.00A3 970507
if (!p_fNoGrepReplaceMsg) {
HDIALOG hd = dialog("WZ Grep 置換");
dialogCaption(hd,"置換を行うには、置換したい行にカーソルを合わせて、");
dialogCaption(hd,"{Shift}+{Enter}します。");
dialogCaption(hd,"置換すると直ちにファイルの内容を書き換えますので、");
dialogCaption(hd,"注意してください。");
dialogCheck(hd,"今後、このメッセージを表示しない",&p_fNoGrepReplaceMsg);
dialogLFV(hd);
//
dialogControlID(hd,IDOK);
dialogCmd(hd,"閉じる",12);
dialogHelp(hd,12,"wz.chp 507");
dialogOpen(hd);
}
}
} else {
txInsert(text," 見つかりませんでした。");
}
}
txJumpFileTop(text);
txSetDispSilent(text); //3.00C 971013 Silent
text->fEdit = FALSE;
text->fNomoveBase = FALSE;//2.94 970121
return context->nfind;
}
int TXAPI grep(TX *text,mchar *szpathBase,mchar *szfind,DWORD searchmode)
{
// 検索パス:szpath,検索文字列szfindで、grepします。
// 見つかったタグ数を返します。
// 結果は、textに次のように入ります。
// ファイル名(フルパス) 論理行番号,論理行頭からバイト数: 行内容[改行]
// 元のtextの内容は全部削除されます
//1.00H2 検索オプションは、searchmodeで指定するように仕様を変更しました。
GREPCONTEXT context;
structClear(context);
return _grep(text,szpathBase,szfind,searchmode,&context,NULL);
}
static BOOL editboxIsEmpty(HWND hctrl)
{
if (hctrl) {
mchar buff[CCHWORD];
GetWindowText(hctrl,buff,CCHWORD);
return !buff[0];
}
return TRUE;
}
BOOL dlgprocGrep(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message) {
case WM_INITDIALOG: {//3.00B1 970613
_fsetfontSearch = wndSetFontAsText(GetDlgItem(hwnd,IDD_SZFIND),textf);
_fsetfontReplace = wndSetFontAsText(GetDlgItem(hwnd,IDD_SZREPLACE),textf);
break;
}
case WM_DESTROY: {//3.00B1 970613
if (_fsetfontSearch) {
_fsetfontSearch = FALSE;
wndSetFontAsTextDelete(GetDlgItem(hwnd,IDD_SZFIND));
}
if (_fsetfontReplace) {
_fsetfontReplace = FALSE;
wndSetFontAsTextDelete(GetDlgItem(hwnd,IDD_SZREPLACE));
}
break;
}
case WM_COMMAND: {
int id = WM_COMMAND_GetId(wParam);
int notify = WM_COMMAND_GetNotify(wParam,lParam);
switch(id) {
case IDOK: {
if (editboxIsEmpty(GetDlgItem(hwnd,IDD_SZPATH))) {
attention("検索パスを指定してください");
return TRUE;
}
if (editboxIsEmpty(GetDlgItem(hwnd,IDD_SZFIND))) {
attention("検索文字列を指定してください");
return TRUE;
}
break;
}
}
return dlgprocSearch(hwnd,message,wParam,lParam);
break;
}
case WM_TXUSER: {
return dlgprocSearch(hwnd,message,wParam,lParam);
}
}
return FALSE;
}
typedef struct {
BOOL fSearchBinary; // バイナリファイルも検索?
BOOL fSearchDirectory; // サブディレクトリ内の検索?
BOOL fParaTop; // 論理行頭のみの検索?
BOOL fSearchBackup; //2.92 バックアップファイル、世代ファイルも検索?
} GREPOPTION;
static int dialogaGrep(BOOL fReplace,txstr szPath,txstr szFind,txstr szReplace,GREPOPTION* option)
{
TX* text = _textGrep;
//2.92 WZ Grep:検索パスは専用ヒストリに格納するようにした
static mchar _szhistid[] = "WZ Grep";
HSTRBLK sb = historyOpen(_szhistid,2048);
//
HDIALOG hd = dialogbig(fReplace ? "WZ Grep 置換" : "WZ Grep");
dialogSetHookEx(hd,"\m.dlgprocGrep");
dialogSetContexthelp(hd,TRUE);
static mchar szinikey[] = "WZ Grep";
dialogSetIniEx(hd,"wz.ini",szinikey); // wz.iniに保存
dialogSetGroupRight(hd,DTCX * 50);
//2.92
static mchar szinikeyMode[] = "検索モード";
TxProfile prof;
profWzIniNew(&prof,szinikey);
_searchopt.category = profReadInt(&prof,szinikeyMode,0);
static mchar szinikeyReplace[] = "置換";
profReadStr(&prof,szinikeyReplace,szReplace,cchtxstr(szReplace),"");
if (fReplace) {//2.92
dialogGroup(hd,"置換(&S)");
dialogControlIniKey(hd,"検索");
dialogControlHelp(hd,190);
dialogControlGuide(hd,"を",3);
dialogControlHistRead(hd,HIST_SEARCH);
dialogControlID(hd,IDD_SZFIND);
dialogStr(hd,NULL,szFind,0,42);
dialogControlIniKey(hd,"置換");
dialogControlHelp(hd,191);
dialogControlGuide(hd,"へ",3);
dialogControlHistRead(hd,HIST_SEARCH);
dialogControlID(hd,IDD_SZREPLACE);//2.00B
dialogStr(hd,NULL,szReplace,0,42);
dialogGroupEnd(hd);
} else {
dialogGroup(hd,"検索(&S)");
dialogControlIniKey(hd,"検索");
dialogControlHist(hd,HIST_SEARCH);
dialogControlHelp(hd,190);
dialogControlID(hd,IDD_SZFIND);
dialogStr(hd,NULL,szFind,0,46);
dialogSetFocus(hd,IDD_SZFIND);
dialogGroupEnd(hd);
}
dialogGroup(hd,"検索パス(&P)");
dialogControlHelp(hd,240);
dialogControlHist(hd,sb);
dialogControlRefer(hd,"-m *.*");
dialogControlID(hd,IDD_SZPATH);
dialogStr(hd,NULL,szPath,0,37);
#if 0//2.92
dialogCaption(hd,\"<例1> c:\wz\*.txt");
dialogCaption(hd,\"<例2> c:\wz\*.txt;*.log");
#endif
//
dialogControlHelp(hd,241);
dialogCheck(hd,"サブディレクトリも検索(&U)",&option->fSearchDirectory);
dialogGroupEnd(hd);
#if 1//3.00A2 970505
dialogSearchOption(hd,&_searchopt,fReplace ? SEARCH_REPLACE : 0);
#else
dialogSearchOption(hd,&_searchopt,fReplace ? SEARCH_REPLACE|REPLACE_CONFIRM : 0);
#endif
dialogGroup(hd,"オプション");
dialogControlHelp(hd,242);
//2.92 論理行の全てをサポート
dialogSelectIDB(hd,"見つけた内容の表示(&D):",&_context.modeDisp,24,20,"表示行の全て","表示行末まで","論理行の全て");
dialogControlHelp(hd,243);
dialogCheck(hd,"論理行頭のみを検索(&T)",&option->fParaTop);
dialogControlHelp(hd,244);
dialogCheck(hd,"バイナリファイルも検索(&B)",&option->fSearchBinary);
dialogControlHelp(hd,244);
dialogCheck(hd,"バックアップファイルも検索(&G)",&option->fSearchBackup);
dialogGroupEnd(hd);
//
int cx = 14;
dialogLFV(hd);
dialogOK(hd,cx);
dialogCancel(hd,cx);
dialogControlID(hd,IDD_REFERSEARCHLIST);
dialogControlHelp(hd,203);
dialogCmd(hd,"検索リスト(&L)...",cx);
if (fReplace) {
dialogControlID(hd,IDD_TOREPLACE);
dialogCmd(hd,"検索(&R) >>",cx);
} else {
#if 1//3.00A2 970505 Grep置換機能実装
dialogControlID(hd,IDD_TOREPLACE);
dialogCmd(hd,"置換(&R) >>",cx);
#else
#if 0//2.99F 970404 Grep置換機能は動作していなかったので、外した
dialogControlID(hd,IDD_TOREPLACE);
dialogCmd(hd,"置換(&R) >>",cx);
#endif
#endif
}
dialogSpaceV(hd);
#if 1//3.00A2 970505
if (fReplace) {
//3.00A3 970507 wz.chpヘルプ呼び出し簡素化
dialogHelp(hd,cx,"wz.chp 507");
} else {
dialogHelp(hd,cx,"wz 正規表現");
}
#else
dialogHelp(hd,cx,"wz 正規表現");
#endif
// load
dialogLoad(hd);
dialogSetLoad(hd,FALSE);
// cmdline
if (_cmdline_szpath != "") {
szPath = _cmdline_szpath;
_cmdline_szpath = "";//2.92 2回目以降は無効にする
}
if (_cmdline_szsearch != "") {
szFind = _cmdline_szsearch;
_cmdline_szsearch = "";//2.92 2回目以降は無効にする
}
if (_cmdline_fSearchDirectory) {
option->fSearchDirectory = TRUE;
_cmdline_fSearchDirectory = FALSE;//2.92 2回目以降は無効にする
}
// default
if (szPath == "") {
driveGetCurDir(0,szPath);
szPath += \"\*.*";
}
//2.99 970320 GrepダイアログではIMEの制御をしないようにした。
// つかいにくかった
text->fNoImeControl++;//2.99 970320
int id = dialogOpen(hd);
text->fNoImeControl--;//2.99 970320
//2.92
historyClose(_szhistid,sb);
if (id) {
profWriteInt(&prof,szinikeyMode,_searchopt.category);
profWriteStr(&prof,szinikeyReplace,szReplace);
}
profDelete(&prof);
//
return id;
}
//2.99C 970326 new
permanent txstr _szFindColoring;
permanent SEARCHMODE _searchmodeColoring;
mchar* gfc(SEARCHMODE* pSearchmode)
{
//2.99C 970326 new
*pSearchmode = _searchmodeColoring;
//statprintf(_szFindColoring);wait(100);
return (mchar*)_szFindColoring;
}
static BOOL _uiGrep(void)
{
TX* text = _textGrep;
txstr szPath(500);
static txstr szFind;
static txstr szReplace;
GREPOPTION option;
structClear(option);
int id = 0;
while(1) {
id = dialogaGrep(_fReplace,szPath,szFind,szReplace,&option);
if (id == IDD_TOREPLACE) {
_fReplace ^= 1;
} else {
break;
}
}
if (id) {
DWORD searchmode = searchmodeFromSearchopt(&_searchopt);
if (option.fParaTop) searchmode |= SEARCH_PARATOP;
if (option.fSearchBinary) searchmode |= GREP_BINARY;
if (option.fSearchDirectory) searchmode |= GREP_DIRECTORY;
if (option.fSearchBackup) searchmode |= GREP_BACKUP;
searchmode &= ~SEARCH_ALLTEXT;//1.01A
//
#ifdef __FLAT__
if (szPath[0] != '"') {
// ""で括る
szPath = "\"" + szPath + "\"";
}
#endif
//
text->fDispFindEnable = TRUE;//2.99C 970326 grepで検索文字色分けON
//2.99C 970326 grepの検索文字列色分けと、WZの検索文字列色分けを分離した
text->fDispFindGrep = TRUE;
_szFindColoring = szFind;
_searchmodeColoring = searchmode;
//
_context.fEcho = TRUE;
if (_fReplace) {
_grep(text,szPath,szFind,searchmode,&_context,szReplace);
} else {
_grep(text,szPath,szFind,searchmode,&_context,NULL);
}
txSave(text);//1.01A Grep:前回の結果を保存するようにした
//
return TRUE;
}
return FALSE;
}
uiGrep
{
BOOL ret = FALSE;
static BOOL _f = FALSE; // 再入防止
if (!_f) {
_f = TRUE;
ret = _uiGrep();
_f = FALSE;
}
return ret;
}
//##tag jump
static void getfilename(mchar szfilename[CCHPATHNAME],mchar* szline)
{
mchar*p = szline;
p += strGetCharSize(p);
int len = strGetWordLen(p);
strcpylen(szfilename,p,len);
pathFormLong(szfilename);
}
typedef struct {
mchar szfilename[CCHPATHNAME];
NPARA npara;
int lx;
//3.00A 970428
BOOL fAddress;
IFILE address;
} TAGANA;
static BOOL tagAnalyze(TAGANA* ana)
{
//2.99 970317 new
mchar szfilename[CCHPATHNAME] = {0};
txstr szline;
txGetLine(text,szline);
int npara = -1;
int lx = -1;
txstr szFind = text->tsztitle[0] + "\"";
structClear(*ana);//3.00A 970428
if (strmatch(szline,szFind)) {
//1.01A ●"ファイル名"の行にカーソルを置いてジャンプしたときは、そのファイルの1行目にジャンプするようにした
getfilename(szfilename,szline);
npara = 1;
} else if (strmatch(szline,"・")/*2.92*/) {
mchar* p = szline;
if (p[2] == 'a' && isdigit(p[3])) {
ana->fAddress = TRUE;
ana->address = atoi(&p[3]);
npara = 1;
lx = 0;
} else {
while(1) {
mchar c = *p;
if (c == 0) break;
if (isdigit(c)) {
if (npara == -1) {
p += strNum(p,&npara);
} else if (lx == -1) {
p += strNum(p,&lx);
break;
} else {
break;
}
} else {
p++;
}
}
}
txSetUndispExSilent(text);
if (txSearchEx(text,szFind,SEARCH_PREV|SEARCH_PARATOP)) {
txGetLine(text,szline);
getfilename(szfilename,szline);
}
txSetDispExSilent(text);
} else {//2.92
return FALSE;
}
//
if (npara == -1) {
//2.92
return FALSE;
}
//
if (lx == -1) lx = 0;
//information("[%s] %ld %d",szfilename,npara,lx);
strcpy(ana->szfilename,szfilename);
ana->npara = npara;
ana->lx = lx;
return TRUE;
}
//2.99 970317 renew
Jump
{
// WZ Grep形式のタグジャンプ
TAGANA ana;
if (tagAnalyze(&ana)) {
if (ana.fAddress) {//3.00A 970428
mchar sw[30];
sprintf(sw,"/k /Ja%ld /Yc",ana.address);
forkstd(ana.szfilename,sw);
return TRUE;
}
txJumpTagExec(text,ana.szfilename,ana.npara,ana.lx,NULL);
return TRUE;
}
return FALSE;
}
//##preview
//2.99 970317
static void previewClose(void)
{
if (_hwndPreview) {
DestroyWindow(_hwndPreview);
_hwndPreview = NULL;
if (_hwndPreviewPartition) {
DestroyWindow(_hwndPreviewPartition);
_hwndPreviewPartition = NULL;
}
//
_textGrep->txnMask = 0;
SendMessage(_textGrep->hwndbase,WM_TXFLUSHWINDOWSIZE,0,0);
}
}
preview
{
if (_hwndPreview) {
previewClose();
p_fPreview = FALSE;
} else {
_hwndPreview = CreateWindowEx(
#ifdef __FLAT__
(_fwin40 * WS_EX_CLIENTEDGE),
#else
0,
#endif
TXWS_SZCLASS,
NULL,
TXWS_TEXT|WS_VSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
_textGrep->hwndbase,
NULL,
_textGrep->hInstance,
NULL
);
if (_hwndPreview) {
_hwndPreviewPartition = CreateWindow(
TXPARTITION_SZCLASS,NULL,
WS_CHILDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
_textGrep->hwndbase,
NULL,
_textGrep->hInstance,
NULL
);
//
TX* text = (LPVOID)SendMessage(_hwndPreview,TXWM_GETTX,0,0);
text->hwndbase = _textGrep->hwndbase;
text->txnMask = TXNM_CONTROLTAB|TXNM_CONTROLF4;
text->fKcAuto = text->share->config.fKcAuto;//3.00B1 970612 Grepプレビューでもconfig.fKcAutoを参照
text->fSpaceLeft = _textGrep->fSpaceLeft;//3.00B2 970616
txOpenText(text);
//
_textGrep->txnMask = TXNM_CHANGENPARA|TXNM_CONTROLTAB;
SendMessage(_textGrep->hwndbase,WM_TXFLUSHWINDOWSIZE,0,0);
p_fPreview = TRUE;
text->fReadOnly = TRUE;//3.00B1 970612 Grepのプレビューウィンドウでfile.vzuiSaveするとGrep結果が上書きされたので、セーブできないようにした
}
}
}
static void previewFlush(TAGANA* ana,BOOL fAnaOk,BOOL fForce)
{
//3.00A2 970505 new
if (_hwndPreview) {
TX* text = (LPVOID)SendMessage(_hwndPreview,TXWM_GETTX,0,0);
if (text) {
if (fAnaOk) {
if (!fForce && !pathCmp(ana->szfilename,text->szfilename,NULL)) {
// 現在開いている
} else {
txClose(text);
txSetFileName(text,ana->szfilename);
txOpenText(text);
// read all for 排他制御
txSetUndispSilent(text);
txJumpFileEnd(text);
txSetDispSilent(text);
}
txSetUndispSilent(text);
if (ana->fAddress) {
txJumpAddress(text,ana->address);
} else {
txJumpNpara(text,ana->npara);
txRightBytes(text,ana->lx);
}
text->fDispFindEnable = TRUE;//2.99C 970326 プレビューで検索文字色分けON
text->fDispFindGrep = TRUE;//2.99C 970326
#if 0 //2.99C 970326 選択すると使いにくい
if (txRight(text)) {
txSelectEx(text,CLIP_MOUSE);
txLeft(text);
}
#endif
txSetDispSilent(text);
} else {
txClose(text);
txOpenText(text);
}
}
}
}
//##置換実行
//3.00A2 970505 new
static int replaceCur(TX* text,BOOL fSilent)
{
// カーソル行の置換を実行
// return IDYES:置換実行した IDNO:しなかった IDCANCEL:中止
BOOL ret = IDNO;
TAGANA ana;
if (tagAnalyze(&ana) && ana.fAddress) {
if (isopen(ana.szfilename)) {
information("%s はオープン中です。\n置換するには閉じてください",ana.szfilename);
return IDCANCEL;
}
txstr szline;
txGetPara(text,szline);
mchar* p = strchr(szline,'(');
if (p && toupper(p[-1]) == 'X') {
p = NULL;
if (!fSilent) information("既に置換したので、置換しません。");
}
if (p) {
p++;
int lchDelete1 = atoi(p);
p = strchr(p,',');
if (p) {
p++;
int lchFind = atoi(p);
p = strchr(p,',');
if (p) {
p++;
int lchReplace = atoi(p);
p = strchr(p,')');
if (p) {
int lchSepa = 4; // " -> "
p++;
if (strlen(p) == lchFind + lchSepa + lchReplace) {
txstr szFind;
txstr szReplace;
txstrcpylen(szFind,p,lchFind);
p += lchFind + lchSepa;
txstrcpylen(szReplace,p,lchReplace);
//information("%d %d %d %s %s",lchDelete1,lchFind,lchReplace,szFind,szReplace);
int d = 0;
BOOL fErr = FALSE;
{
TX* text = textopen(ana.szfilename);
if (text) {
txJumpAddress(text,ana.address);
if (lchDelete1) {
if (txCmpCur(text,szFind)) {
int lch = lchDelete1 - 1;
txDeleteBytes(text,lch);d = -lch;
} else {
fErr = TRUE;
information("Grep検索置換を行ってから、内容が変更されています。置換しません。");
}
}
if (!fErr) {
ret = IDYES;
txInsert(text,szReplace);d += strlen(szReplace);
//dialogaText(text,NULL);
txSave(text);
}
textclose(text);
}
}
if (!fErr) {
txSetUndisp(text);
NPARA npara = text->npara;
//
txJumpParaTop(text);
txSearchEx(text,"(",0);
txLeft(text);
txOverWriteChar(text,'x');
//
//information("d = %d",d);
while(1) {
if (!txNextPara(text)) break;
TAGANA ana;
if (tagAnalyze(&ana) && ana.fAddress) {
txJumpParaTop(text);
txRight(text);
mchar buff[20];
sprintf(buff,"a%lu",(long)ana.address + d);
txOverWrite(text,buff);
} else {
break;
}
}
//
txJumpNpara(text,npara);
// プレビューを更新
if (!fSilent) {
TAGANA ana;
BOOL f = tagAnalyze(&ana);
previewFlush(&ana,f,TRUE);
}
//
txSetDisp(text);
txSave(text);
}
}
}
}
}
}
}
return ret;
}
replace
{
if (text->fClip) {
int n = 0;
txWalkStart(text);
while(txIsWalking(text)) {
int ret = replaceCur(text,TRUE);
if (ret == IDCANCEL) break;
if (ret == IDYES) n++;
if (!txNextPara(text)) break;
}
txWalkEnd(text);
//
TAGANA ana;
BOOL f = tagAnalyze(&ana);
previewFlush(&ana,f,TRUE);
//
statprintf("%d個、置換しました",n);
} else {
if (replaceCur(text,FALSE)) {
txNextPara(text);
}
}
}
//##cmdline
static void pathAdd(txstr szpath,mchar *szsubdir,mchar *szfilename)
{
txstr szwk = text->szexedir;
szwk += szsubdir;
if (strlen(szsubdir)) szwk += "\\";
szwk += szfilename;
//
szpath += szwk;
szpath += " ";
}
static void cmdline(mchar *szCmdLine)
{
UCHAR *p = szCmdLine;
_cmdline_szpath = "";
_cmdline_szsearch = "";//1.00F
while(1) {
p = strGetWordTop(p);
if (*p == 0) break;
int len = strGetWordLen(p);
if (p[0] == '-' && p[1]) {
p += 2;
len -= 2;
switch(p[-1]) {
case 'f'://2.00E "-p"はまずいので"-f"を追加
case 'p': {
if (len) {
//2.00E grep.txe -f"パス"の様なパス指定の対策
mchar sz[CCHPATHNAME];
strcpylenmax(sz,p,len,CCHPATHNAME);
pathFormLong(sz);
_cmdline_szpath += sz + " ";
}
break;
}
case 's': {//1.00F 検索文字列の指定
if (len) {
mchar* q = p;
if (len >= 2 && q[0] == 0x0C && q[len - 1] == 0x0C) {
q++;
len -= 2;
}
txstrcpylen(_cmdline_szsearch,q,len);
}
break;
}
case 't': {//2.99D 970401 空白を含むときは""で括って指定する検索文字列の指定
txstrcpylen(_cmdline_szsearch,p,len);
pathFormLong(_cmdline_szsearch);
break;
}
case 'u': {
_cmdline_fSearchDirectory = TRUE;
break;
}
case 'w': {
if (p[0] == 'z') {
_cmdline_fSearchDirectory = TRUE;
pathAdd(_cmdline_szpath,"","*.txc");
pathAdd(_cmdline_szpath,"","*.c");
pathAdd(_cmdline_szpath,"","*.ci");
pathAdd(_cmdline_szpath,"","*.h");
}
break;
}
}
}
p += len;
}
}
uiAbout
{
ABOUTINFO info;
memset(&info,0,sizeof(info));
info.szicon = "iconWzGrep";
info.szappname = "WZ Grep";
info.szversion = "version " + VER_WZGREP;
info.szcopyright = "Copyright(c)1995-97 TY";
about(&info);
}
HOOKRESULT __wndprocbase(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
//2.99 970317 edit
if (textTarget != _textGrep) return FALSE;
switch(message) {
case WM_TXCOMMAND://3.00A2 970504
case WM_COMMAND: {
if (
_hwndPreviewPartition &&
WM_COMMAND_GetHwndCtrl(wParam,lParam) == _hwndPreviewPartition
) {
SendMessage(hwnd,WM_TXFLUSHWINDOWSIZE,0,0);
return TRUE;
}
switch(LOWORD(wParam)) {
case IDM_CMDLINE: {
cmdline((mchar*)lParam);
break;
}
case IDM_UIGREP: {
uiGrep();
break;
}
default: {
return HOOK_CONTINUE;
}
}
return HOOK_CAPTURE;
}
case WM_TXNOTIFY: {//2.99 970317
if (lParam == TXN_CHANGENPARA) {
#if 1//3.00A2 970505
TAGANA ana;
BOOL f = tagAnalyze(&ana);
previewFlush(&ana,f,FALSE);
#else
TAGANA ana;
BOOL f = tagAnalyze(&ana);
if (_hwndPreview) {
TX* text = (LPVOID)SendMessage(_hwndPreview,TXWM_GETTX,0,0);
if (text) {
if (f) {
if (!pathCmp(ana.szfilename,text->szfilename,NULL)) {
// 現在開いている
} else {
txClose(text);
txSetFileName(text,ana.szfilename);
txOpenText(text);
// read all for 排他制御
txSetUndispSilent(text);
txJumpFileEnd(text);
txSetDispSilent(text);
}
txSetUndispSilent(text);
if (ana.fAddress) {
txJumpAddress(text,ana.address);
} else {
txJumpNpara(text,ana.npara);
txRightBytes(text,ana.lx);
}
text->fDispFindEnable = TRUE;//2.99C 970326 プレビューで検索文字色分けON
text->fDispFindGrep = TRUE;//2.99C 970326
#if 0 //2.99C 970326 選択すると使いにくい
if (txRight(text)) {
txSelectEx(text,CLIP_MOUSE);
txLeft(text);
}
#endif
txSetDispSilent(text);
} else {
txClose(text);
txOpenText(text);
}
}
}
#endif
} else if (lParam == TXN_CONTROLTAB) {
if (wParam == _hwndPreview) {
SetFocus(_textGrep->hwndtext);
macroHookWndBaseReturn(TRUE);
return HOOK_CAPTURE;
} else if (wParam == _textGrep->hwndtext) {
SetFocus(_hwndPreview);
macroHookWndBaseReturn(TRUE);
return HOOK_CAPTURE;
}
} else if (lParam == TXN_CONTROLF4) {
if (wParam == _hwndPreview) {
previewClose();
macroHookWndBaseReturn(TRUE);
return HOOK_CAPTURE;
}
}
break;
}
case WM_TXWINDOWSIZE: {//2.99 970318
if (_hwndPreview) {
RECT* r = (RECT*)lParam;
int cx = rectCx(r);
int cy = rectCy(r);
//
int rate = p_ratePreview;
if (_hwndPreviewPartition) {
rate = SendMessage(_hwndPreviewPartition,WMPB_GETRATE,0,0);
if (rate < 0) {
SendMessage(_hwndPreviewPartition,WMPB_SETRATE,rate = p_ratePreview,0);
}
SendMessage(_hwndPreviewPartition,WMPB_SETRANGE,r->top,r->bottom);
}
if (rate < 10 || rate > 90) rate = DEFAULT_PREVIEW_RATE;
p_ratePreview = rate;
//
int cyPreview = (cy * (100-rate)) / 100;
r->bottom -= cyPreview;
int y = r->bottom;
MoveWindow(_hwndPreviewPartition,r->left,y,cx,5,TRUE);
y += 5;
cyPreview -= 5;
MoveWindow(_hwndPreview,r->left,y,cx,cyPreview,TRUE);
}
break;
}
case WM_TXCLOSE: {//2.99 970318
previewClose();
break;
}
}
return HOOK_CONTINUE;
}
BOOL __txeclosemulti(HWND hwndprev)
{
#if 1//3.00A2 970504
// コマンドラインを解釈させる for -fによるパス指定
SendMessage(hwndprev,WM_TXCOMMAND,IDM_CMDLINE,(LPARAM)text->szCmdLine);
// hwndprevをアクティブにする
PostMessage(hwndprev,WM_TXACTIVE,0,0);//3.00A2 970504
// Grepダイアログを出す
PostMessage(hwndprev,WM_TXCOMMAND,IDM_UIGREP,0);
return TRUE;
#else
// コマンドラインを解釈させる for -fによるパス指定
SendMessage(hwndprev,WM_COMMAND,IDM_CMDLINE,(LPARAM)text->szCmdLine);
// Grepダイアログを出す
PostMessage(hwndprev,WM_COMMAND,IDM_UIGREP,0);
return TRUE;
#endif
}
#if 1//2.99 970317
__txedelete
{
macroHookWndBaseFree();
}
#else
__new
{
//2.94 970121
macroHookWndBase();
}
__delete
{
//2.94 970121
macroHookWndBaseFree();
}
#endif
__txenew
{
_textGrep = text;
macroHookWndBase();//2.99 970317
SetWindowText(text->hwndbase,"WZ Grep");
text->fTXE = TRUE;
text->fNoFlushKey = TRUE;//2.00E WZ Grepで設定ダイアログを開いてOKすると{Enter}でタグジャンプができなくなった
text->fTxeStdKeyCustmize = TRUE;//2.94 970121
text->fTxeOpenHigh = TRUE;//2.94 970122
//2.00E2
text->fConfigstdTextdata = TRUE;
text->fConfigsavePrim = TRUE;
// "grep"または"テキストデータファイル"の設定がロードされる
mchar szfilename[CCHPATHNAME];
pathFullConfig(szfilename,"grep");
txSetFileName(text,szfilename);
searchmodeToSearchopt(text->searchmode,&_searchopt);
_searchopt.fCategory = (text->modeSearchDialog != 0);
//
text->width = MAXWIDTH;
text->fDispUnder = TRUE;
text->fSetWidthByWindow = FALSE;
text->fConfirmNewFile = FALSE;
text->modeWs = text->tmodeWs[0] = WS_DESTEXT;//2.98A 970311 Grepの幅が最大になった
strcpy(text->tsztitle[0],"."); //2.00E2
textSetProcessMode(text->hwndbase,WZPROCESS_EDITORLIKE);//1.01A WZ Grep:txSwitchWindowで切り替えられるようにした
text->fSaveWindowPos = TRUE;//3.00C1 971017 Grepでウィンドウの位置が保存されてなかった
//3.00A 970502 WZ Grepで設定ダイアログを開くと折り返し幅が現在の設定値と違う値が表示された
txConfigOp(text,TXCONFIGOP_EXTSETDISPSTYLE,0);
text->tmodeWidth[text->dispstylemode] = MODEWIDTH_DESIGNATE;
text->twidth[text->dispstylemode] = text->width;
//2.99 970317 WZ Grep:メニューを専用にした
strcpy(text->szMenu,"bartxe_GREP");
strcpy(text->szMenuMouseR,"右クリック_GREP");
//2.99C 970326
text->fDispFindEnable = TRUE;
text->fDispFindGrep = TRUE;
}
main
{
#key
.Jump [ENTER] [MouseL2]
.uiGrep [ESC]
.replace +{Enter}
#end
// 新規ファイルの確認をしない
text->fConfirmNewFile = FALSE;
txJumpFileTop(text);//1.00C
// command line
cmdline(text->szCmdLine);
PostMessage(text->hwndbase,WM_COMMAND,IDM_UIGREP,0);
//
if (p_fPreview) {//2.99 970318
preview();
}
}
txe
{
#WZKEY
// WZ Grepを起動します
#if 1//2.99D 970330 sw
macroFork("grep /i-");
#else
//2.94 970121 "/I"
macroFork("grep /I");
#endif
}
WORD at_cmdcheck(WZCMD wzcmd)
{
mchar* szcmd = wzcmdToSzcmd(wzcmd);
if (!szcmd) return 0;
if (!stricmp(szcmd,"\m.preview")) {
if (_hwndPreview) return MF_CHECKED;
}
return 0;
}