@node viewlib, Variable Index, utils, Top
@comment  node-name,  next,  previous,  up
@chapter viewlib

@menu
* outline_viewlib::             
* check_event.c::               
* v_get_string_pic.c::          
* v_loop.c::                    
* v_open_disp.c::               
* v_text.c::                    
* v_window::                    
* v_XX::                        
@end menu

@node outline_viewlib, check_event.c, viewlib, viewlib
@comment  node-name,  next,  previous,  up
@section ウィンドウ関連コード概要
ウィンドウ操作関数には、

@itemize
@item v_open_disp ディスプレイの生成
@item v_open_win ウィンドウの生成
@end itemize

の関数の他に、ウィンドウの中にオブジェクトを生成し、さまざまな操作を行うオブジェクト操作関数がある。
まず、ライブラリユーザは、ディスプレイを生成し、その中に、いくつかのウィンドウを生成し、最後に、ウィンドウの中に様々なオブジェクトを描画することが出来る。

また、マウスイベントなどのイベントがディスプレイ上で発生した場合には、ユーザ定義のイベントハンドラと各オブジェクトに通知されて所定の処理が行われる。
すべてのオブジェクトのコーディングは、そのオブジェクト名のファイルに記述されており、一種のオブジェクト指向型記述となっている。

オブジェクトに含まれるインスタンス関数には、どのオブジェクトにもある基本関数と、オブジェクト固有な関数がある。基本関数としては、オブジェクト名をXX とすると、

@sp 1
@example
v_redraw_XX
v_XX_handler
v_create_XX
v_set_XX
v_XX_minrect
@end example
@sp 1

以上の５つがある。
また、一つのオブジェクトのインスタンス変数は一つの構造体として定義し、それらをあつめVOBJECTという共用体を定義する。
各オブジェクトの構造体の第一番目のメンバーは、VOBJ_HEADER というヘッダ構造体ではじまる。このヘッダにはオブジェクトを識別するtype などのフィールドが定義されている。

オブジェクト指向のインスタンス変数は通常、オブジェクト外部から読めないのが普通であるが、処理効率を上げることから、特定のインスタンス変数のみは外部から読み書きをしてもよいことにする。どの変数がその対象となるかは、各オブジェクトのインスタンス変数の説明の項目で説明する。

以下、関数の説明は、v_open_disp など、オブジェクト操作以外の関数を説明し、続いてオブジェクトの基本関数。オブジェクト固有な関数と説明をする。

現在サポートしているオブジェクトはimage とtext である。image はピクセルマップイメージのオブジェクトであり、text は文字列描画のオブジェクトである。


@node check_event.c, v_get_string_pic.c, outline_viewlib, viewlib
@comment  node-name,  next,  previous,  up
@section ./check_event.c

@defun check_event
@cartouche
@example
#include "v.h"
int
check_event(
    VWINDOW * @var{win},
    int @var{type},
    int @var{subtype}
);
@end example
@end cartouche

@heading 説明
@example
@var{win}     : イベントの発生したウィンドウ
@var{type}    : イベントのタイプ
@var{subtype} : イベントのサブタイプ
@end example

未処理のイベントの中に、@var{win},@var{type},@var{subtype} で指定されるイベントがあるかどうかチェックする。あると、1,無いと0 を返す。

@heading リターンデータ
@example
0：イベントがなかった。
1：イベントがあった。
@end example

@heading 詳細
@var{type}, @var{subtype} はv_loop の項を参照。

@end defun


@node v_get_string_pic.c, v_loop.c, check_event.c, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_get_string_pic.c


@defun v_get_string_pic
@cartouche
@example
#include "v.h"
void
v_get_string_pic(
    V_STRING_PIC * @var{p},
    VDISPLAY * @var{win},
    L_CHAR * @var{str},
    int @var{size},
    int @var{dir}
)
@end example
@end cartouche

@heading 履歴
@table @samp

@item 01/11/10

基本的に、今までは文字コードの識別をプログラム・コード内にダイレクトに書いて識別していました。それを、@code{d->font work} のテーブルを参照することによって行うように改造しました。
以下にソース変更箇所を示します。

@sp 1
@example
void
v_get_string_pic(
    V_STRING_PIC * @var{p},
    VWINDOW * @var{win},
    L_CHAR * @var{str},
    int @var{size},
    int @var{dir})
@{
    int @var{len};
    int @var{i},@var{j};
    V_STRING_PIC @var{pp};
    L_CHAR @var{unknown};
    int @var{f};
    WRITABLE_CODE_TABLE * @var{t};
    len = l_strlen(str);
    unknown = '?';
    f = 0;
    for ( i = 0 ; i < len ; ) @{
    /* ここのコードが変わりました。*/
        t = get_wct(win->d->font_work,str[i]);
        if ( t ) @{
            for ( j = i ; j < len &&
                (str[j]&t->mask) == t->lcz ; j ++ );
                v_get_string_pic_call(
                    &pp,
                    win,
                    &str[i],
                    j-i,
                    t->work,
                    size,
                    dir,
                    t->mask
                );
                i = j;
        @}
        else @{
                v_get_string_pic_call(
                    &pp,
                    win,
                    &unknown,
                    1,
                    &win->d->iso8859_1,
                    size,
                    dir,
                    LCZM_1B_TYPE);
                    i ++;
        @}
        if ( f == 0 ) @{
            *p = pp;
            f = 1;
        @}
        else @{
            compose_pic(p,&pp);
        @}
    @}
@}
@end example


@item 02/11/19
VWINDOW * の引数をVDISPLAY *に変更しました。これは、文字のビットマップを取り出すときにviewagent ではウィンドウを表示しないので、VWINDOW *はまずいからです。

@end table
@end defun



@node v_loop.c, v_open_disp.c, v_get_string_pic.c, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_loop.c



@defun v_loop
@cartouche
@example
#include "v.h"
int
v_loop( );
@end example
@end cartouche

@heading 説明
ウィンドウイベントをまつイベントループ。

@heading リターンデータ
ごみ

@heading 詳細
現在サポートしているイベントは、
イベントタイプイベントサブタイプ

@example
VE_REDRAW なし
ウィンドウのリドロー要求
VE_BUTTON VES_BUTTON_PRESS
マウスのボタンのプレス検知
VE_BUTTON VES_BUTTON_RELEASE
マウスのボタンのリリース検知
VE_BUTTON VES_BUTTON_MOTION
マウスの移動検知
@end example

の４種類である。
これらのイベントが発生した場合、発生したディスプレイのイベントに対応するユーザ定義のハンドラと、このウィンドウに登録されたおのおののオブジェクトのハンドラを呼び出す。
ディスプレイのユーザ定義ハンドラの呼び出しの場合。

@example
VE_REDRAW:
handler(x,y,w,h):
int x,y,w,h;
ウインドウの右上の座標と、width,height;
VE_BUTTON:
handler(subtype,t,x,y);
int subtype 上述イベントサブタイプ
int t イベント発生時間
int x,y マウスポインタの位置
@end example

オブジェクトのハンドラは、イベントに対応した処理が行えればよいので、実装依存でよい。ただし、どのような操作が行われるかの仕様は、各オブジェクトごとに定義する。

@end defun


@node v_open_disp.c, v_text.c, v_loop.c, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_open_disp.c


@defun v_open_disp
@cartouche
@example
#include "v.h"
VDISPLAY *
v_open_disp(VERROR * @var{err});
@end example
@end cartouche

@heading 説明
@example
@var{err} : エラー結果格納場所
@end example

ディスプレイをひとつ開く。

@heading リターンデータ
ディスプレイ構造体。

@heading 詳細
ディスプレイの初期化などを行って、必要なワークエリアなどを備えたディスプレイ構造体を返す。この構造体では、ディスプレイ内で発生したイベントのユーザ定義ハンドリング関数を格納以外は実装依存である。

@example
typedef struct vdisplay @{
    ...
    int (*handler[VE_MAX])();
    ...
@} VDISPLAY;
@end example

この関数は発生するイベントごとに定義されているので、配列となっている。イベントの種類はv loop の項目を参照されたい。
また、ディスプレイ上で定義されたウィンドウは、この構造体の中のウィンドウリストに登録される。

@end defun


@node v_text.c, v_window, v_open_disp.c, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_text.c
@heading text.c の履歴
char *からL_CHAR *への変更

@sp 1

これらの、テキスト処理において、データがchar *だったものから、L_CHAR *へ変更しました。それに伴い、複数のフォントが使えるようになりました。移植時には、v_get_string_pic のコードも参考になると思います。
ここで問題となるのは、v_text_minrect の処理です。複数のフォントが使用されるので、minrect の計算が大変になります。一応、文字を描画したときに、minrect を合成したminrect をセットしておいて、それを取り出すようにしました。
この方法ではv_move_text でテキストを移動させたときに、問題が起こりますので、移動時には、再描画して再びminrect も計算します。
右から、左からの文字が混在した場合はあまり考慮していません。


@node v_window, v_XX, v_text.c, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_window


@defun _v_clear_window_content
@cartouche
@example
int
_v_clear_window_content(
    V_CLEAR_WINDOW_CONTENT_S * @var{v}
)
@end example
@end cartouche

@heading 説明

@heading リターンデータ
@end defun


@defvar V_CLEAR_WINDOW_CONTENT_S
@cartouche
@example
typedef struct v_clear_window_content_s @{
    VERROR * @var{err};
    VWINDOW * @var{win};
@} V_CLEAR_WINDOW_CONTENT_S;
@end example
@end cartouche

@heading 説明
@example
@var{err} : エラー結果格納場所
@var{win} : 対象ウインドウ
@end example

@end defvar


@defun v_clear_window_content
@cartouche
@example
void
v_clear_window_content(
    VERROR * err, VWINDOW *win
)
@end example
@end cartouche

@heading 説明

@heading リターンデータ

@heading 詳細
src/gbview/interface.c のredraw_handler において以下を追加。

@example
if ( change ) @{
    v_clear_window_content(&err,env.im->header.win); // ←追加
    _ex_lock();
    change_size();
    ......
@end example
@end defun


@defun v_get_window_attribute
@cartouche
@example
#include "v.h"
int
v_get_window_attribute(
    VERROR * @var{err},
    VWINDOW_ATTRIBUTE * @var{attr},
    VWINDOW * @var{win});
@end example
@end cartouche

@heading 説明
@example
@var{err}  : エラー結果格納場所
@var{attr} : ウインドウアトリビュート格納場所
@var{win}  : 対象ウインドウ
@end example

開かれているウィンドウのアトリビュートを返す。


@heading リターンデータ
ごみ

@heading 詳細
現在サポートしているアトリビュートはウィンドウの位置大きさで、

@example
typedef window_attribute @{
    int @var{x},@var{y},@var{w},@var{h};
@} WINDOW_ATTRIBUTE;
@end example

となっている。

@example
@var{x},@var{y} : 表示位置、ウィンドウの左上の座標
@var{w},@var{h} : ウインドウのwidth,height
@end example

@end defun


@defun v_open_win
@cartouche
@example
#include "v.h"
VWINDOW *
v_open_win(VERROR * @var{err},VDISPLAY * @var{d},int @var{x},int @var{y},int @var{w},int @var{h});
@end example
@end cartouche

@heading 説明

@example
@var{err} : エラー結果格納場所
@var{d}   : 表示先ディスプレイ
@var{x},@var{y} : 表示位置、ウィンドウの左上の座標
@var{w},@var{h} : ウインドウのwidth,height
@end example

ウィンドウをひとつ開く。

@heading リターンデータ
ウィンドウ構造体。

@heading 詳細
ウィンドウの初期化などを行って、必要なワークエリアなどを備えたウィンドウ構造体を返す。
ウィンドウ構造体には、ウィンドウ処理のための機種依存ワークエリアなどの他に、描画オブジェクトのリストがある。このウィンドウ上に生成されたオブジェクトはウィンドウ構造体の中のオブジェクトリストに登録される。
現在定義されているオブジェクトはimage オブジェクト(v image.c) とtext オブジェクト(v text.c) のみである。
生成されたウィンドウ構造体は、ディスプレイ構造体のウィンドウリストに登録される。
@end defun



@node v_XX,  , v_window, viewlib
@comment  node-name,  next,  previous,  up
@section ./v_XX


@defun v_create_XX
@cartouche
@example
#include "v.h"
VOBJECT*
v_create_XX(
    VERROR * @var{err},
    VWINDOW * @var{win},
    ...
);
@end example
@end cartouche

@heading 説明
@example
@var{err} : エラーリターンした場合のエラーコード格納場所
@var{win} : オブジェクトを生成するウィンドウ
@var{...} : オブジェクト依存の引数
@end example

与えられた引数の条件で、ウィンドウ上にオブジェクトを生成する。描画もする。

@heading リターンデータ
成功したら、オブジェクト構造体。失敗したら0。err にエラーコードが格納される。

@heading 詳細
オブジェクト依存引数は以下の通りである。

@example
VOBJECT *
v_create_image(
    VERROR * err,
    VWINDOW * win,
    int x,
    int y,
    int w,
    int h);
x,y : 生成するイメージの左上の座標（ウィンドウ内）
w,h : 生成するイメージの大きさ。横w pixel 縦h pixel

VOBJECT *
v_create_text(
    VERROR * err,
    VWINDOW * win,
    unsigned long color,
    unsigned long background,
    int st_x,
    int st_y,
    char * fname,
    char * data,
    int length);

color : 文字の色
background : 文字の背景色
st_x,st_y : 文字を書き始めるスタート座標
fname : フォント名
data : 描画文字列
length : data の長さ
background > 0x1000000 である場合、背景色は透明。
@end example
@end defun



@defun v_move_text
@cartouche
@example
#include "v.h"
VOBJECT*
v_move_text(
    VOBJECT * @var{obj},
    int @var{x},int @var{y}
);
@end example
@end cartouche

@heading 説明
@example
@var{obj} : 対象オブジェクト
@var{x,y} : テキストを動かす方向
@end example

現在の位置からの変位(x,y) へテキストの位置をずらす。

@heading リターンデータ
ごみ

@end defun


@defun v_redraw_XX
@cartouche
@example
#include "v.h"
int
v_redraw_XX(VOBJECT * @var{obj});
@end example
@end cartouche

@heading 説明
@var{obj} ： 対象となるオブジェクトの構造体
オブジェクトを再描画する。

@heading リターンデータ
ごみ

@end defun


@defun v_set_XX
@cartouche
@example
#include "v.h"
VOBJECT*
v_set_XX(
    VOBJECT * obj,
    ...
);
@end example
@end cartouche


@heading 説明
@example
@var{obj} : 対象オブジェクト
@var{...} : オブジェクト依存の引数（v_create_XX と同じ）
@end example

対象オブジェクトのインスタンス変数を書き換える。描画はしない。

@heading リターンデータ
ごみ

@heading 詳細
オブジェクトの状態を書き換えることによって、表示位置を移動したり、表示する文字列を変えたりすることができる。描画はしないので、v redraw XX を呼び出す必要がある。
オブジェクト依存の引数は、以下の値を入れることによって、それぞれたの引数とは独立に無効にすることができる。
char *型の引数の場合0
color を与える変数（int） > 0x2000000
座標は無効にする事が出来ない。

@end defun


@defun v_XX_handler
@cartouche
@example
#include "v.h"
int
v_XX_handler(VOBJECT * @var{obj},int @var{cmd});
@end example
@end cartouche

@heading 説明
@example
@var{obj} : 対象となるオブジェクトの構造体
@var{cmd} : 発生イベント
@end example

イベント処理する。

@heading リターンデータ
ごみ

@heading 詳細
この関数は、v loop によって捕まえられたイベントの実際の処理を行う関数である。それぞれのオブジェクトごとに、処理するイベントと無視するイベントが決まっている。現在サポートしているオブジェクトはimage とtext だけで、いずれも、VE_BUTTON イベントは無視する。VE_REDRAWイベントは処理する。

@end defun


@defun v_XX_minrect
@cartouche
@example
#include "v.h"
VOBJECT*
v_XX_minrect(
    VRECT * @var{r},
    VOBJECT * @var{obj},
    ...
);
@end example
@end cartouche

@heading 説明
@example
@var{r} : オブジェクトを囲む最小長方形
@var{obj} : 対象オブジェクト
@end example

対象オブジェクトを囲むことの出来る最小長方形をかえす。

@heading リターンデータ
ごみ
@end defun


@defvar VIMAGE;
@cartouche
@example
#include "v.h"
typedef struct vimage @{
    VOBJ_HEADER _h;
    int @var{x};
    int @var{y};
    int @var{w};
    int @var{h};
    int @var{w_border};
    機種依存コード
@} VIMAGE;
@end example
@end cartouche

@heading 説明
@example
@var{x},@var{y} : イメージの左上の座標
@var{w},@var{h} : イメージの大きさ　横w pixel 縦h pixel
@var{w_border} : 実際のフレームバッファの横のピクセル長
@end example

ピクセルマップイメージオブジェクトのインスタンス変数。以上の変数が外部からも参照される。

@heading 履歴

@table @samp
@item 02/11/29
VIMAGE にw_border というメンバーを用意しました。これは実際のフレームバッファの横のピクセル長です。いままでの、w は表示される横の長さです。当然

@example
w <= w_border
@end example

です。XWindow では、いつもw = w_border です。
@end table

@end defvar


@defvar VTEXT;
@cartouche
@example
#include "v.h"
typedef struct vtext @{
    VOBJ_HEADER _h;
    機種依存コード
@} VTEXT;
@end example
@end cartouche

@heading 説明
テキストオブジェクトのインスタンス変数。外部から参照できる変数はなし。

@end defvar
