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