プログラム講座 中級編1
- テキストからHTML文書に変換 -
 中級編1です。今回は簡単な「テキストからHTML文書に変換」するアプリケーションを作ってみましょう。まずはHTML文書の構造とダブルバッファリング機構について説明します。
◆HTMLとは?
 HTMLとはHyper Text Markup Languageの略称です。インターネットのホームページで使用されているものですので、聞いたことや目にした事もあると思います。
 HTMLは文章(テキスト)を「タグ」で囲んで文字を修飾したり画像を入れたりします。タグは基本的に以下のようになっています。
<タグ名>テキスト</タグ名>
 このページもこのようなタグを使用して書かれています。HTML(SGMLのサブセット)の特徴は「解釈できない(不明な)タグは無視する」という点です。このおかげでMac, Win, UnixやPDAなど機種を問わずに最低限の文章などを見ることができるようになっているのです。反面勝手にタグを拡張しても大丈夫という部分もあります。
 今回のプログラムでは最低限のタグだけを付加します。普通のテキスト文章と違ってHTMLは改行などを明示的に記述しなければなりません。この改行タグをつけないとひたすら横長に表示されてしまいます。
 現在のHTMLの仕様のバージョンは3.2です。以前と違い<HTML>等のタグは記述しなくてもよくなっています。今回のプログラムで必要最低限なタグは<BR>くらいです。が、お約束として以下のタグを今回は記述する事にします。
<HTML>  HTML文書開始
</HTML>  HTML文書終了
<HEAD>  ヘッダー部分開始
</HEAD>  ヘッダー部分終了
<BR>  改行
 これ以外にHTMLでは不等号記号と&マークは特殊文字として扱われるため以下のように別の記述をします。
< → <
> → >
& → &
 今回のプログラムはテキストからHTMLに変換するのですが、以下のように変換すればいいという事になります。
改行コード → <BR>
< → <
> → >
& → &
◆ダブルバッファリング機構
 今までは文字の表示はPRINT文を使用していました。この命令は非常に手軽で便利ですが、別のウィンドウを上に重ね合わせて移動させると以前に表示した部分が消えてしまいます。これは一度表示したら、表示するだけで以前表示した内容を忘れてしまっているためです。これは、これでいいのですが、やはり手抜きという感じを与えてしまう場合もあるので、今回はPRINT文の代用となるような関数を作成する事にします。
 まず、表示する文字列ですが普通のPRINT文のような汎用性はありません。ウィンドウの右端にきても折り返して表示しません(PRINT文でも、折り返しスイッチがありますが、その折り返しスイッチオフと同様です)。従って1回に表示できる文字数に限度があります。ウィンドウの幅を超えてはならない、255文字を超えてはならないという条件をつけ加えて作成します。
 文字列を表示させる場合、今まではPRINT文を使用していましたが、勝手に改行されたり意味不明な動作をされては困るのと速度の関係からツールボックスコールを使用します。文字列を表示するツールボックスコールで今回はDRAWSTRINGを使用します。1文字づつ表示するものもありますが、これだと日本語が正常に表示できない場合があるのでDRAWSTRINGを使用するというわけです。
 文字列を表示していくと、文字が一番下まで表示されたときに表示内容が一段上にずれます。これをスクロールするといいます。つまり文字列を1段づつずらすプログラムが必要です。こういう事は結構処理速度が低下し面倒なので、今回は手抜きをする事にします。
 通常PRINT文はウィンドウの一番上から文字を表示しますが、これを常に最下段から表示するようにします。次に表示速度(スクロール速度)を稼ぐために「ダブルバッファリング機構」を使用します。ダブルバッファリングというのは、普通PRINT文では1箇所しか文字列を表示しませんが、これを表示画面の2倍のサイズを用意しておき、双方に同じ文字列を表示するというものです。基本的な原理を以下の図に示します。
 表示してスクロールさせる作業を表示位置をずらしてスクロールしているように見せるというものです。ゲームなどでは割と使われた方法です。X68000などのマシンでは表示画面の倍の(表示されない)画面があり、上記のようにしておくと表示位置をずらすだけでいいため、真面目にスクロールさせた場合と比べてかなり処理的に速くなります。
 今回のPRINT文の代用関数printxは、このちょっとしたサンプルと言えます。わからない方はじっくり紙に書いてやってみるといいでしょう。
 今回他にMOVETOというツールボックスコールを使用しています。これは、指定した座標(ウィンドウの左上が原点)に(表示位置を決めるための)ペンを移動させるものです。
◆保存するファイルのタイプとクリエーター指定
 open "O",#2〜命令で書き出されるファイルは真っ白けのアイコンになってしまいます。この出力されるファイルには、ちゃんと「ファイルタイプ」(テキストやPICT)と「クリエーター」(作成されたプログラムを示す識別子)を指定する事ができます。
 ファイルタイプやクリエーターを指定するには以下の命令を使用します。
DEF OPEN "ttttCCCC"
 ttttはファイルタイプです。テキストファイルならばTEXTになります。CCCCはクリエーターでTeachTextではttxtになります。今回はTeachTextでファイルが開けるようにしてあります。つまり、
ファイルタイプ:TEXT
 クリエーター:ttxt
 という具合になっています。
◆ファイルデータの読み込み/書き出し処理
 ファイルのデータを読み込む場合、今まではINPUT #1,a$を使用していましたが、この命令では1行の長さが256文字以上の時におかしな動作をしてしまいます。というのも文字列変数が扱える文字数は255文字までと決まっているからです。
 そこで文字列の長さがどうであろうと動作するように1文字づつ読み込んで処理する事にします。速度は速くありませんが確実な方法です。この1文字づつ(実際は指定された文字数分)読み込むための命令がREAD命令です。この命令は以下のようになっています。
READ #ファイル番号,文字列変数;読み込む文字数
 これと逆の動作をする、つまり指定文字数だけ書き出す命令がWRITE命令です。この命令もREAD命令同様以下の書式になっています。
WRITE #ファイル番号,文字列変数;書き出す文字数
 読み込んだ文字が改行コードかどうか調べて、改行コードであれば、その前にタグを書き出しておきます。同様に&や不等号の処理を行います。
◆指定した名前のアプリケーションにする
 今まで「ビルド...」でアプリケーションを作成していましたが、いちいち作成のたびにファイル名を入れるのは面倒です。このような場合、OUTPUT FILEという命令を使うと、そのような面倒な事をしなくて済むようになります。
◆終わりに
 アプリケーションを作成する場合は、対象となるものをよく知っていないと駄目です。中級編ではグラフィックフォーマット変換なども行いますが、対象となるグラフィックフォーマットを知らないと全く歯が立ちません。今回の場合はHTMLについて知らないと駄目だという事です。プログラムを作成する場合は、まず対象をよく知ること。次に実現のためにどのような部品(関数)が必要か?を考えるようにしましょう。これとは逆にFuture BASICやInside Macをご丁寧に読む必要はありません。必要とする命令や関数があるかどうかを調べるための辞書として使えばいいのです。幸いにしてFuture BASICには、わかりやすく応用の利くサンプルプログラムがついてきます。まずは使ってみて、動作を見極めるというのも1つの方法です。
 次回は・・・まだ決めてません(^^;
◆今回のプログラムリスト
'
' "中級編のプログラム PROGRAM = Convert to HTML"
'
OUTPUT FILE "toHTML":                             ' "作成されるアプリケーション名
DIM wintext$(40):                                 ' "結果のリスト"
textP% = 0:                                       ' "表示位置"
END GLOBALS
' "変換されたファイルをウィンドウに表示する"
' "アップデート処理"
LOCAL FN displayWindow
  WINDOW OUTPUT #1
  CLS
  TEXT _sysFont,9
  FOR I%=0 TO 19
    CALL MOVETO(4,I%*12)
    CALL DRAWSTRING(wintext$(textP% + I%))
  NEXT
END FN
' "1行プリント処理"
LOCAL FN printX(pr$)
  wintext$(textP%) = pr$
  wintext$(textP%+20) = pr$
  textP% = textP% + 1
  IF textP% > 19 THEN textP% = 0
  FN displayWindow
END FN
' "ファイルを開いてデータを変換する"
LOCAL FN openFile
  filename$ = FILES$(_fOpen,"TEXT",,vRefnum%)
  IF filename$="" THEN EXIT FN
  f$ = filename$+".html"
  savefile$ = FILES$(_fSave,"保存ファイル名:",f$,vRefnum2%)
  OPEN "I",#1,filename$,,vRefnum%
  DEF OPEN "TEXTttxt"
  OPEN "O",#2,savefile$,,vRefnum2%
  
  f$="変換元ファイル名:"+filename$
  s$=" 変換ファイル名:"+savefile$
  FN printX(f$)
  FN printX(s$)
  FN printX("変換中です...")
  
  PRINT #2,"";filename$;""
  PRINT #2,""
  br$="
":                                     ' "HTML 改行タグ"
  amp$ = "&":                                  ' "&マーク"
  lt$ = "<":                                    ' "<記号"
  gt$ = ">":                                    ' ">記号"
  
  WHILE NOT EOF(1)
    READ #1,a$;1
    IF a$=CHR$(13) THEN WRITE #2,br$;4
    IF a$="&" THEN WRITE #2,amp$;4:a$=";"
    IF a$="<" THEN WRITE #2,lt$;3:a$=";"
    IF a$=">" THEN WRITE #2,gt$;3:a$=";"
    WRITE #2,a$;1
  WEND
  
  PRINT #2,""
  CLOSE #1,#2
  
  FN printX("変換は終了しました")
END FN
' "アップデートイベントを処理"
LOCAL FN eventProc
  evnt = DIALOG(0)
  IF evnt = _wndRefresh THEN FN displayWindow
  
END FN
' "メニュー構築"
LOCAL FN initMenu
  APPLE MENU "toHTMLについて..."
  'File Menu
  MENU 1,0,_enable,"ファイル"
  MENU 1,1,_enable,"/O開 く..."
  MENU 1,2,_enable,";"
  MENU 1,3,_enable,"/Q終 了"
END FN
' "Aboutの処理"
LOCAL FN ABOUT
  err% = FN ALERT(128,0)
END FN
' "メニュー分岐処理"
LOCAL FN doMenu
  menuID = MENU(_menuID):                         ' "どのメニューバー項目かな?"
  itemID = MENU(_itemID):                         ' "選択項目は何かな?"
  
  SELECT menuID
    CASE 255,127
      SELECT itemID
        CASE 1
          FN ABOUT:                               ' "About...が選択されたので呼び出す"
      END SELECT
    CASE 1 :                                      ' File... Menu
      SELECT itemID
        CASE 1:                                   ' Open File...
          FN openFile
        CASE 3:                                   ' Quit Menu...
          END
      END SELECT
  END SELECT
  MENU
END FN
ON MENU FN doMenu
ON DIALOG FN eventProc
FN initMenu
WINDOW OFF
WINDOW #1,"状 況",(44,50)-(44+340,50+240),_dialogMovable
WHILE 1
  HANDLEEVENTS
WEND