Rich Text Format(RTF)の構造(の覚え書き) - Part 1

| トラックバック(0)
Visual Studioのコードは、コピーすることでリッチテキスト形式のドキュメント(RTF)を取り出すことが出来る。が、リッチテキスト形式からHTMLにダイレクト変換するツールが案外少ないので、作ってしまおう。ということになり、現在作成中。

 リッチテキストといえば、ワードパッドである。つまり、ワードパッドで作成されるファイル(*.rtf)を解析すれば、Visual StudioのコードをHTML化することが可能。

RTFは、Microsoftが開発したドキュメントフォーマットであり、その仕様(英語のみ)はMSのサイトでも公開されているのだが、最新版のVersion 1.9では仕様書だけで11MB超・・・。A4サイズでなんと281ページに及ぶ。RTF⇔HTML変換ソフトが有料版な訳もうなずける。

さてこれだけの規模の仕様を、1~100まで対応するのは到底無理&無駄なので、コードをコピーした際に使われる書式だけ対応すればひとまず目的のものは出来上がる。

と、言うわけでまずはRTFの基本構造から。

 

サンプル ここ太字。ここ斜体。ここ。ここ

 

例えばこのようなリッチテキストがあった場合、そのデータは下記のようになる。(本来改行されていない箇所も見やすくするために改行してある。)

 

{\rtf1\ansi\ansicpg932\deff0\deflang1033\deflangfe1041

    {\fonttbl

        {\f0\froman\fprq1\fcharset128 \'82\'6c\'82\'72 \'82\'6f\'83\'53\'83\'56\'83\'62\'83\'4e;}

    }
    {\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
    {\*\generator Msftedit 5.41.15.1507;}

\viewkind4\uc1\pard\lang1041\f0\fs20\'83\'54\'83\'93\'83\'76\'83\'8b \'82\'b1\'82\'b1\b\'91\'be\'8e\'9a\b0\'81\'42\'82\'b1\'82\'b1\i\'8e\'ce\'91\'cc\i0\'81\'42\'82\'b1\'82\'b1\cf1\'90\'c2\cf0\'81\'42\'82\'b1\'82\'b1\cf2\'90\'d4\cf0\'81\'42\par
}

RTFは"{"から"}"で囲まれたデータの塊(これをグループと呼ぶ)がいくつか入れ子になっている。上記の例だと、最も外側にある「{\rtf1」から始まり文末の「}」で終わるグループ。その中に「{\fonttbl~}」と「{\colortbl~}」と「{\*~}」がそれぞれひとつずつ。更にfonttblには{\f0~}」がある。「fonttbl(フォントテーブル)」は、ドキュメントで使われるフォントの一覧が記載され、実際にそのフォントを使う際には「f0」「f1」といったインデックス番号を指定する。「colortbl(カラーテーブル)」は、ドキュメントで使われる色の一覧。フォントと同じく「fc0」「fc1」といった具合に指定する。ワードパッドは文字の色を決められた16色の中からしか選ぶことが出来ないが、ここを直接書き換えれば、RGBそれぞれ256段階(16,777,216色)で指定出来る。

最も外側に位置するグループ「{\rtf1~}」に書かれた情報が、ドキュメント本体のヘッダと本文。ファイル自体はANSIフォーマットであるため、日本語を記述する際には「あ」であれば「\'82\'a0」のように文字コードを16進数で表記する。

各グループには「コントロールワード」と呼ばれる制御文が記述されている。制御文は「\(バックスラッシュ) + 制御名 [+ 数値] + デリミタ」の書式を取る。制御名は32文字以内という制約があるらしい。

制御文以外の文字は全て「地の文」となり、ドキュメント本文を示す。とはいえ、先に説明したとおり、日本語は全て文字コードの16進数に置き換えられるため、RTFを直接眺めても本文は読み取れない。

制御文の終端の判定となる「デリミタ」はやや複雑で、「次のコントロールワードの開始(/exp01/exp02)」「スペース・改行(/exp01 abc)」「?マーク(/exp01?abc)」「セミコロン(/exp01;)」または「グループの終了(/exp01})」で判別する。ワードパッドではこのほかに、無効な文字をデリミタと判断する動作を示している。例えば「/exp01abc」とすると、「abc」の先頭の「a」をコントロールワードの終端とみなして「abc」と表記する。ただし、数値がない制御文の場合は、デリミタを検出できず、制御文全体を無視する。例えば、段落区切り後に「abc」とする場合は「\par abc」と\parのあとに半角スペースを入れるか改行する必要があるが、これを「\parabc」とつなげてしまうと「parabc」という制御名として判定され無視される。

 

ここまでをまとめると、RTFを解析するには

1. グループの検出

2. コントロールワードの検出

3. 字の文の検出(=!2.)

この3つが必要となる。

トラックバック(0)

トラックバックURL: /mt/mt-tb.cgi/9