home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 3 / FREEWARE.BIN / towns_os / fildlg22 / button.c next >
C/C++ Source or Header  |  1980-01-02  |  10KB  |  459 lines

  1. /*
  2.  *    button.c
  3.  */
  4.  
  5. #include    <stdlib.h>
  6. #include    <string.h>
  7. #include    "display.h"
  8. #include    "mouse.h"
  9. #include    "button.h"
  10.  
  11. #define        GLOBAL
  12.  
  13. #define        TRUE        1
  14. #define        FALSE        0
  15.  
  16.  
  17. /*--------------------------------------*/
  18. /*        定数定義        */
  19. /*--------------------------------------*/
  20.  
  21. #define        MaxButton    20
  22.  
  23.  
  24. /*--------------------------------------*/
  25. /*        変数定義        */
  26. /*--------------------------------------*/
  27.  
  28. /*    ボタン情報        */
  29. button_t    _BT_Buttons[MaxButton];
  30.  
  31. /*    空きボタン先頭ID    */
  32. int        _BT_NextButton    = 0;
  33.  
  34.  
  35. /*--------------------------------------*/
  36. /*        ローカル関数宣言    */
  37. /*--------------------------------------*/
  38.  
  39. /*    ローカル関数は無し    */
  40.  
  41.  
  42. /*--------------------------------------*/
  43. /*        関数定義        */
  44. /*--------------------------------------*/
  45.  
  46. GLOBAL    int
  47. BTN_create(
  48.     button_t    *btn)
  49. /*
  50.  *    PURPOSE
  51.  *        指定されたパラメタでボタンを作成,表示し,ボタンIDを返す.
  52.  *        指定すべきパラメタ(button_tのメンバ名)は以下の通り.
  53.  *            string, enable, repeat, luX, luY
  54.  *    RETURNS
  55.  *        >= 0    : ボタンID
  56.  *        -1    : ボタンの生成不可
  57.  *    NOTICE
  58.  *        本関数はパラメタで渡されたボタン構造体の
  59.  *        メンバstringをそのまま保持するため,
  60.  *        呼出元はstringが指す先の文字列を破壊してはならない.
  61.  *    IMPLEMENT
  62.  *        本来は動的にメモリを確保すべきだが,
  63.  *        ここではとりあえず固定領域を使用する.
  64.  */
  65. {
  66.     int    luX, luY;
  67.     int    rdX, rdY;
  68.     int    strX, strY;
  69.     int    len;
  70.     
  71.     if (_BT_NextButton >= MaxButton)
  72.         return(-1);
  73.     
  74.     _BT_Buttons[_BT_NextButton].next    = NULL;
  75.     _BT_Buttons[_BT_NextButton].string    = btn -> string;
  76.     _BT_Buttons[_BT_NextButton].enable    = btn -> enable;
  77.     _BT_Buttons[_BT_NextButton].on        = FALSE;
  78.     _BT_Buttons[_BT_NextButton].repeat    = btn -> repeat;
  79.     _BT_Buttons[_BT_NextButton].luX        = btn -> luX;
  80.     _BT_Buttons[_BT_NextButton].luY        = btn -> luY;
  81.     _BT_Buttons[_BT_NextButton].btnId    = _BT_NextButton;
  82.     
  83.     luX = btn -> luX;
  84.     luY = btn -> luY;
  85.     strX = luX + 8;
  86.     strY = luY + 8 + 16;
  87.     len = strlen(btn -> string);
  88.     rdX = luX + len * 8 + 16 - 1;
  89.     rdY = luY + 16 + 16 - 1;
  90.     
  91.     DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);
  92.     
  93.     DISP_stringAt(btn -> string, strX, strY,
  94.         (btn -> enable) ? CI_Black : CI_DarkGray);
  95.     
  96.     DISP_line(rdX - 1, luY, luX, luY, CI_White);        /* 外枠 */
  97.     DISP_line(luX, luY, luX, rdY, CI_White);        /* 外枠 */
  98.     
  99.     DISP_line(rdX - 2, luY + 1, luX + 1, luY + 1, CI_Gray);    /* 内枠 */
  100.     DISP_line(luX + 1, luY + 1, luX + 1, rdY - 1, CI_Gray);    /* 内枠 */
  101.     
  102.     DISP_line(rdX, luY, rdX, rdY, CI_Black);        /* 外枠 */
  103.     DISP_line(rdX, rdY, luX + 1, rdY, CI_Black);        /* 外枠 */
  104.     
  105.     DISP_line(rdX - 1, luY + 1, rdX - 1, rdY - 1, CI_DarkGray); /* 内枠 */
  106.     DISP_line(rdX - 1, rdY - 1, luX + 2, rdY - 1, CI_DarkGray); /* 内枠 */
  107.     
  108.     return(_BT_Buttons[_BT_NextButton++].btnId);
  109. }
  110. /* ---    BTN_create()  --- */
  111.  
  112.  
  113. GLOBAL    void
  114. BTN_allDestroy(void)
  115. /*
  116.  *    PURPOSE
  117.  *        全ボタンを削除する.
  118.  *    IMPLEMENT
  119.  *        本来は個別のボタンをひとつずつ解放していくべきだが,
  120.  *        ここでは_BT_NextButtonを初期化するだけとする.
  121.  */
  122. {
  123.     _BT_NextButton = 0;
  124. }
  125. /* ---    BTN_allDestroy()  --- */
  126.  
  127.  
  128. GLOBAL    int
  129. BTN_setName(
  130.     int    btnId,
  131.     char    *string)    /* 変更後のボタン名 */
  132. /*
  133.  *    PURPOSE
  134.  *        指定されたボタンのボタン名を消去後,
  135.  *        指定された文字列をボタン名として表示する.
  136.  *        旧ボタン名と新ボタン名の長さは等しいこと.
  137.  *    RETURNS
  138.  *        0    : 正常終了
  139.  *        -1    : ボタンIDが正しくない
  140.  *    NOTICE
  141.  *        本関数はパラメタstringをそのまま保持するため,
  142.  *        呼出元はstringが指す先の文字列を破壊してはならない.
  143.  */
  144. {
  145.     int        luX, luY;
  146.     int        rdX, rdY;
  147.     int        strX, strY;
  148.     int        len;
  149.     button_t    *pBtn;
  150.     
  151.     if (btnId < 0 || btnId >= _BT_NextButton)
  152.         return(-1);
  153.     
  154.     pBtn = &_BT_Buttons[btnId];
  155.     
  156.     /*    元の領域を消去    */
  157.     luX = pBtn -> luX;
  158.     luY = pBtn -> luY;
  159.     strX = luX + 8;
  160.     strY = luY + 8 + 16;
  161.     len = strlen(pBtn -> string);
  162.     rdX = luX + len * 8 + 16 - 1;
  163.     rdY = luY + 16 + 16 - 1;
  164.     
  165.     DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);
  166.     
  167.     /*    新文字列を表示    */
  168.     DISP_stringAt(string, strX, strY,
  169.         (pBtn -> enable) ? CI_Black : CI_DarkGray);
  170.     
  171.     /*    制御情報を更新    */
  172.     pBtn -> string = string;
  173.     
  174.     return(0);
  175. }
  176. /* ---    BTN_setName()  --- */
  177.  
  178.  
  179. GLOBAL    int
  180. BTN_enable(
  181.     int    btnId,
  182.     int    enable)
  183. /*
  184.  *    PURPOSE
  185.  *        指定されたボタンの有効状態を変更し,表示する.
  186.  *    RETURNS
  187.  *        0    : 正常終了
  188.  *        -1    : ボタンIDが正しくない
  189.  */
  190. {
  191.     int        luX, luY;
  192.     int        rdX, rdY;
  193.     int        strX, strY;
  194.     int        len;
  195.     button_t    *pBtn;
  196.     
  197.     if (btnId < 0 || btnId >= _BT_NextButton)
  198.         return(-1);
  199.     
  200.       pBtn = &_BT_Buttons[btnId];
  201.     
  202.     pBtn -> enable = enable;
  203.     
  204.     luX = pBtn -> luX;
  205.     luY = pBtn -> luY;
  206.     strX = luX + 8;
  207.     strY = luY + 8 + 16;
  208.     len = strlen(pBtn -> string);
  209.     rdX = luX + len * 8 + 16 - 1;
  210.     rdY = luY + 16 + 16 - 1;
  211.     
  212.     /*    文字列の背景は変更せず,文字列だけを再表示する.
  213.     DISP_rectangle(luX + 2, luY + 2, rdX - 2, rdY - 2, CI_Gray);*/
  214.     
  215.     DISP_stringAt(pBtn -> string, strX, strY,
  216.         (pBtn -> enable) ? CI_Black : CI_DarkGray);
  217.     
  218.     return(0);
  219. }
  220. /* ---    BTN_enable()  --- */
  221.  
  222.  
  223. GLOBAL    int
  224. BTN_reverse(
  225.     int    btnId)
  226. /*
  227.  *    PURPOSE
  228.  *        指定したボタンのオンオフを反転し,表示する.
  229.  *    RETURNS
  230.  *        0    : 正常終了
  231.  *        -1    : ボタンIDが正しくない
  232.  */
  233. {
  234.     int        luX, luY;
  235.     int        rdX, rdY;
  236.     int        strX, strY;
  237.     int        len;
  238.     button_t    *pBtn;
  239.     
  240.     if (btnId < 0 || btnId >= _BT_NextButton)
  241.         return(-1);
  242.     
  243.     pBtn = &_BT_Buttons[btnId];
  244.     
  245.     pBtn -> on = (pBtn -> on == FALSE) ? TRUE : FALSE;
  246.     
  247.     luX = pBtn -> luX;
  248.     luY = pBtn -> luY;
  249.     strX = luX + 8;
  250.     strY = luY + 8 + 16;
  251.     len = strlen(pBtn -> string);
  252.     rdX = luX + len * 8 + 16 - 1;
  253.     rdY = luY + 16 + 16 - 1;
  254.     
  255.     DISP_xorRectBox(luX, luY, rdX, rdY, 0xffff);
  256.     DISP_xorRectBox(luX + 1, luY + 1, rdX - 1, rdY - 1, 0xffff);
  257.     
  258.     return(0);
  259. }
  260. /* ---    BTN_reverse()  --- */
  261.  
  262.  
  263. GLOBAL    int
  264. BTN_posCheck(
  265.     int    btnId,
  266.     int    x,
  267.     int    y)
  268. /*
  269.  *    PURPOSE
  270.  *        指定した座標がボタン内か否かを判定し,その結果を通知する.
  271.  *        指定したボタンがenableでなければ,その旨を通知する.
  272.  *    RETURNS
  273.  *        1    : 指定座標はボタン内
  274.  *        0    : ボタン外
  275.  *        -1    : ボタンIDが正しくない
  276.  *        -2    : ボタンがenableでない
  277.  */
  278. {
  279.     int        luX, luY;
  280.     int        rdX, rdY;
  281.     int        strX, strY;
  282.     int        len;
  283.     button_t    *pBtn;
  284.     
  285.     if (btnId < 0 || btnId >= _BT_NextButton)
  286.         return(-1);
  287.     
  288.     pBtn = &_BT_Buttons[btnId];
  289.     
  290.     if (pBtn -> enable == FALSE)
  291.         return(-2);
  292.         
  293.     luX = pBtn -> luX;
  294.     luY = pBtn -> luY;
  295.     strX = luX + 8;
  296.     strY = luY + 8 + 16;
  297.     len = strlen(pBtn -> string);
  298.     rdX = luX + len * 8 + 16 - 1;
  299.     rdY = luY + 16 + 16 - 1;
  300.     
  301.     if (x < luX || x > rdX)
  302.         return(0);
  303.     if (y < luY || y > rdY)
  304.         return(0);
  305.     
  306.     return(1);
  307. }
  308. /* ---    BTN_posCheck()  --- */
  309.  
  310.  
  311. GLOBAL    int
  312. BTN_isRepeat(
  313.     int    btnId)
  314. /*
  315.  *    PURPOSE
  316.  *        指定したボタンがRepeat属性を持つか否かを通知する.
  317.  *    RETURNS
  318.  *        1    : Repeat属性を持つ
  319.  *        0    : Repeat属性を持たない
  320.  *        -1    : ボタンIDが正しくない
  321.  */
  322. {
  323.     button_t    *pBtn;
  324.     
  325.     if (btnId < 0 || btnId >= _BT_NextButton)
  326.         return(-1);
  327.     
  328.     pBtn = &_BT_Buttons[btnId];
  329.     
  330.     if (pBtn -> repeat == FALSE)
  331.         return(0);
  332.         
  333.     return(1);
  334. }
  335. /* ---    BTN_isRepeat()  --- */
  336.  
  337.  
  338. GLOBAL    int
  339. BTN_getButtonEvent(
  340.     int    buttonIds[])
  341. /*
  342.  *    PURPOSE
  343.  *        マウスでクリックされたダイアログボタンの
  344.  *        配列インデックス(イベントID)を通知する.
  345.  *        押下をチェックするダイアログボタンのIDは,
  346.  *        buttonIds[]で指定する.
  347.  *        最終IDの次の要素には-1を格納しておくこと.
  348.  *    RETURNS
  349.  *        配列インデックス(イベントID)
  350.  */
  351. {
  352.     int    item;
  353.     int    mosX, mosY;
  354.     int    mosBtn;
  355.     int    btnStatus;
  356.     int    pushedBtn;
  357.     static    int    repeatId = -1;
  358.     
  359.     while (1) {
  360.         pushedBtn = -1;
  361.         
  362.         /* repeatモードの処理を行う */
  363.         if (repeatId != -1) {
  364.             do {
  365.                 mosBtn = MOU_readPosition(&mosX, &mosY);
  366.                 if (mosBtn & MouseLeftButton)
  367.                     /*
  368.                      * 同じボタンが押され続けていれば,
  369.                      * 復帰する.
  370.                      */
  371.                     if (BTN_posCheck(buttonIds[repeatId],
  372.                             mosX, mosY) == 1) {
  373.                         return(repeatId);
  374.                     }
  375.             } while (mosBtn & MouseLeftButton);
  376.             
  377.             /* repeatモード終了 */
  378.             MOU_display(Off);
  379.             BTN_reverse(buttonIds[repeatId]);
  380.             MOU_display(On);
  381.             repeatId = -1;
  382.         }
  383.         
  384.         /* マウスの左ボタンが押されるのを待つ */
  385.         MOU_waitPress(MouseLeftButton, &mosX, &mosY);
  386.         
  387.         /* アイテムボタンが押されたかチェック */
  388.         for (item = 0; buttonIds[item] >= 0; item++) {
  389.             if (BTN_posCheck(buttonIds[item], 
  390.                     mosX, mosY) == 1) {
  391.                 pushedBtn = buttonIds[item];
  392.                 break;
  393.             }
  394.         }
  395.         
  396.         /* アイテムボタンが押されていたら */
  397.         if (pushedBtn != -1) {
  398.         
  399.             /* ボタンを反転表示する */
  400.             MOU_display(Off);
  401.             BTN_reverse(pushedBtn);
  402.             MOU_display(On);
  403.             btnStatus = ~FALSE;
  404.             /*
  405.              * repeat属性を持ったボタンであれば,
  406.              * repeatIDを設定し,すぐに復帰する.
  407.              */
  408.             if (BTN_isRepeat(pushedBtn)) {
  409.                 repeatId = item;
  410.                 return(item);
  411.             }
  412.             /*
  413.              * 左ボタンが押されている間
  414.              * マウスの位置によりボタン表示を変更し,
  415.              * 左ボタンが離されるのを待つ
  416.              */
  417.             do {
  418.                 mosBtn = MOU_readPosition(&mosX, &mosY);
  419.                 if (btnStatus != FALSE &&
  420.                     !BTN_posCheck(pushedBtn, mosX, mosY)) {
  421.                     MOU_display(Off);
  422.                     BTN_reverse(pushedBtn);
  423.                     MOU_display(On);
  424.                     btnStatus = FALSE;
  425.                 }
  426.                 else if (btnStatus == FALSE &&
  427.                     BTN_posCheck(pushedBtn, mosX, mosY)) {
  428.                     MOU_display(Off);
  429.                     BTN_reverse(pushedBtn);
  430.                     MOU_display(On);
  431.                     btnStatus = ~FALSE;
  432.                 }
  433.             } while (mosBtn & MouseLeftButton);
  434.             /*
  435.              * 左ボタンが離された時点で,マウスカーソルが
  436.              * 最初に押されたボタン上にあれば,ボタンを戻して終了.
  437.              * さもなければ,元へ戻る.
  438.              */
  439.             if (btnStatus != FALSE) {
  440.                 MOU_display(Off);
  441.                 BTN_reverse(pushedBtn);
  442.                 MOU_display(On);
  443.                 return(item);
  444.             }
  445.         }
  446.         
  447.         /* それ以外の領域で押されていた場合 */
  448.         else {
  449.             /* 左ボタンが離されるのを待ち,元へ戻る */
  450.             MOU_waitRelease(MouseLeftButton, &mosX, &mosY);
  451.         }
  452.     }
  453.     /* ここには到達しないため,return文はない */
  454. }
  455. /* ---    BTN_getButtonEvent()  --- */
  456.  
  457.  
  458. /*****    button.c  *****/
  459.