全クラス、名前空間、定数の仕様書

root.html から順にたどってご覧下さい。

ビルド方法

Visual C++ 6.0 SP5 の場合
kilib.dsw を開いて、ビルド(F7)
Visual C++ .NET SP1 の場合
kilib.sln を開いて、ソリューションのビルド
まだ私はVC6で開発してますので、こっちの更新を時々忘れるかも
Borland C++ Compiler 5.51 の場合
プロジェクトのディレクトリをカレントにしてDOS窓を開く。
make と打って Enter。
Digital Mars C++ Compiler 8.27 の場合
プロジェクトのディレクトリをカレントにしてDOS窓を開く。
smake と打って Enter。
Open Watcom 1.0 の場合
リリースされたら対応を考えます〜。
gcc 系の開発環境の場合
誰か対応してくれる人がいるかもと期待。
ccdoc によるドキュメント自動生成
プロジェクトのディレクトリをカレントにしてDOS窓を開く。
makedoc と打って Enter。

とりあえずGreenPadのソースの読み方

・プログラム開始点は、GpMain.cpp の int kmain() です。
 もちろんその前にkilib内部で色々動作は走ってますが、その辺り細かいことは
 気にしないでOK。kmain()からトレースして下さい。

・editwingは、大きく分けて Control, Document, View, Cursor の4パートからなります。

・Control は、いわゆる普通のエディットコントールっぽい体裁をなしています。
 普通に外から触るのはこの部分だけとなるでしょう。

・Document は文字列データを保持します。
 キーワード色分け用設定や、色分け用にパース済みのデータなども持ちます。

・Viewは、データの表示担当です。
 文字列の折り返し箇所や、折り返しの設定、行番号領域の表示/非表示設定を保持します。

・Cursorは、Viewの一部で、ユーザーからの入力処理担当です。
 カーソル位置の制御や、そこへのテキスト入力などを管理します。

・Documentは、単独でも存在できるようになってます。ViewやControlは、
 Documentにイベントリスナとして登録することで、Documentと連携します。

・一つのDocumentに、複数のViewを対応させることが出来ます。
 同じテキストだけど表示箇所は違う、という分割Windowなどを
 サポートできるようにするためです。

・一つのView毎に、一つのCursorを持ちます。

kilib 3rd 構築 私的メモ

☆小型化にあたって

 1.スタートアップコードを省くため、C/C++標準ライブラリを
   用いることができない。ひょっとしたら初期化無しでも使える
   関数があるかもしれないが、いちいち調べるのも面倒なので
   全部使わないことにする。
   ただし、コンパイラによる組み込み関数生成が可能な
        abs, fabs, labs,  memset, memcpy,
        strcat, strcmp, strcpy, strlen
   は例外的に使うことが出来る。memmoveも作ったのでこれも○。

 2.スタートアップを省略した弊害として、グローバルオブジェクト
   やstaticオブジェクトが利用できなくなる。コンストラクタ等の
   呼び出しが行われないためである。関数内のstaticオブジェクト
   の場合はOKとは思うが、いずれにせよデストラクタは呼ばれな
   さそうな気がする。よって×。
   Singletonを作りたい時に少しキビシイが、まぁ大して困らないはず…。

   なお、VC++の場合はマクロSUPERTINYを#undefすることで、他の
   コンパイラの場合は何もしなくても、ライブラリ関数/staticオブジェ
   を使えるように復帰できる。

 3.例外を扱わない。巻き戻し処理の分を省くためである。
   ただし、コンパイルオプションを変更するだけで例外安全を
   保証できるようなソースを書くよう心がける。
   try/catch 無しでも例外安全にすることは不可能ではない。

   …と偉そうなことを書いたのはどこのどいつだムキィ!
   …えーと、めんどーになってきたので程々に。

 4.operator new の実装は、標準のmalloc等を使わず直にHeapAlloc APIを
   毎回呼ぶのがデフォルトになっている、がこれは恐ろしく遅い。
   各種コンテナを書くときや、クラスオブジェクトのデストラクタなどでは
   mem().Alloc/Dealloc() でメモリ操作する。なお、class Object から
   派生することで自動で operator new を mem().Alloc() に振り替えられる。

☆命名規則

 1.クラス名、フリー関数名、メンバ関数名 は基本的に大文字始まり

        ex) class Dog : public Animal { ... };
            int PrintSomeData();

 2.名前空間名は全て小文字

        ex) namespace utility { ... }

 3.ローカル変数名、メンバ変数名は小文字始まり。Java風、ラクダ風。
   メンバ変数の最後には _ をつける。

        ex) int x = this->canvasSize_;

 #4.組込型と同等に扱いたいような基本的なクラスは全て小文字

        ex) template class array { ... };

 #5.単なるプロパティ取得用のメンバ関数は小文字始まり

        ex) int ClassA::sizeOfXxx() { ... }

 #6.参照として用いるポインタ、ハンドル型のメンバ変数には、
      それぞれ接頭辞 p, h をつける。この接頭辞が付いたメンバの
      指すオブジェクトの生成/解放については、そのクラスは関知しない。

        ex) Window* pParent;

   逆に、new/delete で動的に処理するためだけにポインタと
   なっているようなメンバについては、この接頭辞は付けない。

        ex) MyPImpl* impl_;

   参照型変数については、常に前者の使い方しかされないと
   考えられるため、r 等のプレフィックスは不要とする。

 #7.イベントハンドラ関数は on_xxxx_yyy() という名前

        ex) void Dialog::on_button_down() { ... }

☆コーディングスタイル・メモ

 クラスのメンバは、
  ・公開オペレーション関数
  ・公開アトリビュート関数
  ・公開ユーティリティ関数(static)
  ・protected 内部構造体
  ・protected 関数
  ・private 内部構造体
  ・private 関数
  ・private メンバ
  ・friend/NOCOPY など
 の順序で書く。基本的に。

 1文 if/for/while/do-while の場合は {} を用いない。
 私にとってはその方がずっと読みやすいので。ただし、
 if {} else if {} else {} において、{}を用いるものと
 用いないものが入り交じるようには書かない。その場合は
 1文のものでも {} で囲う用にする。

☆コンパイラ識別マクロ…

 _MSC_VER
 __BORLANDC__
 __DMC__

☆プロジェクトの設定(VC++):

 ・プリプロセッサの定義 += SUPERTINY
 ・例外処理, RTTI を無効にする
 ・最適化
  (グローバルの最適化・組み込み関数の生成・サイズ優先・フレームポインタ略)
  ( /GF オプション追加 )
 ・デバッグ /GZ オプション削除
 ・PCH: kilib/stdafx.c   ==> stdafx.hまでで作成
       その他のファイル ==> stdafx.hまでを使用
  どのソースファイルにも一番先頭に
      #include "stdafx.h"
  を記述。kilib配下でないファイルについても上の通りで良い。
  (stdafx.hに対するincludeは自動的にpchへ振り返られる)

☆SHELL32.LIB/IMM32.LIB for DMC++

 まず Borland の impdef.exe で、 -a オプションを付けて shell32.dll から
 定義ファイル作成。あとは @nn という形式で、スタックずらしサイズを手で
 PlatformSDK付属のlibからうつして書いていく。
 完成したら Borland の implib.exe で def から lib を作成。