改行の研究


「改行に注意!」でも改行に関して触れる機会がありましたが、ここでは改行を別な観点から考えてみます。
下のテキストアリアに2行の文章が入っています。「文字数」ボタンを押してみて下さい。



Windows なら、「22字」という答えが表示されるはずです。 入っている文字は20しかないのに、22になるのは、改行コード分が含まれるからです。しかし、なぜ22なのでしょう?

その理由は、Windows などでは CR(carriage return「復帰」)と LF(line feed「行送り」)という2つの制御コードの組み合わせで改行を表しているからです。 それぞれ1バイトで計2バイトとなります。「復帰」というのは元々、行頭に戻ることを意味し、「行送り」は次の行に移ることを意味していました。 つまり或る行の終わりで行頭に帰り、次の行の頭に移るということです。

しかし現在のパソコンでは、この区別は必ずしも厳密なものではなく、システムによっては CR(復帰)だけや、LF(行送り)だけ、 或いは CR/LF とは逆の LF/CR という組み合わせでも改行が行われています。 例えば UNIX のテキストファイルでは LF による改行が一般的なので、UNIX で作成されたテキストを Windows の「メモ帳」などで読み込んだら、 改行が全然されずに1行で表示され、改行されるべき部分が文字化けしていた、という経験を持つ人もいると思います。 「メモ帳」のようなシンプルなエディタでは、LF を CR/LF に変換する処理がされていないからです。

ちなみに改行を含む文字列を JavaScript の escape() メソッドを使って ASCII コードに変換すると、改行に当たる部分は、%0D%0A となります。 %0D がCR(復帰)、%0A がL F(行送り)です。ASCII コードでは、CR は13番目(16進数の 0D)、LF は10番目(16進数の 0A)だからです。

前述の UNIX で作成されたテキストをコピーして Netscape の TEXTAREA にペーストし、これを escape() メソッドで変換すると、 改行に当たる部分は %OA になっています。ところがこの ASCII コードを unescape() メソッドで文字に変換すると、きちんと改行された文になります。 これは、%0A だけや %0D だけのコードを unescape() メソッドが %0D%0A に変換処理してくれるからでしょう。
ところが前述の UNIX で作成されたテキストをコピーして IE 5.0 の TEXTAREA にペーストすると、それだけで改行されて表示されます。 escape() 変換してみると、改行部分が %0D%0A となっていますので、IE 5.0 の TEXTAREA 自身が %0A を %0D%0A に書き換え(内部処理し)ているのだと思います。
下の TEXTAREA でいろいろ試してみて下さい。





ところで JavaScript で改行コードが取得できるなら、改行コードを挿入することも出来るはずです。 この点を応用して、入力欄の文章を一定字数で強制改行するプログラムを作ってみましょう。

自動改行が設定されていない掲示板などで、ユーザが投稿した文が改行されないまま表示されている例をたまに見かけます。 スクロールバーをスクロールしなければ読めないので不便に感じるでしょう。 特に Internet Explorer では TEXTAREA 内の文が(親切にも)ワードラップされて表示されるために、投稿者が自分で改行することを忘れるケースが多いようです。

以下のプログラムでは、TEXTAREA に入力された文章を40バイト(半角40字。全角なら20字)で強制改行します。 TEXTAREA に何か長文を入れ、「各行40バイトにする」ボタンをクリックしてみて下さい。 各行40バイト(但し行中に奇数個の半角文字が含まれる場合は41バイト)で自動改行されます。 (Ver. 4.05 までの Netscape Navigator ではエラーになります。IE 3.0 以上、NN 4.06 以上で試して下さい。)





これは一見したほど簡単ではありません。というのも IE や、また最近の Netscape Navigator では、 全角文字も1字として数えるようになったからです。これは便利な面もありますが、1行に全角文字と半角文字が混じっている場合、 字数を一定バイト数に抑える点では不便です。 そこで「関数集(その1)」で作った IsSingleByteChar 関数を使用して半角英数字と全角文字とを区別します。

function IsSingleByteChar(Char) { //Char が半角英数字記号なら真を返す
var S = escape(Char);
if (S == Char) return true;
else if (S.length == 3)
{
code = S.charAt(1) + S.charAt(2);
nm = parseInt(code, 16);
if (nm > 0 && nm < 127) return true;
}
}

function Trim40(txt) { //引数 txt に TEXTAREA の文を入れ、TEXTAREA を40〜41バイトで改行する処理
j = 0; //バイト数を数える変数 j
str = ''; //変換後の文字列を入れる変数 str
for(i = 0; i < txt.length; i++)
{
S = txt.charAt(eval( i )); //変数Sに txt の各字を入れ、
if (IsSingleByteChar(S) == true) //半角英数字なら
{
j ++; //バイト数1を加える
if (escape(S) == "%0D") //改行コードなら
{
j = j - (j % 40); //改行までのバイト数を減算する
str += S;
}
else //それ以外は
{
if (j % 40 == 0 ) str += S + unescape("%0D%0A"); //40バイト目で改行させる
else str += S;
}
}
else //全角文字なら
{
j += 2; //バイト数2を加える
if (j % 40 == 0 ) str += S + unescape("%0D%0A"); //40バイト目で改行させる
else if ( (j-1) % 40 == 0) str += S + unescape("%0D%0A"); //但し端数が出た場合は41バイト目で改行させる
else str += S;
}
}
document.forms[0].elements[0].value = str; //変換処理後の文字列 str を TEXTAREA に戻す
}

「各行40バイトにする」ボタンをクリックしたとき、この Trim40 関数を呼び出すようにすればOKです。

この方法では、処理後に句読点が文頭に来たり、英単語が途中でチョン切れたりする場合もあり得ます。 もう少し緻密にすれば、そうしたケースも防止できますが、時間がありませんでした。いろいろ工夫してみて下さい。




次のトピックは「MIDI CHANGER を作る」です。

目次 | ← 前のトピック | ↑ページのトップ | 次のトピック →

ご意見・ご質問がありましたら「ザ・掲示板」またはメールにて梅ちゃん堂まで