#include "common.h"

#include <saphire.h>
#include <errno.h>
#include <libgen.h>

#include "config.h"

#if defined(HAVE_CURSES_H)
#include <curses.h>
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#elif defined(HAVE_NCURSES_NCURSES_H)
#include <ncurses/ncurses.h>
#endif

BOOL commands_quit(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(saphire_job_num() == 0) {
        if(vector_size(argv) >= 2) {
            gMainLoop = atoi(string_c_str(vector_item(argv, 1)));
        }
        else {
            gMainLoop = 0;
        }
        *rcode = 0;
    }
    else {
        if(mis_raw_mode()) {
            merr_msg("jobs exist");
        }
        else {
            fprintf(stderr, "jobs exist\n");
        }
    }

    return TRUE;
}

BOOL commands_keycommand(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(vector_size(argv) == 5) {
        char* argv1 = string_c_str(vector_item(argv, 1));
        char* argv2 = string_c_str(vector_item(argv, 2));
        char* argv3 = string_c_str(vector_item(argv, 3));
        char* argv4 = string_c_str(vector_item(argv, 4));

        int meta = atoi(argv1);
        int keycode = atoi(argv2);

        if(!filer_add_keycommand(meta, keycode, argv3, argv4, "run time script")) {
            return FALSE;
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_keycommand2(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int i;
    int meta = 0;
    string_obj* file_type = STRING_NEW("*");
    for(i=0; i<vector_size(argv); i++) {
        char* arg = string_c_str(vector_item(argv, i));
        if(strcmp(arg, "-m") == 0) {
            meta = 1;
            string_delete(vector_item(argv, i));
            vector_erase(argv, i);
            i--;
            continue;
        }
        else if(strcmp(arg, "-f") == 0 && i+1 < vector_size(argv)) {
            string_put(file_type,  string_c_str(vector_item(argv, i+1)));
            string_delete(vector_item(argv, i));
            vector_erase(argv, i);
            string_delete(vector_item(argv, i));
            vector_erase(argv, i);
            i--;
            continue;
        }
    }
    if(vector_size(blocks) == 1 && vector_size(argv) == 2) {
        char* argv1 = string_c_str(vector_item(argv, 1));
        int keycode = atoi(argv1);

        if(!filer_add_keycommand2(meta, keycode, string_c_str(file_type), vector_item(blocks, 0), "run time script")) {
            string_delete(file_type);
            return FALSE;
        }

        *rcode = 0;
    }

    string_delete(file_type);

    return TRUE;
}

BOOL commands_keymap(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(vector_size(argv) == 12) {
        char keys[kKeyMapKeysMax];

        keys[0] = atoi(string_c_str(vector_item(argv, 2)));
        keys[1] = atoi(string_c_str(vector_item(argv, 3)));
        keys[2] = atoi(string_c_str(vector_item(argv, 4)));
        keys[3] = atoi(string_c_str(vector_item(argv, 5)));
        keys[4] = atoi(string_c_str(vector_item(argv, 6)));
        keys[5] = atoi(string_c_str(vector_item(argv, 7)));
        keys[6] = atoi(string_c_str(vector_item(argv, 8)));
        keys[7] = atoi(string_c_str(vector_item(argv, 9)));
        keys[8] = atoi(string_c_str(vector_item(argv, 10)));
        keys[9] = atoi(string_c_str(vector_item(argv, 11)));

        madd_keymap(atoi(string_c_str(vector_item(argv, 1)))
                    , keys);

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_cursor_move(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        char* argv2 = string_c_str((string_obj*)vector_item(argv, 1));

        int cursor_num;
        if(argv2[0] == '+') {
            char buf[BUFSIZ];
            memcpy(buf, argv2+1, strlen(argv2));
            sDir* dir2 = filer_dir(dir);
            if(dir2) {
                cursor_num = dir2->mCursor + atoi(buf);
            }
            else {
                cursor_num = 0;
            }
        }
        else if(argv2[0] == '-') {
            char buf[BUFSIZ];
            memcpy(buf, argv2+1, strlen(argv2));
            sDir* dir2 = filer_dir(dir);
            if(dir2) {
                cursor_num = dir2->mCursor - atoi(buf);
            }
        }
        else if(argv2[0] == '/') {
            char buf[BUFSIZ];
            memcpy(buf,argv2+1, strlen(argv2));
            cursor_num = filer_file2(dir, buf);
            if(cursor_num == -1) {
                cursor_num = 0;
            }
        }
        else {
            cursor_num = atoi(argv2);
        }

        if(dir < 0) {
            int j;
            for(j=0; j<vector_size(gDirs); j++) {
                filer_cursor_move(j, cursor_num);
                *rcode = 0;
            }
        }
        else {
            filer_cursor_move(dir, cursor_num);
            *rcode = 0;
        }
    }

    if(*rcode == 0) {
        char buf[128];
        snprintf(buf, 128, "cursor_move_hook %d", dir);
        int rcode2 = saphire_shell(buf, "cursor_move_hook", nextout, nextin, nexterr);
        saphire_sweep();

        if(rcode2 < 0) {
            if(mis_raw_mode()) {
                merr_msg("%s", string_c_str(gErrMsg));
            }
            else {
                fprintf(stderr, "%s", string_c_str(gErrMsg));
            }

            *rcode = 1;
            return FALSE;
        }
    }

    return TRUE;
}

BOOL commands_mcd(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int dir = adir();
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(dir < 0) {
        merr_msg("can't mcd -d all");
        return FALSE;
    }

    if(vector_size(argv) == 2) {
        char* arg1 = string_c_str(vector_item(argv, 1));

        if(strcmp(arg1, "+") == 0) {
            filer_history_forward(dir);
            *rcode = 0;
        }
        else if(strcmp(arg1, "-") == 0) {
            filer_history_back(dir);
            *rcode = 0;
        }
        else {
            if(filer_cd(dir, arg1) >= 0) {
                *rcode = 0;
            }
        }
    }
    else if(vector_size(argv) == 1) {
        if(filer_cd(dir, "~") >= 0) {
            *rcode = 0;
        }
    }

    /// フック ///
    if(*rcode == 0) {
        char buf[128];
        snprintf(buf, 128, "mcd_hook %d", dir);

        int rcode2 = saphire_shell(buf, "mcd_hook", nextout, nextin, nexterr);
        saphire_sweep();
        if(rcode2 < 0) {
            if(mis_raw_mode()) {
                merr_msg(string_c_str(gErrMsg));
            }
            else {
                fprintf(stderr, "%s", string_c_str(gErrMsg));
            }

            *rcode = 1;

            return FALSE;
        }
    }

    return TRUE;
}

BOOL commands_file_name(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int dir = adir();
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        char* argv2 = string_c_str((string_obj*)vector_item(argv, 1));

        sFile* file = filer_file(dir, atoi(argv2));
        if(file) {
            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(file->mName)))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_path(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        sDir* dir2 = filer_dir(dir);
        if(dir2) {
            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(dir2->mPath)))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }
            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_file_ext(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        char* argv2 = string_c_str((string_obj*)vector_item(argv, 1));
        sFile* file = filer_file(dir, atoi(argv2));
        if(file) {
            char buf[PATH_MAX];
            extname(buf, PATH_MAX, string_c_str(file->mName));
            if(!statment_tree_internal_commands_write_nextout(nextout, buf))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_file_index(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        char* argv1 = string_c_str((string_obj*)vector_item(argv, 1));

        char buf[BUFSIZ];
        snprintf(buf, BUFSIZ, "%d", filer_file2(dir, argv1));

        if(!statment_tree_internal_commands_write_nextout(nextout, buf))
        {
            return FALSE;
        }
        if(new_line) {
            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
            {
                return FALSE;
            }
        }
        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_file_user(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        int argv1 = atoi(string_c_str(vector_item(argv, 1)));

        sFile* file = filer_file(dir, argv1);

        if(file) {
            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(file->mUser)))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_file_group(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        int argv1 = atoi(string_c_str(vector_item(argv, 1)));

        sFile* file = filer_file(dir, argv1);

        if(file) {
            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(file->mGroup)))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_file_perm(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        int argv1 = atoi(string_c_str(vector_item(argv, 1)));

        sFile* file = filer_file(dir, argv1);

        if(file) {
            int n = file->mLStat.st_mode & S_ALLPERM;

            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%o", n);
            if(!statment_tree_internal_commands_write_nextout(nextout, buf))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_file_num(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        sDir* dir2 = filer_dir(dir);
        if(dir2) {
            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%d", vector_size(dir2->mFiles));
            if(!statment_tree_internal_commands_write_nextout(nextout, buf))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }
            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_dir_num(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    if(vector_size(argv) == 1) {
        char buf[BUFSIZ];
        snprintf(buf, BUFSIZ, "%d", vector_size(gDirs));
        if(!statment_tree_internal_commands_write_nextout(nextout, buf))
        {
            return FALSE;
        }
        if(new_line) {
            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
            {
                return FALSE;
            }
        }
        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_cursor_num(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        if(dir < 0) {
            merr_msg("invalid option -d all");
            return FALSE;
        }

        sDir* dir2 = filer_dir(dir);

        if(dir2) {
            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%d", dir2->mCursor);
            if(!statment_tree_internal_commands_write_nextout(nextout, buf))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }
            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_isearch(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    gISearch = TRUE;
    *rcode = 0;

    return TRUE;
}

BOOL commands_cmdline(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL quick = FALSE;
    BOOL continue_ = FALSE;
    int j=0;
    for(j=1; j<vector_size(argv); j++) {
        char* item = string_c_str(vector_item(argv, j));

        if(strcmp(item, "-q") == 0) {
            quick = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
        else if(strcmp(item, "-c") == 0) {
            continue_ = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        cmdline_start("", 0, quick, continue_);
        *rcode = 0;
    }
    else if(vector_size(argv) == 2) {
        char* init_str = string_c_str(vector_item(argv, 1));
        cmdline_start(init_str, -1, quick, continue_);
        *rcode = 0;
    }
    else if(vector_size(argv) == 3) {
        char* init_str = string_c_str(vector_item(argv, 1));
        int cursor = atoi(string_c_str(vector_item(argv, 2)));
        cmdline_start(init_str, cursor, quick, continue_);
        *rcode = 0;
    }
    else if(vector_size(argv) == 4) {
        char* init_str = string_c_str(vector_item(argv, 1));
        int cursor = atoi(string_c_str(vector_item(argv, 2)));

        string_obj* init_str2 = STRING_NEW("");
        cmdline_start(string_c_str(init_str2), cursor, quick, continue_);
        *rcode = 0;
    }

    if(*rcode == 0) {
        int rcode2 = saphire_shell("cmdline_hook", "cursor_move_hook", nextout, nextin, nexterr);
        saphire_sweep();

        if(rcode2 < 0) {
            if(mis_raw_mode()) {
                merr_msg("%s", string_c_str(gErrMsg));
            }
            else {
                fprintf(stderr, "%s", string_c_str(gErrMsg));
            }

            *rcode = 1;
            return FALSE;
        }
    }

    return TRUE;
}

BOOL commands_external(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    BOOL hitanykey = TRUE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-q") == 0) {
            hitanykey = FALSE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        /// 初期化 ///
        const int maxy = mgetmaxy();
        mclear_online(maxy-2);
        mclear_online(maxy-1);
        mmove(maxy-2, 0);
        mrefresh();
        /*
        mclear();
        mmove(0,0);
        mrefresh();
        */
        mendwin();
        mreset_tty();

        /// コマンド実行 ///
        saphire_set_signal();
        sRFd* pipein = sRFd_new(STDIN_FILENO);
        sWFd* pipeout = sWFd_new(STDOUT_FILENO);
        int r = saphire_shell(string_c_str(vector_item(argv, 1)), "run", pipeout, pipein, STDERR_FILENO);
        saphire_sweep();
        set_signal_mfiler();
        sRFd_delete(pipein);
        sWFd_flash(pipeout);
        sWFd_delete(pipeout);

        if(r < 0) { printf("%s", string_c_str(gErrMsg)); }
/*
        /// ディレクトリ再読み込み ///
        if(strcmp(getenv("VIEW_OPTION"), "2pain") == 0) {
            filer_reread(0);
            filer_reread(1);
        }
        else {
            filer_reread(adir());
        }
*/
        /// HIT ANY KEY ///
        if(hitanykey || r < 0) {
            putp(tigetstr("rev"));
            printf("HIT ANY KEY");
            putp(tigetstr("sgr0"));
            fflush(stdout);

            minitscr();
            int meta;
            mgetch(&meta);
        }
        else {
            minitscr();
        }

        //mclear_immediately();

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_activate(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(vector_size(argv) == 2) {
        int n = atoi(string_c_str(vector_item(argv, 1)));
        filer_activate(n);
        *rcode = 0;

        char buf[128];
        snprintf(buf, 128, "activate_hook %d", n);

        int rcode2 = saphire_shell(buf, "activate_hook", nextout, nextin, nexterr);
        saphire_sweep();

        if(rcode2 < 0) {
            if(mis_raw_mode()) {
                merr_msg(string_c_str(gErrMsg));
            }
            else {
                fprintf(stderr, "%s", string_c_str(gErrMsg));
            }
            *rcode = 1;
            return FALSE;
        }
    }


    return TRUE;
}

BOOL commands_defmenu(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    /// 引数のチェック ///
    if(vector_size(argv)%3 != 2) {
        merr_msg("defmenu argument number err");
        return FALSE;
    }
    else {
        char* menu_name = string_c_str(vector_item(argv, 1));
        
        sMenu* new_menu = sMenu_new(menu_name);

        int j;
        for(j=2; j<vector_size(argv); j+=3) {
            char* argv1 = string_c_str(vector_item(argv, j));
            char* argv2 = string_c_str(vector_item(argv, j+1));
            char* argv3 = string_c_str(vector_item(argv, j+2));
            menu_append(new_menu, argv1, atoi(argv2), argv3);
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_addmenu(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    /// 引数のチェック ///
    if(vector_size(argv)%3 != 2) {
        merr_msg("addmenu argument number err");
        return FALSE;
    }
    else {
        char* menu_name = string_c_str(vector_item(argv, 1));
        
        sMenu* menu = hash_item(gMenu, menu_name);

        if(menu) {
            int j;
            for(j=2; j<vector_size(argv); j+=3) {
                char* argv1 = string_c_str(vector_item(argv, j));
                char* argv2 = string_c_str(vector_item(argv, j+1));
                char* argv3 = string_c_str(vector_item(argv, j+2));
                menu_append(menu, argv1, atoi(argv2), argv3);
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_menu(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(vector_size(argv) == 2) {
        char* menu_name = string_c_str(vector_item(argv, 1));

        gActiveMenu = hash_item(gMenu, menu_name);
        if(gActiveMenu) {
            gActiveMenu->mScrollTop = 0;
            gActiveMenu->mCursor = 0;
            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_reread(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        if(dir < 0) {
            int j;
            for(j=0; j<vector_size(gDirs); j++) {
                filer_reread(j);
            }
            *rcode = 0;
        }
        else {
            filer_reread(dir);
            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_allfiles(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL fullpath = FALSE;
    BOOL quote = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-fullpath") == 0) {
            fullpath = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-q") == 0) {
            quote = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(fullpath) {
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    sDir* dir2 = filer_dir(i);

                    int j;
                    for(j=0; j<vector_size(dir2->mFiles); j++) {
                        sFile* file = vector_item(dir2->mFiles, j);

                        if(strcmp(string_c_str(file->mName), ".") != 0
                            && strcmp(string_c_str(file->mName), "..") != 0) 
                        {
                            char path[PATH_MAX];
                            xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                            xstrncat(path, string_c_str(file->mName), PATH_MAX);

                            string_obj* str = STRING_NEW("");
                            if(quote) {
                                saphire_get_quoted_fname(path, str);
                            }
                            else {
                                string_put(str, path);
                            }

                            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                            {
                                string_delete(str);
                                return FALSE;
                            }
                            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                            {
                                string_delete(str);
                                return FALSE;
                            }

                            string_delete(str);
                        }
                    }
                }
            }
            else {
                sDir* dir2 = filer_dir(dir);

                int j;
                for(j=0; j<vector_size(dir2->mFiles); j++) {
                    sFile* file = vector_item(dir2->mFiles, j);
                    if(strcmp(string_c_str(file->mName), ".") != 0
                        && strcmp(string_c_str(file->mName), "..") != 0) 
                    {
                        char path[PATH_MAX];
                        xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                        xstrncat(path, string_c_str(file->mName), PATH_MAX);

                        string_obj* str = STRING_NEW("");
                        if(quote) {
                            saphire_get_quoted_fname(path, str);
                        }
                        else {
                            string_put(str, path);
                        }

                        if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                        {
                            string_delete(str);
                            return FALSE;
                        }
                        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                        {
                            string_delete(str);
                            return FALSE;
                        }

                        string_delete(str);
                    }
                }

            }

            *rcode = 0;
        }
    }
    else {
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    sDir* dir2 = filer_dir(i);

                    int j;
                    for(j=0; j<vector_size(dir2->mFiles); j++) {
                        sFile* file = vector_item(dir2->mFiles, j);

                        if(strcmp(string_c_str(file->mName), ".") != 0
                            && strcmp(string_c_str(file->mName), "..") != 0) 
                        {
                            string_obj* str = STRING_NEW("");
                            if(quote) {
                                saphire_get_quoted_fname(string_c_str(file->mName), str);
                            }
                            else {
                                string_put(str, string_c_str(file->mName));
                            }

                            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                            {
                                string_delete(str);
                                return FALSE;
                            }
                            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                            {
                                string_delete(str);
                                return FALSE;
                            }

                            string_delete(str);
                        }
                    }
                }
            }
            else {
                sDir* dir2 = filer_dir(dir);

                int j;
                for(j=0; j<vector_size(dir2->mFiles); j++) {
                    sFile* file = vector_item(dir2->mFiles, j);
                    if(strcmp(string_c_str(file->mName), ".") != 0
                        && strcmp(string_c_str(file->mName), "..") != 0) 
                    {
                        string_obj* str = STRING_NEW("");
                        if(quote) {
                            saphire_get_quoted_fname(string_c_str(file->mName), str);
                        }
                        else {
                            string_put(str, string_c_str(file->mName));
                        }

                        if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                        {
                            string_delete(str);
                            return FALSE;
                        }
                        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                        {
                            string_delete(str);
                            return FALSE;
                        }

                        string_delete(str);
                    }
                }

            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_markfiles(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL fullpath = FALSE;
    BOOL quote = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-q") == 0) {
            quote = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-fullpath") == 0) {
            fullpath = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }


    if(fullpath) {
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    if(filer_marking(i)) {
                        sDir* dir2 = filer_dir(i);

                        int j;
                        for(j=0; j<vector_size(dir2->mFiles); j++) {
                            sFile* file = vector_item(dir2->mFiles, j);
                            if(file->mMark) {
                                char path[PATH_MAX];
                                xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                                xstrncat(path, string_c_str(file->mName), PATH_MAX);

                                string_obj* str = STRING_NEW("");
                                if(quote) {
                                    saphire_get_quoted_fname(path, str);
                                }
                                else {
                                    string_put(str, path);
                                }

                                if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                                {
                                    string_delete(str);
                                    return FALSE;
                                }
                                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                                {
                                    string_delete(str);
                                    return FALSE;
                                }

                                string_delete(str);
                            }
                        }
                    }
                    else {
                        sDir* dir2 = filer_dir(i);
                        sFile* file = filer_cursor_file(i);

                        char path[PATH_MAX];
                        xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                        xstrncat(path, string_c_str(file->mName), PATH_MAX);

                        string_obj* str = STRING_NEW("");
                        if(quote) {
                            saphire_get_quoted_fname(path, str);
                        }
                        else {
                            string_put(str, path);
                        }

                        if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                        {
                            string_delete(str);
                            return FALSE;
                        }

                        string_delete(str);
                    }
                }
            }
            else {
                if(filer_marking(dir)) {
                    sDir* dir2 = filer_dir(dir);

                    int j;
                    for(j=0; j<vector_size(dir2->mFiles); j++) {
                        sFile* file = vector_item(dir2->mFiles, j);
                        if(file->mMark) {
                            char path[PATH_MAX];
                            xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                            xstrncat(path, string_c_str(file->mName), PATH_MAX);

                            string_obj* str = STRING_NEW("");
                            if(quote) {
                                saphire_get_quoted_fname(path, str);
                            }
                            else {
                                string_put(str, path);
                            }

                            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                            {
                                string_delete(str);
                                return FALSE;
                            }
                            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                            {
                                string_delete(str);
                                return FALSE;
                            }

                            string_delete(str);
                        }
                    }
                }
                else {
                    sDir* dir2 = filer_dir(dir);
                    sFile* file = filer_cursor_file(dir);

                    char path[PATH_MAX];
                    xstrncpy(path, string_c_str(dir2->mPath), PATH_MAX);
                    xstrncat(path, string_c_str(file->mName), PATH_MAX);

                    string_obj* str = STRING_NEW("");
                    if(quote) {
                        saphire_get_quoted_fname(path, str);
                    }
                    else {
                        string_put(str, path);
                    }

                    if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                    {
                        string_delete(str);
                        return FALSE;
                    }

                    string_delete(str);
                }
            }

            *rcode = 0;
        }
    }
    else {
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    if(filer_marking(i)) {
                        sDir* dir2 = filer_dir(i);

                        int j;
                        for(j=0; j<vector_size(dir2->mFiles); j++) {
                            sFile* file = vector_item(dir2->mFiles, j);
                            if(file->mMark) {
                                string_obj* str = STRING_NEW("");
                                if(quote) {
                                    saphire_get_quoted_fname(string_c_str(file->mName), str);
                                }
                                else {
                                    string_put(str, string_c_str(file->mName));
                                }

                                if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                                {
                                    string_delete(str);
                                    return FALSE;
                                }
                                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                                {
                                    string_delete(str);
                                    return FALSE;
                                }

                                string_delete(str);
                            }
                        }
                    }
                    else {
                        sFile* file = filer_cursor_file(i);

                        string_obj* str = STRING_NEW("");
                        if(quote) {
                            saphire_get_quoted_fname(string_c_str(file->mName), str);
                        }
                        else {
                            string_put(str, string_c_str(file->mName));
                        }

                        if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                        {
                            string_delete(str);
                            return FALSE;
                        }

                        string_delete(str);
                    }
                }
            }
            else {
                if(filer_marking(dir)) {
                    sDir* dir2 = filer_dir(dir);

                    int j;
                    for(j=0; j<vector_size(dir2->mFiles); j++) {
                        sFile* file = vector_item(dir2->mFiles, j);
                        if(file->mMark) {
                            string_obj* str = STRING_NEW("");
                            if(quote) {
                                saphire_get_quoted_fname(string_c_str(file->mName), str);
                            }
                            else {
                                string_put(str, string_c_str(file->mName));
                            }

                            if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                            {
                                string_delete(str);
                                return FALSE;
                            }
                            if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                            {
                                string_delete(str);
                                return FALSE;
                            }

                            string_delete(str);
                        }
                    }
                }
                else {
                    sFile* file = filer_cursor_file(dir);

                    string_obj* str = STRING_NEW("");
                    if(quote) {
                        saphire_get_quoted_fname(string_c_str(file->mName), str);
                    }
                    else {
                        string_put(str, string_c_str(file->mName));
                    }

                    if(!statment_tree_internal_commands_write_nextout(nextout, string_c_str(str)))
                    {
                        string_delete(str);
                        return FALSE;
                    }

                    string_delete(str);
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_mark(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
// user group perm
    int l;
    BOOL toggle = FALSE;
    BOOL files = FALSE;
    BOOL number = FALSE;
    BOOL all = FALSE;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-t") == 0) {
            toggle = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-f") == 0) {
            files = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-n") == 0) {
            number = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-a") == 0) {
            all = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(dir < 0) {
        merr_msg("invalid mark option. can't use to mark -d all");
        return FALSE;
    }

    /// 状態参照 ///
    if(!all && !toggle && vector_size(argv) == 2)
    {
        char* arg1 = string_c_str(vector_item(argv, 1));

        int arg1_num;
        if(number) {
            arg1_num = atoi(arg1);
        }
        else {
            arg1_num = filer_file2(dir, arg1);
        }

        if(arg1_num >= 0) {
            if(filer_mark(dir, arg1_num)) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "1"))
                {
                    return FALSE;
                }
                if(new_line) {
                    if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                    {
                        return FALSE;
                    }
                }

                *rcode = 0;
            }
            else {
                if(!statment_tree_internal_commands_write_nextout(nextout, "0"))
                {
                    return FALSE;
                }
                if(new_line) {
                    if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                    {
                        return FALSE;
                    }
                }

                *rcode = 0;
            }
        }
    }
    /// 状態セット all toggleオン ///
    else if(all && toggle && vector_size(argv) == 1) {
        sDir* dir2 = filer_dir(dir);
        int i;
        for(i=0; i<vector_size(dir2->mFiles); i++) {
            sFile* file = vector_item(dir2->mFiles, i);
            if(strcmp(string_c_str(file->mName), ".") != 0
                && strcmp(string_c_str(file->mName), "..") != 0)
            {
                if(!files || !S_ISDIR(file->mStat.st_mode)) {
                    file->mMark = !file->mMark;
                }
            }
        }

        *rcode = 0;
    }
    /// 状態セット all toggleオフ 数値指定 ///
    else if(all && !toggle && vector_size(argv) == 2) {
        int arg1 = atoi(string_c_str(vector_item(argv, 1)));

        sDir* dir2 = filer_dir(dir);
        int i;
        for(i=0; i<vector_size(dir2->mFiles); i++) {
            sFile* file = vector_item(dir2->mFiles, i);
            if(strcmp(string_c_str(file->mName), ".") != 0
                && strcmp(string_c_str(file->mName), "..") != 0)
            {
                if(!files || !S_ISDIR(file->mStat.st_mode)) {
                    file->mMark = arg1 != 0;
                }
            }
        }

        *rcode = 0;
    }

    /// 状態セット ファイルひとつ ///
    else if(!all && !toggle && vector_size(argv) == 3) {
        char* arg1 = string_c_str(vector_item(argv, 1));

        int arg1_num;
        if(number) {
            arg1_num = atoi(arg1);
        }
        else {
            arg1_num = filer_file2(dir, arg1);
        }

        int arg2 = atoi(string_c_str(vector_item(argv, 2)));
        if(arg1_num >= 0) filer_set_mark(dir, arg1_num, arg2 != 0);

        *rcode = 0;
    }

    /// 状態セット ファイルひとつ ///
    else if(!all && toggle && vector_size(argv) == 2) {
        char* arg1 = string_c_str(vector_item(argv, 1));

        int arg1_num;
        if(number) {
            arg1_num = atoi(arg1);
        }
        else {
            arg1_num = filer_file2(dir, arg1);
        }

        if(arg1_num >= 0) filer_toggle_mark(dir, arg1_num);

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_new_dir(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    string_obj* mask = STRING_NEW(".+");
    BOOL dotdir_mask = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-m") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            string_put(mask, darg);

            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-dotdir") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            dotdir_mask = atoi(darg);

            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        char* dir = string_c_str(vector_item(argv, 1));
        int dir2 = filer_new_dir(dir, dotdir_mask, string_c_str(mask));
        if(dir2 >= 0) {
            *rcode = 0;
        }
    }

    string_delete(mask);

    return TRUE;
}

BOOL commands_del_dir(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(dir < 0) {
        merr_msg("can't run marking -d all");
        return FALSE;
    }

    if(vector_size(argv) == 1) {
        filer_del_dir(dir);

        *rcode = 0;
    }

    return TRUE;
}



BOOL commands_marking(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(dir < 0) {
        merr_msg("can't run marking -d all");
        return FALSE;
    }

    if(vector_size(argv) == 1) {
        if(filer_marking(dir)) {
            if(!statment_tree_internal_commands_write_nextout(nextout, "1"))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }
        }
        else {
            if(!statment_tree_internal_commands_write_nextout(nextout, "0"))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mask(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    int dir = adir();
    BOOL dotdir = FALSE;
    BOOL reread = FALSE;
    BOOL new_line = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-d") == 0 && l+1 < vector_size(argv)) {
            char* darg = string_c_str(vector_item(argv, l+1));
            if(strcmp(darg, "all") == 0) {
                dir = -1;
            }
            else if(strcmp(darg, "adir") == 0) {
                dir = adir();
            }
            else if(strcmp(darg, "sdir") == 0) {
                dir = sdir();
            }
            else {
                dir = atoi(string_c_str(vector_item(argv, l+1)));
            }
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-dotdir") == 0) {
            dotdir = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-r") == 0) {
            reread = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(dotdir) {
        /// 状態参照 ///
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                merr_msg("invalid use. mask -d all");
                return FALSE;
            }

            if(filer_dotdir_mask(dir)) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "1"))
                {
                    return FALSE;
                }
                if(new_line) {
                    if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                    {
                        return FALSE;
                    }
                }
            }
            else {
                if(!statment_tree_internal_commands_write_nextout(nextout, "0"))
                {
                    return FALSE;
                }
                if(new_line) {
                    if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                    {
                        return FALSE;
                    }
                }
            }

            *rcode = 0;
        }

        /// 状態セット ///
        else if(vector_size(argv) == 2) {
            int arg2 = atoi(string_c_str(vector_item(argv, 1)));

            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    filer_set_dotdir_mask(i, arg2 != 0);
                }
            }
            else {
                filer_set_dotdir_mask(dir, arg2 != 0);
            }

            *rcode = 0;
        }
    }
    else {
        /// 状態参照 ///
        if(vector_size(argv) == 1) {
            if(dir < 0) {
                merr_msg("invalid use. mask -d all");
                return FALSE;
            }

            char* p = filer_mask(dir);
            if(!statment_tree_internal_commands_write_nextout(nextout, p))
            {
                return FALSE;
            }
            if(new_line) {
                if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
                {
                    return FALSE;
                }
            }

            *rcode = 0;
        }

        /// 状態セット ///
        else if(vector_size(argv) == 2) {
            if(dir < 0) {
                int i;
                for(i=0; i<vector_size(gDirs); i++) {
                    filer_set_mask(i, string_c_str(vector_item(argv, 1)));
                }

                if(reread) {
                    filer_reread(0);
                    filer_reread(1);
                }
            }
            else {
                filer_set_mask(dir, string_c_str(vector_item(argv, 1)));

                if(reread) {
                    if(dir == 0)
                        filer_reread(0);
                    else if(dir == 1) 
                        filer_reread(1);
                }
            }

            *rcode = 0;
        }
    }

    return TRUE;
}

BOOL commands_vd(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    filer_vd_start(adir());
    filer_vd_add(adir(), "..");
    
    while(1) {
        string_obj* line = STRING_NEW("");
        int result = statment_tree_internal_commands_read_nextin_oneline(nextin, line);
        if(result < 0) {
            merr_msg("interrupt");
            string_delete(line);
            return FALSE;
        }
        else if(result == 1) {
            string_delete(line);
            break;
        }
        string_chomp(line);
        if(strcmp(string_c_str(line), "") != 0) {
            filer_vd_add(adir(), string_c_str(line));
        }

        string_delete(line);

        if(gKitutukiSigInt) {
            *rcode = 1;
            merr_msg("interrupt");
            return FALSE;
        }
        *rcode = 0;
    }

vd_end:

    return TRUE;
}

BOOL commands_mrename(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int l;
    BOOL reread = FALSE;
    BOOL cursor_move = FALSE;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-r") == 0) {
            reread = TRUE;

            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
        else if(strcmp(arg, "-c") == 0) {
            cursor_move = TRUE;

            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }

    if(vector_size(argv) == 3) {
        char* source = string_c_str(vector_item(argv, 1));
        char* distination = string_c_str(vector_item(argv, 2));

        if(access(source, F_OK) != 0) {
            if(mis_raw_mode()) {
                merr_msg("%s does not exist.", source);
            }
            else {
                fprintf(stderr, "%s does not exist.", source);
            }
            return FALSE;
        }

        if(access(distination, F_OK) == 0) {
            if(mis_raw_mode()) {
                merr_msg("%s exists. can't rename", distination);
            }
            else {
                fprintf(stderr, "%s exists. can't rename", distination);
            }
            return FALSE;
        }

        if(rename(source, distination) < 0) {
            if(mis_raw_mode()) {
                merr_msg("rename error");
            }
            else {
                fprintf(stderr, "rename error");
            }
            return FALSE;
        }

        if(reread) {
            filer_reread(adir());
        }
        
        if(cursor_move) {
            int n = filer_file2(adir(), distination);
            filer_cursor_move(adir(), n);
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_row(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[BUFSIZ];
    snprintf(buf, BUFSIZ, "%d", filer_row(adir()));
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }
    *rcode = 0;

    return TRUE;
}

BOOL commands_row_max(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[BUFSIZ];
    snprintf(buf, BUFSIZ, "%d", filer_row_max(adir()));
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }
    *rcode = 0;

    return TRUE;
}

BOOL commands_line(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[BUFSIZ];
    snprintf(buf, BUFSIZ, "%d", filer_line(adir()));
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }

    *rcode = 0;

    return TRUE;
}

BOOL commands_line_max(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[BUFSIZ];
    snprintf(buf, BUFSIZ, "%d", filer_line_max(adir()));
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }

    *rcode = 0;

    return TRUE;
}

//// 端末制御がかかわるもの ///
static int gProgressMark = 0;

static void draw_progress_box(int mark_num)
{
    const int maxx = mgetmaxx();
    const int maxy = mgetmaxy();
    
    const int y = maxy/2;
    
    mbox(y, (maxx-22)/2, 22, 3);
    mmvprintw(y, (maxx-22)/2+2, "progress");
    mmvprintw(y+1, (maxx-22)/2+1, "(%d/%d) files", gProgressMark, mark_num);
}

BOOL commands_mcp(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    BOOL preserve = FALSE;
    int i;
    const int len = vector_size(argv);
    for(i=0; i<len; i++) {
        char* arg = string_c_str(vector_item(argv, i));
        if(strcmp(arg, "-p") == 0) {
            preserve = TRUE;
            string_delete(vector_item(argv, i));
            vector_erase(argv, i);
            i--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        gCopyOverride = kNone;
        gWriteProtected = kWPNone;

        /// 引数チェック ///
        char distination[PATH_MAX];
        xstrncpy(distination, string_c_str(vector_item(argv, 1)), PATH_MAX);

        /// 対象がディレクトリかチェック ///
        if(distination[strlen(distination)-1] != '/')
        {
            xstrncat(distination, "/", PATH_MAX);
        }

        /// ディレクトリが無いなら作成 ///
        if(access(distination, F_OK) != 0) {
            char* str[] = {
                "yes", "no"
            };

            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%s doesn't exist. create?", distination);

            if(select_str(buf, str, 2, 1) == 0) {
                snprintf(buf, BUFSIZ, "mkdir -p %s", distination);
                if(system(buf) < 0) {
                    merr_msg("mcp: making directory err(%s)", distination);
                    return FALSE;
                }
            }
            else {
                merr_msg("mcp: destination err(%s)", distination);
                return FALSE;
            }
        }

        /// 目標ディレクトリがディレクトリじゃないならエラー ///
        struct stat dstat;
        if(stat(distination, &dstat) < 0 || !S_ISDIR(dstat.st_mode)) {
            merr_msg("mcp: distination is not directory");
            return FALSE;
        }

        /// go ///
        vector_obj* markfiles = filer_mark_files(adir());
        const int mark_file_num = vector_size(markfiles);
        gProgressMark = mark_file_num;

        sDir* dir = filer_dir(adir());
        int j;
        for(j=0; j<mark_file_num; j++) {
            sFile* file = vector_item(markfiles, j);
            char* fname = string_c_str(file->mName);
            char source[PATH_MAX];

            xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
            xstrncat(source, fname, PATH_MAX);
            
            if(strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) {
                int num;
                if((num = filer_file2(adir(), fname)) < 0) 
                {
                    merr_msg("%s doesn't exist", fname);
                    break;
                }
                else
                {
                    filer_cursor_move(adir(), num);

                    view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                    //draw_progress_box(mark_file_num);
                    mrefresh();
                    
                    if(!file_copy(source, distination, FALSE, preserve)) 
                    {
                        break;
                    }

                    gProgressMark--;
                    
                    filer_set_mark(adir(), num, FALSE);
                }
            }
        }

        vector_delete(markfiles);
        
        /*
        mclear();
        view();
        mrefresh();
        */

        dir = filer_dir(0);
        if(strcmp(distination, string_c_str(dir->mPath)) == 0) {
            filer_reread(0);
        }

        dir = filer_dir(1);
        if(strcmp(distination, string_c_str(dir->mPath)) == 0) {
            filer_reread(1);
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mbackup(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    BOOL preserve = FALSE;
    int i;
    const int len = vector_size(argv);
    for(i=0; i<len; i++) {
        char* arg = string_c_str(vector_item(argv, i));
        if(strcmp(arg, "-p") == 0) {
            preserve = TRUE;
            string_delete(vector_item(argv, i));
            vector_erase(argv, i);
            i--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        gCopyOverride = kNone;
        gWriteProtected = kWPNone;

        sDir* dir = filer_dir(adir());

        /// 引数チェック ///
        char distination[PATH_MAX];
        xstrncpy(distination, string_c_str(dir->mPath), PATH_MAX);
        xstrncat(distination, string_c_str(vector_item(argv, 1)), PATH_MAX);

        /// 対象があるかどうかチェック ///
        if(access(distination, F_OK) == 0) {
            merr_msg("distination exists");
            return FALSE;
        }

        /// go //
        sFile* file = filer_cursor_file(adir());
        
        char* fname = string_c_str(file->mName);
        char source[PATH_MAX];

        xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
        xstrncat(source, fname, PATH_MAX);
            
        if(strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) {
            int num;
            if((num = filer_file2(adir(), fname)) < 0) 
            {
                merr_msg("%s doesn't exist", fname);
                return FALSE;
            }
            else
            {
                filer_cursor_move(adir(), num);

                view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                //draw_progress_box(mark_file_num);
                mrefresh();
                
                if(!file_copy(source, distination, FALSE, preserve)) {
                    return FALSE;
                }

                filer_set_mark(adir(), num, FALSE);
            }
        }
        
        filer_reread(adir());

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mmv(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    BOOL force = FALSE;
    BOOL preserve = FALSE;
    int j=0;
    for(j=1; j<vector_size(argv); j++) {
        char* item = string_c_str(vector_item(argv, j));

        if(strcmp(item, "-f") == 0) {
            force = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
        else if(strcmp(item, "-p") == 0) {
            preserve = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
    }

    if(vector_size(argv) == 2) {
        if(force) {
            gCopyOverride = kYesAll;
        }
        else {
            gCopyOverride = kNone;
        }

        gWriteProtected = kWPNone;

        /// 引数チェック ///
        char distination[PATH_MAX];
        xstrncpy(distination, string_c_str(vector_item(argv, 1)), PATH_MAX);

        /// 対象がディレクトリ ///
        if(distination[strlen(distination)-1] != '/') {
            xstrncat(distination, "/", PATH_MAX);
        }

        /// ディレクトリが無いなら作成 ///
        if(access(distination, F_OK) != 0)
        {
            char* str[] = {
                "yes", "no"
            };

            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%s doesn't exist. create?", distination);

            if(select_str(buf, str, 2, 1) == 0) {
                snprintf(buf, BUFSIZ, "mkdir -p %s", distination);
                if(system(buf) < 0) {
                    merr_msg("mmv: making directory err(%s)", distination);
                    return FALSE;
                }
            }
            else {
                merr_msg("mmv: destination err(%s)", distination);
                return FALSE;
            }
        }

        /// 目標ファイルがディレクトリかどうかチェック ///
        struct stat dstat;
        if(stat(distination, &dstat) < 0 || !S_ISDIR(dstat.st_mode)) {
            merr_msg("mmv: distination is not directory");
            return FALSE;
        }

        /// go ///
        sDir* dir = filer_dir(adir());

        vector_obj* markfiles = filer_mark_files(adir());
        const int mark_file_num = vector_size(markfiles);
        gProgressMark = mark_file_num;

        int j;
        for(j=0; j<mark_file_num; j++) {
            sFile* file = vector_item(markfiles, j);
            char* fname = string_c_str(file->mName);
            char source[PATH_MAX];

            xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
            xstrncat(source, fname, PATH_MAX);

            if(strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) {
                int num;
                if((num = filer_file2(adir(), fname)) < 0) {
                    merr_msg("%s doesn't exist", fname);
                    break;
                }
                else
                {
                    filer_cursor_move(adir(), num);

                    view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                    //draw_progress_box(mark_file_num);
                    mrefresh();
                    
                    if(!file_copy(source, distination, TRUE, preserve)) {
                        break;
                    }

                    gProgressMark--;
                    
                    filer_set_mark(adir(), num, FALSE);
                }
            }
        }

        vector_delete(markfiles);
        
        /*
        mclear();
        view();
        mrefresh();
        */

        filer_reread(0);
        filer_reread(1);

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mrm(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }
                
    if(vector_size(argv) == 1) {
        gCopyOverride = kNone;
        gWriteProtected = kWPNone;

        /// go ///
        vector_obj* markfiles = filer_mark_files(adir());
        const int mark_file_num = vector_size(markfiles);
        gProgressMark = mark_file_num;

        int j;
        for(j=0; j<mark_file_num; j++) {
            sFile* file = vector_item(markfiles, j);
            char* item = string_c_str(file->mName);

            if(strcmp(item, ".") != 0 && strcmp(item, "..") != 0) {
                char source[PATH_MAX];

                sDir* dir = filer_dir(adir());
                xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
                xstrncat(source, item, PATH_MAX);

                int num;
                if((num = filer_file2(adir(), item)) < 0) {
                    merr_msg("%s doesn't exist", item);
                    break;
                }
                else {
                    filer_cursor_move(adir(), num);

                    view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                    //draw_progress_box(mark_file_num);
                    mrefresh();
                    
                    if(!file_remove(source, FALSE, TRUE)) {
                        break;
                    }

                    gProgressMark--;
                    
                    filer_set_mark(adir(), num, FALSE);
                }
            }
        }
        
        /*
        mclear();
        view();
        mrefresh();
        */

        filer_reread(0);
        filer_reread(1);

        *rcode = 0;

        vector_delete(markfiles);
    }

    return TRUE;
}

BOOL commands_kanjicode_file_name(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    int j=0;
    for(j=1; j<vector_size(argv); j++) {
        char* item = string_c_str(vector_item(argv, j));
/*
        if(strcmp(item, "-s") == 0) {
            gKanjiCodeFileName = kSjis;
            *rcode = 0;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
        else if(strcmp(item, "-e") == 0) {
            gKanjiCodeFileName = kEucjp;
            *rcode = 0;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
*/
        if(strcmp(item, "-w") == 0) {
            gKanjiCodeFileName = kUtf8;
            *rcode = 0;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
        else if(strcmp(item, "-m") == 0) {
            gKanjiCodeFileName = kUtf8Mac;
            *rcode = 0;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
    }

    return TRUE;
}

BOOL commands_mtrashbox(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    BOOL force = FALSE;
    BOOL preserve = FALSE;
    int j=0;
    for(j=1; j<vector_size(argv); j++) {
        char* item = string_c_str(vector_item(argv, j));

        if(strcmp(item, "-f") == 0) {
            force = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
        else if(strcmp(item, "-p") == 0) {
            preserve = TRUE;
            string_delete(vector_item(argv, j));
            vector_erase(argv, j);
            j--;
            continue;
        }
    }

    if(vector_size(argv) == 1) {
        if(force) {
            gCopyOverride = kYesAll;
        }
        else {
            gCopyOverride = kNone;
        }

        gWriteProtected = kWPNone;

        /// 引数チェック ///
        char distination[PATH_MAX];

        char* env = getenv("TRASHBOX_DIR");
        if(env) {
            xstrncpy(distination, env, PATH_MAX);
        }
        else {
            xstrncpy(distination, getenv("MF3HOME"), PATH_MAX);
            xstrncat(distination, "/trashbox/", PATH_MAX);
        }

        if(distination[strlen(distination)-1] != '/') {
            xstrncat(distination, "/", PATH_MAX);
        }

        /// ディレクトリが無いなら作成 ///
        if(access(distination, F_OK) != 0)
        {
            char* str[] = {
                "yes", "no"
            };

            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%s doesn't exist. create?", distination);

            if(select_str(buf, str, 2, 1) == 0) {
                snprintf(buf, BUFSIZ, "mkdir -p %s", distination);
                if(system(buf) < 0) {
                    merr_msg("mmv: making directory err(%s)", distination);
                    return FALSE;
                }
            }
            else {
                merr_msg("mmv: destination err(%s)", distination);
                return FALSE;
            }
        }

        /// 目標ファイルがディレクトリかどうかチェック ///
        struct stat dstat;
        if(stat(distination, &dstat) < 0 || !S_ISDIR(dstat.st_mode)) {
            merr_msg("mmv: distination is not directory");
            return FALSE;
        }

        /// go ///
        sDir* dir = filer_dir(adir());

        vector_obj* markfiles = filer_mark_files(adir());
        const int mark_file_num = vector_size(markfiles);
        gProgressMark = mark_file_num;

        int j;
        for(j=0; j<mark_file_num; j++) {
            sFile* file = vector_item(markfiles, j);
            char* fname = string_c_str(file->mName);
            char source[PATH_MAX];

            xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
            xstrncat(source, fname, PATH_MAX);

            if(strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) {
                int num;
                if((num = filer_file2(adir(), fname)) < 0) {
                    merr_msg("%s doesn't exist", fname);
                    break;
                }
                else
                {
                    filer_cursor_move(adir(), num);

                    view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                    //draw_progress_box(mark_file_num);
                    mrefresh();
                    
                    if(!file_copy(source, distination, TRUE, preserve)) {
                        break;
                    }

                    gProgressMark--;
                    
                    filer_set_mark(adir(), num, FALSE);
                }
            }
        }

        vector_delete(markfiles);
        
        /*
        mclear();
        view();
        mrefresh();
        */

        filer_reread(0);
        filer_reread(1);

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mln(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    if(vector_size(argv) == 2) {
        /// 引数チェック ///
        char distination[PATH_MAX];
        xstrncpy(distination, string_c_str(vector_item(argv, 1)), PATH_MAX);

        if(distination[strlen(distination)-1] != '/') {
            xstrncat(distination, "/", PATH_MAX);
        }

        /// ディレクトリが無いなら作成 ///
        if(access(distination, F_OK) != 0) {
            char* str[] = {
                "yes", "no"
            };

            char buf[BUFSIZ];
            snprintf(buf, BUFSIZ, "%s doesn't exist. create?", distination);

            if(select_str(buf, str, 2, 1) == 0) {
                snprintf(buf, BUFSIZ, "mkdir -p %s", distination);
                if(system(buf) < 0) {
                    merr_msg("mcp: making directory err(%s)", distination);
                    return FALSE;
                }
            }
            else {
                merr_msg("mcp: destination err(%s)", distination);
                return FALSE;
            }
        }

        /// 目標ディレクトリがディレクトリじゃないならエラー ///
        struct stat dstat;
        if(stat(distination, &dstat) < 0 || !S_ISDIR(dstat.st_mode)) {
            merr_msg("mcp: distination is not directory");
            return FALSE;
        }

        /// go ///
        vector_obj* markfiles = filer_mark_files(adir());
        const int mark_file_num = vector_size(markfiles);
        gProgressMark = mark_file_num;

        sDir* dir = filer_dir(adir());
        int j;
        for(j=0; j<mark_file_num; j++) {
            sFile* file = vector_item(markfiles, j);
            char* fname = string_c_str(file->mName);
            char source[PATH_MAX];

            xstrncpy(source, string_c_str(dir->mPath), PATH_MAX);
            xstrncat(source, fname, PATH_MAX);

            if(strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) {
                int num;
                if((num = filer_file2(adir(), fname)) < 0) 
                {
                    merr_msg("%s doesn't exist", fname);
                    break;
                }
                else
                {
                    filer_cursor_move(adir(), num);

                    view(FALSE); // これはコピーの上書き確認のときに正しい位置にカーソルがある必要があったり、＊印の描写などが正しく描写されている必要があるので必要
                    //draw_progress_box(mark_file_num);
                    mrefresh();

                    char dfile[PATH_MAX];
                    xstrncpy(dfile, distination, PATH_MAX);
                    xstrncat(dfile, fname, PATH_MAX);

                    if(symlink(source, dfile) < 0) {
                        merr_msg("can't make symlink(%s). Is it attempt to make on vfat?", dfile);
                        break;
                    }

                    gProgressMark--;
                    
                    filer_set_mark(adir(), num, FALSE);
                }
            }
        }

        vector_delete(markfiles);
        
        /*
        mclear();
        view();
        mrefresh();
        */

        dir = filer_dir(0);
        if(strcmp(distination, string_c_str(dir->mPath)) == 0) {
            filer_reread(0);
        }

        dir = filer_dir(1);
        if(strcmp(distination, string_c_str(dir->mPath)) == 0) {
            filer_reread(1);
        }

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_mclear_immediately(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
    }

    mclear_immediately();
    *rcode = 0;

    return TRUE;
}

BOOL commands_mchoise(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    if(!mis_raw_mode()) {
/*
        merr_msg("invalid terminal setting. not raw mode");
        return FALSE;
*/
    }

    if(vector_size(argv) >= 3) {
        char* msg = string_c_str(vector_item(argv, 1));
        char** str = MALLOC(sizeof(char*)*vector_size(argv));

        int j;
        for(j=2; j<vector_size(argv); j++) {
            str[j-2] = string_c_str(vector_item(argv, j));
        }

        char* smsg = choise(msg, str, vector_size(argv) -2, -1);
        char buf[BUFSIZ];
        if(smsg == NULL) {
            snprintf(buf, BUFSIZ, "cancel");
        }
        else {
            snprintf(buf, BUFSIZ, "%s", smsg);
        }

        if(!statment_tree_internal_commands_write_nextout(nextout, buf))
        {
            return FALSE;
        }

        FREE(str);

        *rcode = 0;
    }

    return TRUE;
}

BOOL commands_adir(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[256];
    snprintf(buf, 256, "%d", adir());
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }

    *rcode = 0;

    return TRUE;
}

BOOL commands_sdir(int* rcode, vector_obj* argv, vector_obj* blocks, vector_obj* parent_blocks, sWFd* nextout, sRFd* nextin, int nexterr, char* title, BOOL input)
{
    BOOL new_line = FALSE;
    int l;
    for(l=0; l<vector_size(argv); l++) {
        char* arg = string_c_str(vector_item(argv, l));

        if(strcmp(arg, "-l") == 0) {
            new_line = TRUE;
            string_delete(vector_item(argv, l));
            vector_erase(argv, l);
            l--;
            continue;
        }
    }
    char buf[256];
    snprintf(buf, 256, "%d", sdir());
    if(!statment_tree_internal_commands_write_nextout(nextout, buf))
    {
        return FALSE;
    }
    if(new_line) {
        if(!statment_tree_internal_commands_write_nextout(nextout, "\n"))
        {
            return FALSE;
        }
    }

    *rcode = 0;

    return TRUE;
}

void commands_init()
{
    saphire_add_inner_command("quit", commands_quit);
    saphire_add_inner_command("keycommand", commands_keycommand);
    saphire_add_inner_command("keycommand2", commands_keycommand2);
    saphire_add_inner_command("keymap", commands_keymap);
    saphire_add_inner_command("cursor_move", commands_cursor_move);
    saphire_add_inner_command("mcd", commands_mcd);
    saphire_add_inner_command("cmdline", commands_cmdline);
    saphire_add_inner_command("file_num", commands_file_num);
    saphire_add_inner_command("file_perm", commands_file_perm);
    saphire_add_inner_command("file_group", commands_file_group);
    saphire_add_inner_command("file_user", commands_file_user);
    saphire_add_inner_command("file_index", commands_file_index);
    saphire_add_inner_command("file_ext", commands_file_ext);
    saphire_add_inner_command("file_name", commands_file_name);
    saphire_add_inner_command("path", commands_path);
    saphire_add_inner_command("cursor_num", commands_cursor_num);
    saphire_add_inner_command("external", commands_external);
    saphire_add_inner_command("isearch", commands_isearch);
    saphire_add_inner_command("mchoise", commands_mchoise);
    saphire_add_inner_command("activate", commands_activate);
    saphire_add_inner_command("defmenu", commands_defmenu);
    saphire_add_inner_command("addmenu", commands_addmenu);
    saphire_add_inner_command("menu", commands_menu);
    saphire_add_inner_command("reread", commands_reread);
    saphire_add_inner_command("markfiles", commands_markfiles);
    saphire_add_inner_command("allfiles", commands_allfiles);
    saphire_add_inner_command("mark", commands_mark);
    saphire_add_inner_command("marking", commands_marking);
    saphire_add_inner_command("mclear_immediately", commands_mclear_immediately);
    saphire_add_inner_command("vd", commands_vd);
    saphire_add_inner_command("mcp", commands_mcp);
    saphire_add_inner_command("mrm", commands_mrm);
    saphire_add_inner_command("mmv", commands_mmv);
    saphire_add_inner_command("mtrashbox", commands_mtrashbox);
    saphire_add_inner_command("mln", commands_mln);
    saphire_add_inner_command("mrename", commands_mrename);
    saphire_add_inner_command("mask", commands_mask);
    saphire_add_inner_command("dir_num", commands_dir_num);
    saphire_add_inner_command("del_dir", commands_del_dir);
    saphire_add_inner_command("new_dir", commands_new_dir);
    saphire_add_inner_command("mbackup", commands_mbackup);

    saphire_add_inner_command("row", commands_row);
    saphire_add_inner_command("row_max", commands_row_max);
    saphire_add_inner_command("line", commands_line);
    saphire_add_inner_command("line_max", commands_line_max);
    saphire_add_inner_command("adir", commands_adir);
    saphire_add_inner_command("sdir", commands_sdir);
    saphire_add_inner_command("kanjicode_file_name", commands_kanjicode_file_name);
}

void commands_final()
{
}
