2. サンプルプログラム集
サンプルプログラムは、拡張子が.txcのファイルに作成してください。ファイルは任意のフォルダに作成できます。
1つのファイルに複数のマクロコマンドを作成できます。サンプルプログラムはsample.txcというファイルを作成して、すべてのサンプルコマンドを入力します。
旧WZ EDITORのTX-Cでは、プログラムのフォルダはマクロパスに固定でしたが、Text-Cではこの制限はなくなりました。
プログラムは「wzcfg://textc\mine」フォルダに置くことを推奨します。初めにWZ6のファイラーを起動して準備をおこないます。
-
WZ6を起動。
[ツール]-[Textc Filer]を実行して「Textc Filer」を起動。
[ツール]-[パス入力]を実行し、「wzcfg://textc」を入力して[Enter]キーを押す。
「mine」フォルダがなければ、[ファイル]-[フォルダの新規作成]を実行して「mine」フォルダを作成。
一覧から「mine」を選択して[Enter]キーを押す。
プログラムファイルを作成するには、次の操作をおこないます。
-
[ツール]-[Textc Filer]を実行して「Textc Filer」を起動。
[ツール]-[パス入力]を実行し、「wzcfg://textc\mine」を入力して[Enter]キーを押す。
[ファイル]-[新規作成]を実行し、ファイル名を入力してファイルを作成。
一覧から作成したファイルを選択して[Enter]キーを押す。WZ6でファイルが開かれ編集できます。
テキストに連番を振る
WZでsample.txcを開いて、以下のプログラムを入力して上書き保存します。
マクロを実行するには、次の操作をおこないます。
-
sample.txcを開いて[マクロ]メニューから[実行]を実行。
「プログラムの実行」ダイアログで、「renban」と「テキスト全体の各行に連番を振ります」の表示を確認。
OKを押し実行。
sample.txcのプログラムに連番が振られます。
他のテキストに連番を振るには、次の操作をおこないます。
-
テキストを開いて、[マクロ]メニューから[最近使ったプログラム]を実行。
一覧から「renban@C:\...\sample.txc」を選択。
OKを押し実行。
現在のテキストに対して連番が実行されます。
一覧の「C:\...\sample.txc"」を選んでOKすると、「プログラムの実行」と同じダイアログが表示されて、sample.txc内のコマンドを選んで実行できます。
プログラムの説明
このプログラムの名前(コマンド名)はrenbanです。名前には半角の英数字と_(アンダーバー)を組み合わせて好きな名前を付けられます。英字の大文字と小文字は区別されます。
title:に続けてコマンドの説明を書いておくと「プログラムの実行」ダイアログで説明が表示されます。説明は1行で書きます。
HTEXT textは、テキスト型(HTEXT)の変数textの使用を宣言しています。getfocus()はWZで用意しているAPIで、現在カーソルがあるテキストを返します。textにgetfocus()の返り値を代入しています。
int iは、整数型(int)の変数iを宣言し、初期値に1を代入しています。
walk(text) {...}は、textの現在位置を先頭から終わりまで1段落ずつ移動しながら{...}内を処理する記述です。
addf(text,"%d: ",i)は、textの現在位置にiを文字列に変えて": "を追加する記述です。
renban {
title: テキスト全体の各行に連番を振ります
HTEXT text = getfocus(); // 対象のテキストを取得します。
int i = 1; // 番号の初期値を1とします。
walk(text) { // テキストの現在位置を、先頭から終わりまで1段落ずつ移動します。
addf(text,"%d: ",i); // 段落の先頭部分に番号を挿入します。
i++; // 番号を1つ増やします。
}
}
日付を挿入する
sample.txcをWZで開いて、renbanプログラムの後ろに以下のプログラムを入力して、上書き保存します。
これ以降のサンプルも同様に、sample.txcの後ろに追加入力して上書き保存してください。
このプログラムではWindowsAPIを使います。sample.txcの先頭部分に以下のinclude文を記述してください。
この記述がないと、WindowsAPIを使ったプログラムはエラーになります。
#include <windows.h>
#include <text.h>
この記述は、プログラムの先頭部分で1回だけおこないます。
GetLocalTime(&st)で、変数stに今日の日付を取得しています。年はst.wYear,月はst.wMonth,日はst.wDayに取得されます。
addfでテキストに追加しています。"%04d"は4桁で数値を文字列に変換する指定です。4桁に満たない場合は0を補って4桁にします。"%02d"は2桁で変換する指定です。
text.v.getcur();は、textの現在位置にカーソルを動かす記述です。この記述がないと、日付を挿入してもカーソル位置が変わりません。
insert_date {
title: カーソル位置に現在の日付を挿入します。
HTEXT text = getfocus();
SYSTEMTIME st;
GetLocalTime(&st); // 今の日付を取得するWindowsAPIを呼び出しています。
addf(text,"%04d/%02d/%02d",st.wYear,st.wMonth,st.wDay);
text.v.getcur();
}
ダイアログを表示する(1)
dlgtextは、テキストの内容をダイアログボックスで表示します。
ダイアログボックスでテキストを編集すると、元のテキストにも反映されます。
dialog1 {
title: テキストをダイアログで表示します。
HTEXT text = getfocus();
dlgtext(text);
}
ダイアログを表示する(2)
text.vはテキストのビューハンドルを取得しています。ビューハンドルは、テキストの内容を表示するウィンドウです。HVIEW型の変数vに代入しています。
dlgnewは、ダイアログボックスを作成するAPIです。返り値はテキストなので、HTEXTのdlgに代入しています。
vnewcmdbarは、ダイアログにOKとキャンセルボタンを追加します。
vnewは、ダイアログにtextを表示するビューを作成します。TWS_LISTで、リストボックス表示を指定しています。TWS_EDITORの指定に変更すると、エディトボックスで表示できます。
同一のテキストに対して複数のビューを作成できます。それぞれのビューは同じ内容を表示します。ビューでテキストの内容を編集すると、他のビューにも編集内容が反映されます。
dlg.doは、ダイアログを表示し、OKかキャンセルされるまでループします。キャンセルされたら0、OKされたら0以外の値を返します。
v.getcur()で、リストボックスで選択した位置にカーソルをセットします。
dialog2 {
title: テキストをリストボックスで表示します。
HTEXT text = getfocus();
HVIEW v = text.v;
HTEXT dlg = dlgnew("リストボックス");// ダイアログを作成
vnewcmdbar(dlg.w);// ダイアログにOKとキャンセルボタンを追加
vnew(text,dlg.w,WS_VISIBLE|WS_TABSTOP|WS_HSCROLL|WS_VSCROLL|TWS_BORDER|TWS_LIST,WID1,0);// ダイアログにテキストをリストボックスで表示
if (dlg.do()) {// ダイアログを表示しOKかキャンセルされるまで待つ。
v.getcur();// OKされたら現在位置を設定
}
}
カーソル位置の単語で辞書ファイルを引く
getword(text)は、textのカーソル位置から単語を取得して、新規作成したテキストハンドルに単語を挿入します。
テキストが返されますので、wordに代入しています。
new()は、新規作成したテキストハンドルを返すので、これをdicに代入しています。
loadは、ファイルの内容をテキストにロードします。
searchは、テキストから語句を検索します。wordの現在段落の文字列で検索します。
statprintfは、ステータスウィンドウに指定された文字を表示します。
"%s"はwordの現在段落の内容を文字列で表示する指定です。
dlgtextは、テキストの内容をダイアログボックスで表示します。
find_dic {
title: カーソル位置の単語で辞書(text.h)を引きます
HTEXT text = getfocus();
HTEXT word = getword(text);// textの現在位置から単語を取得します。
if (word) {// 単語が取得できた場合。
HTEXT dic = new();// 新しくテキストを作成します(dic)。
load(dic,"wz://text.h");// dicにWZフォルダのtext.hをロードします。
if (search(dic,word,SEARCH_ALL)) {// dicから取得した単語を検索します。
statprintf("%sを見つけました",word);
} else {
statprintf("%sは見つかりません",word);
}
dlgtext(dic);// dicをダイアログで表示します。
}
}
メニューを表示
pretext{...} szmenuは、{}内の文字列をテキストデータとして変数szmenuに代入します。
HTEXT menu = dup(szmenu);は、メニューのテキストデータを作成してmenuに代入します。
メニューは1段落に1つのコマンドを記述します。「コマンドID」「タブ」「説明」「改行」の書式で記述します。
コマンドIDは6文字までの英数字が使えます。大文字と小文字は区別されず同一として扱われます。これを識別値と呼びます。
selectmenuで、メニュー選択をおこないます。選択されたメニューコマンドIDが返されます。
switchで分岐処理をします。コマンドIDはプログラム中では、頭にID_を付けて大文字で記述します。
inputlinetextは1行の入力ダイアログを表示します。行番号の入力を求めて結果がlineというテキストに入力されます。
atoi(getdata(line))は、lineに文字列として入力された行番号を整数値に変換します。getdata(line)は、lineに入っているテキストデータをCの文字列として返します。
pretext {
PARA<タブ>段落(&P)...
DIC<タブ>辞書を引く(&D)
TOP<タブ>先頭(&T)
END<タブ>末尾(&E)
} szmenu;
// <タブ>はタブ文字(文字コード0x09)で置き換えてください。
menu_jump {
title: ジャンプメニューを表示します。
HTEXT text = getfocus();
HTEXT menu = dup(szmenu);
switch(selectmenu(menu)) {
case ID_PARA: {
HTEXT line = new();
if (inputlinetext("段落へジャンプ","行番号",line)) {
int npara = atoi(getdata(line));
jumppara(text,npara);text.v.getcur();
}
break;
}
case ID_TOP: jumptop(text);text.v.getcur();break;
case ID_END: jumpend(text);text.v.getcur();break;
case ID_DIC: find_dic();break;
}
}
メニューコマンド「ジャンプ」のフック
プラグインで、WZの標準のコマンドの動作を変更できます。
プラグインは登録が必要です。作者名(author)と、プログラムの名前(name)を指定します。
sample.txcに下記のプログラムを追加して、[マクロ]メニューから[&(admin)プログラムの登録]を実行すると、プラグインとして登録されます。
-
「WZフォルダ\textc\author」フォルダにnameの名前としてプログラムが追加されます。
プラグインの一覧に\\author\nameとして登録されます。
登録後、新しく開いたファイルから、プログラムが有効になります。
プラグインは1つのプログラムファイルに1つ作成できます。複数のプラグインは、それぞれ別のファイルに作成してください。
case ID_JUMPの部分でフックしています。case文を増やして他のコマンドもフックできます。
author: mine
name: jumphook.txc
title: ジャンプメニューのフック
BOOL vhookproc(HWND w,UINT message,WPARAM wParam,LPARAM lParam,LPVOID arg)
{
switch(message) {
case TWM_COMMAND: {
HVIEW v = w.v;// 対象になるビュー
HTEXT text = v.text;// 対象になるテキスト
vcmdpre(v);
BOOL ret = FALSE;
switch(wParam) {
case ID_JUMP: {
menu_jump();
ret = TRUE;
break;
}
}
vcmdpost(v,ret?wParam:0);
return ret;// 0(FALSE)以外を返すと標準のコマンド処理はスキップされます。
}
}
return FALSE;
}
int plugin_editor(HWND w)
{
// EDITORのVIEWが作成されたときに呼ばれます。
if (!wishook(w,vhookproc)) {
waddhook(w,vhookproc,0);
}
return 0;
}
大文字小文字変換
ch = getcurchar(text);は、カーソル位置の1文字を読み取って、文字を整数値でchに代入します。
if (isalpha(ch)) {...}は、chが半角英字なら{}内を実行します。
IFILE adr = getadr(text);は、テキストの現在位置のアドレスをadrに代入します。アドレスはテキストの先頭が0、末尾がテキストのサイズになります。テキストの現在位置の先頭からのバイト数を示します。原則として半角文字は1バイト、全角文字は2バイトです。
BOOL fup = isupper(ch);はchが英大文字ならTRUE(0以外の値)、英大文字以外はFALSE(0)をfupに代入します。
do {...} while(isalpha(ch));は、{...}内を一度実行し、isalpha(ch)がTRUEなら再度{...}内を実行します。isalpha(ch)がFALSEなら処理を終えて次の行へ移動します。
addchar(res,fup ? tolower(ch) : toupper(ch));は、fupがTRUEならtolower(ch)でchを小文字に変換し、FALSEならtoupper(ch)で大文字に変換し、resに文字として追加します。rightchar(text)は、カーソルを1文字進めます。
jumpadr(text,adr);は、カーソルを最初の場所に戻します。
del(text,adr1-adr);は、変換前の文字列を削除します。
insert(text,res);は、変換結果を挿入します。
upper_lower {
title: カーソル位置の英単語の大文字・小文字を切り替えます。
HTEXT text = getfocus();
int ch = getcurchar(text);
if (isalpha(ch)) {
IFILE adr = getadr(text);
BOOL fup = isupper(ch);
HTEXT res = new();
do {
addchar(res,fup ? tolower(ch) : toupper(ch));
rightchar(text);ch = getcurchar(text);
} while(isalpha(ch));
IFILE adr1 = getadr(text);
jumpadr(text,adr);del(text,adr1-adr);
insert(text,res);
}
}
半角全角変換
kind = charkind(getcurchar(text));は、テキストのカーソル位置の文字の文字種をkindに代入します。全角英数字はID_ZALNUM、半角英数字はID_ALNUMを代入します。
insertarea(res,text,adr,adr1);は、resに、textのテキストアドレスadrからadr1の範囲の文字列を挿入します。
insert(text,zen_to_han(res));は、textに、resの内容を半角に変更した文字列を挿入します。
insert(text,han_to_zen(res));は、textに、resの内容を全角に変更した文字列を挿入します。
zen_han {
title: カーソル位置の英単語や数字の全角・半角を切り替えます。
HTEXT text = getfocus();
int kind = charkind(getcurchar(text));
if (kind==ID_ZALNUM || kind==ID_ALNUM) {
IFILE adr = getadr(text);
BOOL fzen = (kind==ID_ZALNUM);
do {
rightchar(text);
kind = charkind(getcurchar(text));
} while(kind==ID_ZALNUM || kind==ID_ALNUM);
IFILE adr1 = getadr(text);
HTEXT res = new();
insertarea(res,text,adr,adr1);
jumpadr(text,adr);del(text,adr1-adr);
if (fzen) {
insert(text,zen_to_han(res));
} else {
insert(text,han_to_zen(res));
}
}
}
プロパティを使った定形入力(日記)
pretext{...}は、プロパティを定義します。プロパティを使うと定型入力ができます。1段落に1項目を定義し、項目は「項目ID」「タブ」「名称」「タブ」「種類(strなら文字列)」と、「;」に続けてオプションを指定できます。「;」に続けて「str=文字列,文字列」を指定すると、ドロップダウンリストに表示する規定値を登録できます。項目IDは識別値(6文字までの英数字)で指定します。
テキストcfgに入力の初期値を定義します。idsetfで、cfgのID_DATE項目の初期値を今日の日付にセットします。
propertyで、プロパティ入力を実行します。入力結果はcfgにセットされます。
addf(text,"...%cs\n",cfg.clmdate);は、"..."とcfgのID_DATE項目の内容をtextに追加します。cfgの文字列プロパティの内容を追加するには、"%cs"を指定してcfg.clmに続けて項目IDを記述します。
cfgの整数値プロパティの内容を追加するには、addf(text,"%d\n",cfg.int);を記述します。
プログラム中のバックスラッシュ \ は半角円記号 \ です。
pretext {
DATE<タブ>日付<タブ>str
TENKI<タブ>天気<タブ>str;str=晴れ,曇り,雨,雪
} prop_date;
// <タブ>はタブ文字(文字コード0x09)で置き換えてください。
template_date {
title: カーソル位置に今日の日付で見出しを作成し、天気などを定形入力します。
HTEXT text = getfocus();
HTEXT cfg = new();
SYSTEMTIME st;GetLocalTime(&st);
idsetf(cfg,ID_DATE,"%04d/%02d/%02d",st.wYear,st.wMonth,st.wDay);
if (property(cfg,"日記",prop_date,0)) {
jumpparatop(text);
insertlf(text);
addf(text,"...%cs\n",cfg.clmdate);
addf(text,"天候: %cs\n",cfg.clmtenki);
insertlf(text);
text.v.getcur();
}
}
住所録
テキストファイルの住所録編集をおこなうプログラムです。
住所録は、1つの住所録データを1段落で表現し、「名前」「住所」「電話」「E-Mail」の各項目をタブ区切りで順に並べる形式です。
このプログラムでは段落の住所録データを読み取り、ダイアログで項目の内容を変更して段落データを書き換えます。
改行して新しい行を作成してプログラムを実行すると、新しい住所録データを追加できます。
テキストファイルの住所録は、「タブ区切りテキスト」文書スタイルで、それぞれの項目の桁を揃えて見やすく表示します。
WZの検索や絞込み機能で、データの検索も可能です。
pretext {
NAME<タブ>名前<タブ>str
ADR<タブ>住所<タブ>str;str=東京都
TEL<タブ>電話<タブ>str
EMAIL<タブ>E-Mail<タブ>str
} prop_adrbook;
// <タブ>はタブ文字(文字コード0x09)で置き換えてください。
adrbook {
title: 住所録:カーソル位置のレコードの内容を変更します。
HTEXT text = getfocus();
HTEXT cfg = new();
idsetclm(cfg,ID_NAME,iclmget(text,1));
idsetclm(cfg,ID_ADR,iclmget(text,2));
idsetclm(cfg,ID_TEL,iclmget(text,3));
idsetclm(cfg,ID_EMAIL,iclmget(text,4));
if (property(cfg,"住所録の編集",prop_adrbook,0)) {
iclmset(text,1,cfg.clmname);
iclmset(text,2,cfg.clmadr);
iclmset(text,3,cfg.clmtel);
iclmset(text,4,cfg.clmemail);
}
}