home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 3
/
FREEWARE.BIN
/
towns_os
/
fildlg22
/
button.c
next >
Wrap
C/C++ Source or Header
|
1980-01-02
|
10KB
|
459 lines
/*
* button.c
*/
#include <stdlib.h>
#include <string.h>
#include "display.h"
#include "mouse.h"
#include "button.h"
#define GLOBAL
#define TRUE 1
#define FALSE 0
/*--------------------------------------*/
/* 定数定義 */
/*--------------------------------------*/
#define MaxButton 20
/*--------------------------------------*/
/* 変数定義 */
/*--------------------------------------*/
/* ボタン情報 */
button_t _BT_Buttons[MaxButton];
/* 空きボタン先頭ID */
int _BT_NextButton = 0;
/*--------------------------------------*/
/* ローカル関数宣言 */
/*--------------------------------------*/
/* ローカル関数は無し */
/*--------------------------------------*/
/* 関数定義 */
/*--------------------------------------*/
GLOBAL int
BTN_create(
button_t *btn)
/*
* PURPOSE
* 指定されたパラメタでボタンを作成,表示し,ボタンIDを返す.
* 指定すべきパラメタ(button_tのメンバ名)は以下の通り.
* string, enable, repeat, luX, luY
* RETURNS
* >= 0 : ボタンID
* -1 : ボタンの生成不可
* NOTICE
* 本関数はパラメタで渡されたボタン構造体の
* メンバstringをそのまま保持するため,
* 呼出元はstringが指す先の文字列を破壊してはならない.
* IMPLEMENT
* 本来は動的にメモリを確保すべきだが,
* ここではとりあえず固定領域を使用する.
*/
{
int luX, luY;
int rdX, rdY;
int strX, strY;
int len;
if (_BT_NextButton >= MaxButton)
return(-1);
_BT_Buttons[_BT_NextButton].next = NULL;
_BT_Buttons[_BT_NextButton].string = btn -> string;
_BT_Buttons[_BT_NextButton].enable = btn -> enable;
_BT_Buttons[_BT_NextButton].on = FALSE;
_BT_Buttons[_BT_NextButton].repeat = btn -> repeat;
_BT_Buttons[_BT_NextButton].luX = btn -> luX;
_BT_Buttons[_BT_NextButton].luY = btn -> luY;
_BT_Buttons[_BT_NextButton].btnId = _BT_NextButton;
luX = btn -> luX;
luY = btn -> luY;
strX = luX + 8;
strY = luY + 8 + 16;
len = strlen(btn -> string);
rdX = luX + len * 8 + 16 - 1;
rdY = luY + 16 + 16 - 1;
DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);
DISP_stringAt(btn -> string, strX, strY,
(btn -> enable) ? CI_Black : CI_DarkGray);
DISP_line(rdX - 1, luY, luX, luY, CI_White); /* 外枠 */
DISP_line(luX, luY, luX, rdY, CI_White); /* 外枠 */
DISP_line(rdX - 2, luY + 1, luX + 1, luY + 1, CI_Gray); /* 内枠 */
DISP_line(luX + 1, luY + 1, luX + 1, rdY - 1, CI_Gray); /* 内枠 */
DISP_line(rdX, luY, rdX, rdY, CI_Black); /* 外枠 */
DISP_line(rdX, rdY, luX + 1, rdY, CI_Black); /* 外枠 */
DISP_line(rdX - 1, luY + 1, rdX - 1, rdY - 1, CI_DarkGray); /* 内枠 */
DISP_line(rdX - 1, rdY - 1, luX + 2, rdY - 1, CI_DarkGray); /* 内枠 */
return(_BT_Buttons[_BT_NextButton++].btnId);
}
/* --- BTN_create() --- */
GLOBAL void
BTN_allDestroy(void)
/*
* PURPOSE
* 全ボタンを削除する.
* IMPLEMENT
* 本来は個別のボタンをひとつずつ解放していくべきだが,
* ここでは_BT_NextButtonを初期化するだけとする.
*/
{
_BT_NextButton = 0;
}
/* --- BTN_allDestroy() --- */
GLOBAL int
BTN_setName(
int btnId,
char *string) /* 変更後のボタン名 */
/*
* PURPOSE
* 指定されたボタンのボタン名を消去後,
* 指定された文字列をボタン名として表示する.
* 旧ボタン名と新ボタン名の長さは等しいこと.
* RETURNS
* 0 : 正常終了
* -1 : ボタンIDが正しくない
* NOTICE
* 本関数はパラメタstringをそのまま保持するため,
* 呼出元はstringが指す先の文字列を破壊してはならない.
*/
{
int luX, luY;
int rdX, rdY;
int strX, strY;
int len;
button_t *pBtn;
if (btnId < 0 || btnId >= _BT_NextButton)
return(-1);
pBtn = &_BT_Buttons[btnId];
/* 元の領域を消去 */
luX = pBtn -> luX;
luY = pBtn -> luY;
strX = luX + 8;
strY = luY + 8 + 16;
len = strlen(pBtn -> string);
rdX = luX + len * 8 + 16 - 1;
rdY = luY + 16 + 16 - 1;
DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);
/* 新文字列を表示 */
DISP_stringAt(string, strX, strY,
(pBtn -> enable) ? CI_Black : CI_DarkGray);
/* 制御情報を更新 */
pBtn -> string = string;
return(0);
}
/* --- BTN_setName() --- */
GLOBAL int
BTN_enable(
int btnId,
int enable)
/*
* PURPOSE
* 指定されたボタンの有効状態を変更し,表示する.
* RETURNS
* 0 : 正常終了
* -1 : ボタンIDが正しくない
*/
{
int luX, luY;
int rdX, rdY;
int strX, strY;
int len;
button_t *pBtn;
if (btnId < 0 || btnId >= _BT_NextButton)
return(-1);
pBtn = &_BT_Buttons[btnId];
pBtn -> enable = enable;
luX = pBtn -> luX;
luY = pBtn -> luY;
strX = luX + 8;
strY = luY + 8 + 16;
len = strlen(pBtn -> string);
rdX = luX + len * 8 + 16 - 1;
rdY = luY + 16 + 16 - 1;
/* 文字列の背景は変更せず,文字列だけを再表示する.
DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);*/
DISP_stringAt(pBtn -> string, strX, strY,
(pBtn -> enable) ? CI_Black : CI_DarkGray);
return(0);
}
/* --- BTN_enable() --- */
GLOBAL int
BTN_reverse(
int btnId)
/*
* PURPOSE
* 指定したボタンのオンオフを反転し,表示する.
* RETURNS
* 0 : 正常終了
* -1 : ボタンIDが正しくない
*/
{
int luX, luY;
int rdX, rdY;
int strX, strY;
int len;
button_t *pBtn;
if (btnId < 0 || btnId >= _BT_NextButton)
return(-1);
pBtn = &_BT_Buttons[btnId];
pBtn -> on = (pBtn -> on == FALSE) ? TRUE : FALSE;
luX = pBtn -> luX;
luY = pBtn -> luY;
strX = luX + 8;
strY = luY + 8 + 16;
len = strlen(pBtn -> string);
rdX = luX + len * 8 + 16 - 1;
rdY = luY + 16 + 16 - 1;
DISP_xorRectBox(luX, luY, rdX, rdY, 0xffff);
DISP_xorRectBox(luX + 1, luY + 1, rdX - 1, rdY - 1, 0xffff);
return(0);
}
/* --- BTN_reverse() --- */
GLOBAL int
BTN_posCheck(
int btnId,
int x,
int y)
/*
* PURPOSE
* 指定した座標がボタン内か否かを判定し,その結果を通知する.
* 指定したボタンがenableでなければ,その旨を通知する.
* RETURNS
* 1 : 指定座標はボタン内
* 0 : ボタン外
* -1 : ボタンIDが正しくない
* -2 : ボタンがenableでない
*/
{
int luX, luY;
int rdX, rdY;
int strX, strY;
int len;
button_t *pBtn;
if (btnId < 0 || btnId >= _BT_NextButton)
return(-1);
pBtn = &_BT_Buttons[btnId];
if (pBtn -> enable == FALSE)
return(-2);
luX = pBtn -> luX;
luY = pBtn -> luY;
strX = luX + 8;
strY = luY + 8 + 16;
len = strlen(pBtn -> string);
rdX = luX + len * 8 + 16 - 1;
rdY = luY + 16 + 16 - 1;
if (x < luX || x > rdX)
return(0);
if (y < luY || y > rdY)
return(0);
return(1);
}
/* --- BTN_posCheck() --- */
GLOBAL int
BTN_isRepeat(
int btnId)
/*
* PURPOSE
* 指定したボタンがRepeat属性を持つか否かを通知する.
* RETURNS
* 1 : Repeat属性を持つ
* 0 : Repeat属性を持たない
* -1 : ボタンIDが正しくない
*/
{
button_t *pBtn;
if (btnId < 0 || btnId >= _BT_NextButton)
return(-1);
pBtn = &_BT_Buttons[btnId];
if (pBtn -> repeat == FALSE)
return(0);
return(1);
}
/* --- BTN_isRepeat() --- */
GLOBAL int
BTN_getButtonEvent(
int buttonIds[])
/*
* PURPOSE
* マウスでクリックされたダイアログボタンの
* 配列インデックス(イベントID)を通知する.
* 押下をチェックするダイアログボタンのIDは,
* buttonIds[]で指定する.
* 最終IDの次の要素には-1を格納しておくこと.
* RETURNS
* 配列インデックス(イベントID)
*/
{
int item;
int mosX, mosY;
int mosBtn;
int btnStatus;
int pushedBtn;
static int repeatId = -1;
while (1) {
pushedBtn = -1;
/* repeatモードの処理を行う */
if (repeatId != -1) {
do {
mosBtn = MOU_readPosition(&mosX, &mosY);
if (mosBtn & MouseLeftButton)
/*
* 同じボタンが押され続けていれば,
* 復帰する.
*/
if (BTN_posCheck(buttonIds[repeatId],
mosX, mosY) == 1) {
return(repeatId);
}
} while (mosBtn & MouseLeftButton);
/* repeatモード終了 */
MOU_display(Off);
BTN_reverse(buttonIds[repeatId]);
MOU_display(On);
repeatId = -1;
}
/* マウスの左ボタンが押されるのを待つ */
MOU_waitPress(MouseLeftButton, &mosX, &mosY);
/* アイテムボタンが押されたかチェック */
for (item = 0; buttonIds[item] >= 0; item++) {
if (BTN_posCheck(buttonIds[item],
mosX, mosY) == 1) {
pushedBtn = buttonIds[item];
break;
}
}
/* アイテムボタンが押されていたら */
if (pushedBtn != -1) {
/* ボタンを反転表示する */
MOU_display(Off);
BTN_reverse(pushedBtn);
MOU_display(On);
btnStatus = ~FALSE;
/*
* repeat属性を持ったボタンであれば,
* repeatIDを設定し,すぐに復帰する.
*/
if (BTN_isRepeat(pushedBtn)) {
repeatId = item;
return(item);
}
/*
* 左ボタンが押されている間
* マウスの位置によりボタン表示を変更し,
* 左ボタンが離されるのを待つ
*/
do {
mosBtn = MOU_readPosition(&mosX, &mosY);
if (btnStatus != FALSE &&
!BTN_posCheck(pushedBtn, mosX, mosY)) {
MOU_display(Off);
BTN_reverse(pushedBtn);
MOU_display(On);
btnStatus = FALSE;
}
else if (btnStatus == FALSE &&
BTN_posCheck(pushedBtn, mosX, mosY)) {
MOU_display(Off);
BTN_reverse(pushedBtn);
MOU_display(On);
btnStatus = ~FALSE;
}
} while (mosBtn & MouseLeftButton);
/*
* 左ボタンが離された時点で,マウスカーソルが
* 最初に押されたボタン上にあれば,ボタンを戻して終了.
* さもなければ,元へ戻る.
*/
if (btnStatus != FALSE) {
MOU_display(Off);
BTN_reverse(pushedBtn);
MOU_display(On);
return(item);
}
}
/* それ以外の領域で押されていた場合 */
else {
/* 左ボタンが離されるのを待ち,元へ戻る */
MOU_waitRelease(MouseLeftButton, &mosX, &mosY);
}
}
/* ここには到達しないため,return文はない */
}
/* --- BTN_getButtonEvent() --- */
/***** button.c *****/