ファイルビュワー作成日誌 #006:テキストビュワー
概要
テキストビュワーができました。
但し、開くときの文字コードチェックが遅いのであとで改良します。
一度開いてしまえば、表示は速いですから。
1文字でも表示できない文字が入ってたらエラーではじいてるんですが、
ファイルサイズがでかいやつは、先頭の何行かに絞った方がビュワーとしては合目的的かと思いやす。
現状、ファイルサイズが 100KB 超えるといらつくレベルです。
文字コードは Shift-JIS 以外に Unicode と UTF-8 に対応しました。
Unicode は BOM 必須ですが、UTF-8 はあってもなくても構いません。
開くとき全部スキャンしてるんで。
テキストビュークラス
テキストビュークラスは、ファイルビュークラスの派生クラスです。
Open() 関数でファイルオープンするとき、CheckFileType() 関数でテキストファイルかどうかチェックしてます。
なのでファイル拡張子とか一切無視してチェックします。
そのファイルに表示可能なデータしかなければ、それはテキストファイルとみなします。
なのでXファイルとか各種ソースファイルとか、拡張子をチェックする必要が一切ありません。
手抜きするためならどんな苦労も厭いません。
その代わり、でかいテキストファイルを開くのが遅いです。
本当のバイナリファイルならすぐチェックではじかれるので問題ないのですが、
Xファイルのソースみたいな、メガサイズのテキストファイルはちょっと非実用レベルです。
class TextView : public FileView { public : struct LinePos { UINT line; LONGLONG pos; }; static const INT nMaxLinePos = 1000; static const INT nMinLineBound = 100; static const LPCTSTR pszKeyTabSize; public : LinePos linePos[ nMaxLinePos ]; UINT nLinePosCount; UINT nLinePosBound; UINT nTabSize; BOOL bEOF; BOOL bError; UINT nLineColumn; public : virtual inline LPCTSTR GetRegistClassName() { return _T( "ClassTextView" ); } virtual inline LPCTSTR GetSectionName() { return _T( "TextView" ); } virtual BOOL CheckFileType(); virtual BOOL ScanLineToFileEnd( UINT line ); virtual VOID UpdateFileData( LONGLONG pos, LONGLONG size ); virtual VOID AddLinePos( UINT line, LONGLONG pos ); virtual LONGLONG GetLinePos( UINT line ); virtual DWORD ScanLineData( LPTSTR buffer = NULL, DWORD size = 0, TCHAR chTab = _T( ' ' ) ); virtual LRESULT OnWmCreate(); virtual LRESULT OnWmDestroy(); virtual LRESULT OnWmPaint(); };
解説
linPos 配列には、適当な間隔で行のファイルポジションが保存されてます。
なので表示の時は速いのです。
以前エディットコントロールをファイルビュワーとして使おうとしましたが、とてもとても遅くて使い物になりませんでした。
なので表示だけは速いものにしたかったのです。
オープンするときファイルビュークラスの方でコードページをチェックしてますが、
BOM なしの UTF-8 に関しては、こっちの ScanLineData() 関数でチェックしてます。
ScanLineData() 関数では、スキャンするついでに表示文字列も作成します。