Last active
November 20, 2018 16:10
-
-
Save u27a4/e2097564770ee4ed7d16954d6c2ee132 to your computer and use it in GitHub Desktop.
ファイルツリー for WZ Editor (https://www.wzsoft.jp/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* .概要 | |
* WZ Editor にファイルツリーを追加するマクロ | |
* | |
* .使い方 | |
* フォルダをエディタにドラッグ&ドロップすると、ツールウィンドウにファイル一覧が表示されます。 | |
* ファイル一覧は右クリックメニューの設定から、ワイルドカードを使用してある程度カスタマイズできます。 | |
* | |
* .導入方法 | |
* このファイルをエディタ(管理者モード)で開き「メニュー > マクロ > プログラムの登録」を実行します。 | |
* プラグインはエディタ再起動後から有効化されます。 | |
* | |
* .動作環境 | |
* WZ Editor 9 / 10 | |
* | |
* filetree.c | |
* Copyright (c) 2018 u27a4 | |
* MIT License | |
* http://opensource.org/licenses/mit-license.php | |
**/ | |
#include <windows.h> | |
#include <text.h> | |
// プラグインの情報 | |
author: u27a4 | |
name: filetree | |
title: ファイルツリー | |
// 設定ダイアログの定義 | |
pretext { | |
.フォルダ設定 | |
FOLDER フォルダ(&F) str;histid=FOLDER;lcx=40;fit | |
MASK マスク(&K) str;histid=MASK;fit | |
DEMASK 除外マスク(&H) str;histid=DEMASK;fit | |
.表示設定 | |
FICON ファイルアイコン(&A) str;str=📄;histid=FICON;fit | |
DICON フォルダアイコン(&B) str;str=📁;histid=DICON;fit | |
} prefs_dialog; | |
// 右クリックメニューの定義 | |
pretext { | |
OK エディタで開く(&E) | |
NEWWND 新しいウィンドウで開く(&N) | |
EXPLOR エクスプローラで開く(&O) | |
RELOAD 更新(&R) | |
PREFS 設定(&S) | |
} popup_menu_items; | |
// ショートカットキーの定義 | |
pretext { | |
{Enter} OK | |
{F5} RELOAD | |
} shortcut_keys; | |
// ID_FLTREE: ツールウィンドウのId | |
// ID_FLTRCG: ツールコンフィグのId | |
static void OpenFileTree(); | |
// ファイル一覧を生成する | |
static void GetFiles(HTEXT filepaths, HTEXT filenames, HTEXT dir, CLM filter, CLM ignore, int depth, CLM dicon, CLM ficon) | |
{ | |
WIN32_FIND_DATA fd; | |
HTEXT curFilePaths = newtext(); | |
HTEXT curFileNames = newtext(); | |
// 指定ディレクトリ内のすべてのファイルを列挙していく | |
HANDLE h = filefindfirst(textprintf("%s\\*", dir), &fd); | |
if (h != INVALID_HANDLE_VALUE) | |
{ | |
do | |
{ | |
if (ffdisdotdir(&fd) != FALSE // カレントor親ディレクトリの除外 | |
|| fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN // 隠しファイルを除外 | |
|| fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) // システムファイルを除外 | |
{ | |
continue; | |
} | |
HTEXT filename = textprintf("%ws", fd.cFileName); | |
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
{ | |
for (int i = 0; i <= depth; i++) | |
{ | |
add(filenames, "."); | |
} | |
addf(filenames, "%cs %s\n", dicon, filename); | |
addf(filepaths, "%s\\%s\n", dir, filename); | |
// ディレクトリを再帰的に探索する | |
GetFiles(filepaths, filenames, textprintf("%s\\%s", dir, filename), filter, ignore, depth + 1, dicon, ficon); | |
} | |
else if (!filter || pathmasksmatch(filename, filter) // 検索パターンに一致するファイルを追加 | |
&& (!ignore || !pathmasksmatch(filename, ignore))) // 除外パターンに一致するファイルを除外 | |
{ | |
for (int i = 0; i <= depth; i++) | |
{ | |
add(curFileNames, "."); | |
} | |
addf(curFileNames, "%cs %s\n", ficon, filename); | |
addf(curFilePaths, "%s\\%s\n", dir, filename); | |
} | |
} while (filefindnext(h, &fd)); | |
addwhole(filenames, curFileNames); | |
addwhole(filepaths, curFilePaths); | |
filefindclose(h); | |
} | |
} | |
// 設定ダイアログを開く | |
static BOOL OpenPrefsDialog() | |
{ | |
BOOL result; | |
HTEXT cfg = cfgnew(ID_FLTRCG); | |
HTEXT args = newtext(); | |
args.cur = ID_FOLDER; | |
if (result = property(cfg, "ファイルツリー", dupstr(prefs_dialog), args)) | |
{ | |
idsetclm(cfg, ID_FILTER, cfg.clmfilter); | |
idsetclm(cfg, ID_IGNORE, cfg.clmignore); | |
idsetclm(cfg, ID_FOLDER, cfg.clmfolder); | |
} | |
return result; | |
} | |
// ビューフックプロシージャ | |
static BOOL ViewHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, HTEXT source) | |
{ | |
switch(message) | |
{ | |
case TWM_EVENT: | |
switch (wParam) | |
{ | |
// ファイルがダブルクリックされたらエディタで開く | |
case ID_MUSDKL: | |
jumppara(source.textpaths, getcurpara(source.textnames)); | |
if (fileisdir(source.textpaths) == FALSE) | |
{ | |
return PostMessage(hWnd, TWM_EVENT, ID_CMDNT, ID_OK); | |
} | |
break; | |
// フォルダドロップされたら一覧を更新 | |
case ID_DROP: | |
if (fileisdir((LPVOID)lParam)) | |
{ | |
HTEXT cfg = cfgnew(ID_FLTRCG); | |
idsetclm(cfg, ID_FOLDER, (LPVOID)lParam); | |
OpenFileTree(); | |
return TRUE; | |
} | |
break; | |
} | |
break; | |
case TWM_COMMAND: | |
// メニュー選択時の処理 | |
if (wParam == ID_CMENU) | |
{ | |
int cmd = selectmenu(dup(popup_menu_items)); | |
if (cmd) | |
{ | |
PostMessage(hWnd, TWM_EVENT, ID_CMDNT, cmd); | |
} | |
return TRUE; | |
} | |
break; | |
} | |
return FALSE; | |
} | |
// ツールフックプロシージャ | |
static BOOL ToolWindowHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, HTEXT source) | |
{ | |
HTEXT cfg; | |
switch (message) | |
{ | |
case TWM_NOTIFYCMD: | |
switch (wParam) | |
{ | |
case ID_OK: | |
case ID_NEWWND: | |
case ID_EXPLOR: | |
case ID_RELOAD: | |
case ID_PREFS: | |
return PostMessage(hWnd, TWM_COMMAND, wParam, 0); | |
} | |
break; | |
case TWM_COMMAND: | |
// 選択項目を取得できるようにしておく | |
jumppara(source.textpaths, getcurpara(source.textnames)); | |
switch (wParam) { | |
case ID_OPEN: | |
case ID_OK: | |
// 選択項目がファイルなら絞り込みを解除してエディタで開く | |
if (fileisdir(source.textpaths) == FALSE) | |
{ | |
source.textnames.v.clmfilter = NULL; | |
openfileeditor(source.textpaths, "-fhist(0) "); | |
} | |
break; | |
case ID_NEWWND: | |
// 選択項目がファイルなら絞り込みを解除してエディタで開く (SDI) | |
if (fileisdir(source.textpaths) == FALSE) | |
{ | |
source.textnames.v.clmfilter = NULL; | |
openfileeditor(source.textpaths, "-fhist(0) -sdi"); | |
} | |
break; | |
case ID_EXPLOR: | |
// 選択項目がファイルなら親ディレクトリをエクスプローラで開く | |
if (fileisdir(source.textpaths) == FALSE) | |
{ | |
HTEXT dir = dupstr(source.textpaths); | |
pathsetparent(dir); | |
shellopen(dir); | |
} | |
else | |
{ | |
shellopen(source.textpaths); | |
} | |
break; | |
case ID_PREFS: | |
// 設定を開く | |
if (OpenPrefsDialog()) | |
{ | |
PostMessage(hWnd, TWM_COMMAND, ID_RELOAD, 0); | |
} | |
break; | |
case ID_RELOAD: | |
// 最新の情報に更新 | |
cfg = cfgnew(ID_FLTRCG); | |
if (fileisdir(cfg.clmfolder)) | |
{ | |
HTEXT dir = dupclm(cfg.clmfolder); | |
pathsetdir(dir, FALSE); | |
delall(source.textnames); | |
delall(source.textpaths); | |
addf(source.textnames, ".%cs %s\n", cfg.clmdicon, pathgetfile(dir)); | |
addf(source.textpaths, "%s\n", dir); | |
GetFiles(source.textpaths, source.textnames, dir, cfg.clmfilter, cfg.clmignore, 1, cfg.clmdicon, cfg.clmficon); | |
jumptop(source.textnames); | |
jumptop(source.textpaths); | |
vcmdexec(source.textnames.v, ID_OLFL1); // 先頭ノードを開く | |
} | |
break; | |
case ID_CLOSE: | |
case ID_CANCEL: | |
PostMessage(hWnd, WM_CLOSE, 0, 0); | |
break; | |
} | |
break; | |
case WM_TIMER: | |
if (wParam == 101) { | |
// テキストの参照管理(?) | |
HTEXT text = getfocus(); | |
if (text && text != source.text) | |
{ | |
if (text.v.mode == 0 || text.v.mode == ID_EDITOR) | |
{ | |
delete(source.text); | |
source.text = NULL; | |
source.text = refer(text); | |
} | |
} | |
} | |
break; | |
case WM_DESTROY: | |
// テキスト削除 | |
delete(source.textpaths); | |
delete(source.textnames); | |
delete(source.text); | |
delete(source); | |
break; | |
} | |
return FALSE; | |
} | |
// エディタのフックプロシージャ | |
BOOL EditorHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, HTEXT source) | |
{ | |
switch (message) | |
{ | |
case TWM_EVENT: | |
switch (wParam) | |
{ | |
case ID_DROP: | |
if (fileisdir((LPVOID)lParam)) | |
{ | |
HTEXT cfg = cfgnew(ID_FLTRCG); | |
idsetclm(cfg, ID_FOLDER, (LPVOID)lParam); | |
OpenFileTree(); | |
return TRUE; | |
} | |
break; | |
} | |
break; | |
} | |
return FALSE; | |
} | |
// ファイルツリーウィンドウを生成する | |
static HWND CreateFileTree() | |
{ | |
HTEXT cfg = cfgnew(ID_FLTRCG); | |
// 引数のファイルパス末尾に '\' があれば除去 | |
HTEXT filepath = dupclm(cfg.clmfolder); | |
pathsetdir(filepath, FALSE); | |
// ツールウィンドウの生成とプロパティの設定 | |
HWND hWnd = wtoolnew(ID_FLTREE); | |
hWnd.clmtitle = "ファイル"; | |
hWnd.sbhorz = TRUE; | |
// ツリービューで使用するテキストの生成 | |
HTEXT source = refer(newtext()); | |
source.text = refer(getfocus()); | |
source.textnames = newtext(); | |
source.textpaths = newtext(); | |
// ツリービューの生成とショートカットの登録 | |
HWND hDialog = dialogpanenew(hWnd); | |
HVIEW view = vnew(source.textnames, hDialog, WS_VISIBLE | WS_TABSTOP | TWS_OLT | TWS_BORDER | WS_HSCROLL | WS_VSCROLL, WID1, 0); | |
jumptop(view.textkey); | |
add(view.textkey, shortcut_keys); | |
// フックプロシージャの登録 | |
vsethook(view, (WHOOKPROC)ViewHookProc, source); | |
wsethook(hWnd, (LPVOID)ToolWindowHookProc, source); | |
// 「標準」の色設定を反映 | |
HTEXT text = newtext(); | |
if (load(text,"wzcfg://idview.cfg")) | |
{ | |
msgjumpbody(text); | |
HTEXT msg = walkmsgs(text); | |
do | |
{ | |
if (!clmcmp(mhgetclm(msg, ID_TITLE), "標準")) | |
{ | |
HTEXT props = vpropget(view); | |
props.coltxt = msg.coltxt; | |
props.colbak = msg.colbak; | |
props.colsel = msg.colsel; | |
props.colbks = msg.colbks; | |
view.flush(); | |
break; | |
} | |
} while (!(msg = walkmsgs(text))); | |
} | |
// ファイル一覧を更新 | |
PostMessage(hWnd, TWM_COMMAND, ID_RELOAD, 0); | |
// 参照管理用のタイマー起動 | |
SetTimer(hWnd, 101, 100, 0); | |
return hWnd; | |
} | |
// ファイルツリーを開く | |
static void OpenFileTree() | |
{ | |
HWND hWnd = wtoolfind(ID_FLTREE); | |
if (hWnd) | |
{ | |
// 既存ウィンドウをポップアップしてリロード | |
hWnd.popup(); | |
PostMessage(hWnd, TWM_COMMAND, ID_RELOAD, 0); | |
} | |
else | |
{ | |
dialogopen(CreateFileTree()); | |
} | |
} | |
// プラグインがロードされたときに実行される | |
int plugin_editor(HWND hWnd) | |
{ | |
if (!wishook(hWnd, (LPVOID)EditorHookProc)) | |
{ | |
waddhook(hWnd, (LPVOID)EditorHookProc, NULL); | |
} | |
return 0; | |
} | |
filetree { | |
title: 「ファイルツリー」ツールをツールビューに表示します。 | |
tool: filetree | |
if (OpenPrefsDialog()) | |
{ | |
OpenFileTree(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment