拡張構文
walk文
テキストの先頭から末尾までを、段落ごとに処理するプログラムは、for文と3つのAPIで記述します。
for (jumptop(text);!iscureof(text);jumpnextpara(text)) {
printf("%s\n",text);// 段落毎の処理
}
walk文では、同じ処理が簡潔に記述できます。
walk(text) {
printf("%s\n",text);// 段落毎の処理
}
textのビューの選択段落を、処理する記述も可能です。
選択されていない時は、カーソル行の段落が処理されます。
walk(text;select) {// walk(text.v;select)とも記述できます。
printf("%s\n",text);// 選択段落の処理
}
walkのブロックでは、breakとcontinue文に対応しています。
break文で、walkのブロックを抜けます。continue文で、次の段落の処理へ進みます。
文字単位の処理の記述も可能です。
walk(text;char) {
int c = getcurchar(text);
}
- walkのブロックでは、カーソル位置を移動できません。無限ループになる可能性があります。
- walk文には副作用があり、プログラムが意図通りに動作しない場合があります。
この場合はfor文を用います。
- walkのブロックでは、returnやgoto文に対応していません。
pretext文と文字列
pretext文は、プログラムにテキストデータを記述します。
pretext {
NEW<タブ>新規作成(&N)
--
REPLY<タブ>返信(&C)
RPLFRM<タブ>差出人へメール(&M)
FWARD<タブ>転送(&W)
} menu_main;
// <タブ>はタブ文字(文字コード0x09)で置き換えて入力
char*型の変数menu_mainに、テキストデータがセットされます。
- pretext文は、関数定義の外部で記述します。
- pretextと { は、同じ段落に記述します。次行から行頭の } までが、テキストデータとなります。
「\\"文字列"」の構文による、関数内部でのテキストデータの記述には、WZ6.0.62から対応しました。
\\" から行頭の " までに、テキストデータを記述します。
func {
int a = 10;
mchar* szstring = \\"
NEW<タブ>新規作成(&N)
--
REPLY<タブ>返信(&C)
RPLFRM<タブ>差出人へメール(&M)
FWARD<タブ>転送(&W)
";
information("%d\n%s",a,szstring);
}
「\"文字列"」の構文で、\ 文字を含む文字列を記述できます。
フルパスのファイル名が、記述しやすくなります。
mchar* szstring = \"c:\text\main.c";
printf文
printf文の実行結果は、C言語では標準出力に出力されますが、Text-Cではステータスウィンドウに出力されます。
- ステータスウィンドウは、WZ画面の下部に表示されるテキストボックスです。
- ステータスウィンドウを表示するには、[ウィンドウ]メニューの[ツールビューへ]を実行します。
- iprintf文は、ステータスウィンドウへの出力と、ステータスウィンドウの表示をONにします。
- textprintf文は、新規作成したテキストに結果を出力して返します。
printf,iprintf,textprintfでは、各種の数値や文字列の書式に対応しています。
%d | 数値を表示 |
%.d | 数値の1/10を表示 |
%..d | 数値の1/100を表示 |
%id | 数値を小文字の識別値で表示 |
%ID | 数値を大文字の識別値で表示 |
%u | 符号無しの数値を表示 |
%x | 16進数の小文字で表示 |
%X | 16進数の大文字で表示 |
%zd | 数値をatozで変換して表示(36進) |
%e | double数値を「xxx e xxx」形式で表示 |
%f | double数値を「xxx.xxx」形式で表示 |
%p | ポインタを表示 |
%/ | \を表示 |
%% | %を表示 |
%c | 文字を小文字で表示 |
%C | 文字を大文字で表示 |
%s | 文字列(STR)を表示 |
%cs | カラム文字列(CLM)を表示 |
%ns | 文字列を文字数まで表示 (例) printf("%ns","abcd",2)は「ab」を表示 |
%ws | UNICODE文字を表示 |
%es | 文字列をエンコードして表示 |
%m | (MESSAGEID*)を表示 |
%t | (UTCFILETIME*)を表示 |
%gt | GMTを表示 |
コマンド関数定義
コマンドの関数は、引数を省略して記述します。
- この記述で定義した関数は、マクロプログラムを実行すると、コマンドの一覧に表示されます。
main {
...
}
上記の記述は、以下の記述と同等です。
int main(void)
{
...
}
WindowsAPIとDLL
Text-Cは、WindowsAPIの呼び出しに対応しています。
WindowsAPIを使用するには、拡張子「.c」でプログラムファイルを作成し、プログラムの先頭で下記のincludeを記述します。
#include <windows.h>
#include <text.h>
- #include <windows.h>を記述すると、以前の#define,typedefの定義はすべてクリアされます。
Text-Cは、WindowsAPIのデータを内蔵していますので、SDKは必要ありません。
Text-Cの制限により、一部に対応しないWindowsAPIがあります。
Text-Cでは、DLLの関数の呼び出しに対応しています。
extern文で、DLL関数を宣言します。
extern "DLL名" {
関数宣言
}
(例)「testl.dll」の「test1func」の呼び出し
extern "test.dll" {
BOOL WINAPI test1func(int arg1,LPVOID arg2);
BOOL WINAPI test2func(int arg1,LPVOID arg2);
}
main {
test1func1(arg1,arg2);
}
モジュールの呼び出し
他の、Text-Cプログラムファイルの関数を呼び出すには、extern宣言の後で関数を呼び出します。
extern "txtool.c" {
void wsplit(void);
}
上記の例では、"txtool.c"ファイルのwsplit関数を宣言しています。
[マクロ]メニューの[プログラムの登録]で登録されている、Text-Cプログラムを呼び出すには、「\\」に続けて「author」とファイル名を指定します。
extern "\\system\txtool.c" {
void wsplit(void);
}
この指定は、#include文にも記述できます。
#include "\\system\test.h"
暗黙のinclude
Text-Cでは、プログラムファイルの先頭で、暗黙の#includeをおこないます。
#include <text.h>
この#include文で、Text-CのAPIが使用可能になります。
拡張子が「.c」のプログラムファイルでは、暗黙の#includeはおこないません。
Text-CのAPIを使用するには、#include <text.h>を記述します。
文字コード
Text-Cでは、シフトJISを拡張した「SJIS-EX」文字コードを用います。
シフトJISはUnicodeの全文字に対応していませんが、SJIS-EXではシフトJISの未使用領域にUnicode特有の文字を割り当て、Unicodeの全文字に対応しました。
- シフトJISの文書を、変換なしでロード・セーブできます。
- シフトJISにないUnicode特有文字を、すぐに検索できます。
- WZ5(2003年)、WZモバイル、WZ6、WZ7で対応しています。
SJIS-EXでは、シフトJISで表現可能な文字はすべてシフトJISで表します。
Unicode特有の文字は3バイトのデータで表します。
0x80+2バイト
0xA0+2バイト
+2バイトのデータは、それぞれ0x40〜0xFFの範囲となります。
Text-CではSJIS-EX文字列を、mchar*型(LPBYTEと同じ)で扱います。
- SJIS-EXでは一文字のバイト数は、1,2,3,6バイトになります。
- 1バイトはASCII、2バイトはシフトJISの文字です。
- 3バイトはUnicode特有文字、6バイトはサロゲートペアのUnicode文字です。
Text-CからWindowsAPIへ文字列を引き渡すには、SJIS-EX文字列をUnicodeに変換して、WindowsAPIのUnicode版を呼び出します。
HTEXT text = dup("SJIS-EX文字列");
sjisto(text,ID_UNIB);// textをUnicodeに変換。
MessageBox(NULL,(LPVOID)getdata(text),L"msg",MB_OK);// WindowsAPI
- Unicode特有文字を含まない文字列は、WndowsAPIのANSI版を呼び出せます。
Text-Cには、各種の文字コードの変換のAPIが用意されています。
wchar* wstrdupA(mchar* sz) | szのSJIS-EX文字列をUNICODEに変換してmallocしたメモリブロックにセットして返します。末尾の0もセットされます。 メモリブロックはfreeが必要です。 |
wchar* wstrdupLenA(mchar* sz,int lch) | szのSJIS-EX文字列の先頭からlchバイトまでをUNICODEに変換して、mallocしたメモリブロックにセットして返します。 末尾の0もセットされます。 メモリブロックはfreeが必要です。 |
wchar* wdupfn(CLM fn) | fnをUNICODE文字列に変換して、mallocしたバッファにセットして返します。末尾の0もセットされます。 fnの先頭部に"wz://","wzcfg://"を指定するとフルパスに変換します。 メモリブロックはfreeが必要です。 |
mchar* strdupW(wchar* wsz) | wszのUNICODE文字列をSJIS-EXに変換して、mallocしたメモリブロックにセットして返します。末尾の0もセットされます。 メモリブロックはfreeが必要です。 |
mchar* strdupLenW(wchar* wsz,int lch) | wszのUNICODE文字列の先頭から、lch文字をSJIS-EXに変換して、mallocしたメモリブロックにセットして返します。 末尾の0もセットされます。 メモリブロックはfreeが必要です。 |
BOOL tosjis(HTEXT text,int id) | textの文字コードを、idからSJIS-EXに変換します。 idにはID_UNI(BOMあり),ID_UNIB(BOMなし), ID_SJIS,ID_JIS,ID_EUC,ID_UTF,ID_ASCIIを指定します。 |
BOOL sjisto(HTEXT text,int id); | textの文字コードを、SJIS-EXからidに変換します。 idにはID_UNI(BOMあり),ID_UNIB(BOMなし), ID_SJIS,ID_JIS,ID_EUC,ID_UTF,ID_ASCIIを指定します。 |
BOOL h_issjisex(int c) | cがSJIS-EXの拡張文字(0x80,0xA0)ならTRUEを返します。 0<=cかつc<=0xFFを仮定しています。 |
IFILE buffgetcharsize(mchar* p) | SJIS-EX文字列の、p位置の文字のバイト数を返します。 |
テキストバッファ
テキストは、テキストバッファに格納されます。
テキストバッファは、バッファサイズの拡大と縮小が容易な構造です。
テキストバッファ先頭
テキスト(A)
ギャップ先頭
ギャップ終わり
テキスト(B)
テキストバッファ末尾
テキストバッファは、ギャップ(緩衝域)でAとBの2つに分かれています。
- 挿入はギャップから領域を確保します。
- 削除はギャップを増やして、高速に挿入削除を実行します。
- ギャップが不足した場合は、テキストバッファを再アロケートします。
ギャップは、テキストの段落を分割しない位置に作成します。
- テキストAが、段落末尾で終わる位置にギャップを作成します。
- ギャップの先頭には0が入ります。
- 64KBまでの段落は、ギャップによって段落が分割されることはありません。
64KBを超える段落は、文字を分断しない位置にギャップを作成します。
段落操作のAPIは、ギャップで分割された段落を、複数の段落として扱います。
テキストの自動削除
new()で作成したテキストは自動的に削除されて、テキストハンドルとテキストバッファが解放されます。
テキストをC言語の自動変数と同様に簡単に扱えます。
テキストの削除は、関数の終了時に実行されます。
下記の例では、return文の直後で削除が実行されます。
int test(void)
{
HTEXT text = new();
...
return 10;
}
テキストを関数内の任意の場所で手動で削除するには、delete文を記述します。
int test(void)
{
HTEXT text = new();
...
delete(text);
return 10;
}
ビューでテキストの表示中は、関数終了時の削除は実行されません。
ユーザがウィンドウを閉じてビューを削除すると、テキストの削除が実行されます。
int test(void)
{
HTEXT text = new();// 参照カウント=1
vnew(text,...);// 参照カウント=2
return 10;// ここではtextは削除されない。
}
テキストの削除は、参照カウンタで判定します。
- new()時点では、参照カウンタは1です。
- 関数の終了時に、カウンタを1つ減らします。0になると、削除を実行します。
- ビューを作成すると、参照カウンタを1つ増やします。
- ビューを削除すると、参照カウンタを1つ減らします。
new()で作成したテキストを返す関数は、関数の宣言および定義にnewobj修飾子を指定します。
HTEXT newobj test(void)
{
HTEXT text = new();
...
return text;
}
newobj修飾子を付けた関数は、return文で返すテキストの削除は実行しません。
プログラムからnewobj修飾の関数を呼び出すと、関数の終了時にテキストを自動削除します。
void test2(void)
{
HTEXT text = test();
...
return; // textは自動削除される
}
スレッドとスタック
Text-Cは、マルチスレッドに対応しています。
スレッドの開始ルーチンは_threadクラスを付加して、返り値なし、引数1つの関数として定義します。
static void _thread start(HTEXT mailer)
{
... // 処理
}
スレッドを終了するには、return; 文を記述します。return文を省略すると、関数の最後で終了します。
_threadクラスを付加しない方法もあります。スレッドを終了するには、threaddelete APIを呼び出します。関数終了時のテキストの自動削除は実行されません。
static void start(HTEXT mailer)
{
... // 処理
threaddelete();
}
スレッドを開始するには、threadnew APIを用います。
HANDLE h = threadnew(start,mailer);
threadnewに、スレッドの開始ルーチンと引数を指定すると、スレッドを開始してWindowsのスレッドハンドルを返します。
Text-Cのスタックサイズは、32KB固定です。
- 大きな配列は、mallocやテキストを用いて記述します。
- スタックがオーバーフローすると、エラーメッセージを表示します。
関数実行を停止し、呼び出し元へ0を返します。
浮動小数点
Text-Cは、浮動小数点に対応しています。
浮動小数点の変数は、double型またはfloat型で定義します。Text-Cではfloatはdoubleと同じ有効桁数です。
double型は8バイトの符号付き、1.7E +/- 308の範囲で15桁の有効桁数があります。
double型は、C言語との相違や制限事項があります。関数の引数として「doubleを渡す」、返り値として「doubleを返す」は、C言語と同様に可能です。
- 演算子「%=」に対応していません。「double a;a%=10;」はエラーになります。
「a = a % 10;」と記述します。
演算子「+=」「-=」「*=」「/=」には対応します。
- 四則演算「+」「-」「*」「/」、代入「=」、比較「==」「!=」「>=」「<=」「>」「<」に対応しています。sinなどの数学関数には対応していません。
- 「a ? b : c」文の、bとcのdoubleの指定に対応していません。
- 静的変数のdoubleの初期化に対応していません。「static double a=10.5;」はエラーになります。
静的変数を初期化するには、関数内で代入をします。
自動変数のdoubleの初期化には対応します。
- 配列の初期化に対応していません。「double t[3] = {1,2,3};」はエラーになります。
配列を初期化するには、「t[0]=1;」と、1つ1つ代入します。
- doubleをメンバに持つ構造体の初期化に対応していません。
初期化するには、プログラムで代入処理をします。
- 文字列からのdouble数値の取得は、atopf(mchar* p,double* pf) APIで対応します。
pの浮動小数点実数をdoubleに変換して*pfに代入します。変換できたらTRUEを返します。
C言語のatofはisspace(*p)なら空白をスキップして処理しますが、atopfは0を返します。
- modpf APIは、double数値の整数部と小数部を求めて返します。
- double専用のスタックのサイズは256KBです。
関数内でdoubleの演算をループで数万回実行するとスタックオーバーフローして停止します
回避するには、加算のプログラムを別関数に切り出してループ内で関数を呼び出します。
- printf/sprintf/textprintfは、「%f」「%e」によるdouble変数の数値表示に対応します。
%fや%eには必ずdouble型の変数を指定します。
int型の変数を指定すると、アプリケーションエラーが発生します。
printfの使用例 | double x = 123.5678 |
printf("%f",x) | 123.567800 |
printf("%3.3f",x) | 123.568 |
printf("%.f",x) | 124 |
printf("%e",x) | 1.235678e+002 |
printf("%.3e",x) | 1.236e+002 |