hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
String/改行 - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

文字列の改行 (HSP3)

 文字列の自動改行の解説です。
実装できればアドベンチャーゲームなどの作成などで使えそうな機能です。

2バイト文字判定

 あとあと何かと必要になってくる2バイト文字の判定関数モジュールです。

 文字は通常、日本語や記号は2バイト、それ以外は1バイトを使用して表現されています。 またこれらは文字列中に混在するので多少厄介です。
しかしHSPで通常扱われているシフトJISコードにおいては次のルールが適用されているようです。
シフトJISコードが2バイト文字で使用している値
1バイト目:0x81〜0x9f, 0xe0〜0xfc
2バイト目:0x40〜0x7e, 0x80〜0xfc

マニュアルにも記載があります。

コードが129〜159か、224〜252の範囲にある場合は、次の1バイトと合わせて1文字の全角コードとなる。 
(HSPマニュアルより引用)

1バイト文字と2バイト文字の領域を次のように色分けして表示してみます。

1バイト文字
2バイト文字
その他

このように2バイト文字の2バイト目では、1バイト文字 2バイト文字両方の領域で重なっていることが分かります。

1バイト目0x200x7e0x810x9f0xA10xdf0xe00xfc
2バイト目0x400x7e0x800xfc

 1バイトずつ順番に取り出して、これを用いて判定すれば1バイト文字か2バイト文字かの判定が出来ます。
順番を数え間違えると2バイト文字の1バイト目なのか2バイト目なのか分からなくなるので注意が必要です。

取り出した1バイトが2バイト文字の1バイト目領域内にあるかどうかの判定を行うモジュールが次のものになります。
(※アドベンチャーエンジンのところから持ってきました。)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 
 
 
 
 
 
 
 
 
#module
;文字コード判定関数
;	Shift-JISの2バイト文字の1バイト目領域内かを判定します。
;	RV = IsByte( int p1 )
;	p1 : 判定する文字コード
;	RV : 1=2byte文字の1文字目 (これ以外は 0)
    #defcfunc IsByte int p1
    return ((p1>=129)&(p1<=159) )|( (p1>=224)&(p1<=252))
#global

文字列を順番に取り出していき、最初にIsByte?()=1が出たところが2バイト文字1バイト目、次のバイトはIsByte?()は0でも1でも2バイト文字2バイト目になります。
これ以外のときのIsByte?()=0が1バイト文字となります。


_mbsbtype

msvcrt.dllの_mbsbtype関数の動きをHSP標準命令で作ったモジュールで再現してみました。

+  _mbsbtype(by msvcrt.dll)
+  _mbsbtype(by HSP標準命令)

文字列の改行サンプル

とりあえずやってみたサンプル

自動改行(文字列幅指定タイプ)

String/矩形で解説されている、文字列サイズの取得機能を使用することで、指定サイズでの 改行を実現します。
これによりプロポーショナルフォント*1を使用した場合でも自然な位置に改行を入れることができるはずです。

+  自動改行 moji06





禁則処理

 禁則処理とは行末や行頭に来ると見た目の悪い文字の配置を調整する処理のことです。
「】」や「?」、「『」など行頭や行末に来ると見栄えの悪いものを行末に押し込んだりあるいは行頭に移動したり(行頭禁則、行末禁則)、「19,800円」など途中に改行を入れると見栄えの悪いものを前の行の行末や今の行の行頭に全部押し込んでしまう処理(分離禁則)のことを言います。

禁則処理対象文字リスト 行末禁則文字:

‘“(〔[{〈《「『【

行頭禁則文字:

、。,.’”)〕]}〉》」』】
・:;?!ヽヾゝゞ〃々ー―〜…‥
っゃゅょッャュョぁぃぅぇぉァィゥェォ




DrawText?を使った改行処理

APIのDrawText?を使用すると禁則処理などに対応した自動改行が簡単に表現できるようです。

+  DrawText?使用サンプル




文字列の改行モジュール

モジュール化しました。

自動改行(文字数指定タイプ)モジュール

2バイト文字対応型の自動改行サンプル(禁則処理非対応)をモジュール化したものです。
モジュール化での大きな変更点は、改行を入れる際に

buf+="\n"

poke buf,  j, 13
poke buf,j+1, 10

に変えた点です。 変数は初期化せずに使用しており、かつ処理中は終了コードを入れないので、処理中は前の 変数内容が残った状態になっています。
うかつに+=を使うと変なところに追加されてしまうのでpokeで上書きしています。

+  自動改行 moji20

自動改行(文字数指定タイプ、禁則処理対応)モジュール

 上のサンプルのやりかたで禁則処理に対応しようとするとなかなかに難しいことが分かりました。orz
そこでサンプルとは手法を変え、やり方を整理して、さらに禁則処理に対応させたものがこれです。

 キーボードの←→キーを押すか、マウスクリックで改行位置が変わります。
実行して確認してみてください。

+  自動改行モジュールサンプル moji18
  • アルゴリズムはこんな感じ。
     頭から順に改行候補位置をおさえながら1文字ずつコピーしていきます。
    文字列の長さが1行分に達したら、改行を改行候補位置に挿入します。
    これの繰り返しです。


自動改行(文字幅指定タイプ、禁則処理対応)モジュール

 String/矩形で解説されている、文字列サイズの取得機能を使用することで、プロポーショナルフォント*2を使用した場合での改行を実現します。
これによりプロポーショナルフォントを使用した場合でも自然な位置に改行を入れることができるようになります。

+  自動改行 moji21

 基本的には文字数指定タイプと同じです。
改行を挿入するトリガーが文字数から文字幅サイズに変わっただけです。

 文字幅を1文字ずつ計って加算して、指定サイズを超えたら改行するようになっています。
改行後の文字幅を取得するため、改行候補位置までの文字幅も記録しています。

ilenstr	;1行の文字列xサイズ
ilenstret	;1行の改行候補文字までの文字列xサイズ
  • 文字列幅は1文字ずつチェックしていますので、1行中で各文字に任意にばらばらの文字幅を指定した場合にも応用できるんじゃないでしょうか?


駄目文字

 文字の処理をする際、2バイト目に\(0x5c)を含む駄目文字があるため取扱いは注意が必要です。
該当文字は次の通り。

ソ噂浬欺圭構蚕十申曾箪貼能表暴予禄兔喀媾彌拿杤歃濬畚秉綵臀藹觸軆鐔饅鷭



コメント

  • 禁則処理までやる予定です。 -- GENKI? 2006-11-03 (金) 23:04:12
  •  
    +  _mbsbtype
    これで、普通に SJIS の何 byte 目かは判断できますが...。 -- Irisawa 2006-11-03 (金) 23:11:56
  • HSP2掲示板の過去ログ21では文字の種類を判定する方法も書いています。ただし、 msvcrt.dll を使用しているので動作保証は...。 -- Irisawa 2006-11-03 (金) 23:19:32
  • 出力結果はこうなります。
    0
    1
    2
    #pragma twiceの解説によれば…
    0:シングルバイト(1バイト文字)
    1:マルチバイトの先行バイト(2バイト文字の1バイト目)
    2:マルチバイト文字の後続バイト(2バイト文字の2バイト目)
    出力すると「\ソ」だから1文字目が1バイト文字、2文字目が2バイト文字なわけですね。これでどこを見ても判定できると。 しかしmsvcrt.dllはVCにしか入っていないランタイムだから使うにはベクターでランタイムDLしてこないといけませんね。 -- GENKI? 2006-11-04 (土) 13:00:36
  • 禁則処理について調べてたらワードラップ処理っていうのもあるんですね。どうしようかな…。 -- GENKI? 2006-11-04 (土) 13:08:53
  • DrawText?使えばこんな簡単だったんですね..._| ̄|○ -- GENKI? 2006-11-04 (土) 17:29:08
  • あとは分離禁則(数字やアルファベットは途切れ目での改行)に対応すればだいたい完璧? -- GENKI? 2006-11-05 (日) 00:45:27
  • msvcrt.dll は Explorer などのシステムアプリケーションも依存している RTL なので最近の Windows には標準で入っています。
    ただし上記の理由からユーザーアプリケーションでの利用は推奨されていないようです。 -- naznyark? 2006-11-05 (日) 00:49:59
  • ベクターにファイルあったからDLしないといけないものだと思ってました。 [worried2]あれはバージョン違いとかなのかな。 推奨されないものならあまり使わないほうがいいのでしょうね。 -- GENKI? 2006-11-05 (日) 12:07:08
  • DrawText?ってスゴイですねっ★アメリカで作られたのに、日本語までしっかり折り返してる・・・m( ̄ε ̄* ・・・けどよく考えたら、一文字ずつ表示するアドベンチャーでは使えなかったデス(笑)自動改行モジュールを参考にさせていただきますm(_ _)m -- りさ 2006-11-06 (月) 02:24:27
  • あと、全く関係ない話なんですが、アタシは「1バイトか?」という意味で IsByte? と名付けたのですが、「2バイトか?」なら IsBytes? じゃなんでしょうか?? 調べたら、単数が Byt だったり、単数も複数も関係なく Byte だったり色々でシタ(比べているのが一つの対象なので、AreBytes? じゃないのは分かるんですが) -- りさ 2006-11-06 (月) 02:53:02
  • [tere] [sig] 別に深い意味はないのです…。その場その場で行き当たりばったりで変数名とか命令名とかつけちゃうので、結果的にあんなふうになっちゃったと…。 -- GENKI? 2006-11-06 (月) 22:08:04
  • DrawText?←調べたら右から書く国の文字にも対応してるっぽいです。さすが世界で使われるだけのことはあります。 -- GENKI? 2006-11-06 (月) 22:10:12
  • アドベンチャーではフォントサイズが変わる場合も考えられるのでstrmidを使った改行ではなく1文字ずつ調べる方法を取りました。ここでは文字数カウントで改行していますが、これを文字幅に変えれば対応できそうかな?という感じです。実際できるかはやってみないとなんともですが。 -- GENKI? 2006-11-06 (月) 22:14:01
  • 1バイト文字の分離禁則みたいなのを検討中。ようやく1バイトのみの文字列でちゃんと動くようになったのであとは2バイトに対応させれば…。 -- GENKI? 2006-11-07 (火) 00:42:16
  • DrawText?はかなり複雑な関数なんですネ☆ちなみに 英語ではハイフンで繋ぐのでhyphenation(ハイフォネーション)と呼び、日本語で使われているのは、Japanesehyphenation と呼ぶらしいデス。=禁則処理 のようです。 -- りさ 2006-11-07 (火) 02:50:32
  • 画面の真ん中から表示することもあるので、そういう意味でも(x軸)の値を使うことになりそうデス☆ -- りさ 2006-11-07 (火) 03:06:55
  • HSPのモジュールで作ったMbsbType?命令に正常に検知できないバグがあったので修正しました。…調査不足が原因です。orz -- GENKI? 2006-11-09 (木) 01:36:29
  • 機能追加しようとしたらバグ多発につき、スクリプトの改装・整理中。…バグがバグがぁ [sad2] -- GENKI? 2006-11-09 (木) 01:44:54
  • 「ニャッ!!」 ←っていう場合もありマスよね(涙)切捨ては簡単にできたんですが、禁則処理付きの折り返しが思ったより難しいことに気が付きました(笑) -- りさ 2006-11-09 (木) 21:33:29
  • Wikiで表書くのって難しい…_| ̄|○ -- GENKI? 2006-11-09 (木) 22:12:08
  • 自動改行はmoji18.hspが最終バージョンです。他のサンプルとかはバグがあるのでご注意ください。2バイト文字の禁則処理(行頭・行末禁止)に対応。英単語を単語をハイフンで区切るハイフネーションには対応していません。半角文字は分離禁則を採用しました。 -- GENKI? 2006-11-11 (土) 23:40:29
  • 次の問題があるため場合によっては表示範囲を超える行が出ることがあります。 -- GENKI? 2006-11-11 (土) 23:43:48
    • 禁則処理対象の文字が1行以上続くと改行しない。
    • 分離禁則文字列が1行以上つづいても強制改行しない。
  • 今、オーナードローでちまちまとテキストエディタを作ってるんで、ここのモジュールはすごくいい資料になりそうです。GENKIさんがんばってください! -- 猫太? 2006-11-12 (日) 15:37:07
  • オーナードローですか、大変そうですね。猫太さんも頑張ってください。いい資料になれば幸いです。 -- GENKI? 2006-11-12 (日) 18:28:14
  • 自動改行文字幅指定タイプのモジュールが思いのほか簡単に出来ちゃったので、ほんとうに大丈夫なのか逆に不安です。 [worried2] あ、そうだ、文字幅指定タイプのサンプル差し替え用のを作らないといけませんね…。バグが残ったままだ。 -- GENKI? 2006-11-12 (日) 23:48:30
  • シフト漢字コードメモ…。 -- GENKI? 2007-08-18 (土) 00:43:28
  • 2byte文字の判定のスクリプトを行頭と行末のタブとスペースを取り除くモジュールのページにて使用させていただきました。便利なスクリプトを作成していただいてありがとうございます。これからもちょくちょく使わせてください -- y.tack? 2008-12-18 (木) 11:40:27
  • 自動改行(文字幅指定タイプ、禁則処理対応)モジュール」の禁則処理関係のバグ修正版を公開しました。(m_stringモジュール)主な修正内容は次の2件。 -- GENKI? 2009-01-04 (日) 22:03:21
    • 禁則処理対象の文字が1行以上続くと改行しない。
    • 英文ワードラップの影響で英数字が1行以上つづいても強制改行しない。

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

*1 文字ごとに幅が指定されたフォント。例:「i」より「w」のほうが幅が広い。
*2 文字ごとに幅が指定されたフォント。例:「i」より「w」のほうが幅が広い。
添付ファイル:
filemoji20.hsp
507件 [詳細]
filemoji21.hsp
542件 [詳細]
filemoji19.hsp
361件 [詳細]
filemoji18.hsp
514件 [詳細]
filemoji11.hsp
279件 [詳細]
filemoji08.hsp
272件 [詳細]
filemoji06.hsp
518件 [詳細]
filemoji04.hsp
369件 [詳細]
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2012-03-03 (土) 15:03:03 (645d)