/*
 *  TMENU.INF Editor    アイテム移動画面
*/

#include "config.h"
#include "edit.h"

#define MAX_DSP 25      /*  一度に画面に表示できる数  */
#define item_x(x)   (((x)%5)*ITEM_X_SIZ+ITEM_X)
#define item_y(y)   (((y)/5)*ITEM_Y_SIZ+ITEM_Y)

#define DISP_NUM    /*  アイテムの番号を表示する場合は定義する  */
#undef  DISP_NUM

#define MV_START    0
#define MV_RESTART  1
#define MV_LOOP     2
#define MV_END      3

INFO    info[MULTI_BUF] ;
int     active_buf = 0 ;

ICON    icon[ 128 ] ;
INF     inf[ MAX_INF ] ;        /*  現在編集中のデータ  */
INF     org_inf[ MAX_INF ] ;    /*  ロードしたときのデータ  */
int     org_maxnum ;            /*  ロードしたときの最大数  */

int     load_count = 0 ;    /*  TMENU.INF をロードした回数  */
int     maxnum = 0 ;

int     mos_disp = MOS_OFF ;
int     menu_event = 0 ;
int     now_palet = 0 ;
int     writepage = PAGE0 ;

static  INF     tmpinf = { 0 } ;
static  char    mark[ MAX_INF ] ;
static  int     vol_size = 0 ;
static  int     pos = 0 ;
static  int     marknum = 0 ;
static  int     item_move = -1 ;
static  int     item_copy = -1 ;

static  char    *func_btn[ MAX_FUNC ] =
                 { " 移 動 ", " 交 換 ", " 削 除 ", " 編 集 ", " 複 写 " } ;
static  int     func = -1 ;

static  CDBUF   wild_inf[ CARD_MAX ] =
{
    { OFF,FALSE,"*.*" }, { ON ,FALSE,"*.INF" }, { OFF,FALSE,"*.BAK" },
    { OFF,TRUE, NULL  }, { OFF,TRUE,  NULL   }, { OFF,TRUE,  NULL   },
    { OFF,TRUE, NULL  }, { OFF,TRUE,  NULL   }, { OFF,TRUE,  NULL   },
    { OFF,TRUE, NULL  },
} ;

static  CDBUF   wild_new[ CARD_MAX ] =
{
    { OFF,FALSE,"*.*"   }, { ON, FALSE,"*.EXP" }, { ON, FALSE,"*.EXE" },
    { ON, FALSE,"*.COM" }, { ON, FALSE,"*.BAT" }, { OFF,TRUE,  NULL   },
    { OFF,TRUE, NULL    }, { OFF,TRUE,  NULL   }, { OFF,TRUE,  NULL   },
    { OFF,TRUE, NULL    },
} ;

static  char    tmp[ 256 ] ;


extern  char    *select_file( char *def_file, char cmd ) ;
extern  void    click_item( int item ) ;
extern  void    move( int func, int x, int y ) ;
extern  void    clear_mark( void ) ;
extern  int     del_item( void ) ;
extern  void    del_inf( int i ) ;
extern  void    ins_inf( int i ) ;
extern  void    dsp_scrn( int, int ) ;
extern  void    dsp_scrn( int, int ) ;
extern  void    dsp_item( int, INF *, int ) ;
extern  void    dsp_bar( int num ) ;
extern  void    dsp_func_btn( void ) ;
extern  void    dsp_func( int num ) ;
extern  void    dsp_mark( int num, int sw ) ;
extern  void    dsp_menu( char *file ) ;
extern  int     readinf( char * ) ;
extern  int     writeinf( char * ) ;
extern  void    item_recover( int redisplayflag ) ;
extern  void    item_rewrite( int, int, int ) ;
extern  void    chg_mark( int ) ;
extern  void    unset_mark( int ) ;
extern  void    set_mark( int ) ;
extern  void    MENU_clip( REGS EVENT *ep, int x, int y, int sw ) ;
extern  void    MOVE_clip( REGS EVENT *ep, int x, int y, int sw ) ;
extern  void    ITEM_clip( REGS EVENT *ep, int x, int y, int sw ) ;

void    toupper_inf( INF *ip )
{
    REGS    int     i ;
    auto    char    type[256] ;

    typecheck( type, (char *)ip->fname, IR_FNAMLEN ) ;
    for( i = 0 ; i < IR_FNAMLEN ; i ++ )
        if( type[i] == IS_ANK )
            ip->fname[i] = toupper( ip->fname[i] ) ;

    typecheck( type, (char *)ip->fext, IR_FEXTLEN ) ;
    for( i = 0 ; i < IR_FEXTLEN ; i ++ )
        if( type[i] == IS_ANK )
            ip->fext[i] = toupper( ip->fext[i] ) ;

    typecheck( type, (char *)ip->cmd, IR_CMDLEN ) ;
    for( i = 0 ;
             i < IR_CMDLEN && ip->cmd[i] != '\0' && ip->cmd[i] != ' ' ; i ++ )
        if( type[i] == IS_ANK )
            ip->cmd[i] = toupper( ip->cmd[i] ) ;
    if( ( i = strlen( ip->cmd ) ) < IR_CMDLEN-1 )
        ip->cmd[i] = ' ', ip->cmd[i+1] = '\0' ;
}

int     sep_dirmode( char *file )
{
    int     len = strlen( file ) ;

    if( file[len-1] == 0x10 )       /*  dir  */
    {
        file[len-1] = '\0' ;
        return 0x10 ;
    }
    else
        return 0 ;
}

void    init_file_buf( int max )
{
    int     i ;

    for( i = 0 ; i < max ; i ++ )
    {
        info[i].pathlist[0] = '\0' ;
        info[i].maxnum = 0 ;
        info[i].org_maxnum = 0 ;
        memcpy( &info[i].icon, &icon, sizeof( icon ) ) ;
    }
}

char    *change_buf( char *file )
{
    INFO    *ip ;

    load_count ++ ;     /*  TMENU.ICN が切り替わったことを明示  */

    /*  現在のデータを退避  */
    ip = &info[ active_buf ] ;

    strcpy( ip->pathlist, file ) ;
    memcpy( ip->icon, icon, sizeof( icon ) ) ;
    ip->maxnum = maxnum ;
    memcpy( ip->inf, inf, sizeof( inf ) ) ;
    ip->org_maxnum = org_maxnum ;
    memcpy( ip->org_inf, org_inf, sizeof( inf ) ) ;

    /*  切り換え  */
    if( ( ++ active_buf ) >= MULTI_BUF )
        active_buf = 0 ;

    /*  復帰  */
    ip = &info[ active_buf ] ;

    memcpy( icon, ip->icon, sizeof( icon ) ) ;
    maxnum = ip->maxnum ;
    memcpy( inf, ip->inf, sizeof( inf ) ) ;
    org_maxnum = ip->org_maxnum ;
    memcpy( org_inf, ip->org_inf, sizeof( inf ) ) ;

    return ip->pathlist ;
}

char    *select_file( char *def_file, char cmd )
{
    auto    int     sw, mos_x, mos_y ;
    auto    int     mos = mos_disp ;
    auto    char    *ret_file, *msg ;
    auto    int     dirflag ;

    MOS_PAD_rdpos( &sw, &mos_x, &mos_y ) ;

    if( now_palet != 1 )
        chg_palette( 0, 1 ) ;
    switch( cmd )
    {
      case 'N': msg = "新規登録する実行ファイルを選択してください" ;
        dirflag = ON ;
        break ;
      case 'L': msg = "読み込むアイテムファイルを選択してください" ;
        dirflag = OFF ;
        break ;
      case 'S': msg = "書き込むアイテムファイルを指定してください" ;
        dirflag = OFF ;
        break ;
    }
    ret_file = file_select( def_file, msg,
            ( cmd == 'N' ) ? wild_new : wild_inf, dirflag ) ;
    MOS_disp( MOS_OFF ) ;

    cls( 1, 0 ) ;
    DSP_writePage( egbwork, 0 ) ;

    MOS_writePage( 0 ) ;
    MOS_horizon ( MIN_HORIZON,  MAX_HORIZON ) ;
    MOS_vertical( MIN_VERTICAL, MAX_VERTICAL ) ;

    MOS_setpos( mos_x, mos_y ) ;
    MOS_disp( mos ) ;

    chg_palette( 0, now_palet ) ;

    return( ret_file ) ;
}

/*
 *  ファイルをロードする
 *

 *  戻り値  まともに読めた場合      -> パス名へのポインタ
 *          キャンセルした場合      -> NULL ポインタ
 *          読んだけど失敗した場合  -> 長さ0の文字列
*/

char    *load_file( void )
{
    auto    char    *file = NULL ;
    static  char    buf[ 256 ] ;

    chg_palette( 0, now_palet = 1 ) ;

    file = select_file( NULL, 'L' ) ;

    if( file != NULL )
    {
        switch( readinf( file ) )   /*  ロードを実行  */
        {
          case ERR_ABORT:   /*  回復不能  */
            *file = '\0' ;
            break ;

          case ERR_BREAK:   /*  回復可能  */
            file = NULL ;
            break ;

          case ERR_NOERROR: /*  エラーなし  */
            strcpy( buf, file ) ;
            file = buf ;
            break ;
        }
    }

    chg_palette( 0, now_palet = 0 ) ;
    KAN_dispMode() ;        /*  モード再表示  */

    return( file ) ;
}


/*
 *  ファイルをセーブする
 *

 *  パラメータ  現在のファイル

 *  戻り値  まともに書けた場合      -> 書いたファイル名
 *          キャンセルした場合      -> NULL
 *          書き込みに失敗した場合  -> NULL
*/

char    *save_file( char *file )
{
    auto    char    filename[ 256 ] ;
    auto    int     pal = now_palet ;

    chg_palette( 0, now_palet = 1 ) ;

    file = select_file( file, 'S' ) ;

    if( file == NULL || *file == '\0' )
    {
        chg_palette( 0, now_palet = pal ) ;
        KAN_dispMode() ;        /*  モード再表示  */
        return( NULL ) ;
    }
    strcpy( filename, file ) ;

    if( writeinf( filename ) == ERROR )     /*  書き込みに失敗した  */
    {
        chg_palette( 0, now_palet = pal ) ;
        KAN_dispMode() ;        /*  モード再表示  */
        return( NULL ) ;
    }

    chg_palette( 0, now_palet = pal ) ;
    KAN_dispMode() ;        /*  モード再表示  */

    return( filename ) ;
}


/*  アイテム移動画面のメイン処理部  */


int     edit_move( char file[] )
{
    int     num = 0, rewrite = TRUE ;
    int     ret_val = RET_DEFAULT ;
    int     ch = 0 ;
    char    *tmpfile ;

    if( func == -1 )            /*  起動時のデフォルト・ファンクション  */
        func = setup.func ;

    MOS_disp( mos_disp = FALSE ) ;

    EVT_reset() ;
    dsp_menu( file ) ;      /*  一番上の行などなど  */

    MOS_disp( mos_disp = TRUE ) ;

    do
    {
        dsp_scrn( num, rewrite ) ;
        rewrite = FALSE ;

        do
        {
            menu_event = 0 ;

            EVT_loop( 0,3 ) ;

            if( kbhit( OFF ) != FALSE )       /*  キー入力センス  */
            {
                switch( ch = getch() )
                {
                  case 0x807C:      /*  BREAK : 読み込み  */
                    menu_event = 15 ;   break ;
                  case 0x807D:      /*  COPY : 新規  */
                    menu_event = 4 ;    break ;

                  case 0x805D:      /*  PF1 : 移動  */
                    menu_event = 5 ;    break ;
                  case 0x805E:      /*  PF2 : 交換  */
                    menu_event = 6 ;    break ;
                  case 0x805F:      /*  PF3 : 削除  */
                    menu_event = 7 ;    break ;
                  case 0x8060:      /*  PF4 : 編集  */
                    menu_event = 8 ;    break ;
                  case 0x8061:      /*  PF5 : 複写  */
                    menu_event = 9 ;    break ;

                  case 0x8066:      /*  PF10 : 終了  */
                    menu_event = 1 ;    break ;
                  case 0x8069:      /*  PF11 : 読み込み  */
                    menu_event = 2 ;    break ;
                  case 0x805B:      /*  PF12 : 書き込み  */
                    menu_event = 3 ;    break ;

                  case 0x806E:      /*  前行  */
                    menu_event = 10 ;   break ;
                  case 0x8070:      /*  次行  */
                    menu_event = 11 ;   break ;

                  default:          /*  無視  */
                    break ;
                }
            }

            if( cancel_on != FALSE )        /*  キャンセル  */
            {
                if( item_move != -1 || marknum > 0 || item_copy != -1 )
                {
                    MOS_disp( mos_disp = FALSE ) ;

                    if( item_move != -1 )
                        item_recover( TRUE ) ;
                    item_copy = -1 ;
                    move( MV_END, 0,0 ) ;
                    clear_mark() ;          /*  マークを解除  */

                    MOS_disp( mos_disp = TRUE ) ;
                }

                cancel_on = FALSE ;
            }

            switch( menu_event )
            {
              case 1:                       /*  終了  */
                if( end_assert( file ) == TRUE )
                    ret_val = RET_QUIT ;
                else
                {
                    menu_event = 0 ;
                    title( file ) ;
                }
                break ;

              case 2:                       /*  読み込み  */
                if( ( tmpfile = load_file() ) == NULL )
                    menu_event = 0 ;
                else
                {
                    if( *tmpfile == '\0' )
                        maxnum = 0 ;
                    strcpy( file, tmpfile ) ;
                    rewrite = TRUE ;
                    num = pos = 0 ;
                    title( file ) ;
                }
                break ;

              case 3:                       /*  書き込み  */
                if( item_move != -1 )
                    item_recover( TRUE ) ;
                if( ( tmpfile = save_file( file ) ) == NULL )
                    menu_event = 0 ;
                else
                {
                    strcpy( file, tmpfile ) ;
                    title( file ) ;
                }
                break ;

              case 4:                       /*  新規  */
                if( ( tmpfile = select_file( NULL, 'N' ) ) == NULL )
                    menu_event = 0 ;
                else
                {
                    int     dirmode = 0 ;

                    dirmode = sep_dirmode( tmpfile ) ;
                    init_inf( &inf[maxnum], tmpfile, NULL,-1 ) ;
                    inf[maxnum].dirflag = dirmode ;
                    mark[maxnum] = FALSE ;

                    if( edit_item( &inf[maxnum] ) == FALSE )   /*  中止  */
                        menu_event = 0 ;
                    else
                    {
                        maxnum ++ ;
                        rewrite = TRUE ;
                    }
                }
                break ;

              case 5:                       /*  移動  */
                if( func != FUNC_MOVE )
                    dsp_func( func ), dsp_func( func = FUNC_MOVE ) ;

                if( marknum > 0 )
                    clear_mark() ;
                menu_event = 0 ;
                break ;

              case 6:                       /*  交換  */
                if( func != FUNC_CHG )
                    dsp_func( func ), dsp_func( func = FUNC_CHG ) ;

                if( marknum > 0 )
                    clear_mark() ;
                if( item_move != -1 )
                    item_recover( TRUE ) ;
                if( item_copy != -1 )
                    item_copy = -1 ;
                menu_event = 0 ;
                break ;

              case 7:                       /*  削除  */
                /*  機能を削除にする  */
                if( func != FUNC_DEL )
                    dsp_func( func ), dsp_func( func = FUNC_DEL ) ;

                menu_event = 0 ;

                if( item_copy != -1 )
                    item_copy = -1 ;
                if( marknum != 0 || item_move != -1 )
                {               /*  マークされているものを削除  */
                    if( item_move != -1 )   /*  移動中のものは元に戻す  */
                    {
                        int num = item_move ;
                        item_recover( TRUE ) ;
                        chg_mark( num ) ;
                    }
                    del_item() ;
                }
                break ;

              case 8:                       /*  編集  */
                if( func != FUNC_EDIT )
                    dsp_func( func ), dsp_func( func = FUNC_EDIT ) ;

                if( marknum > 0 )
                    clear_mark() ;
                if( item_move != -1 )
                    item_recover( TRUE ) ;
                if( item_copy != -1 )
                    item_copy = -1 ;
                menu_event = 0 ;
                break ;

              case 9:                       /*  複写  */
                if( func != FUNC_COPY )
                    dsp_func( func ), dsp_func( func = FUNC_COPY ) ;

                if( marknum > 0 )
                    clear_mark() ;
                if( item_move != -1 )
                    item_recover( TRUE ) ;
                menu_event = 0 ;
                break ;

              case 10:                      /*  ↑  */
                num = pos - 5 ;
                break ;

              case 11:                      /*  ↓  */
                num = pos + 5 ;
                break ;

              case 12:                      /*  バッファの切り換え  */
/*                if( item_move != -1 )
                    item_recover( FALSE ) ; */
                if( marknum > 0 )
                    clear_mark() ;

                if( ( tmpfile = change_buf( file ) ) != NULL )
                {
                    strcpy( file, tmpfile ) ;
                    title( file ) ;
                    rewrite = TRUE ;
                }
                break ;

              case 15:                      /*  編集モードへの切り換え  */
                if( item_move != -1 )       /*  移動中  */
                    item_recover( TRUE ) ;
                ret_val = RET_MODE ;
                break ;

              case 100:                     /*  再表示  */
                num = pos ;
                rewrite = TRUE ;
                break ;

              default:
                if( menu_event >= 20 && menu_event < 20+MAX_DSP )
                {
                    click_item( menu_event - 20 ) ;
                    menu_event = 0 ;
                }
            }

        } while( menu_event == 0 ) ;

    } while( ret_val == RET_DEFAULT ) ;

    return( ret_val ) ;
}

void    unset_mark( int num )
{
    marknum -- ;
    mark[ num ] = FALSE ;
}
void    set_mark( int num )
{
    marknum ++ ;
    mark[ num ] = TRUE ;
}

void    chg_mark( int num )
{
    if( mark[ num ] == TRUE )       /*  マークされているので解除  */
        unset_mark( num ) ;
    else
        set_mark( num ) ;

    MOS_disp( FALSE ) ;
    dsp_mark( num-pos, mark[ num ] ) ;
    MOS_disp( mos_disp ) ;
}

void    clear_mark( void )
{
    int     i ;

    if( marknum > 0 )       /*  マークを解除  */
    {
        MOS_disp( FALSE ) ;

        for( i = 0 ; i < MAX_DSP ; i ++ )
            if( mark[ i+pos ] == TRUE )
                dsp_mark( i, FALSE ) ;

        marknum = 0 ;

        for( i = 0 ; i < maxnum ; i ++ )
            mark[ i ] = FALSE ;

        MOS_disp( mos_disp ) ;
    }
}


void    click_item( int item )
{
    static  int     last_mouse = 0, last_item = -1 ;
    auto    int     now_mouse = 0 ;
    auto    int     src, mos ;
    auto    int     num = item + pos ;
    auto    int     db = FALSE ;        /*  ダブルクリック  */


    /*  ダブル・クリックの確認  */
    now_mouse = MOS_getTime() ;
    if( item == last_item && now_mouse <= last_mouse + 15 )
        db = TRUE ;
    last_mouse = now_mouse ;
    last_item = item ;

    MOS_disp( mos_disp = MOS_OFF ) ;    /*  処理中は表示しない  */

    switch( func )
    {
    /*
     *  『削除』
    */

      case FUNC_DEL:
        mos = TRUE ;       /*  終了後は表示  */

        if( num >= maxnum )    /*  無視  */
            break ;

        if( db == TRUE )    /*  ダブルクリックならば、実行  */
            del_item() ;
        else                /*  普通のクリックならば、マークの反転  */
            chg_mark( num ) ;

        break ;


    /*
     *  『編集』
    */

      case FUNC_EDIT:
        mos = TRUE ;       /*  終了後は表示  */

        if( num >= maxnum )    /*  無視  */
            break ;

        /*  編集  */
        if( edit_item( &inf[num] ) != FALSE )
            dsp_item( item, &inf[num], TRUE ) ;

        break ;


    /*
     *  『移動』
    */
      case FUNC_MOVE:
        mos = TRUE ;       /*  終了後は表示  */

        if( item_move != -1 )       /*  移動中である  */
        {
            item_move = -1 ;

            move( MV_END, 0,0 ) ;
            MOS_disp( mos_disp = FALSE ) ;

            if( num >= maxnum )
                num = maxnum ;
            ins_inf( num ) ;
            inf[ num ] = tmpinf ;   /*  挿入  */
        }
        else                        /*  移動中ではない  */
        {
            if( num >= maxnum )     /*  無視  */
                break ;

            move( MV_START, item_x(item), item_y(item) ) ;

            tmpinf = inf[ num ] ;   /*  退避  */
            del_inf( num ) ;        /*  コピー元を削除  */

            item_move = num ;
            mos = FALSE ;      /*  終了後も表示しない  */
        }

        item_rewrite( num, num+MAX_DSP, TRUE ) ;

        break ;

    /*
     *  『交換』
    */
      case FUNC_CHG:
        mos = TRUE ;       /*  終了後は表示  */

        if( num >= maxnum )     /*  無視  */
            break ;

        if( marknum > 0 )       /*  交換先を探していた  */
        {
            move( MV_END, 0,0 ) ;
            MOS_disp( FALSE ) ;

            if( mark[ num ] == TRUE )   /*  キャンセル  */
            {
                unset_mark( num ) ;
                dsp_mark( item, mark[ num ] ) ;

                break ;
            }

            for( src = 0 ; src < maxnum ; src ++ )
            {
                if( mark[ src ] == TRUE )     /*  コピー元  */
                {
                    mark[ src ] = FALSE ;
                    marknum -- ;

                    tmpinf = inf[ src ] ;     /*  交換  */
                    inf[ src ] = inf[ num ] ;
                    inf[ num ] = tmpinf ;

                    if( src >= pos && src < pos+MAX_DSP )
                        item_rewrite( src, src, FALSE ) ;
                    item_rewrite( num, num, FALSE ) ;

                    break ;
                }
            }
        }
        else        /*  マークする  */
        {
            move( MV_START, item_x(item), item_y(item) ) ;

            chg_mark( num ) ;

            mos = FALSE ;      /*  終了後も表示しない  */
        }
        break ;

    /*
     *  『複写』
    */
      case FUNC_COPY:
        mos = TRUE ;       /*  終了後は表示  */

        if( item_copy != -1 )   /*  コピー先を探していた  */
        {
            item_copy = -1 ;

            move( MV_END, 0,0 ) ;
            MOS_disp( mos_disp = FALSE ) ;

            if( num >= maxnum )
                num = maxnum ;
            ins_inf( num ) ;
            inf[ num ] = tmpinf ;   /*  挿入  */
            mark[ num ] = FALSE ;

            item_rewrite( num, num+MAX_DSP, TRUE ) ;
            dsp_bar( pos ) ;
        }
        else        /*  マークする  */
        {
            if( num >= maxnum )     /*  無視  */
                break ;

            move( MV_START, item_x(item), item_y(item) ) ;

            tmpinf = inf[ num ] ;   /*  バッファへコピー  */

            item_copy = num ;
            mos = FALSE ;      /*  終了後も表示しない  */
        }

        break ;
    }

    MOS_disp( mos_disp = mos ) ;
}

void    item_recover( int redisplayflag )
{
    ins_inf( item_move ) ;
    inf[ item_move ] = tmpinf ;

    if( redisplayflag )
    {
        MOS_disp( MOS_OFF ) ;
        item_rewrite( item_move, item_move+MAX_DSP, FALSE ) ;
        MOS_disp( mos_disp ) ;
    }
    move( MV_END, 0,0 ) ;

    item_move = -1 ;
}

/*
 *  マークされているアイテムを削除する

 *  １つでも削除したら、ＴＲＵＥを返す
*/

int     del_item( void )
{
    int     i, ret ;

    if( marknum == 0 )      /*  マークなし  */
        return( FALSE ) ;

    chg_palette( 0, now_palet = 1 ) ;

    msg[0] = "マークされたものを削除します" ;
    msg[1] = "よろしいですか？" ;
    msg[2] = NULL ;

    if( select_mode( msg_kakunin, msg, msg_btn2 ) == 0 )
    {
        /*  削除  */
        for( i = 0 ; i < maxnum ; i ++ )
            if( mark[i] == TRUE )
            {
                del_inf( i ) ;
                i -- ;
            }
        marknum = 0 ;

        /*  画面書換え  */
        dsp_scrn( pos, TRUE ) ;
        ret = TRUE ;
    }
    else
        ret = FALSE ;

    chg_palette( 0, now_palet = 0 ) ;

    return ret ;
}

void    del_inf( int i )
{
    REGS    int     j ;

    for( j = i + 1 ; j < maxnum ; j ++ )
    {
        inf[ j-1 ] = inf[ j ] ;
        mark[ j-1 ] = mark[ j ] ;
    }
    maxnum -- ;
}

static  void    ins_inf( int i )
{
    REGS    int     j ;

    for( j = maxnum + 1 ; j > i ; j -- )
    {
        inf[ j ] = inf[ j-1 ] ;
        mark[ j ] = mark[ j-1 ] ;
    }
    maxnum ++ ;
}

void    title( char *name )
{
    int     len ;
    char    buf[48] ;

    if( name == NULL || ( len = strlen( name ) ) < 1 )
    {
        sprintf( tmp,"<<< TMENU.INF EDITOR : TIE  %s %s >>>",
                                                        VERSION, DATE ) ;
    }
    else
    {
        name = strncpy( buf, name, 34 ) ;
        name[34] = '\0' ;
        sprintf( tmp, "<< TIE %s >>   %-34s", VERSION, name ) ;
    }

    wrt( tmp, writepage, 48,1, COL_1,COL_7, 16 ) ;
}

static  void    dsp_func( int num )
{
    int     x = FN_X, xs = FNSIZX ;
    int     y = FN_Y, ys = FNSIZY ;

    MOS_disp( FALSE ) ;

    EGB_writeMode( egbwork, 4 ) ;
    x += xs * num ;
    dsp_box( x+1,y+1, x+xs-1,y+ys-1, 15,15,15 ) ;
    EGB_writeMode( egbwork, 0 ) ;

    MOS_disp( mos_disp ) ;
}

static  void    dsp_func_btn( void )
{
    int     x = FN_X, xs = FNSIZX ;
    int     y = FN_Y, ys = FNSIZY ;
    int     i ;

    MOS_disp( FALSE ) ;

    dsp_box( x+2,y+2, x+xs*MAX_FUNC+2,y+ys+2, 1,1,1 ) ;

    for( i = 0 ; i < MAX_FUNC ; i ++ )
    {
        dsp_box( x,y, x+xs,y+ys, 1,1,15 ) ;
        wrt( func_btn[i], writepage, x+6,y+2, COL_1,COL_15,16 ) ;
        EVT_set_node( x,y, x+xs,y+ys, 1,MENU_clip,5+i, OFF ) ;
        x += xs ;
    }

    MOS_disp( mos_disp ) ;
}

#define NEW_X   40          /*  [新規]ボタンの位置  */
#define NEW_Y   (TOP_Y)
#define LD_X    (549-38)
#define LD_Y    (18)
#define SV_X    (LD_X+BSIZ_X2)
#define SV_Y    (18)
#define CH_X    (LD_X)
#define CH_Y    (3)

void    dsp_menu2( char *file, void (*menu)(), void (*move)() )
{
    dsp_box( SYS_X1,SYS_Y1, SYS_X2,SYS_Y2, 7,7,7 ) ;

    title( file ) ;

    dsp_box( NEW_X+2,NEW_Y+2, NEW_X+FNSIZX+2,NEW_Y+FNSIZY+2, 1,1,1 ) ;
    dsp_box( NEW_X,NEW_Y, NEW_X+FNSIZX,NEW_Y+FNSIZY, 1,1,15 ) ;
    wrt( " 新 規 ", writepage, NEW_X+6,NEW_Y+2, COL_1,COL_15,16 ) ;
    EVT_set_node( NEW_X,NEW_Y, NEW_X+FNSIZX,NEW_Y+FNSIZY, 1,menu,4,OFF ) ;

    dsp_box( CH_X+2,CH_Y+2, CH_X+BSIZ_X2*2+2,CH_Y+14+2, 1,1,1 ) ;
    dsp_box( CH_X,CH_Y, CH_X+BSIZ_X2*2,CH_Y+14, 1,1,15 ) ;
    wrt( "切り換え", writepage, CH_X+10,CH_Y+4, COL_1, COL_15, 8 ) ;
    EVT_set_node( CH_X,CH_Y, CH_X+BSIZ_X2*2,CH_Y+14, 1,menu,12, OFF ) ;

    dsp_box( LD_X+2,LD_Y+2, LD_X+BSIZ_X2+2,LD_Y+BSIZ_Y+2, 1,1,1 ) ;
    dsp_box( LD_X,LD_Y, LD_X+BSIZ_X2,LD_Y+BSIZ_Y, 1,1,15 ) ;
    wrt( " 読 ", writepage, LD_X+6,LD_Y+2, COL_1, COL_15, 16 ) ;
    EVT_set_node( LD_X,LD_Y, LD_X+BSIZ_X2,LD_Y+BSIZ_Y, 1,menu,2, OFF ) ;

    dsp_box( SV_X+2,SV_Y+2, SV_X+BSIZ_X2+2,SV_Y+BSIZ_Y+2, 1,1,1 ) ;
    dsp_box( SV_X,SV_Y, SV_X+BSIZ_X2,SV_Y+BSIZ_Y, 1,1,15 ) ;
    wrt( " 書 ", writepage, SV_X+6,SV_Y+2, COL_1, COL_15, 16 ) ;
    EVT_set_node( SV_X,SV_Y, SV_X+BSIZ_X2,SV_Y+BSIZ_Y, 1,menu,3, OFF ) ;

    dsp_box( MD_X+2,MD_Y+2, MD_X+35,MD_Y+35, 0,0,0 ) ;
    dsp_box( MD_X,MD_Y, MD_X+33,MD_Y+33, 0,0,15 ) ; /*  画面切り替えボタン  */
    EVT_set_node( MD_X,MD_Y,MD_X+33,MD_Y+33, 1, menu, 15, FALSE ) ;

    dsp_box( EX_X+2,EX_Y+2, EX_X+35,EX_Y+35, 0,0,0 ) ;
    dsp_box( EX_X,EX_Y, EX_X+33,EX_Y+33, 0,0,15 ) ; /*  終了ボタン  */
    dsp_ptn( EX_X+1,EX_Y+1, ptn_door, 0 ) ;
    EVT_set_node( EX_X,EX_Y,EX_X+33,EX_Y+33, 1, menu, 1, FALSE ) ;

    dsp_box( UP_X, UP_Y, UP_X+19, UP_Y+19, 0,0,15 ) ;
    wrt( "▲", writepage, UP_X+2, UP_Y+2, COL_0, COL_15, 16 ) ;
    dsp_box( DW_X, DW_Y, DW_X+19, DW_Y+19, 0,0,15 ) ;
    wrt( "▼", writepage, DW_X+2, DW_Y+2, COL_0, COL_15, 16 ) ;
    EVT_set_node( UP_X,UP_Y,UP_X+19,UP_Y+19, 1,menu,10, TRUE ) ;
    EVT_set_node( DW_X,DW_Y,DW_X+19,DW_Y+19, 1,menu,11, TRUE ) ;

    EVT_set_node( BAR_X,BAR_Y,BAR_X+19,BAR_Y+BAR_SIZ, 1,move,1, OFF ) ;
}

static  void    dsp_menu( char *file )
{
    dsp_menu2( file, MENU_clip, MOVE_clip ) ;   /*  編集／移動 共通部分  */

    dsp_ptn( MD_X+1,MD_Y+1, ptn_move, 0 ) ;

    dsp_func_btn() ;        /*  機能ボタン一覧  */
    dsp_func( func ) ;      /*  アクティブな機能ボタン  */

    /*  画面全体・キャンセル  */
    EVT_set_node( SCR_X1,SCR_Y1, SCR_X2,SCR_Y2, 2, ITEM_clip, 1, FALSE ) ;
    EVT_set_cancel( 1, click_cancel ) ;
}

/*  アイコンを表示する  */

static  void    dsp_scrn( int num, int rewrite )
{
    int     i, dif ;
    int     st, ed ;
    int     max = ( maxnum + 4 ) / 5 * 5 ;
    static  struct {
        short x1, y1, x2, y2 ;
    } para = { SCR_X1,SCR_Y1, SCR_X2,SCR_Y2 } ;

    if( num + MAX_DSP > max )
        num = max - MAX_DSP ;
    if( num < 0 )
        num = 0 ;

    if( rewrite != TRUE && ( dif = pos - num ) == 0 )
    {
        MOS_disp( mos_disp = TRUE ) ;
        return ;
    }

    MOS_disp( FALSE ) ;
    EGB_color( egbwork, 1, 15 ) ;

    if( rewrite == TRUE || abs( dif ) > 5 )     /*  再表示  */
    {
        dsp_box( SCR_X1,SCR_Y1, SCR_X2,SCR_Y2, 15,15,15 ) ;
        st = 0 ;    ed = ( maxnum-num > MAX_DSP ) ? MAX_DSP : (maxnum-num) ;
    }
    else if( dif < 0 )
    {
        EGB_partScroll( egbwork, 1, 0, -(ITEM_Y_SIZ), (char *)&para ) ;
        st = MAX_DSP-5 ;    ed = MAX_DSP ;
    }
    else if( dif > 0 )
    {
        EGB_partScroll( egbwork, 1, 0, ITEM_Y_SIZ, (char *)&para ) ;
        st = 0 ;    ed = 5 ;
    }
    else
        st = 0, ed = 0 ;

    pos = num ;

    for( i = st ; i+num < maxnum && i < ed ; i ++ )
        dsp_item( i, &inf[i+num], FALSE ) ;

    dsp_bar( num ) ;

    MOS_disp( mos_disp ) ;
}

/*  アイテム１個を表示する  */

void    dsp_item( int num, INF *ip, int clear )
{
    int     x, y ;

    x = item_x( num ) ;
    y = item_y( num ) ;

    if( clear == TRUE )
        dsp_box( x-4,y-5, x+108,y+60, 15,15,15 ) ;

    dsp_ptn( x+36,y+21, (char *)&icon[ ip->icon_num ], 1 ) ;
    dsp_box( x,y+17, x+104,y+17, 1,1,1 ) ;

    ip->name[12] = '\0' ;
    wrt( center( (char *)ip->name, 12 ), writepage,x+4,y, COL_1,BAK_COL, 16 ) ;

#ifdef DISP_NUM
    sprintf( tmp, "%2d", pos+num+1 ) ;
    wrt( tmp, writepage, x+4,y+19+4, COL_1,BAK_COL, 8 ) ;
#endif

    if( mark[ pos+num ] == TRUE )
        dsp_mark( num, TRUE ) ;
}


/*  スクロール・バーを表示する  */

static  void    dsp_bar( int num )
{
    auto    int     sz, ps ;
    auto    int     x = BAR_X ;
    auto    int     y = BAR_Y ;
    static  char    *vol_ptn = NULL ;
    auto    int     max = ( maxnum + 4 ) / 5 * 5 ;

    if( maxnum == 0 )
    {
        sz = BAR_SIZ ;
        vol_size = ps = 0 ;
    }
    else
    {
        if( ( sz = BAR_SIZ * MAX_DSP / max ) > BAR_SIZ )
            sz = BAR_SIZ ;
        vol_size = ( BAR_SIZ - sz ) ;
        ps = BAR_SIZ * num / max ;
    }

    if( vol_ptn == NULL )
    {
        dsp_box( x, y, x+19, y+BAR_SIZ+5, 0,0,15 ) ;
        dsp_box( x+7, y+3, x+12, y+BAR_SIZ+2, 0,0,8 ) ;
        if( ( vol_ptn = (char *)malloc( 20*(BAR_SIZ+7)+16) ) != NULL )
        {
            DWORD(vol_ptn+0) = (int)vol_ptn + 16 ;
            WORD(vol_ptn+4) = getds() ;
            WORD(vol_ptn+6) = x ;
            WORD(vol_ptn+8) = y ;
            WORD(vol_ptn+10) = x+19 ;
            WORD(vol_ptn+12) = y+BAR_SIZ+5 ;
            EGB_getBlock( egbwork, vol_ptn ) ;
        }
    }
    else
        EGB_putBlock( egbwork, 0, vol_ptn ) ;
    dsp_box( x+3, y+ps+3, x+16, y+ps+sz+3, 0,0,15 ) ;
}

char    *center( char *str, int width )
{
    static  char    buf[ 128 ] ;
    auto    int     i, len, left ;

    left = ( width - ( len = strlen( str ) ) ) / 2 ;
    if( left*2 + len != width )
        left ++ ;

    for( i = 0 ; i < left ; i ++ )
        buf[ i ] = ' ' ;
    strcpy( &buf[ left ], (char *)str ) ;

    return( buf ) ;
}


/*  TMENU.ICN ファイルを読み込む  */

void    readicon( char *path )
{
    auto    FILE    *fp ;
    auto    long    fsize ;
    auto    int     comp = FALSE ;
    REGS    int     i, j ;

    /*  読み込み  */
    if( ( fp = fopen( path, "rb" ) ) != NULL )
    {
        if( (u_int)( fsize = get_fsize( fp ) ) == sizeof( icon ) )
        {
            fread( icon, 1, sizeof( icon ), fp ) ;
            comp = TRUE ;
        }
        fclose( fp ) ;
    }

    if( comp != TRUE )                  /*  読み込み失敗  */
        for( i = 0 ; i < 128 ; i ++ )
            for( j = 0 ; j < 128 ; j ++ )
                icon[i].pat[j] = 0xFF ;
}


/*
 *  .inf を読み込む

 *  戻り値
 *    ERR_NOERROR: エラーなし
 *    ERR_ABORT:   バッファ破壊後のエラー
 *    ERR_BREAK:   バッファ破壊前のエラー
*/

int     readinf( char *path )
{
    auto    FILE    *fp ;
    auto    INF     *ip ;
    auto    long    fsize ;
    auto    int     i ;

    readicon( "\\tmenu.icn" ) ; /*  アイコン読み込み  */
    load_count ++ ;

    /*  読み込む  */
    if( ( fp = fopen( path, "rb" ) ) == NULL )
    {
        msg[0] = "ファイルがオープンできません" ;
        sprintf( tmp, "(%s)", path ) ;
        msg[1] = tmp ;
        msg[2] = NULL ;
        select_mode( msg_error, msg, msg_btn1 ) ;

        return ERR_BREAK ;
    }
    fsize = get_fsize( fp ) ;
    if( fsize % sizeof( INF ) != 0 ||
        ( maxnum = fsize / INFBUFSIZ ) > MAX_INF )
    {
        fclose( fp ) ;

        msg[0] = "ファイルの形式がおかしい" ;
        msg[1] = NULL ;
        select_mode( msg_error, msg, msg_btn1 ) ;

        return ERR_BREAK ;
    }
    if( fread( &inf, 1, fsize, fp ) != fsize )
    {
        fclose( fp ) ;

        msg[0] = "ファイルを正常に読めませんでした" ;
        msg[1] = NULL ;
        select_mode( msg_error, msg, msg_btn1 ) ;

        return ERR_ABORT ;
    }
    fclose( fp ) ;

    for( i = 0 ; i < maxnum ; i ++ )
    {
        ip = &inf[i] ;

        if( ( ip->dot != '.' && ip->dot != ' ' ) || ip->icon_num > 127 )
        {
            msg[0] = "不思議なデータが含まれています" ;
            msg[1] = NULL ;
            select_mode( msg_error, msg, msg_btn1 ) ;

            return ERR_ABORT ;
        }
    }

    /*  ここまできたら正常に読み込めた  */

    /*  ロード時のデータを覚えておく  */
    for( i = 0 ; i < maxnum ; i ++ )
        refresh_inf( &inf[i] ) ;
    memcpy( &org_inf[0], &inf[0], maxnum*INFBUFSIZ ) ;
    org_maxnum = maxnum ;

    /*  マークをリセット  */
    for( i = 0 ; i < MAX_INF ; i ++ )
        mark[ i ] = FALSE ;
    marknum = 0 ;

    return ERR_NOERROR ;
}

/*
 *  .inf を書き込む

 *  戻り値
 *      正常に書き込んだ                    ERROR 以外
 *      なんらかの理由で書き込めなかった    ERROR
*/

static  int     writeinf( char *path )
{
    auto    FILE    *fp ;
    auto    long    fsize, wsize ;
    auto    int     ret_value = ERROR ;
    auto    char    *title = "データのセーブ" ;
    auto    int     i ;

    chg_palette( 0, now_palet = 1 ) ;

    /*  上書き確認  */
    if( ( fp = fopen( path, "rb" ) ) != NULL )
    {
        fclose( fp ) ;
        msg[0] = "データを上書きします。よろしいですか？" ;
        msg[1] = path ;
        msg[2] = NULL ;
        if( select_mode( title, msg, msg_btn2 ) != 0 )
            return( ERROR ) ;
    }

    /*  値の整形  */
    for( i = 0 ; i < maxnum ; i ++ )
        refresh_inf( &inf[i] ) ;
    for( i = 0 ; i < maxnum ; i ++ )
        toupper_inf( &inf[i] ) ;

    /*  書き込む  */
    if( ( fp = fopen( path, "wb" ) ) == NULL )
    {
        msg[0] = "ファイルがオープンできません" ;
        sprintf( tmp, "(%s)", path ) ;
        msg[1] = tmp ;
        msg[2] = NULL ;
        select_mode( title, msg, msg_btn1 ) ;
    }
    else
    {
        fsize = (long)sizeof( INF ) * maxnum ;

        wsize = fwrite( &inf, 1, fsize, fp ) ;
        fclose( fp ) ;

        if( wsize != fsize )
        {
            msg[0] = "ファイルを正常に書き込めませんでした" ;
            msg[1] = NULL ;
            select_mode( title, msg, msg_btn1 ) ;
        }
        else
        {
            msg[0] = "書き込み完了しました" ;
            msg[1] = NULL ;
            assert( title, msg ) ;
            ret_value = ERROR + 1 ;
        }
    }

    /*  セーブしたので、ロード時のデータを書き換える  */
    if( ret_value != ERROR )
    {
        for( i = 0 ; i < maxnum ; i ++ )
            refresh_inf( &inf[i] ) ;
        memcpy( &org_inf[0], &inf[0], maxnum*INFBUFSIZ ) ;
        org_maxnum = maxnum ;
    }

    chg_palette( 0, now_palet = 0 ) ;

    return( ret_value ) ;
}


void    mos_ptn( int no )   /*  マウス・カーソルの切り換え  */
{
    static  int     mos_csr_ptn = -1 ;      /*  マウス・カーソルの番号  */
    auto    MOS     *mp = &mosptn[ no ] ;

    if( mos_csr_ptn != no )
    {
        MOS_type( 1, mp->x, mp->y, &mp->xsiz ) ;
        MOS_color( 0, 15 ) ;
        mos_csr_ptn = no ;
    }
}

/*  スクロール・バーのクリップ  */

static  void    MOVE_clip( REGS EVENT *ep, int x, int y, int sw )
{
    auto    int     dum ;

    dum = x, dum = sw ;     /*  意味なし。ワーニングを避けるため  */

    switch( ep->now )
    {
      case EVT_ON_MOS:
        mos_ptn( 1 ) ;
        break ;

      case EVT_CLIP_MOS:
        mos_ptn( 1 ) ;
        MOS_horizon( ep->x1+9, ep->x1+11 ) ;
        MOS_vertical( ep->y1, ep->y2 ) ;
        ep->now = EVT_REP_MOS ;
      case EVT_REP_MOS:
        if( vol_size > 0 )
            dsp_scrn( ( ( y - ep->y1 ) * maxnum / BAR_SIZ ) / 5 * 5, FALSE ) ;
        break ;

      case EVT_DOLACK_MOS:
        ep->now = EVT_NON ;
      case EVT_OFF_MOS:
      case EVT_MOVE_MOS:
      case EVT_SELECT_MOS:
        mos_ptn( 0 ) ;
        MOS_horizon ( MIN_HORIZON,  MAX_HORIZON  ) ;
        MOS_vertical( MIN_VERTICAL, MAX_VERTICAL ) ;
        break ;
    }
}


void    move( int func, int x, int y )
{
    static  int     last_x = 0, last_y = 0 ;
    static  char    ptn[ (120+7) * (72+1) * 4 / 8 ] ;   /*  移動アイテム  */
    static  int     last_func = MV_START ;
    static  struct
    {
        u_short x1,y1, x2,y2 ;
    } para ;

    switch( func )
    {
      case MV_START:        /*  開始  */
        MOS_disp( mos_disp = FALSE ) ;
        DSP_writePage( egbwork, 0 ) ;
        getputBlock( x-4,y-5, x+108,y+60, ptn, TRUE ) ;
        func = MV_END ;
        break ;

      case MV_RESTART:      /*  再開始  */
        MOS_disp( mos_disp = FALSE ) ;
        cls( 1, 0 ) ;
        EGB_displayStart( egbwork, 1, OFFSET,0 ) ;
        getputBlock( x-55,y-32, x+57,y+33, ptn, FALSE ) ;
        DSP_writePage( egbwork, 0 ) ;
        break ;

      case MV_END:
        cls( 1, 0 ) ;
        EGB_displayStart( egbwork, 1, 0,0 ) ;
        DSP_writePage( egbwork, 0 ) ;
        MOS_disp( mos_disp = TRUE ) ;
        break ;

      case MV_LOOP:
        if( last_func == MV_END )
            move( MV_RESTART, x,y ) ;

        if( last_x == x && last_y == y )
            break ;

        if( last_x < x )    { para.x1 = last_x-55 ; para.x2 = x+57 ; }
        else                { para.x1 = last_x+57 ; para.x2 = x-57 ; }
        if( last_y < y )    { para.y1 = last_y-32 ; para.y2 = y+33 ; }
        else                { para.y1 = last_y+33 ; para.y2 = y-32 ; }

        DSP_writePage( egbwork, 1 ) ;
        EGB_color( egbwork, 1, 0 ) ;
        EGB_partScroll( egbwork, 1, x-last_x, y-last_y, (char*)&para ) ;
        DSP_writePage( egbwork, 0 ) ;

        break ;
    }

    last_func = func ;
    last_x = x ;    last_y = y ;
}


/*  アイテムのクリック  */

static  void    ITEM_clip( REGS EVENT *ep, int x, int y, int sw )
{
    auto    int     num ;
    sw = sw ;                   /*  意味なし。ワーニングを避けるため  */

    switch( ep->now )
    {
      case EVT_ON_MOS:
        if( item_move != -1 || item_copy != -1 ||
            ( marknum > 0 && func != FUNC_DEL ) )
            move( MV_LOOP, x+OFFSET,y ) ;
        else
        {       /*  マウスカーソルの形状  */
                 if( func == FUNC_MOVE ) num = 3 ;
            else if( func == FUNC_DEL  ) num = 4 ;
            else if( func == FUNC_CHG  ) num = 5 ;
            else if( func == FUNC_EDIT ) num = 6 ;
            else                         num = 1 ;
            mos_ptn( num ) ;
        }
        break ;

      case EVT_DLSEL_MOS:
      case EVT_CLIP_MOS:
        break ;

      case EVT_MOVE_MOS:
      case EVT_DOLACK_MOS:
        ep->now = EVT_NON ;
        goto off ;

      case EVT_SELECT_MOS:
        menu_event = 20 + ( x - ITEM_X ) / ITEM_X_SIZ +
                          ( ( y - ITEM_Y ) / ITEM_Y_SIZ ) * 5 ;
        if( func == FUNC_DEL )
            break ;
      case EVT_OFF_MOS:
off:
        move( MV_END, 0,0 ) ;

        mos_ptn( 0 ) ;
        MOS_disp( mos_disp = TRUE ) ;

        break ;
    }
}

static  void    item_rewrite( int src, int dest, int last_clear )
{
    REGS    int     i ;

    if( dest < src )
        i = src, src = dest, dest = i ;
    if( dest < pos || src > pos+MAX_DSP )
        return ;
    if( ( src -= pos ) < 0 )
        src = 0 ;
    if( ( dest -= pos ) >= MAX_DSP )
        dest = MAX_DSP - 1 ;

    for( i = src ; i <= dest && i+pos < maxnum ; i ++ )
        dsp_item( i, &inf[ i+pos ], TRUE ) ;

    if( last_clear && i < MAX_DSP )
    {
        int     xpos = item_x( i ) ;
        int     ypos = item_y( i ) ;
        dsp_box( xpos-4,ypos-5, xpos+108,ypos+60, 15,15,15 ) ;
    }
}

static  void    dsp_mark( int num, int sw )
{
    int     x = item_x( num ) ;
    int     y = item_y( num ) ;
    int     col = sw == TRUE ? 0 : 15 ;

    box( x-4,y-4, x+108,y+58, col, LINE_PTN, 0 ) ;
}


static  void    MENU_clip( REGS EVENT *ep, int x, int y, int sw )
{
#define TICK_LIMIT 2000
    static  int     tick = 0 ;
    auto    int     now ;
    auto    int     dum ;

    dum = x, dum = y, dum = sw ;    /*  意味なし。ワーニングを避けるため  */
    now = ep->now ;

    switch( now )
    {
      case EVT_ON_MOS:
        mos_ptn( 1 ) ;
        break ;

      case EVT_OFF_MOS:
        mos_ptn( 0 ) ;
        break ;

      case EVT_CLIP_MOS:
        mos_ptn( 1 ) ;
        DSP_clip_on( ep ) ;
        if( ep->rep != FALSE )
            ep->now = EVT_REP_MOS ;
        tick = 0 ;
        break ;

      case EVT_REP_MOS:
        if( ++tick > TICK_LIMIT )
        {
            menu_event = ep->no ;
            tick = 0 ;
        }
        break ;

      case EVT_DOLACK_MOS:
        ep->now = EVT_NON ;
      case EVT_MOVE_MOS:
        DSP_clip_off( ep ) ;
        mos_ptn( 0 ) ;
        break ;

      case EVT_SELECT_MOS:
        menu_event = ep->no ;
        DSP_clip_off( ep ) ;
        mos_ptn( 0 ) ;
        break ;
    }
}

/*  終了確認  */

int     end_assert( char *file )
{
    int     change = FALSE ;
    int     i, ret, bnum ;
    char    *p, *btn[MAX_BTN_MSG+1] ;

    for( bnum = 0 ; bnum < MULTI_BUF ; bnum ++ )
    {
        if( maxnum == 0 && org_maxnum == 0 )
            change = FALSE ;
        else if( maxnum != org_maxnum )
            change = TRUE ;
        else
        {
            for( i = 0 ; i < maxnum ; i ++ )
                toupper_inf( &inf[i] ) ;
            for( i = 0 ; i < maxnum ; i ++ )
                refresh_inf( &inf[i] ) ;

            for( i = 0 ; i < maxnum ; i ++ )
                if( memcmp( &inf[i], &org_inf[i], INFBUFSIZ ) != 0 )
                {
                    change = TRUE ;
                    break ;
                }
        }

        chg_palette( 0, now_palet = 1 ) ;

        if( change != FALSE )
        {
            msg[0] = "変更したデータを保存していません" ;
            sprintf( tmp, "( %s )",
                        strlen( file ) > 0 ? file : "ファイル名未定" ) ;
            msg[1] = tmp ;
            msg[2] = "  このまま終了するとデータが失われます  " ;
            msg[3] = "どうしますか？" ;
            msg[4] = NULL ;

            btn[0] = "保存して終了", btn[1] = "放棄して終了",
            btn[2] = "終了しない",   btn[3] = NULL ;

            switch( select_mode( "！ 警  告 ！", msg, btn ) )
            {
              case 0:
                if( ( p = save_file( file ) ) == NULL )
                {
                    chg_palette( 0, now_palet = 0 ) ;
                    return FALSE ;
                }
                else
                    strcpy( file, p ) ;
                break ;

              case 1:       /*  強制終了  */
                break ;

              case 2:
                chg_palette( 0, now_palet = 0 ) ;
                return FALSE ;
            }
        }
        strcpy( file, change_buf( file ) ) ;
    }


    chg_palette( 0, now_palet = 1 ) ;

    msg[0] = "終了します。よろしいですか？", msg[1] = NULL ;

    btn[0] = "終  了", btn[1] = "中  止", btn[2] = NULL ;

    ret = select_mode( msg_kakunin, msg, btn ) == 0 ? TRUE : FALSE ;

    chg_palette( 0, now_palet = 0 ) ;

    return ret ;
}

