home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 3 / FREEWARE.BIN / towns_os / fildlg22 / filedlg.c < prev    next >
C/C++ Source or Header  |  1980-01-02  |  40KB  |  1,585 lines

  1. /*
  2.  *    filedlg.c
  3.  *        ファイルダイアログ表示ルーチン
  4.  */
  5.  
  6. #include    <stdio.h>
  7. #include    <stdlib.h>
  8. #include    <string.h>
  9. #include    <setjmp.h>
  10. #include    "button.h"
  11. #include    "display.h"
  12. #include    "mouse.h"
  13. #include    "msdos.h"
  14. #include    "setup.h"
  15. #include    "filedlg.h"
  16.  
  17. #define        GLOBAL
  18. #define        LOCAL
  19.  
  20. #define        TRUE        1
  21. #define        FALSE        0
  22.  
  23.  
  24. /*--------------------------------------*/
  25. /*        型定義            */
  26. /*--------------------------------------*/
  27.  
  28. /*    Boolean型定義        */
  29.  
  30. typedef        int    Bool_t;
  31.  
  32. /*    ファイル情報構造体の定義    */
  33.  
  34. typedef    struct    fileInfo    {
  35.     struct fileInfo    *next;        /* 次要素 */
  36.     struct fileInfo    *prev;        /* 前要素 */
  37.     char        name[13];
  38.     char        attr;
  39.     unsigned short    date;
  40.     unsigned short    time;
  41.     long        size;
  42.     int        select;
  43. }    fileInfo_t;
  44.  
  45.  
  46. /*--------------------------------------*/
  47. /*        定数定義        */
  48. /*--------------------------------------*/
  49.  
  50. /* --------    ファイル関連    --------*/
  51.  
  52. #define        PathLen        80
  53. #define        FnameLen    12
  54. #define        DriveQ        17
  55.  
  56. /* --------    イベントID    --------*/
  57.  
  58. /*    イベントIDはlong型であり,
  59.  *    short型のmajorイベントIDと,short型のminorイベントIDからなる.
  60.  *    majorイベントIDはイベントを区別し,
  61.  *    minorイベントIDは各イベントの詳細を識別する.
  62.  */
  63.  
  64. /*    majorIDとminorIDを取り出すマクロ    */
  65. #define        major(id)    (id & 0xffff)
  66. #define        minor(id)    ((id >> 16) & 0xffff)
  67.  
  68. /*    majorイベントID        */
  69. #define        BtnDriveLeft    0
  70. #define        BtnDriveCenter    1
  71. #define        BtnDriveRight    2
  72. #define        BtnParent    3
  73. #define        BtnScrollUp    4
  74. #define        BtnScrollDown    5
  75. #define        BtnOk        6
  76. #define        BtnCancel    7
  77. #define        MaxButtons    8
  78. #define        FileList    9
  79.  
  80. /* --------    エラーコード    --------*/
  81.  
  82. #define        NoAvailableMemory    1
  83. #define        IllegalDirection    2
  84.  
  85. /* --------    画面関連定数    --------*/
  86. /*        単位はピクセル        */
  87.  
  88. int    FD_CharWidth    = 8;        /* 1バイト文字の横方向ドット数    */
  89. int    FD_CharHeight    = 16;        /* 1バイト文字の縦方向ドット数    */
  90.  
  91. /* --------    デフォルトダイアログボックス    --------*/
  92. /*
  93.  *    デフォルトダイアログボックスの表示位置等の定義情報
  94.  *        本ダイアログボックスは640×480ピクセルの画面を想定している.
  95.  */
  96. int    FD_DialogPosX    = 240;        /* ダイアログボックス左上x座標    */
  97. int    FD_DialogPosY    = 40;        /* ダイアログボックス左上y座標    */
  98.  
  99. int    FD_DriveBtnWidth = 32;
  100.         /* ドライブ中央ボタンのドット数                */
  101.         /* = strlen(FD_DriveName[0]) * FD_CharWidth + 8 * 2    */
  102. int    FD_ParentBtnWidth = 32;
  103.         /* 親ディレクトリボタンのドット数            */
  104.         /* = strlen(FD_ParentBtnName) * FD_CharWidth + 8 * 2    */
  105. int    FD_ScrollBtnWidth = 32;
  106.         /* スクロールボタンのドット数                */
  107.         /* = strlen(FD_ScrollBtnName[0]) * FD_CharWidth + 8 * 2    */
  108. int    FD_OkNgBtnWidth = 48;
  109.         /* 確認/取消ボタンのドット数                */
  110.         /* = strlen(FD_OkNgBtnName[0]) * FD_CharWidth + 8 * 2    */
  111. int    FD_ButtonHeight    = 32;
  112.         /* ボタンの縦方向ドット数                */
  113.         /* = FD_CharHeight + 8 * 2                */
  114.  
  115. int    FD_LeftMargin    = 8;        /* ドライブ左ボタンまでのオフセット */
  116. int    FD_TopMargin    = 8;        /* タイトル文字列までのオフセット */
  117. int    FD_RightMargin    = 8;        /* 取消ボタンからのオフセット    */
  118. int    FD_BottomMargin    = 8;        /*    同上            */
  119.  
  120. int    FD_FilesInList    = 10;    /* ファイルリストに表示するファイル数    */
  121.  
  122. /* --------    ダイアログボタンの表示文字    --------*/
  123. /*        これを変更すると,ボタンの文字を変更可能 */
  124.  
  125. char    *FD_DriveName[] = {
  126.     " ", "A", "B", "C", "D", "E", "F", "G", "H",
  127.     "I", "J", "K", "L", "M", "N", "O", "P", "Q"
  128. };
  129. char    *FD_ParentBtnName = "親";
  130. char    *FD_ScrollBtnName[] = {"▲", "▼"};
  131. char    *FD_OkNgBtnName[] = {"実行", "取消"};
  132.  
  133.  
  134. /*--------------------------------------*/
  135. /*        変数定義        */
  136. /*--------------------------------------*/
  137.  
  138. /*
  139.  *    大域ジャンプ(エラーリカバリ)用実行環境保存領域
  140.  */
  141. jmp_buf        _FileDialogEnv;
  142.  
  143. /*
  144.  *    ダイアログボタンのID
  145.  *        インデックスはmajorイベントIDで指定する
  146.  */
  147. int        _FD_ButtonIds[MaxButtons];
  148.  
  149. /*
  150.  *    ファイルリストのリンクの先頭と最後,及び表示中ファイルの先頭
  151.  */
  152. fileInfo_t    *_FileInfoTop;
  153. fileInfo_t    *_FileInfoTail;
  154. fileInfo_t    *_FileDispTop;
  155.  
  156. /*
  157.  *    _scrollFileList()関数内で使用する矩形ピクセル移動用作業域
  158.  *        FD_openDialog()の先頭で確保し,最後で解放する
  159.  */
  160. char        *_BufPixelBlock = NULL;
  161.  
  162. /*--------------------------------------*/
  163. /*        ローカル関数宣言    */
  164. /*--------------------------------------*/
  165.  
  166. LOCAL    void
  167. _showFileDialog(
  168.     fileDialog_t    *pFd);
  169. LOCAL    int
  170. _getCurrentDir(
  171.     char        *path,
  172.     fileDialog_t    *pFd);
  173. LOCAL    void
  174. _showDirname(
  175.     char        *name,
  176.     fileDialog_t    *pFd);
  177. LOCAL    void
  178. _initFileList(
  179.     fileDialog_t    *pFd);
  180. LOCAL    void
  181. _getFiles(
  182.     char        *pattern,
  183.     fileDialog_t    *pFd);
  184. LOCAL    fileInfo_t *
  185. _makeFileInfo(
  186.     struct find_t    *buf,
  187.     fileInfo_t    *next,
  188.     fileInfo_t    *prev);
  189. LOCAL    void
  190. _freeFileInfo(
  191.     fileInfo_t    *top);
  192. LOCAL    void
  193. _sortFileList(
  194.     fileInfo_t    *top,
  195.     int        (*comp)(fileInfo_t *p1, fileInfo_t *p2));
  196. LOCAL    int
  197. _compName(
  198.     fileInfo_t    *pFi1,
  199.     fileInfo_t    *pFi2);
  200. LOCAL    void
  201. _showFileList(
  202.     fileInfo_t    *pFi,
  203.     fileDialog_t    *pFd);
  204. LOCAL    void
  205. _scrollFileList(
  206.     int        direction,
  207.     fileDialog_t    *pFd);
  208. LOCAL    void
  209. _showFilename(
  210.     char        *name,
  211.     fileDialog_t    *pFd);
  212. LOCAL    long
  213. _getFdEvent(
  214.     fileDialog_t    *pFd);
  215. LOCAL    int
  216. _checkFileList(
  217.     int        x,        /* チェック対象座標 */
  218.     int        y,        /*    同上    */
  219.     fileDialog_t    *pFd);
  220. LOCAL    void
  221. _reverseFileName(
  222.     int        fileNo,        /* 反転対象ファイル番号(先頭は0) */
  223.     fileDialog_t    *pFd);
  224. LOCAL    void
  225. _errorFatal(
  226.     int    errorCode);
  227.  
  228.  
  229. /*--------------------------------------*/
  230. /*        関数定義        */
  231. /*--------------------------------------*/
  232.  
  233. GLOBAL    int
  234. FD_openDialog(
  235.     char    *filename,        /* 選択されたファイルのフルパス名 */
  236.     file_t    *fileinfo,        /* 選択されたファイルの各種情報 */
  237.     char    *pattern,        /* 選択対象とするファイル名 */
  238.     fileDialog_t    *pFd)        /* 使用するダイアログ構造体 */
  239. /*
  240.  *    PURPOSE
  241.  *        現在の書き込みページに対してファイルダイアログを表示し,
  242.  *        選択されたファイル名のフルパスをパラメタfilenameで通知する.
  243.  *        また選択されたファイルのファイル名(ディレクトリ部以外),
  244.  *        ファイル属性,更新日時,大きさをfileinfoで通知する.
  245.  *    PARAMETERS
  246.  *        filenameパラメタにはファイル名の通知に充分な領域への
  247.  *        ポインタを指定すること.
  248.  *        fileInfoにNULLを指定した場合は,ファイル情報は通知しない.
  249.  *        patternには,ダイアログに表示する選択ファイルのマスクパターン
  250.  *        (例. "*.*", "*.TIF")を指定する.NULLを指定した場合は,
  251.  *        "*.*"が指定されたものとみなす.
  252.  *        pFdがNULLであれば既定のファイルダイアログ
  253.  *        (640*480 16色 CLUT無変更を前提とする)を使用する.
  254.  *        NULLでなければ,指定されたダイアログを使用する.
  255.  *
  256.  *        本関数の復帰後,
  257.  *        現在の書き込みページはダイアログが表示された状態で,
  258.  *        マウスカーソルは非表示状態となる.
  259.  *    RETURNS
  260.  *        1    : ファイル選択取消
  261.  *        0    : 正常終了. この場合のみfilename,fileinfoの内容が有効.
  262.  *        < 0    : エラー発生
  263.  */
  264. {
  265.     fileDialog_t    fdStructure;
  266.     char        bufInfo[200];        /* setup情報通知領域 */
  267.     int        drive;
  268.     int        driveStatus[DriveQ + 1];
  269.         /* 先頭要素[0]はダミーで,要素[1]から順に
  270.          * ドライブA, B, ・・・, Qに対応
  271.          * 0:FPD, 1:Rsv, 2:HD, 3:RamDisk, -1:未接続
  272.          */
  273.     int        status;
  274.     unsigned    currentDrive;
  275.     unsigned    tmpDrive;
  276.     unsigned    maxDrive;
  277.     char        currentPath[PathLen];        /* ルートの\を含む */
  278.     char        currentFilename[FnameLen + 1];    /* '\0'を含む */
  279.     fileInfo_t    *saveInfoTop, *saveInfoTail, *saveDispTop;
  280.     long        event;
  281.     fileInfo_t    *pFi;
  282.     int        i;
  283.     int        retCode = 0;
  284.     Bool_t        bExit = FALSE;
  285.     
  286.     /* エラー用 */
  287.     if ((retCode = setjmp(_FileDialogEnv)) != 0) {
  288.         if (_BufPixelBlock != NULL) {
  289.             free(_BufPixelBlock);
  290.             _BufPixelBlock = NULL;
  291.         }
  292.         return(-retCode);
  293.     }
  294.     
  295.     /* ファイル検索パターンが指定されていなけれは,"*.*"とみなす */
  296.     if (pattern == NULL)
  297.         pattern = "*.*";
  298.     
  299.     /* ダイアログ定義体が指定されていなければ,デフォルトの定義体を作成 */
  300.     if (pFd == NULL) {
  301.         pFd = &fdStructure;
  302.         FD_setDefDialog(pFd);
  303.     }
  304.     
  305.     /* ダイアログを表示 */
  306.     _showFileDialog(pFd);
  307.     
  308.     /* _scrollFileList()用作業域を確保 */
  309.     _BufPixelBlock = (char *)malloc(FD_CharWidth * (FnameLen+2)
  310.                     * FD_CharHeight * FD_FilesInList);
  311.     if (_BufPixelBlock == NULL)
  312.         _errorFatal(NoAvailableMemory);
  313.     
  314.     /* 接続ドライブ情報を取得 */
  315.     ESR_setupInfo(bufInfo);
  316.     for (drive = 1; drive < DriveQ; drive++)
  317.         driveStatus[drive] = bufInfo[0x30 + (drive - 1) * 2];
  318.     /* CD-ROMのドライブ情報は,0(FPD)としておく */
  319.     driveStatus[DriveQ] = 0;
  320.     
  321.     /* カレントドライブ取得,表示 */
  322.     _dos_getdrive(¤tDrive);
  323.     tmpDrive = currentDrive;
  324.     
  325.     BTN_setName(_FD_ButtonIds[BtnDriveCenter],  FD_DriveName[currentDrive]);    
  326.     /* 既にEnableになっているため BTN_enable()は呼ばない */
  327.     
  328.     /* 必要な変数を初期化 */
  329.     _FileInfoTop = _FileInfoTail = _FileDispTop = NULL;
  330.     currentFilename[0] = '\0';
  331.     
  332.     /* マウス表示 */
  333.     MOU_display(On);
  334.     
  335.     /* カレントディレトクリ取得,表示 */
  336.     status = _getCurrentDir(currentPath, pFd);
  337.     
  338.     /* ファイルリスト初期化 */
  339.     _initFileList(pFd);
  340.     
  341.     if (status == 0)
  342.         /* ファイル一覧取得,表示 */
  343.         _getFiles(pattern, pFd);
  344.     
  345.     /* イベント処理 */
  346.     do {
  347.         event = _getFdEvent(pFd);
  348.         switch (major(event)) {
  349.         case BtnDriveLeft:
  350.             /*
  351.              * カレントドライブから他に移動する場合,
  352.              * パス名,ファイルリスト,ファイル名領域を消去
  353.              */
  354.             if (tmpDrive == currentDrive) {
  355.                 _showDirname("\\", pFd);
  356.                 /* ファイルリスト変数を保存 */
  357.                 saveInfoTop = _FileInfoTop;
  358.                 saveInfoTail = _FileInfoTail;
  359.                 saveDispTop = _FileDispTop;
  360.                 /* ファイル情報がフリーされないようにする */
  361.                 _FileInfoTop = NULL;
  362.                 /* ファイルリスト領域を消去 */
  363.                 _initFileList(pFd);
  364.                 /* ファイル名領域を消去 */
  365.                 _showFilename("", pFd);
  366.             }
  367.             /* カレントドライブ変更 */
  368.             do {
  369.                 tmpDrive--;
  370.                 if (tmpDrive == 0)
  371.                     tmpDrive = DriveQ;
  372.                 status = driveStatus[tmpDrive];
  373.             } while (status != 0 && status != 2 && status != 3);
  374.             
  375.             /* ドライブボタン表示の変更 */
  376.             MOU_display(Off);
  377.             BTN_setName(_FD_ButtonIds[BtnDriveCenter],
  378.                 FD_DriveName[tmpDrive]);
  379.             MOU_display(On);
  380.             /*
  381.              * カレントドライブに移動する場合,
  382.              * 各種表示を復元
  383.              */
  384.             if (tmpDrive == currentDrive) {
  385.                 _showDirname(currentPath, pFd);
  386.                 _FileInfoTop = saveInfoTop;
  387.                 _FileInfoTail = saveInfoTail;
  388.                 _FileDispTop = saveDispTop;
  389.                 _showFileList(_FileDispTop, pFd);
  390.                 /* 選択ファイルが存在する場合,それを表示 */
  391.                 MOU_display(Off);
  392.                 pFi = _FileDispTop;
  393.                 for (i = 0; i < FD_FilesInList; i++) {
  394.                     if (pFi == NULL)
  395.                         break;
  396.                     if (pFi -> select == TRUE)
  397.                         _reverseFileName(i, pFd);
  398.                     pFi = pFi -> next;
  399.                 }
  400.                 MOU_display(On);
  401.                 _showFilename(currentFilename, pFd);
  402.             }
  403.             break;
  404.             
  405.         case BtnDriveCenter:
  406.             /* Waitマウスカーソルに変更 */
  407.             MOU_setCursorType(1);
  408.             
  409.             /* カレントドライブを設定 */
  410.             _dos_setdrive(tmpDrive, &maxDrive);
  411.             
  412.             /* カレントドライブ取得,表示 */
  413.             _dos_getdrive(¤tDrive);
  414.             tmpDrive = currentDrive;
  415.             
  416.             /* カレントディレトクリ取得,表示 */
  417.             status = _getCurrentDir(currentPath, pFd);
  418.             _initFileList(pFd);
  419.             if (status == 0)
  420.                 /* ファイル一覧取得,表示 */
  421.                 _getFiles(pattern, pFd);
  422.                 
  423.             /* ファイル名消去 */
  424.             currentFilename[0] = '\0';
  425.             _showFilename(currentFilename, pFd);
  426.             
  427.             /* システムマウスカーソルに変更 */
  428.             MOU_setCursorType(0);
  429.             
  430.             break;
  431.             
  432.         case BtnDriveRight:
  433.             /*
  434.              * カレントドライブから他に移動する場合,
  435.              * パス名,ファイルリスト,ファイル名領域を消去
  436.              */
  437.             if (tmpDrive == currentDrive) {
  438.                 _showDirname("\\", pFd);
  439.                 /* ファイルリスト変数を保存 */
  440.                 saveInfoTop = _FileInfoTop;
  441.                 saveInfoTail = _FileInfoTail;
  442.                 saveDispTop = _FileDispTop;
  443.                 /* ファイル情報がフリーされないようにする */
  444.                 _FileInfoTop = NULL;
  445.                 /* ファイルリスト領域を消去 */
  446.                 _initFileList(pFd);
  447.                 /* ファイル名領域を消去 */
  448.                 _showFilename("", pFd);
  449.             }
  450.             /* カレントドライブ変更 */
  451.             do {
  452.                 tmpDrive++;
  453.                 if (tmpDrive == DriveQ + 1)
  454.                     tmpDrive = 1;        /* Drive A: */
  455.                 status = driveStatus[tmpDrive];
  456.             } while (status != 0 && status != 2 && status != 3);
  457.             
  458.             /* ドライブボタン表示の変更 */
  459.             MOU_display(Off);
  460.             BTN_setName(_FD_ButtonIds[BtnDriveCenter],
  461.                 FD_DriveName[tmpDrive]);
  462.             MOU_display(On);
  463.             /*
  464.              * カレントドライブに移動する場合,
  465.              * 各種表示を復元
  466.              */
  467.             if (tmpDrive == currentDrive) {
  468.                 _showDirname(currentPath, pFd);
  469.                 _FileInfoTop = saveInfoTop;
  470.                 _FileInfoTail = saveInfoTail;
  471.                 _FileDispTop = saveDispTop;
  472.                 _showFileList(_FileDispTop, pFd);
  473.                 /* 選択ファイルが存在する場合,それを表示 */
  474.                 MOU_display(Off);
  475.                 pFi = _FileDispTop;
  476.                 for (i = 0; i < FD_FilesInList; i++) {
  477.                     if (pFi == NULL)
  478.                         break;
  479.                     if (pFi -> select == TRUE)
  480.                         _reverseFileName(i, pFd);
  481.                     pFi = pFi -> next;
  482.                 }
  483.                 MOU_display(On);
  484.                 _showFilename(currentFilename, pFd);
  485.             }
  486.             break;
  487.             
  488.         case BtnParent:
  489.             /* カレントディレクトリ変更 */
  490.             chdir("..");
  491.             
  492.             /* カレントディレクトリ取得,表示 */
  493.             status = _getCurrentDir(currentPath, pFd);
  494.             _initFileList(pFd);
  495.             if (status == 0)
  496.                 /* ファイル一覧表示 */
  497.                 _getFiles(pattern, pFd);
  498.             
  499.             /* ファイル名消去 */
  500.             currentFilename[0] = '\0';
  501.             _showFilename(currentFilename, pFd);
  502.             
  503.             break;
  504.             
  505.         case BtnScrollUp:
  506.         case BtnScrollDown:
  507.             /* ファイル一覧をスクロール */
  508.             _scrollFileList(major(event), pFd);
  509.             break;
  510.             
  511.         case BtnOk:
  512.             /* 選択されたファイル名をfilenameに設定 */
  513.             if (strlen(currentFilename)) {
  514.                 filename[0] = currentDrive + 'A' - 1;
  515.                 filename[1] = ':';
  516.                 filename[2] = '\0';
  517.                 strcat(filename, currentPath);
  518.                 if (strcmp(currentPath, "\\"))
  519.                     strcat(filename, "\\");
  520.                 strcat(filename, currentFilename);
  521.                 bExit = TRUE;
  522.                 retCode = 0;
  523.             }
  524.             break;
  525.             
  526.         case BtnCancel:
  527.             bExit = TRUE;
  528.             retCode = 1;
  529.             break;
  530.             
  531.         case FileList:
  532.             pFi = _FileDispTop;
  533.             for (i = 0; i < minor(event); i++)
  534.                 pFi = pFi -> next;
  535.             
  536.             if (pFi -> attr & _A_SUBDIR) {
  537.                 /* カレントディレクトリ変更 */
  538.                 chdir(pFi -> name);
  539.                 
  540.                 /* カレントディレクトリ取得,表示 */
  541.                 status = _getCurrentDir(currentPath, pFd);
  542.                 _initFileList(pFd);
  543.                 if (status == 0)
  544.                     /* ファイル一覧表示 */
  545.                     _getFiles(pattern, pFd);
  546.                 
  547.                 /* ファイル名消去 */
  548.                 currentFilename[0] = '\0';
  549.                 _showFilename(currentFilename, pFd);
  550.             }
  551.             else {
  552.                 /* 選択されたファイル名をfilenameに設定 */
  553.                 pFi -> select = TRUE;
  554.                 strcpy(currentFilename, pFi -> name);
  555.                 
  556.                 /* 各種のファイル情報を通知 */
  557.                 if (fileinfo != NULL) {
  558.                     strcpy(fileinfo -> name, pFi -> name);
  559.                     fileinfo -> attr = pFi -> attr;
  560.                     fileinfo -> date = pFi -> date;
  561.                     fileinfo -> time = pFi -> time;
  562.                     fileinfo -> size = pFi -> size;
  563.                 }
  564.                 /* ファイル名を表示する */
  565.                 _showFilename(currentFilename, pFd);
  566.             }
  567.             break;
  568.         }
  569.     } while (bExit != TRUE);
  570.     
  571.     /* 使用した資源を解放 */
  572.     _freeFileInfo(_FileInfoTop);
  573.     free(_BufPixelBlock);
  574.     _BufPixelBlock = NULL;
  575.     
  576.     BTN_allDestroy();
  577.     
  578.     MOU_display(Off);
  579.     
  580.     return(retCode);
  581. }
  582. /* ---    FD_openDialog()  --- */
  583.  
  584.  
  585. GLOBAL    void
  586. FD_setDefDialog(
  587.     fileDialog_t    *pFd)
  588. /*
  589.  *    PURPOSE
  590.  *        デフォルトファイルダイアログを作成する.
  591.  *        本ダイアログは640×480ドットの画面を想定している.
  592.  */
  593. {
  594.     /* ファイルダイアログの初期設定 */
  595.     pFd -> originX    = FD_DialogPosX;
  596.     pFd -> originY    = FD_DialogPosY;
  597.     pFd -> title    = NULL;            /* タイトルは無し */
  598.     pFd -> titleX    = -1;            /* センタリング指定 */
  599.     pFd -> titleY    = FD_TopMargin;
  600.     pFd -> driveLX    = FD_LeftMargin;
  601.     pFd -> driveLY    = pFd->titleY + FD_CharHeight + 8;
  602.     pFd -> driveCX    = pFd->driveLX + FD_CharWidth + 8 * 2;
  603.     pFd -> driveCY    = pFd->driveLY;
  604.     pFd -> driveRX    = pFd->driveCX + FD_DriveBtnWidth;
  605.     pFd -> driveRY    = pFd->driveLY;
  606.     pFd -> pathX    = FD_LeftMargin;
  607.     pFd -> pathY    = pFd->driveLY + FD_ButtonHeight + 8;
  608.     pFd -> parentX    = pFd->pathX + FD_CharWidth * FnameLen + 8;
  609.     pFd -> parentY    = pFd->driveLY + FD_CharHeight + 8;
  610.     pFd -> fileListX = FD_LeftMargin;
  611.     pFd -> fileListY = pFd->pathY + FD_CharHeight + 8;
  612.     pFd -> upX    = pFd->fileListX + FD_CharWidth * (FnameLen+2) + 8;
  613.     pFd -> upY    = pFd->fileListY;
  614.     pFd -> downX    = pFd->upX;
  615.     pFd -> downY    = pFd->fileListY + FD_CharHeight * (FD_FilesInList-1);
  616.     pFd -> fileNameX = FD_LeftMargin;
  617.     pFd -> fileNameY = pFd->fileListY + FD_CharHeight * FD_FilesInList + 8;
  618.     pFd -> okX    = FD_LeftMargin + 48;
  619.     pFd -> okY    = pFd->fileNameY + FD_CharHeight + 8;
  620.     pFd -> cancelX    = pFd->okX + FD_OkNgBtnWidth + 8;
  621.     pFd -> cancelY    = pFd->okY;
  622.     pFd -> rightBottomX = pFd->cancelX + FD_OkNgBtnWidth + FD_RightMargin;
  623.     pFd -> rightBottomY = pFd->okY + FD_ButtonHeight + FD_BottomMargin;
  624. }
  625. /* ---    FD_setDefDialog()  --- */
  626.  
  627.  
  628. LOCAL    void
  629. _showFileDialog(
  630.     fileDialog_t    *pFd)
  631. /*
  632.  *    PURPOSE
  633.  *        ファイルダイアログを表示する.
  634.  */
  635. {
  636.     int        width, x;
  637.     button_t    button;
  638.     
  639.     /* 背景の設定 */
  640.     DISP_rectangle(
  641.         pFd->originX,
  642.         pFd->originY,
  643.         pFd->originX + pFd->rightBottomX - 1,
  644.         pFd->originY + pFd->rightBottomY - 1,
  645.         CI_Gray);
  646.     
  647.     /* 枠の設定 */
  648.     DISP_rectBox(
  649.         pFd->originX,
  650.         pFd->originY,
  651.         pFd->originX + pFd->rightBottomX - 1,
  652.         pFd->originY + pFd->rightBottomY - 1,
  653.         CI_Black);
  654.     
  655.     /* ダイアログタイトル表示 */
  656.     if (pFd -> title != NULL) {
  657.  
  658.         /* 表示開始x座標を求める */
  659.         if (pFd -> titleX == -1) {
  660.             /* センタリング処理 */
  661.             width = strlen(pFd -> title) * FD_CharWidth;
  662.             if ((x = pFd->rightBottomX - width) < 0)
  663.                 x = 0;
  664.             x /= 2;
  665.         }
  666.         else
  667.             x = pFd -> titleX;
  668.         
  669.         DISP_stringAt(
  670.             pFd->title,
  671.             pFd->originX + x,
  672.             pFd->originY + pFd->titleY + FD_CharHeight - 1,
  673.             CI_Black);
  674.     }
  675.     
  676.     /* パス表示エリア作成 */
  677.     DISP_rectangle(
  678.         pFd->originX + pFd->pathX,
  679.         pFd->originY + pFd->pathY,
  680.         pFd->originX + pFd->pathX + FD_CharWidth * FnameLen - 1,
  681.         pFd->originY + pFd->pathY + FD_CharHeight - 1,
  682.         CI_Black);
  683.         
  684.     /* ファイルリストエリア作成 */
  685.     DISP_rectangle(
  686.         pFd->originX + pFd->fileListX,
  687.         pFd->originY + pFd->fileListY,
  688.         pFd->originX + pFd->fileListX + FD_CharWidth * (FnameLen+2) - 1,
  689.         pFd->originY + pFd->fileListY + FD_CharHeight * FD_FilesInList - 1,
  690.         CI_Black);
  691.         
  692.     /* ファイル名エリア作成 */
  693.     DISP_rectangle(
  694.         pFd->originX + pFd->fileNameX,
  695.         pFd->originY + pFd->fileNameY,
  696.         pFd->originX + pFd->fileNameX + FD_CharWidth * FnameLen - 1,
  697.         pFd->originY + pFd->fileNameY + FD_CharHeight - 1,
  698.         CI_Black);
  699.     
  700.     /* ドライブボタン作成 */
  701.     button.string    = "<";
  702.     button.enable    = TRUE;
  703.     button.repeat    = FALSE;
  704.     button.luX    = pFd->originX + pFd->driveLX;
  705.     button.luY    = pFd->originY + pFd->driveLY;
  706.     _FD_ButtonIds[BtnDriveLeft] = BTN_create(&button);
  707.     
  708.     button.string    = FD_DriveName[0];
  709.     button.enable    = TRUE;
  710.     button.repeat    = FALSE;
  711.     button.luX    = pFd->originX + pFd->driveCX;
  712.     button.luY    = pFd->originY + pFd->driveCY;
  713.     _FD_ButtonIds[BtnDriveCenter] = BTN_create(&button);
  714.     
  715.     button.string    = ">";
  716.     button.enable    = TRUE;
  717.     button.repeat    = FALSE;
  718.     button.luX    = pFd->originX + pFd->driveRX;
  719.     button.luY    = pFd->originY + pFd->driveRY;
  720.     _FD_ButtonIds[BtnDriveRight] = BTN_create(&button);
  721.     
  722.     /* 親ディレクトリボタン作成 */
  723.     button.string    = FD_ParentBtnName;
  724.     button.enable    = FALSE;
  725.     button.repeat    = FALSE;
  726.     button.luX    = pFd->originX + pFd->parentX;
  727.     button.luY    = pFd->originY + pFd->parentY;
  728.     _FD_ButtonIds[BtnParent] = BTN_create(&button);
  729.     
  730.     /* スクロールボタン作成 */
  731.     button.string    = FD_ScrollBtnName[0];
  732.     button.enable    = FALSE;
  733.     button.repeat    = TRUE;            /* repeat 有り */
  734.     button.luX    = pFd->originX + pFd->upX;
  735.     button.luY    = pFd->originY + pFd->upY;
  736.     _FD_ButtonIds[BtnScrollUp] = BTN_create(&button);
  737.     
  738.     button.string    = FD_ScrollBtnName[1];
  739.     button.enable    = FALSE;
  740.     button.repeat    = TRUE;            /* repeat 有り */
  741.     button.luX    = pFd->originX + pFd->downX;
  742.     button.luY    = pFd->originY + pFd->downY;
  743.     _FD_ButtonIds[BtnScrollDown] = BTN_create(&button);
  744.     
  745.     /* 確認取消ボタン作成 */
  746.     button.string    = FD_OkNgBtnName[0];
  747.     button.enable    = FALSE;        /* 最初は disable 状態 */
  748.     button.repeat    = FALSE;
  749.     button.luX    = pFd->originX + pFd->okX;
  750.     button.luY    = pFd->originY + pFd->okY;
  751.     _FD_ButtonIds[BtnOk] = BTN_create(&button);
  752.     
  753.     button.string    = FD_OkNgBtnName[1];
  754.     button.enable    = TRUE;
  755.     button.repeat    = FALSE;
  756.     button.luX    = pFd->originX + pFd->cancelX;
  757.     button.luY    = pFd->originY + pFd->cancelY;
  758.     _FD_ButtonIds[BtnCancel] = BTN_create(&button);
  759. }
  760. /* ---    _showFileDialog()  --- */
  761.  
  762.  
  763. LOCAL    int
  764. _getCurrentDir(
  765.     char        *path,
  766.     fileDialog_t    *pFd)
  767. /*
  768.  *    PURPOSE
  769.  *        カレントディレクトリを取得し,
  770.  *        ルートを示す \ を含んだフルパスでpathに返す.
  771.  *        また,ダイアログのパス表示エリアにも表示し,
  772.  *        親ディレクトリ移動ボタンのenable/disableを制御する.
  773.  *        エラー時には,pathは"????????"を表示し通知する.
  774.  *    RETURNS
  775.  *        0    : 正常終了
  776.  *        -1    : エラー
  777.  */
  778. {
  779.     char    *p;
  780.     int    ret;
  781.     
  782.     path[0] = '\\';
  783.     p = getcwd(&path[1], PathLen);
  784.     if (p != NULL) {        /* エラー無し */
  785.         ret = 0;
  786.     }
  787.     else {                /* エラー発生 */
  788.         strcpy(&path[1], "????????");
  789.         ret = -1;
  790.     }
  791.     _showDirname(path, pFd);
  792.     return(ret);
  793. }
  794. /* ---    _getCurrentDir()  --- */
  795.  
  796.  
  797. LOCAL    void
  798. _showDirname(
  799.     char        *path,
  800.     fileDialog_t    *pFd)
  801. /*
  802.  *    PURPOSE
  803.  *        パス名領域を消去後,指定されたパスの最終ディレクトリ名を
  804.  *        表示する.
  805.  *        その後,親ディレクトリ移動ボタンのenable/disableを設定する.
  806.  *        渡されたパス名はルートの \ を含んでいるとみなす.
  807.  */
  808. {
  809.     char    *p;
  810.     
  811.     /* マウスを非表示にする */
  812.     MOU_display(Off);
  813.     
  814.     /* パス名領域消去 */
  815.     DISP_rectangle(
  816.         pFd->originX + pFd->pathX,
  817.         pFd->originY + pFd->pathY,
  818.         pFd->originX + pFd->pathX + FD_CharWidth * FnameLen - 1,
  819.         pFd->originY + pFd->pathY + FD_CharHeight - 1,
  820.         CI_Black);
  821.     
  822.     /* ディレクトリ名抽出 */
  823.     p = (char *)jstrrchr((unsigned char *)path, '\\');
  824.     
  825.     /* \の次の文字からパス名領域に表示する */
  826.     p++;
  827.     DISP_stringAt(p,
  828.         pFd->originX + pFd->pathX,
  829.         pFd->originY + pFd->pathY + FD_CharHeight - 1,
  830.         CI_White);
  831.     /*
  832.      * ルートディレクトリか,読み込み失敗ディレクトリなら,
  833.      * 親ディレクトリ移動ボタンをdisable
  834.      */
  835.     if (*p == '\0' || strcmp(p, "????????") == 0)
  836.         BTN_enable(_FD_ButtonIds[BtnParent], FALSE);
  837.     else
  838.     /*
  839.      * 通常のサブディレクトリなら,
  840.      * 親ディレクトリ移動ボタンをenable
  841.      */
  842.         BTN_enable(_FD_ButtonIds[BtnParent], TRUE);
  843.         
  844.     /* マウスを表示する */
  845.     MOU_display(On);
  846. }
  847. /* ---    _showDirname()  --- */
  848.  
  849.  
  850. LOCAL    void
  851. _initFileList(
  852.     fileDialog_t    *pFd)
  853. /*
  854.  *    PURPOSE
  855.  *        ファイルリストの解放,ファイルリスト領域の消去と
  856.  *        スクロールボタンのdisableを行う.
  857.  *    GLOBAL VAR. (set)
  858.  *        _FileInfoTop, _FileInfoTail, _FileDispTop
  859.  */
  860. {
  861.     /* ファイルリストを解放 */
  862.     _freeFileInfo(_FileInfoTop);
  863.     _FileInfoTop = _FileInfoTail = _FileDispTop = NULL;
  864.     
  865.     /* マウスを非表示にする */
  866.     MOU_display(Off);
  867.     
  868.     /* ファイルリスト領域を消去する */
  869.     DISP_rectangle(
  870.         pFd->originX + pFd->fileListX,
  871.         pFd->originY + pFd->fileListY,
  872.         pFd->originX + pFd->fileListX + FD_CharWidth * (FnameLen+2) - 1,
  873.         pFd->originY + pFd->fileListY + FD_CharHeight * FD_FilesInList - 1,
  874.         CI_Black);
  875.     
  876.     /* スクロールボタンをdisableする */
  877.     BTN_enable(_FD_ButtonIds[BtnScrollUp], FALSE);
  878.     BTN_enable(_FD_ButtonIds[BtnScrollDown], FALSE);
  879.  
  880.     /* マウスを表示する */
  881.     MOU_display(On);
  882. }
  883. /* ---    _initFileList()  --- */
  884.  
  885.  
  886. LOCAL    void
  887. _getFiles(
  888.     char        *pattern,
  889.     fileDialog_t    *pFd)
  890. /*
  891.  *    PURPOSE
  892.  *        カレントディレクトリに存在するサブディレクトリとファイルを
  893.  *        取得し,ファイルリストの生成とファイルリストダイアログの
  894.  *        表示を行う.
  895.  *        全サブディレクトリとpatternで指定されたファイル名を持つ
  896.  *        通常ファイルを検索する.
  897.  *    GLOBAL VAR. (set)
  898.  *        _FileInfoTop, _FileInfoTail, _FileDispTop
  899.  */
  900. {
  901.     fileInfo_t    *pFi;
  902.     struct find_t    fBuf;
  903.     
  904.     _FileInfoTop = _FileInfoTail = NULL;
  905.     
  906.     /* サブディレクトリ探索 */
  907.     if (_dos_findfirst("*.*", _A_SUBDIR, &fBuf) == 0) {
  908.         
  909.         /* サブディレクトリの場合,. エントリは対象外 */
  910.         if (strcmp(fBuf.name, ".") == 0) {
  911.             /* 次の .. エントリも読み飛ばす */
  912.             _dos_findnext(&fBuf);
  913.         }
  914.         else {
  915.             if (fBuf.attrib & _A_SUBDIR) {
  916.                 pFi = _makeFileInfo(&fBuf, NULL, _FileInfoTail);
  917.                 if (pFi == NULL)
  918.                     _errorFatal(NoAvailableMemory);
  919.                 _FileInfoTop = pFi;
  920.                 _FileInfoTail = pFi;
  921.             }
  922.         }
  923.         while (_dos_findnext(&fBuf) == 0) {
  924.             if (fBuf.attrib & _A_SUBDIR) {
  925.                 pFi = _makeFileInfo(&fBuf, NULL, _FileInfoTail);
  926.                 if (pFi == NULL)
  927.                     _errorFatal(NoAvailableMemory);
  928.                 if (_FileInfoTop == NULL) {
  929.                     _FileInfoTop = pFi;
  930.                     _FileInfoTail = pFi;
  931.                 }
  932.                 else {
  933.                     _FileInfoTail -> next = pFi;
  934.                     _FileInfoTail = pFi;
  935.                 }
  936.             }
  937.         }
  938.     }
  939.     
  940.     /* ファイル探索 */
  941.     if (_dos_findfirst(pattern, _A_NORMAL, &fBuf) == 0) {
  942.         
  943.         pFi = _makeFileInfo(&fBuf, NULL, _FileInfoTail);
  944.         if (pFi == NULL)
  945.             _errorFatal(NoAvailableMemory);
  946.         if (_FileInfoTop == NULL) {
  947.             _FileInfoTop = pFi;
  948.             _FileInfoTail = pFi;
  949.         }
  950.         else {
  951.             _FileInfoTail -> next = pFi;
  952.             _FileInfoTail = pFi;
  953.         }
  954.         
  955.         while (_dos_findnext(&fBuf) == 0) {
  956.             pFi = _makeFileInfo(&fBuf, NULL, _FileInfoTail);
  957.             if (pFi == NULL)
  958.                 _errorFatal(NoAvailableMemory);
  959.             _FileInfoTail -> next = pFi;
  960.             _FileInfoTail = pFi;
  961.         }
  962.     }
  963.     /* ソート: ファイル名順 */
  964.     _sortFileList(_FileInfoTop, _compName);
  965.     
  966.     /* ファイルリスト表示 */
  967.     _showFileList(_FileInfoTop, pFd);
  968.     _FileDispTop = _FileInfoTop;
  969. }
  970. /* ---    _getFiles()  --- */
  971.  
  972.  
  973. LOCAL    fileInfo_t *
  974. _makeFileInfo(
  975.     struct find_t    *buf,        /* _dos_find**** の結果 */
  976.     fileInfo_t    *next,
  977.     fileInfo_t    *prev)
  978. /*
  979.  *    PURPOSE
  980.  *        ファイル情報領域を確保し,必要な情報を設定する.
  981.  *    RETURNS
  982.  *        非NULL    : 確保したファイル情報へのポインタ
  983.  *        NULL    : メモリ不足により確保失敗
  984.  */
  985. {
  986.     fileInfo_t    *pFi;
  987.     
  988.     pFi = (fileInfo_t *)malloc(sizeof(fileInfo_t));
  989.     if (pFi == NULL)
  990.         return(NULL);        /* malloc()失敗 */
  991.     
  992.     pFi -> next    = next;
  993.     pFi -> prev    = prev;
  994.     strcpy(pFi -> name, buf -> name);
  995.     pFi -> attr    = buf -> attrib;
  996.     pFi -> date    = buf -> wr_date;
  997.     pFi -> time    = buf -> wr_time;
  998.     pFi -> size    = buf -> size;
  999.     pFi -> select    = FALSE;
  1000.     return(pFi);
  1001. }
  1002. /* ---    _makeFileInfo()  --- */
  1003.  
  1004.  
  1005. LOCAL    void
  1006. _freeFileInfo(
  1007.     fileInfo_t    *top)        /* 解放する先頭ノード */
  1008. /*
  1009.  *    PURPOSE
  1010.  *        ファイル情報リストを解放する.
  1011.  */
  1012. {
  1013.     fileInfo_t    *pFi;
  1014.     fileInfo_t    *next;
  1015.     
  1016.     for (pFi = top; pFi != NULL; pFi = next) {
  1017.         next = pFi -> next;
  1018.         free(pFi);
  1019.     }
  1020. }
  1021. /* ---    _freeFileInfo()  --- */
  1022.  
  1023.  
  1024. LOCAL    void
  1025. _sortFileList(
  1026.     fileInfo_t    *top,
  1027.     int        (*comp)(fileInfo_t *p1, fileInfo_t *p2))
  1028. /*
  1029.  *    PURPOSE
  1030.  *        ファイル情報のリストをファイル名の順にソートする.
  1031.  *    IMPLEMENT
  1032.  *        最大探索入れ換え法(?)
  1033.  */
  1034. {
  1035.     fileInfo_t    *p, *min;
  1036.     fileInfo_t    temp;
  1037.     
  1038.     /* ソート対象がまったく存在しなければ,すぐに復帰 */
  1039.     if (top == NULL)
  1040.         return;
  1041.         
  1042.     for ( ; top -> next != NULL; top = top -> next) {
  1043.         min = top;
  1044.         for (p = top -> next; p != NULL; p = p -> next)
  1045.             if ((*comp)(p, min) < 0)
  1046.                 min = p;
  1047.         if (min != top) {
  1048.             /* 入れ換え実行 */
  1049.             strcpy(&temp.name[0], min -> name);
  1050.             temp.attr = min -> attr;
  1051.             temp.date = min -> date;
  1052.             temp.time = min -> time;
  1053.             temp.size = min -> size;
  1054.             strcpy(min -> name, top -> name);
  1055.             min -> attr = top -> attr;
  1056.             min -> date = top -> date;
  1057.             min -> time = top -> time;
  1058.             min -> size = top -> size;
  1059.             strcpy(top -> name, &temp.name[0]);
  1060.             top -> attr = temp.attr;
  1061.             top -> date = temp.date;
  1062.             top -> time = temp.time;
  1063.             top -> size = temp.size;
  1064.         }
  1065.     }
  1066. }
  1067. /* ---    sortFileInfo()  --- */
  1068.  
  1069.  
  1070. LOCAL    int
  1071. _compName(
  1072.     fileInfo_t    *pFi1,
  1073.     fileInfo_t    *pFi2)
  1074. /*
  1075.  *    PURPOSE
  1076.  *        ファイル名を比較し,比較結果を通知する.
  1077.  *        ディレクトリは,ファイルより小さい.
  1078.  *        同種の中では,ファイル名/ディレクトリ名の順に従う.
  1079.  *    RETURNS
  1080.  *        1    : pFi1 は pFi2 より大きい
  1081.  *        0    : pFi1 と pFi2 は等しい
  1082.  *        -1    : pFi1 は pFi2 より小さい
  1083.  */
  1084. {
  1085.     if (pFi1 -> attr & _A_SUBDIR) {
  1086.         if (pFi2 -> attr & _A_SUBDIR)
  1087.             return(strcmp(pFi1 -> name, pFi2 -> name));
  1088.         return(-1);
  1089.     }
  1090.     else {
  1091.         if (pFi2 -> attr & _A_SUBDIR)
  1092.             return(1);
  1093.         return(strcmp(pFi1 -> name, pFi2 -> name));
  1094.     }
  1095.     /* ここには到達しない */
  1096. }
  1097. /* ---    _compName()  --- */
  1098.  
  1099.  
  1100. LOCAL    void
  1101. _showFileList(
  1102.     fileInfo_t    *pFi,
  1103.     fileDialog_t    *pFd)
  1104. /*
  1105.  *    PURPOSE
  1106.  *        ファイル情報のリストをファイルリスト領域に表示し,
  1107.  *        必要に応じてスクロールボタンをenableにする.
  1108.  */
  1109. {
  1110.     int    i;
  1111.     char    name[15];
  1112.     
  1113.     /* マウスを非表示にする */
  1114.     MOU_display(Off);
  1115.     
  1116.     /* スクロールボタン▲をenable */
  1117.     if (pFi != NULL && pFi -> prev != NULL)
  1118.         BTN_enable(_FD_ButtonIds[BtnScrollUp], TRUE);
  1119.     
  1120.     /* ファイルリストを表示 */
  1121.     for (i = 0; i < FD_FilesInList; i++) {
  1122.         if (pFi == NULL)
  1123.             break;
  1124.         /*
  1125.          * サブディレクトリなら,< >で括って表示する.
  1126.          */
  1127.         if (pFi -> attr & _A_SUBDIR) {
  1128.             strcpy(name, "<");
  1129.             strcat(name, pFi -> name);
  1130.             strcat(name, ">");
  1131.         }
  1132.         else
  1133.             strcpy(name, pFi -> name);
  1134.         
  1135.         DISP_stringAt(
  1136.             name,
  1137.             pFd->originX + pFd->fileListX,
  1138.             pFd->originY + pFd->fileListY + FD_CharHeight * (i+1) - 1,
  1139.             CI_White);
  1140.         pFi = pFi -> next;
  1141.     }
  1142.     /* スクロールボタン▼をenable */
  1143.     if (pFi != NULL)
  1144.         BTN_enable(_FD_ButtonIds[BtnScrollDown], TRUE);
  1145.     
  1146.     /* マウスを表示する */
  1147.     MOU_display(On);
  1148. }
  1149. /* ---    _showFileList()  --- */
  1150.  
  1151.  
  1152. LOCAL    void
  1153. _scrollFileList(
  1154.     int        direction,
  1155.     fileDialog_t    *pFd)
  1156. /*
  1157.  *    PURPOSE
  1158.  *        ファイルリストをdirectionで指定された方向にスクロールする.
  1159.  *        スクロール対象ファイル数に応じて,
  1160.  *        スクロールボタンのenableを変更する.
  1161.  *    GLOBAL VAR. (set)
  1162.  *        _FileDispTop
  1163.  */
  1164. {
  1165.     int        i;
  1166.     fileInfo_t    *pFi;
  1167.     int        luX, luY, rdX, rdY;
  1168.     int        lu2X, lu2Y, rd2X, rd2Y;
  1169.     int        lueX, lueY, rdeX, rdeY;
  1170.     char        name[15];
  1171.     int        revFile;
  1172.     int        btn1, btn2;
  1173.     fileInfo_t    *btn2On;
  1174.     
  1175.     switch (direction) {
  1176.     case BtnScrollDown:        /* ▼ */
  1177.         for (pFi = _FileDispTop, i = 0; i < FD_FilesInList; i++)
  1178.             pFi = pFi -> next;
  1179.         _FileDispTop = _FileDispTop -> next;
  1180.         revFile = FD_FilesInList - 1;
  1181.         
  1182.         /* スクロールボタンをenable化 */
  1183.         btn1 = _FD_ButtonIds[BtnScrollUp];
  1184.         btn2 = _FD_ButtonIds[BtnScrollDown];
  1185.         btn2On = pFi -> next;
  1186.         
  1187.         /* 複写元領域の設定 */
  1188.         luX = pFd->originX + pFd->fileListX;
  1189.         luY = pFd->originY + pFd->fileListY + FD_CharHeight;
  1190.         rdX = pFd->originX + pFd->fileListX
  1191.             + FD_CharWidth * (FnameLen+2) - 1;
  1192.         rdY = pFd->originY + pFd->fileListY
  1193.             + FD_CharHeight * FD_FilesInList - 1;
  1194.         
  1195.         /* 複写先領域の設定 */
  1196.         lu2X = pFd->originX + pFd->fileListX;
  1197.         lu2Y = pFd->originY + pFd->fileListY;
  1198.         rd2X = pFd->originX + pFd->fileListX
  1199.             + FD_CharWidth * (FnameLen+2) - 1;
  1200.         rd2Y = pFd->originY + pFd->fileListY
  1201.             + FD_CharHeight * (FD_FilesInList-1) - 1;
  1202.         
  1203.         /* 消去領域の設定 */
  1204.         lueX = pFd->originX + pFd->fileListX;
  1205.         lueY = pFd->originY + pFd->fileListY
  1206.             + FD_CharHeight * (FD_FilesInList-1);
  1207.         rdeX = pFd->originX + pFd->fileListX
  1208.             + FD_CharWidth * (FnameLen+2) - 1;
  1209.         rdeY = pFd->originY + pFd->fileListY
  1210.             + FD_CharHeight * FD_FilesInList - 1;
  1211.         break;
  1212.         
  1213.     case BtnScrollUp:        /* ▲ */
  1214.         pFi = _FileDispTop -> prev;
  1215.         _FileDispTop = _FileDispTop -> prev;
  1216.         revFile = 0;
  1217.         
  1218.         /* スクロールボタンをenable化 */
  1219.         btn1 = _FD_ButtonIds[BtnScrollDown];
  1220.         btn2 = _FD_ButtonIds[BtnScrollUp];
  1221.         btn2On = pFi -> prev;
  1222.         
  1223.         /* 複写元領域の設定 */
  1224.         luX = pFd->originX + pFd->fileListX;
  1225.         luY = pFd->originY + pFd->fileListY;
  1226.         rdX = pFd->originX + pFd->fileListX
  1227.             + FD_CharWidth * (FnameLen+2) - 1;
  1228.         rdY = pFd->originY + pFd->fileListY
  1229.             + FD_CharHeight * (FD_FilesInList-1) - 1;
  1230.         
  1231.         /* 複写先領域の設定 */
  1232.         lu2X = pFd->originX + pFd->fileListX;
  1233.         lu2Y = pFd->originY + pFd->fileListY + FD_CharHeight;
  1234.         rd2X = pFd->originX + pFd->fileListX
  1235.             + FD_CharWidth * (FnameLen+2) - 1;
  1236.         rd2Y = pFd->originY + pFd->fileListY
  1237.             + FD_CharHeight * FD_FilesInList - 1;
  1238.         
  1239.         /* 消去領域の設定 */
  1240.         lueX = pFd->originX + pFd->fileListX;
  1241.         lueY = pFd->originY + pFd->fileListY;
  1242.         rdeX = pFd->originX + pFd->fileListX
  1243.             + FD_CharWidth * (FnameLen+2) - 1;
  1244.         rdeY = pFd->originY + pFd->fileListY + FD_CharHeight - 1;
  1245.         break;
  1246.         
  1247.     default:
  1248.         _errorFatal(IllegalDirection);
  1249.         break;
  1250.     }
  1251.     /* ファイルリスト領域の移動,消去,表示 */
  1252.     MOU_display(Off);
  1253.     DISP_getPixelBlock(luX, luY, rdX, rdY, _BufPixelBlock);
  1254.     DISP_putPixelBlock(lu2X, lu2Y, rd2X, rd2Y, _BufPixelBlock);
  1255.     DISP_rectangle(lueX, lueY, rdeX, rdeY, CI_Black);
  1256.     /*
  1257.      * サブディレクトリなら,< >で括って表示する.
  1258.      */
  1259.     if (pFi -> attr & _A_SUBDIR) {
  1260.         strcpy(name, "<");
  1261.         strcat(name, pFi -> name);
  1262.         strcat(name, ">");
  1263.     }
  1264.     else
  1265.         strcpy(name, pFi -> name);
  1266.     
  1267.     DISP_stringAt(name, lueX, rdeY, CI_White);
  1268.     
  1269.     if (pFi -> select == TRUE)
  1270.         _reverseFileName(revFile, pFd);
  1271.         
  1272.     /* スクロールボタンをenable化 */
  1273.     BTN_enable(btn1, TRUE);
  1274.     BTN_enable(btn2, (btn2On != NULL) ? TRUE : FALSE);
  1275.  
  1276.     MOU_display(On);
  1277. }
  1278. /* ---    _scrollFileList()  --- */
  1279.  
  1280.  
  1281. LOCAL    void
  1282. _showFilename(
  1283.     char        *name,
  1284.     fileDialog_t    *pFd)
  1285. /*
  1286.  *    PURPOSE
  1287.  *        ファイル名領域を消去後,指定されたファイル名を表示する.
  1288.  *        ファイル名が空文字列でなければ,確認ボタンをenableし,
  1289.  *        空文字列であれば,確認ボタンをdisableする.
  1290.  */
  1291. {
  1292.     /* マウスを非表示にする */
  1293.     MOU_display(Off);
  1294.     
  1295.     /* ファイル名エリア消去 */
  1296.     DISP_rectangle(
  1297.         pFd->originX + pFd->fileNameX,
  1298.         pFd->originY + pFd->fileNameY,
  1299.         pFd->originX + pFd->fileNameX + FD_CharWidth * FnameLen - 1,
  1300.         pFd->originY + pFd->fileNameY + FD_CharHeight - 1,
  1301.         CI_Black);
  1302.     
  1303.     /* ファイル名表示 */
  1304.     DISP_stringAt(
  1305.         name,
  1306.         pFd->originX + pFd->fileNameX,
  1307.         pFd->originY + pFd->fileNameY + FD_CharHeight - 1,
  1308.         CI_White);
  1309.         
  1310.     /* 確認ボタンの表示変更 */
  1311.     BTN_enable(_FD_ButtonIds[BtnOk], (*name == '\0') ? FALSE : TRUE);
  1312.     
  1313.     /* マウスを表示する */
  1314.     MOU_display(On);
  1315. }
  1316. /* ---    _showFilename()  --- */
  1317.  
  1318.  
  1319. LOCAL    long
  1320. _getFdEvent(
  1321.     fileDialog_t    *pFd)
  1322. /*
  1323.  *    PURPOSE
  1324.  *        発生したイベントを通知する.
  1325.  *        マウスボタンのクリックのみが,イベントを発生させうる.
  1326.  *        イベントはボタンイベントとファイルリストイベントに分かれる.
  1327.  *        ボタンはenableであるもののみがイベントを発生させうる.
  1328.  *        ファイルリストにファイルが表示されている場合のみ,
  1329.  *        ファイルイベントが発生する.ファイルイベントでは,
  1330.  *        ファイルリスト内での位置をminorイベントIDで通知する.
  1331.  *    RETURNS
  1332.  *        イベントID
  1333.  *    GLOBAL VAR. (ref)
  1334.  *        _FileInfoTop, _FileDispTop
  1335.  */
  1336. {
  1337.     int    item;
  1338.     int    mosX, mosY;
  1339.     int    mosButton;
  1340.     int    btnStatus;
  1341.     int    pushedBtn;        /* 通常モードで押されたボタンID */
  1342.     int    selectedFile, newFile;
  1343.     int    i;
  1344.     static    int    repeatId = -1;    /* repeatモードに入ったイベントID */
  1345.     fileInfo_t    *pFi;
  1346.     
  1347.     while (1) {
  1348.         pushedBtn = -1;
  1349.         selectedFile = -1;
  1350.         
  1351.         /* repeatモードの処理を行う */
  1352.         if (repeatId != -1) {
  1353.             do {
  1354.                 mosButton = MOU_readPosition(&mosX, &mosY);
  1355.                 if (mosButton & MouseLeftButton)
  1356.                     /*
  1357.                      * 同じボタンが押され続けていれば,
  1358.                      * 復帰する.
  1359.                      */
  1360.                     if (BTN_posCheck(_FD_ButtonIds[repeatId],
  1361.                             mosX, mosY) == 1) {
  1362.                         return(repeatId);
  1363.                     }
  1364.             } while (mosButton & MouseLeftButton);
  1365.             
  1366.             /* repeatモード終了 */
  1367.             MOU_display(Off);
  1368.             BTN_reverse(_FD_ButtonIds[repeatId]);
  1369.             MOU_display(On);
  1370.             repeatId = -1;
  1371.         }
  1372.         
  1373.         /* 左ボタンが押されるのを待つ */
  1374.         MOU_waitPress(MouseLeftButton, &mosX, &mosY);
  1375.         
  1376.         /* ダイアログアイテムボタンが押されたかチェック */
  1377.         for (item = 0; item < MaxButtons; item++) {
  1378.             if (BTN_posCheck(_FD_ButtonIds[item], mosX, mosY) == 1) {
  1379.                 pushedBtn = _FD_ButtonIds[item];
  1380.                 break;
  1381.             }
  1382.         }
  1383.         
  1384.         /* 押されていなければ,ファイルリストをチェック */
  1385.         if (pushedBtn == -1)
  1386.             selectedFile = _checkFileList(mosX, mosY, pFd);
  1387.         
  1388.         /*
  1389.          * 左ボタンの押下対象(アイテムボタン,ファイルリスト, その他)
  1390.          * ごとに処理する
  1391.          */
  1392.         
  1393.         /* アイテムボタンが押されていたら */
  1394.         if (pushedBtn != -1) {
  1395.         
  1396.             /* ボタンを反転表示する */
  1397.             MOU_display(Off);
  1398.             BTN_reverse(pushedBtn);
  1399.             MOU_display(On);
  1400.             btnStatus = ~FALSE;
  1401.             /*
  1402.              * repeat属性を持ったボタンであれば,
  1403.              * repeatIDを設定し,すぐに復帰する.
  1404.              */
  1405.             if (BTN_isRepeat(pushedBtn)) {
  1406.                 repeatId = item;
  1407.                 return(item);
  1408.             }
  1409.             /*
  1410.              * 左ボタンが押されている間
  1411.              * マウスの位置によりボタン表示を変更し,
  1412.              * 左ボタンが離されるのを待つ
  1413.              */
  1414.             do {
  1415.                 mosButton = MOU_readPosition(&mosX, &mosY);
  1416.                 if (btnStatus != FALSE &&
  1417.                     !BTN_posCheck(pushedBtn, mosX, mosY)) {
  1418.                     MOU_display(Off);
  1419.                     BTN_reverse(pushedBtn);
  1420.                     MOU_display(On);
  1421.                     btnStatus = FALSE;
  1422.                 }
  1423.                 else if (btnStatus == FALSE &&
  1424.                     BTN_posCheck(pushedBtn, mosX, mosY)) {
  1425.                     MOU_display(Off);
  1426.                     BTN_reverse(pushedBtn);
  1427.                     MOU_display(On);
  1428.                     btnStatus = ~FALSE;
  1429.                 }
  1430.             } while (mosButton & MouseLeftButton);
  1431.             /*
  1432.              * 左ボタンが離された時点で,マウスカーソルが
  1433.              * 最初に押されたボタン上にあれば,ボタンを戻して終了.
  1434.              * さもなければ,元へ戻る.
  1435.              */
  1436.             if (btnStatus != FALSE) {
  1437.                 MOU_display(Off);
  1438.                 BTN_reverse(pushedBtn);
  1439.                 MOU_display(On);
  1440.                 return(item);
  1441.             }
  1442.         }
  1443.         
  1444.         /* ファイルリスト内が選択されていたら */ 
  1445.         else if (selectedFile != -1) {
  1446.         
  1447.             /*
  1448.              * 既に存在する反転表示を元に戻した後,
  1449.              * 指定された項目を反転表示する.
  1450.              */
  1451.             MOU_display(Off);
  1452.             for (i = 0, pFi = _FileDispTop; i < FD_FilesInList; i++) {
  1453.                 if (pFi == NULL)
  1454.                     break;
  1455.                 if (pFi -> select == TRUE)
  1456.                     _reverseFileName(i, pFd);
  1457.                 pFi -> select = FALSE;
  1458.                 pFi = pFi -> next;
  1459.             }
  1460.             for (pFi = _FileInfoTop; pFi != NULL; pFi = pFi -> next)
  1461.                 pFi -> select = FALSE;
  1462.             _reverseFileName(selectedFile, pFd);
  1463.             MOU_display(On);
  1464.             /*
  1465.              * 左ボタンが押されている間,マウスの位置により
  1466.              * ファイル名の反転表示を変更し,
  1467.              * 左ボタンが離されるのを待つ.
  1468.              */
  1469.             do {
  1470.                 mosButton = MOU_readPosition(&mosX, &mosY);
  1471.                 newFile = _checkFileList(mosX, mosY, pFd);
  1472.                 
  1473.                 if (selectedFile != -1 &&
  1474.                     newFile != selectedFile) {
  1475.                     MOU_display(Off);
  1476.                     _reverseFileName(selectedFile, pFd);
  1477.                     MOU_display(On);
  1478.                 }
  1479.                 if (newFile != -1 &&
  1480.                     selectedFile != newFile) {
  1481.                     MOU_display(Off);
  1482.                     _reverseFileName(newFile, pFd);
  1483.                     MOU_display(On);
  1484.                 }
  1485.                 
  1486.                 selectedFile = newFile;
  1487.                 
  1488.             } while (mosButton & MouseLeftButton);
  1489.             /*
  1490.              * 左ボタンが離された時点で,マウスカーソルが
  1491.              * ファイル名上にあれば,そのまま終了.
  1492.              * さもなければ,元へ戻る.
  1493.              */
  1494.             if (newFile != -1) {
  1495.                 return((newFile << 16) | FileList);
  1496.             }
  1497.         }
  1498.         
  1499.         /* それ以外の領域で押されていた場合 */
  1500.         else {
  1501.             /* 左ボタンが離されるのを待ち,元へ戻る */
  1502.             MOU_waitRelease(MouseLeftButton, &mosX, &mosY);
  1503.         }
  1504.     }
  1505.     /* ここには到達しないため,return文はない */
  1506. }
  1507. /* ---    _getFdEvent()  --- */
  1508.  
  1509.  
  1510. LOCAL    int
  1511. _checkFileList(
  1512.     int        x,        /* チェック対象座標 */
  1513.     int        y,        /*    同上    */
  1514.     fileDialog_t    *pFd)
  1515. /*
  1516.  *    PURPOSE
  1517.  *        指定した座標が,
  1518.  *        ファイルリストに表示中のファイル名のうち,
  1519.  *        何番目のファイル名の位置に相当するかを判定して,通知する.
  1520.  *        ファイルリスト中であっても,ファイル名が表示していない位置
  1521.  *        であれば,-1 を通知する.
  1522.  *    RETURNS
  1523.  *        -1    : 指定した座標はファイル名を指していない
  1524.  *        >= 0    : ファイル番号(先頭は0)
  1525.  *    GLOBAL VAR. (ref)
  1526.  *        _FileDispTop
  1527.  */
  1528. {
  1529.     int    i;
  1530.     int    checkY;
  1531.     fileInfo_t    *pFi;
  1532.     
  1533.     /* ファイルリスト内か? */
  1534.     if (pFd->originX + pFd->fileListX > x ||
  1535.         pFd->originX + pFd->fileListX + FD_CharWidth * (FnameLen+2) - 1 < x)
  1536.         return(-1);
  1537.     if (pFd->originY + pFd -> fileListY > y)
  1538.         return(-1);
  1539.     
  1540.     /* 何番目か? */
  1541.     checkY = pFd->originY + pFd->fileListY + FD_CharHeight - 1;
  1542.     pFi = _FileDispTop;
  1543.     for (i = 0; i < FD_FilesInList; i++) {
  1544.         if (pFi == NULL)
  1545.             return(-1);    /* ファイル名なし */
  1546.         if (y < checkY)
  1547.             return(i);    /* ファイル名あり */
  1548.         checkY += FD_CharHeight;
  1549.         pFi = pFi -> next;
  1550.     }
  1551.     return(-1);            /* ファイルリスト外 */
  1552. }
  1553. /* ---    _checkFileList()  --- */
  1554.  
  1555.  
  1556. LOCAL    void
  1557. _reverseFileName(
  1558.     int        fileNo,        /* 反転対象ファイル番号(先頭は0) */
  1559.     fileDialog_t    *pFd)
  1560. {
  1561.     DISP_xorRectangle(
  1562.         pFd->originX + pFd->fileListX,
  1563.         pFd->originY + pFd->fileListY + FD_CharHeight * fileNo,
  1564.         pFd->originX + pFd->fileListX + FD_CharWidth * (FnameLen+2) - 1,
  1565.         pFd->originY + pFd->fileListY + FD_CharHeight * (fileNo+1) - 1,
  1566.         0xffff);
  1567. }
  1568. /* ---    _reverseFileName()  --- */
  1569.  
  1570.  
  1571. LOCAL    void
  1572. _errorFatal(
  1573.     int    errorCode)
  1574. /*
  1575.  *    PURPOSE
  1576.  *        致命的エラー処理ルーチン
  1577.  */
  1578. {
  1579.     longjmp(_FileDialogEnv, errorCode);
  1580. }
  1581. /* ---    _errorFatal()  --- */
  1582.  
  1583.  
  1584. /*****    filedlg.c  *****/
  1585.