WZエディタの作りかけ自作マクロ放置場

 非常に中途半端な作りかけマクロです。
 すべてWZ4.0以降用
 マクロを使用しての損害に対して当方は全く責任をとれません。ソースをよく読んで安全性を確認してから使用してください。

 一覧

HTMLファイルに直接書けない記号等をエスケープ(2003/04/30)

 HTMLファイルで使用すると都合が悪い記号などをエスケープされた形に変換。
例: > → >

使い方:「ツール」、「マクロを実行」から "htmlmarkesc.MarkEscape" 。
 範囲選択内のみ適用することも出来ます。

2003/04/30
 範囲内適用がかなりバグってたので修正。
//#HTMLマークエスケープ
//<>&"などを&lt;と言う形に変換

void MarkEscape(TX* text) {
	BOOL bSelect = FALSE;
	char hexh, hexl, c;
	int	CurPos;

	//カーソル位置保存
	CurPos = txGetAddress(text);

	if (txSelectGetMode(text)) {
		//選択範囲されていれば
		bSelect = TRUE;
		txWalkStart(text);
		txJumpAddress(text, txGetAddressSelectTop(text));
	} else {
		//先頭にカーソル移動
		txJumpPara(text,1);
	}

	//メインループ
	while(!txIsCurEof(text)) {
		if (bSelect && !txIsWalking(text)) break;
		switch (txReadChar(text)) {
			case '<':
				txDeletePrev(text);
				txInsert(text,"&lt;");
				break;
			case '>':
				txDeletePrev(text);
				txInsert(text,"&gt;");
				break;
			case '&':
				txDeletePrev(text);
				txInsert(text,"&amp;");
				break;
			case '"':
				txDeletePrev(text);
				txInsert(text,"&quot;");
				break;
		}
	}

	if (bSelect == TRUE) {
		//選択範囲ウォーク終了
		txWalkEnd(text);
	}

	//カーソル位置の復元
	txJumpAddress(text, CurPos);
}
お持ち帰り(HTMLファイルに直接書けない記号等をエスケープ)

拡張子が.cgiのファイルを強制的にEUCにする(2000/07/23)

 プラグインマクロに登録してください。
 拡張子が.cgiのファイルがSJISと判断されると、EUCからSJISへの文字コード変換をします。
 EUCが間違ってSJISと判断されるのを修正しますが、本当にSJISで書いていた場合文字化けします。
//#拡張子連動文字コード つくったひと:20000718
/*	内容
・拡張子に連動して漢字コード設定
*/
/*	履歴
20000718	
*/

#include "_idmcmd.h"
#include <windows.h>

void __pluginGetProperty(mchar* prop,txstr res) {
	if (!stricmp(prop,"name")) res =  "拡張子連動文字コード";
	if (!stricmp(prop,"author")) res =  "m.ohta";
	if (!stricmp(prop,"version")) res =  "0.01";
}


BOOL EUC2SJIS(TX* text) {
	//全部変換
	BOOL bChange = FALSE;
	txJumpFileTop(text);
	while(!txIsCurEof(text)) {
		unsigned char ch = txGetChar(text);
		if (ch == 0x8E) {
			txDeleteChar(text);
			txRight(text);
			bChange = TRUE;
			continue;
		}
		if (ch>=0xA1 && ch<=0xDE) {
			unsigned char c = ch & 0x7f;
			c = ((c - 0x21) >> 1) + 0x81;
			if (c > 0x9f) c += 0x40;
			txDeleteChar(text);
			txInsertChar(text,c);

			c = txGetChar(text);
			c = c & 0x7f;
			c += (ch & 1) ? 0x1f : 0x7d;
			if (c >= 0x7f) c++;
			txDeleteChar(text);
			txInsertChar(text,c);
			bChange = TRUE;
			continue;
		}
		txRight(text);
	}
	return bChange;
}

//起動時イベント
void __on_txFrameNew(TX* text) {
	char	*lc, *lcExt;
	lc = text->szfilename;
	while (*(++lc) != '¥0') {
		if (*lc == '.')
			lcExt = lc+1;
	}
	if (lcExt) {
		if (strcmp(lcExt, "cgi") == 0) {
			if (text->kcSave == KC_SJIS) {
				text->kcSave = KC_EUC;
				txSetUndispEx(text);
				txSetHigh(text);
				BOOL bChange = EUC2SJIS(text);
				txResetHigh(text);
				txSetDispEx(text);
				if (bChange) statprintf("SJISからEUCに変更してみました");
			}
		}
	}
}
お持ち帰り(拡張子が.cgiのファイルを強制的にEUCにする)

中括弧閉じる時インデント自動調整(2003/05/01)

 MSVCPPのエディタみたいになります。閉じ中括弧を書いたときソースをさかのぼって読み、対応する開き中括弧がある行と同じだけのインデントを閉じ中括弧の行に設定します。
 閉じ中括弧入力の判定が多少強引です。
 中括弧の対応はかなり簡易で改善の余地があります。厳密にやるととても大変だと思いますが。

2003/04/30
 ほぼ3年ぶりに奇跡的にバージョンアップしました。//のコメント行と文字列内を検索しないようにしました。#ifや/*〜*/は相変わらず引っかかります。
2003/12/10
 WZ5対応でバージョンアップ。WZ5でアウトライン表示時にマクロで高速編集モードを使うとアウトライン中のカーソル位置がどこにもいない状態になるようだ。
2003/12/12
 '#'を入力するとインデント削除。
 '#'で始まる行で改行するとそれ以前のインデント引き継ぎ。

//#VCPPのようなもの つくったひと:太田雅之 20000523
/*	内容
・中括弧を閉じるとインデントを自動調整
・開き中括弧+改行でインデント1つ増やす
*/
/*	履歴
20000524	開き中括弧改行でインデント(CMDEXからぱくり)
20000525	']'入力で動作しないようにした
20030430	'',""内、C++1行コメント内の'{'を認識しないようにした
20031210	0.04	
	・高速編集モードを外した(WZ5のアウトライン対応)
	・':'の後でもインデント
20031211	0.05
	・#を入力したらインデント削除
	・#から始まる行で改行したらそれ以前のインデントを引き継ぐ
*/

#include "_idmcmd.h"
#include <windows.h>

void __pluginGetProperty(mchar* prop,txstr res) {
	if (!stricmp(prop,"name")) res =  "MSVCPPっぽい中括弧";
	if (!stricmp(prop,"author")) res =  "m.ohta";
	if (!stricmp(prop,"version")) res =  "0.05";
}

//空白?
BOOL CheckSpace(TX* text) {
	if (txGetChar(text) == ' ' || txGetChar(text) == '¥t') {
		return TRUE;
	}
	return FALSE;
}



//コメント削除関係
int MoveNextChara(char *p) {
	//次の有効文字へ移動
	int r = 0;
	if (*p == '¥'') {
		//シングルクォートは1文字パス
		p++;r++;
		if (*p == '¥¥') {
			p++;r++;
		}
		p++;r++;
		if (*p != '¥'') {
			//なんか変だな
			return 1;
		}
		p++;r++;
		return r;
	}
	if (*p == '¥"') {
		p++;r++;
		while(*p) {
			if (*p == '¥"') {
				return r+1;
			}
			if (*p == '¥¥') {
				p++;r++;
			}
			p++;r++;
		}
	}
	return 1;
}
void CutComment(txstr buf) {
	//コメントをカットする
	char *p = buf;
	//"//"
	while (*p) {
		if (*p == '/' && *(p+1) == '/') {
			*p = '¥0';
			break;
		}
		p+=MoveNextChara(p);
	}
}


//閉じ括弧移動
void MoveBraket(TX* text) {
	int	BraketCount;

	txSetUndispEx(text);

	//カーソル以前に他の文字が書いてあるか調べる
	while (!txIsCurParaTop(text)) {
		txLeft(text);
		if (!CheckSpace(text)) {
			//前に文字があったためそのまま出力
			txSetDispEx(text);
			return;
		}
	}
	txRight(text);

	//対応する閉じ括弧がある行を検索
	BraketCount = 1;
	while (BraketCount>0) {
		if (!txPrevPara(text)) {
			txSetDispEx(text);
//			statprintf("開き括弧の数が足りません");
			return;
		}
		txstr buf;
		txGetPara(text, buf);
		CutComment(buf);
		char *p = buf;
		while(*p) {
			if (*p =='}') {
				BraketCount++;
			} else if (*p == '{') {
				BraketCount--;
				if (BraketCount == 0) {
					break;
				}
			}
			p+=MoveNextChara(p);
		}
	}

	//行頭の空白をチェック
	txJumpParaTop(text);
	char szSpace[254];
	int length = 0;
	while(CheckSpace(text)) {
		szSpace[length++] = txGetChar(text);
		txRight(text);
	}
	szSpace[length] = '¥0';
	txSetDispEx(text);

	//インデント操作
	while(!txIsCurParaTop(text)) {
		txLeft(text);
		txDeleteChar(text);
	}
	txInsert(text,szSpace);
	return;
}
void MoveSharp(TX* text) {
//'#'を入力したら行頭に持っていく
	txSetUndispEx(text);
	//カーソル以前に他の文字が書いてあるか調べる
	while (!txIsCurParaTop(text)) {
		txLeft(text);
		if (!CheckSpace(text)) {
			//前に文字があったためそのまま出力
			txSetDispEx(text);
			return;
		}
	}
	txSetDispEx(text);
	while(!txIsCurParaTop(text)) {
		txLeft(text);
		txDeleteChar(text);
	}
}


// C編集用インデント Enter
BOOL WriteReturnC (TX *text) {
	if (text->modeKeisen && txKeisenGetLeft(text)) return FALSE;
	if (!text->fOverWrite && txIsCurReturn(text)) {
		if (txGetPrevChar(text) == '{' || txGetPrevChar(text) == ':') {
			txWriteReturn(text);
			txWriteTab(text);
		} else {
			//プリプロセッサ行チェック
			txSetUndispEx(text);
			txJumpParaTop(text);
			if (txGetChar(text)!='#') {
				txSetDispEx(text);
				txWriteReturn(text);
				return;
			}
			while (txPrevPara(text)) {
				if (txGetChar(text)!='#') {
					//この行のインデントをコピー
					char szSpace[254];
					int length = 0;
					while(CheckSpace(text)) {
						szSpace[length++] = txGetChar(text);
						txRight(text);
					}
					szSpace[length] = '¥0';
					txSetDispEx(text);
					txWriteReturn(text);
					txInsert(text,szSpace);
					return;
				}
			}
			txSetDispEx(text);
			txWriteReturn(text);
		}
	} else {
		txWriteReturn(text);
	}
	return TRUE;
}

HOOKRESULT CALLBACK texthookMSVCPP(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) {
	TX* text = hwndtextGetText(hwnd);
	switch (message) {
		case WM_KEYDOWN: {
			if (wParam == 0xDD) {	//'}'
				if (GetAsyncKeyState(VK_SHIFT)<0) {
					MoveBraket(text);
					return HOOK_CAPTURE;
				}
			}
			if (wParam == 0x33) {	//'#'
				if (GetAsyncKeyState(VK_SHIFT)<0) {
					MoveSharp(text);
					return HOOK_CAPTURE;
				}
			}
			break;
		}
		case WM_TXEVENT: {
			if (wParam == TXEVENT_IDMEXEC && lParam == IDM_INSERTRETURN) {
				if (WriteReturnC(text)) {
					return HOOK_CAPTURE;
				}
			}
			break;
		}
	}
	return HOOK_CONTINUE;
}
void __on_txFrameNew(TX* text) {
	if (text->filekind == TEXT_C) {
		txSetHookWndproctextTxpcode(text,texthookMSVCPP);
	}
}
お持ち帰り(URLエンコード文字列をデコード/行入れ替え/カレント指定grep&filer呼び出し)

行を入れ替える(制作日:まあまあ古い)

 Emacs風キーバインドでの"Ctrl-T"は文字の入れ替えですが、これは行の入れ替えです。アセンブラのパイプライン調整なんかに威力を発揮する、かもしれません。
 "Ctrl-Shift-T"に割り当てると良い。
//#行を入れ替える
void LineExchange (TX* text) {
	txJumpLineTop(text);
	txSelectEx(text, CLIP_LINE);
	if (!txNextPara(text)) {
		txSelectQuit(text);
		return;
	}
	txPrivateClear(text);
	txPrivatePush(text);
	txSelectDelete(text);
	txSelectQuit(text);
	txPrevPara(text);
	txPrivatePaste(text);
	txNextPara(text);
}
お持ち帰り(URLエンコード文字列をデコード/行入れ替え/カレント指定grep&filer呼び出し)

カレントディレクトリを指定するシリーズ(制作日:ちょっと古い)

 WZのgrepやdird…じゃなくてファイラーはとっても便利、なのですが、カレントディレクトリが前回使用した位置になっています。とっても使いにくいと思うので現在開いているファイルのディレクトリにしてみました。
//##カレントディレクトリを指定するファイラー
void filer (TX *text) {
	char	currentdir[256] = "";
	char	*pc = currentdir;
	char	*pcExt = NULL;
	if (text->szfilename[0] != '¥0') {
		strcpy(currentdir, text->szfilename);
		while (*(pc+1) != '¥0') pc++;
		while (*pc != '¥¥') {
			if (*pc == '.') pcExt = pc+1;
			pc--;
		}
		*(++pc) = '*'; *(++pc) = '.';
#if 0
//マスクとして拡張子を送る
		if (pcExt) while (*pcExt != '¥0') *(++pc) = *(pcExt++);
#else
		*(++pc) = '*';
#endif
		*(pc+1) = '¥0';
		wzexec("/fWzFiler -f¥""+currentdir+"¥"");
	} else {
		wzexec("/fWzFiler");
	}
}
//##カレントディレクトリを指定するgrep
void grep (TX *text) {
	char	currentdir[256] = "";
	char	*pc = currentdir;
	char	*pcExt = NULL;
	strcpy(currentdir, text->szfilename);
	while (*pc != '¥0') pc++;
	pc--;
	while (*pc != '¥¥') {
		if (*pc == '.') pcExt = pc+1;
		pc--;
	}
	*(++pc) = '*';
	if (pcExt) {
		*(++pc) = '.';
		while (*pcExt != '¥0') *(++pc) = *(pcExt++);
	}
	*(pc+1) = '¥0';
	if (txIsClipInPara(text)) {
		txstr sz;
		txGetWord(text,sz);
		wzexec("/fWzGrep -s¥""+sz+"¥" -f¥""+currentdir+"¥"");
	} else {
		wzexec("/fWzGrep -f¥""+text->szfilename+"¥"");
	}
}
お持ち帰り(URLエンコード文字列をデコード/行入れ替え/カレント指定grep&filer呼び出し)

全角日付挿入(制作日:結構古い)

2000年5月25日(木)
 こんな感じ。
 HTMLファイルで使用するとH4タグで勝手に囲みます。気に入らなければソースを書き換えてください。HTMLファイルの判定が変ですね。
void FullLetter(TX *text, int num) {
	char szstr[] = "0123456789";
	insertchar(szstr[num*2]);
	insertchar(szstr[num*2+1]);
}
void FullDayOfWeek(TX *text, int i) {
	char szstr[] = "日月火水木金土";
	insertchar(szstr[i*2]);
	insertchar(szstr[i*2+1]);
}
void FullNumber(TX *text, int num) {
	int i, j = 0;

	i = 10000;
	while (i>0) {
		if (num>=i || j == 1) {
			FullLetter( text, num/i );
			j = 1;
		}
		num = num % i;
		i = i / 10;
	}
}

InsertDate {
//日記用の日付を挿入
//1997/12/28 Masayuki Ohta
	char	*lc, *lcExt;
	BOOL	bHtml;
	lc = text->szfilename;
	lcExt = NULL;
	while (*(++lc) != '¥0') {
		if (*lc == '.')
			lcExt = lc+1;
	}
	bHtml = FALSE;
	if (lcExt) {
		if (strcmp(lcExt, "html") == 0)
			bHtml = TRUE;
	}

	if (bHtml)
		Insertf("<H4>");
	FullNumber( text, timeGetYear() );
	Insertf("年");
	FullNumber( text, timeGetMonth() );
	Insertf("月");
	FullNumber( text, timeGetDay() );
	Insertf("日(");
	FullDayOfWeek( text, timeGetDayofWeek() );
	Insertf(")");
	if (bHtml)
		Insertf("</H4>");
	Insertf("¥n");
}
お持ち帰り(インクリメントナンバー/全角日付挿入)

インクリメントナンバー(制作日:かなり古い)

 クリップボードに入っているテキストの数値部分をインクリメントしてペースト。
 昔、配列に一括代入できない言語を使っていたとき、テーブルを作成するために作成したマクロ。最近は立派な『Cたすたす言語』しか使っていないから用なし。

 例:
	array[0] = 2;
 という行をコピーして、このincrementnumberコマンドでペーストすると以下のようになります。
	array[1] = 3;
	array[2] = 4;
	array[3] = 5;
	array[4] = 6;
	array[5] = 7;
 複数の数列があると、あるだけ増やしちゃいます。
//インクリメントナンバー
//内容・クリップボードにあるテキストの数値をインクリメントしてペースト
//1997/11/29 Masayuki Ohta

///#include <_wz.h>

void IncNumLine(tx *text) {
	int mode;
	txJumpParaEnd(text);	//行末に移動
	mode = 0;
	while (1) {
		left;
		IBUFF str=GetChar;
//		printf("%d¥n",str);
		if (str != '.') {
			if (str >= '0' && str <= '9') {
				if (mode < 2) {
					if (str == '9') {
						str = '0';
						mode = 1;
					} else {
						str += 1;
						mode = 2;
					}
					//書き込み
					DeleteChar;
					InsertChar(str);
					left;
				}
			} else {
				if (mode == 1) {
					right;
					InsertChar('1');
					left;
					left;
				}
				mode = 0;
			}
		}
		if (IsCurParaTop) break;
	}
}

void IncNumLoop (tx *text) {
	jumpfiletop;	//
	while (1) {
		if (IsCurReturn==0) {
			IncNumLine(text);
		}
		if (!nextpara) break;
	}
}

incrementnumber(TX *text) {
//##incrementnumber
//インクリメントナンバー
//内容・クリップボードにあるテキストの数値をインクリメントしてペースト
//1997/11/29 Masayuki Ohta
//20000525	選択されていたら削除

	if (txSelectGetMode(text)) {
		//選択範囲されていれば
		txSelectDelete(text);
	}

	TX	text2;
	txInitText(&text2);
	txOpenText(&text2);
	txPaste(&text2);

	IncNumLoop(&text2);

	txSelectAll(&text2);
	txInsertTextSelect(text, &text2);

	txSelectAll(&text2);
	txSelectCopy(&text2);
	txClose(&text2);
}
お持ち帰り(インクリメントナンバー/全角日付挿入)
mailto: ohta1999@hotmail.com
Last update: 2003/12/12