#include "common.h"
#include <time.h>

int gViewHookLineNum;

bool cDirWnd::gViewMTime = false;
bool cDirWnd::gViewSize = false;
bool cDirWnd::gViewGroup = false;
bool cDirWnd::gViewOwner = false;
bool cDirWnd::gViewNLink = false;
bool cDirWnd::gViewPermission = false;
bool cDirWnd::gViewFnameDivideExt = false;

VALUE gOptionPageViewWay = Qfalse;
VALUE gFileSizeViewWay = INT2NUM(kFSNormal);

void MakeSizeStr(char* result, double size)
{
    if(gFileSizeViewWay == INT2NUM(kFSHuman)) {
        char tmp[256];
        double size2;
        if(size < 1024) {
            size2 = size;
            sprintf(tmp, "%.0f", size2);

            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 7) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 4) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }

            *p2 = 0;
        }
        else if(size < 1024*1024) {
            size2 = size / 1024;
            sprintf(tmp, "%.1f", size2);

            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 9) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 6) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }

            *p2++ = 'k';
            *p2 = 0;
        }
        else if(size < 1024*1024*1024) {
            size2 = size / (1024*1024);
            sprintf(tmp, "%.1f", size2);

            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 9) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 6) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }

            *p2++ = 'M';
            *p2 = 0;
        }
        else {
            size2 = size / (1024*1024*1024);
            sprintf(tmp, "%.1f", size2);

            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 9) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 6) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }

            *p2++ = 'G';
            *p2 = 0;
        }
    }
    else if(gFileSizeViewWay == INT2NUM(kFSNormal)) {
        if(size < 1024*1024) {
            char tmp[256];
            sprintf(tmp, "%.0f", size);
            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 7) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 4) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }
            *p2 = 0;
        }
        else {
            size = size / (1024*1024);

            char tmp[256];
            sprintf(tmp, "%.1f", size);
            char* end = tmp + strlen(tmp);

            char* p = tmp;
            char* p2 = result;
            
            while(*p) {
                if(end - p == 9) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else if(end - p == 6) {
                    *p2++ = *p++;
                    *p2++ = ',';
                }
                else {
                    *p2++ = *p++;
                }
            }
            *p2++ = 'M';
            *p2 = 0;
        }
    }
    else if(gFileSizeViewWay == INT2NUM(kFSPlane)) {
        char tmp[256];
        sprintf(tmp, "%.0f", size);
        char* end = tmp + strlen(tmp);

        char* p = tmp;
        char* p2 = result;
        
        while(*p) {
            if(end - p == 10) {
                *p2++ = *p++;
                *p2++ = ',';
            }
            else if(end - p == 7) {
                *p2++ = *p++;
                *p2++ = ',';
            }
            else if(end - p == 4) {
                *p2++ = *p++;
                *p2++ = ',';
            }
            else {
                *p2++ = *p++;
            }
        }
        *p2 = 0;
    }
}

void cDirWnd::MakeSizeStr2(char* result, double size)
{
    char tmp[256];
    sprintf(tmp, "%.0f", size);
    char* end = tmp + strlen(tmp);

    char* p = tmp;
    char* p2 = result;
    
    while(*p) {
        if(end - p == 13) {
            *p2++ = *p++;
            *p2++ = ',';
        }
        else if(end - p == 10) {
            *p2++ = *p++;
            *p2++ = ',';
        }
        else if(end - p == 7) {
            *p2++ = *p++;
            *p2++ = ',';
        }
        else if(end - p == 4) {
            *p2++ = *p++;
            *p2++ = ',';
        }
        else {
            *p2++ = *p++;
        }
    }
    *p2 = 0;
}

/// buf は充分なスペースが必要 ///
void cDirWnd::make_file_stat(sFile* file, char* buf)
{
    strcpy(buf, "");

    if(gViewPermission) {
        char permission[12];
        strcpy(permission, "----------");
        if(S_ISDIR(file->mLStat.st_mode)) permission[0] = 'd';
        if(S_ISCHR(file->mLStat.st_mode)) permission[0] = 'c';
        if(S_ISBLK(file->mLStat.st_mode)) permission[0] = 'b';
        if(S_ISFIFO(file->mLStat.st_mode)) permission[0] = 'p';
        if(S_ISLNK(file->mLStat.st_mode)) permission[0] = 'l';
        if(S_ISSOCK(file->mLStat.st_mode)) permission[0] = 's';
    
        mode_t smode = file->mLStat.st_mode;
        if(smode & S_IRUSR) permission[1] = 'r';
        if(smode & S_IWUSR) permission[2] = 'w';
        if(smode & S_IXUSR) permission[3] = 'x';
        if(smode & S_IRGRP) permission[4] = 'r';
        if(smode & S_IWGRP) permission[5] = 'w';
        if(smode & S_IXGRP) permission[6] = 'x';
        if(smode & S_IROTH) permission[7] = 'r';
        if(smode & S_IWOTH) permission[8] = 'w';
        if(smode & S_IXOTH) permission[9] = 'x';
        if(smode & S_ISUID) permission[3] = 's';
        if(smode & S_ISGID) permission[6] = 's';
#if defined(S_ISTXT)
        if(smode & S_ISTXT) permission[9] = 't';
#endif
#if defined(S_ISVTX)
        if(smode & S_ISVTX) permission[9] = 't';
#endif

        sprintf(buf + strlen(buf), " %s", permission);
    }

    if(gViewNLink) {
        sprintf(buf + strlen(buf), " %3d", file->mStat.st_nlink);
    }

    if(gViewOwner) {
        char owner[256];
        char* tmp = file->mUser;
        if(tmp) {
            if(gKanjiCode == kUtf8)
                str_cut2(tmp, 8, owner, 256);
            else
                cut(tmp, owner, 8);
        }
        else {
            sprintf(owner, "%d", file->mLStat.st_uid);
        }

        sprintf(buf + strlen(buf), " %-8s", owner);
    }

    if(gViewGroup) {
        char group[256];
        char* tmp = file->mGroup;
        if(tmp) {
            if(gKanjiCode == kUtf8)
                str_cut2(tmp, 8, group, 256);
            else
                cut(tmp, group, 8);
        }
        else {
            sprintf(group, "%d", file->mLStat.st_gid);
        }

        sprintf(buf + strlen(buf), " %-8s", group);
    }

    if(gViewSize) {
        char size[256];
        MakeSizeStr(size, file->mLStat.st_size);
        if(S_ISDIR(file->mStat.st_mode)) {
            sprintf(buf + strlen(buf), "         <DIR>");
        }
        else {
            sprintf(buf + strlen(buf) , "%14s", size);
        }
    }

    if(gViewMTime) {
        time_t t = file->mLStat.st_mtime;
        struct tm* tm_ = (struct tm*)localtime(&t);

        int year = tm_->tm_year-100;
        if(year < 0) year+=100;
        while(year > 100) year-=100;

        sprintf(buf + strlen(buf), " %02d-%02d-%02d %02d:%02d"
               , year, tm_->tm_mon+1
               , tm_->tm_mday, tm_->tm_hour, tm_->tm_min);
    }

    sprintf(buf + strlen(buf), " ");
}

/// fnameは充分なスペースが必要 extは使用後FREEする必要がある ///
void cDirWnd::make_file_name(sFile* file, char* fname, char** ext, char* dot, int name_len)
{
    strcpy(fname, file->mNameView);

    if(mViewRemoveDir) {
        char* p = fname + strlen(fname);
        while(1) {
            if(*p == '/') {
                strcpy(fname, p+1);
                break;
            }
            else if(p == fname) {
                break;
            }

            p--;
        }
    }

    if(S_ISDIR(file->mStat.st_mode)) {
         strcat(fname, "/");
    }
    else if(S_ISFIFO(file->mLStat.st_mode)) {
        strcat(fname, "|");
    }
    else if(S_ISSOCK(file->mLStat.st_mode)) {
        strcat(fname, "=");
    }
    else if(gExecutiveFileBold
             &&(file->mStat.st_mode&S_IXUSR
                || file->mStat.st_mode&S_IXGRP
                || file->mStat.st_mode&S_IXGRP))
    {
         strcat(fname, "*");
    }
    else if(S_ISLNK(file->mLStat.st_mode)) {
        strcat(fname, "@");
    }

    if(S_ISLNK(file->mLStat.st_mode)) {
        sprintf(fname + strlen(fname), " -> %s", file->mLinkTo);
    }

    if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
        *ext = STRDUP("");
        *dot = ' ';
    }
    else {
        *ext = extname(fname);
        *dot = ' ';

        if(strcmp(*ext, "") != 0) {
            fname[strlen(fname) - strlen(*ext) -1] = 0;
            *dot = '.';
        }
        if(strlen(*ext) > 4) {
            (*ext)[4] = 0;
        }
    }

    if(name_len > 0) {
        if(mViewFocusBack) {
            if(gKanjiCode == kUtf8) 
                str_cut3(fname, name_len, fname, PATH_MAX);
            else
                str_cut3_nonutf8(fname, name_len, fname);
        }
        else {
            if(gKanjiCode == kUtf8)
                str_cut2(fname, name_len, fname, PATH_MAX);
            else 
                cut(fname, fname, name_len);
        }
    }
    else {
        strcpy(fname, "");
    }
}

void cDirWnd::View()
{
    const int maxx = mgetmaxx();
    const int maxy = mgetmaxy();

    VALUE ret = rb_funcall(rb_cObject, rb_intern("view_hook_filer"), 0);
    gViewHookLineNum = NUM2INT(ret);

    const int jobs_exist = vector_size(gJobs) > 0 ? 1 : 0;
    const int dstack_exist = vector_size(gDirStack) > 0 ? 1 : 0;

    ////////////////////////////////////////////////////////////
    // １画面１行
    ////////////////////////////////////////////////////////////
    if(cDirWnd::gViewOption == kOneDir) {
        if(mActive) {
            mbox(dstack_exist, 0, maxx-1, maxy-2-dstack_exist-gViewHookLineNum-jobs_exist);

            char path[PATH_MAX];

            VALUE path_original;
            if(gLDir == this)
                path_original = rb_gv_get("view_path_ldir");
            else
                path_original = rb_gv_get("view_path_rdir");

            if(path_original == Qnil) {
                strcpy(path, mPath);
                strcat(path, mMask);
            }
            else {
                strcpy(path, RSTRING(path_original)->ptr);
            }

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
            char tmp[PATH_MAX];
            if(kanji_convert(path, tmp, PATH_MAX, gKanjiCodeFileName, gKanjiCode) != -1) {
                strcpy(path, tmp);
            }
#endif

            const int len = strlen(path);
            if(len < maxx-4) {
                mattron(kCABold);
                mmvprintw(0 + dstack_exist, 2, "%s", path);
                mattroff();
            }
            else {
                if(gKanjiCode == kUtf8) {
                    char buf[PATH_MAX];

                    str_cut3(path, maxx-4, buf, PATH_MAX);

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
                else {
                    bool kanji[PATH_MAX];
                    for(int i=0; i<len; i++) {
                        if(is_kanji(path[i])) {
                            kanji[i] = true;
                            i++;
                            kanji[i] = false;
                        }
                        else {
                            kanji[i] = false;
                        }
                    }

                    char buf[PATH_MAX];
                    if(kanji[len-(maxx-4)-1]) {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                        buf[0] = ' ';
                    }
                    else {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                    }

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
            }

            for(int i=mScrollTop; 
                i-mScrollTop < maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist&& i<vector_size(mFiles);
                i++)
            {
                int attr = 0;
                sFile* file = (sFile*)vector_item(mFiles, i);

                if(gColor) {
                    char tmp[PATH_MAX];

                    if(this == gLDir) {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(0, %d) then color = item[1]; break; end end; color", i);
                    }
                    else {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(1, %d) then color = item[1]; break; end end; color", i);
                    }
                    int error;
                    VALUE color = rb_eval_string_protect(tmp, &error);

                    attr = NUM2INT(color);
                }
                
                if(mCursor == i && mActive) {
                     attr |= kCAReverse;
                }
        
                if(S_ISDIR(file->mStat.st_mode)) {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorDir;
                     }
                     else {
                         if(gBoldDir) attr |= kCABold;
                     }
                }
                else if(gExecutiveFileBold
                         &&(file->mStat.st_mode&S_IXUSR
                            || file->mStat.st_mode&S_IXGRP
                            || file->mStat.st_mode&S_IXGRP))
                {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorExe;
                     }
                     else {
                         if(gBoldExe) attr |= kCABold;
                     }
                }
                else if(S_ISLNK(file->mLStat.st_mode)) {
                    if(gColor && !file->mMark) attr |= gColorLink;
                }

                char buf[1024];
                make_file_stat(file, buf);

                int name_len;
                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    name_len = maxx-2-2-strlen(buf);
                }
                else {
                    name_len = maxx-2-5-2-strlen(buf);
                }

                char fname[1024];
                char* ext;
                char dot;
                make_file_name(file, fname, &ext, &dot, name_len);


                if(file->mMark) {
                    if(gColor)
                        attr |= gColorMark;
                    else
                        attr != kCABold;
                }
                
                mattron(attr);

                if(file->mMark) {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, 1, "*");
                }
                else {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, 1, " ");
                }

                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, 2, "%s%s", fname,buf);
                }
                else {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, 2, "%s%c%-4s%s", fname, dot, ext,buf);
                }
                FREE(ext);
                
                mattroff();
            }

            char size[256];
            MakeSizeStr2(size, MarkFileSize());
            if(gOptionPageViewWay == Qtrue) {
                const int p = (((float)mCursor+1)
                                    /((float)vector_size(mFiles)))*100;
                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%3d%%)", MarkFileNum()
                        , vector_size(mFiles)-1, size, p);
            }
            else {
                const int cur_page = mCursor/(maxy-5) + 1;
                const int max_page = vector_size(mFiles)/(maxy-5) + 1;

                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%d/%d)", MarkFileNum()
                        , vector_size(mFiles)-1, size, cur_page, max_page);
            }
       }
    }
    //////////////////////////////////////////////////////////// 
    // １画面２行
    //////////////////////////////////////////////////////////// 
    else if(cDirWnd::gViewOption == kOneDir2) {
        if(mActive) {
            mbox(dstack_exist, 0, maxx-1, maxy-2-dstack_exist-gViewHookLineNum-jobs_exist);

            char path[PATH_MAX];

            VALUE path_original;
            if(gLDir == this)
                path_original = rb_gv_get("view_path_ldir"); else
                path_original = rb_gv_get("view_path_rdir");

            if(path_original == Qnil) {
                strcpy(path, mPath);
                strcat(path, mMask);
            }
            else {
                strcpy(path, RSTRING(path_original)->ptr);
            }

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
            char tmp[PATH_MAX];
            if(kanji_convert(path, tmp, PATH_MAX, gKanjiCodeFileName, gKanjiCode) != -1) {
                strcpy(path, tmp);
            }
#endif

            const int len = strlen(path);
            if(len < maxx-4) {
                mattron(kCABold);
                mmvprintw(0 + dstack_exist, 2, "%s", path);
                mattroff();
            }
            else {
                if(gKanjiCode == kUtf8) {
                    char buf[PATH_MAX];

                    str_cut3(path, maxx-4, buf, PATH_MAX);

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
                else {
                    bool kanji[PATH_MAX];
                    for(int i=0; i<len; i++) {
                        if(is_kanji(path[i])) {
                            kanji[i] = true;
                            i++;
                            kanji[i] = false;
                        }
                        else {
                            kanji[i] = false;
                        }
                    }

                    char buf[PATH_MAX];
                    if(kanji[len-(maxx-4)-1]) {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                        buf[0] = ' ';
                    }
                    else {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                    }

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
            }
            for(int i=mScrollTop;
                i-mScrollTop<(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)*2
                            && i<vector_size(mFiles);
                i++)
            {
                int attr = 0;
                sFile* file = (sFile*)vector_item(mFiles, i);
               
                if(gColor) {
                    char tmp[PATH_MAX];

                    if(this == gLDir) {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(0, %d) then color = item[1]; break; end end; color", i);
                    }
                    else {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(1,%d) then color = item[1]; break; end end; color", i);
                    }
                    int error;
                    VALUE color = rb_eval_string_protect(tmp, &error);

                    attr = NUM2INT(color);
                }

                if(mCursor == i && mActive) {
                     attr |= kCAReverse;
                }
        
                if(S_ISDIR(file->mStat.st_mode)) {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorDir;
                     }
                     else {
                         if(gBoldDir) attr |= kCABold;
                     }
                }
                else if(gExecutiveFileBold
                         &&(file->mStat.st_mode&S_IXUSR
                            || file->mStat.st_mode&S_IXGRP
                            || file->mStat.st_mode&S_IXGRP))
                {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorExe;
                     }
                     else {
                         if(gBoldExe) attr |= kCABold;
                     }
                }
                else if(S_ISLNK(file->mLStat.st_mode)) {
                    if(gColor && !file->mMark) attr |= gColorLink;
                }

                char buf[1024];
                make_file_stat(file, buf);

                int name_len;
                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    name_len = maxx/2-2-2-strlen(buf);
                }
                else {
                    name_len = maxx/2-2-5-2-strlen(buf);
                }

                char fname[1024];
                char* ext;
                char dot;
                make_file_name(file, fname, &ext, &dot, name_len);

                const int x = (i-mScrollTop)
                                /(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                *(maxx/2) + 1;
                const int y = (i-mScrollTop)
                                %(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                    + 1 + dstack_exist;

                if(file->mMark) {
                    if(gColor)
                        attr |= gColorMark;
                    else
                        attr != kCABold;
                }
                
                mattron(attr);

                if(file->mMark) {
                    mmvprintw(y, x, "*");
                }
                else {
                    mmvprintw(y, x, " ");
                }

                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    mmvprintw(y, x+1, "%s%s", fname,buf);
                }
                else {
                    mmvprintw(y, x+1, "%s%c%-4s%s", fname, dot, ext,buf);
                }
                FREE(ext);
                
                mattroff();
            }

            char size[256];
            MakeSizeStr2(size, MarkFileSize());

            if(gOptionPageViewWay == Qtrue) {
                const int p = (((float)mCursor+1)/((float)vector_size(mFiles)))*100;
                
                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%3d%%)", MarkFileNum(), vector_size(mFiles)-1, size, p);
            }
            else {
                const int cur_page = mCursor/((maxy-5)*2) + 1;
                const int max_page = vector_size(mFiles)/((maxy-5)*2) + 1;

                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%d/%d)", MarkFileNum()
                        , vector_size(mFiles)-1, size, cur_page, max_page);
            }
        }
    }
    //////////////////////////////////////////////////////////////////////////
    // １画面３行
    //////////////////////////////////////////////////////////////////////////
    else if(cDirWnd::gViewOption == kOneDir3) {
        if(mActive) {
            mbox(dstack_exist, 0, maxx-1, maxy-2-dstack_exist-gViewHookLineNum-jobs_exist);

            char path[PATH_MAX];

            VALUE path_original;
            if(gLDir == this)
                path_original = rb_gv_get("view_path_ldir");
            else
                path_original = rb_gv_get("view_path_rdir");

            if(path_original == Qnil) {
                strcpy(path, mPath);
                strcat(path, mMask);
            }
            else {
                strcpy(path, RSTRING(path_original)->ptr);
            }

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
            char tmp[PATH_MAX];
            if(kanji_convert(path, tmp, PATH_MAX, gKanjiCodeFileName, gKanjiCode) != -1) {
                strcpy(path, tmp);
            }
#endif

            const int len = strlen(path);
            if(len < maxx-4) {
                mattron(kCABold);
                mmvprintw(0 + dstack_exist, 2, "%s", path);
                mattroff();
            }
            else {
                if(gKanjiCode == kUtf8) {
                    char buf[PATH_MAX];

                    str_cut3(path, maxx-4, buf, PATH_MAX);

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
                else {
                    bool kanji[PATH_MAX];
                    for(int i=0; i<len; i++) {
                        if(is_kanji(path[i])) {
                            kanji[i] = true;
                            i++;
                            kanji[i] = false;
                        }
                        else {
                            kanji[i] = false;
                        }
                    }

                    char buf[PATH_MAX];
                    if(kanji[len-(maxx-4)-1]) {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                        buf[0] = ' ';
                    }
                    else {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                    }

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
            }

            for(int i=mScrollTop;
                i-mScrollTop<(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)*3
                            && i<vector_size(mFiles);
                i++)
            {
                int attr = 0;
                sFile* file = (sFile*)vector_item(mFiles, i);
                
                if(gColor) {
                    char tmp[PATH_MAX];
                    if(this == gLDir) {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(0, %d) then color = item[1]; break; end end; color", i);
                    }
                    else {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(1, %d) then color = item[1]; break; end end; color", i);
                    }

                    int error;
                    VALUE color = rb_eval_string_protect(tmp, &error);

                    attr = NUM2INT(color);
                }

                if(mCursor == i && mActive) {
                     attr |= kCAReverse;
                }
        
                if(S_ISDIR(file->mStat.st_mode)) {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorDir;
                     }
                     else {
                         if(gBoldDir) attr |= kCABold;
                     }
                }
                else if(gExecutiveFileBold
                         &&(file->mStat.st_mode&S_IXUSR
                            || file->mStat.st_mode&S_IXGRP
                            || file->mStat.st_mode&S_IXGRP))
                {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorExe;
                     }
                     else {
                         if(gBoldExe) attr |= kCABold;
                     }
                }
                else if(S_ISLNK(file->mLStat.st_mode)) {
                    if(gColor && !file->mMark) attr |= gColorLink;
                }

                char buf[1024];
                make_file_stat(file, buf);

                int name_len;
                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    name_len = maxx/3-2-2-strlen(buf);
                }
                else {
                    name_len = maxx/3-2-5-2-strlen(buf);
                }

                char fname[1024];
                char* ext;
                char dot;
                make_file_name(file, fname, &ext, &dot, name_len);

                const int x = (i-mScrollTop)
                                /(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                *(maxx/3) + 1;
                const int y = (i-mScrollTop)
                                %(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                    + 1 + dstack_exist;

                if(file->mMark) {
                    if(gColor)
                        attr |= gColorMark;
                    else
                        attr != kCABold;
                }
                
                mattron(attr);

                if(file->mMark) {
                    mmvprintw(y, x, "*");
                }
                else {
                    mmvprintw(y, x, " ");
                }

                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    mmvprintw(y, x+1, "%s%s", fname,buf);
                }
                else {
                    mmvprintw(y, x+1, "%s%c%-4s%s", fname, dot, ext,buf);
                }
                FREE(ext);
                
                mattroff();
            }
            
            char size[256];
            MakeSizeStr2(size, MarkFileSize());

            if(gOptionPageViewWay == Qtrue) {
                const int p = (((float)mCursor+1)/((float)vector_size(mFiles)))*100;
                
                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%3d%%)", MarkFileNum(), vector_size(mFiles)-1, size, p);
            }
            else {
                const int cur_page = mCursor/((maxy-5)*3) + 1;
                const int max_page = vector_size(mFiles)/((maxy-5)*3) + 1;

                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%d/%d)", MarkFileNum()
                        , vector_size(mFiles)-1, size, cur_page, max_page);
            }
        }
    }
    
    //////////////////////////////////////////////////////////////////////////
    // １画面５行
    //////////////////////////////////////////////////////////////////////////
    else if(cDirWnd::gViewOption == kOneDir5) {
        if(mActive) {
            mbox(dstack_exist, 0, maxx-1, maxy-2-dstack_exist-gViewHookLineNum-jobs_exist);

            char path[PATH_MAX];

            VALUE path_original;
            if(gLDir == this)
                path_original = rb_gv_get("view_path_ldir");
            else
                path_original = rb_gv_get("view_path_rdir");

            if(path_original == Qnil) {
                strcpy(path, mPath);
                strcat(path, mMask);
            }
            else {
                strcpy(path, RSTRING(path_original)->ptr);
            }

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
            char tmp[PATH_MAX];
            if(kanji_convert(path, tmp, PATH_MAX, gKanjiCodeFileName, gKanjiCode) != -1) {
                strcpy(path, tmp);
            }
#endif

            const int len = strlen(path);
            if(len < maxx-4) {
                mattron(kCABold);
                mmvprintw(0 + dstack_exist, 2, "%s", path);
                mattroff();
            }
            else {
                if(gKanjiCode == kUtf8) {
                    char buf[PATH_MAX];

                    str_cut3(path, maxx-4, buf, PATH_MAX);

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
                else {
                    bool kanji[PATH_MAX];
                    for(int i=0; i<len; i++) {
                        if(is_kanji(path[i])) {
                            kanji[i] = true;
                            i++;
                            kanji[i] = false;
                        }
                        else {
                            kanji[i] = false;
                        }
                    }

                    char buf[PATH_MAX];
                    if(kanji[len-(maxx-4)-1]) {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                        buf[0] = ' ';
                    }
                    else {
                        int i;
                        for(i=len-(maxx-4); i<len; i++) {
                            buf[i-len+(maxx-4)] = path[i];
                        }
                        buf[i-len+(maxx-4)] = 0;
                    }

                    mattron(kCABold);
                    mmvprintw(0 + dstack_exist, 2, "%s", buf);
                    mattroff();
                }
            }

            for(int i=mScrollTop;
                i-mScrollTop<(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)*5
                            && i<vector_size(mFiles);
                i++)
            {
                int attr = 0;
                sFile* file = (sFile*)vector_item(mFiles, i);
                
                if(gColor) {
                    char tmp[PATH_MAX];

                    if(this == gLDir) {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(0, %d) then color = item[1]; break; end end; color", i);
                    }
                    else {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(1, %d) then color = item[1]; break; end end; color", i);
                    }

                    int error;
                    VALUE color = rb_eval_string_protect(tmp, &error);

                    attr = NUM2INT(color);
                }

                if(mCursor == i && mActive) {
                     attr |= kCAReverse;
                }
        
                if(S_ISDIR(file->mStat.st_mode)) {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorDir;
                     }
                     else {
                         if(gBoldDir) attr |= kCABold;
                     }
                }
                else if(gExecutiveFileBold
                         &&(file->mStat.st_mode&S_IXUSR
                            || file->mStat.st_mode&S_IXGRP
                            || file->mStat.st_mode&S_IXGRP))
                {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorExe;
                     }
                     else {
                         if(gBoldExe) attr |= kCABold;
                     }
                }
                else if(S_ISLNK(file->mLStat.st_mode)) {
                    if(gColor && !file->mMark) attr |= gColorLink;
                }

                char buf[1024];
                make_file_stat(file, buf);

                int name_len;
                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    name_len = maxx/5-2-2-strlen(buf);
                }
                else {
                    name_len = maxx/5-2-5-2-strlen(buf);
                }

                char fname[1024];
                char* ext;
                char dot;
                make_file_name(file, fname, &ext, &dot, name_len);

                if(file->mMark) {
                    if(gColor)
                        attr |= gColorMark;
                    else
                        attr != kCABold;
                }

                mattron(attr);

                const int x = (i-mScrollTop)
                                /(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                *(maxx/5) + 1;
                const int y = (i-mScrollTop)
                                %(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist)
                                    + 1 + dstack_exist;
                
                if(file->mMark) {
                    mmvprintw(y, x, "*");
                }
                else {
                    mmvprintw(y, x, " ");
                }

                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    mmvprintw(y, x+1, "%s%s", fname,buf);
                }
                else {
                    mmvprintw(y, x+1, "%s%c%-4s%s", fname, dot, ext,buf);
                }
                FREE(ext);
                
                mattroff();
            }

            char size[256];
            MakeSizeStr2(size, MarkFileSize());

            if(gOptionPageViewWay == Qtrue) {
                const int p = (((float)mCursor+1)/((float)vector_size(mFiles)))*100;
                
                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%3d%%)", MarkFileNum(), vector_size(mFiles)-1, size, p);
            }
            else {
                const int cur_page = mCursor/((maxy-5)*5) + 1;
                const int max_page = vector_size(mFiles)/((maxy-5)*5) + 1;

                mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, 2
                        , "(%d/%d)-%sbytes-(%d/%d)", MarkFileNum()
                        , vector_size(mFiles)-1, size, cur_page, max_page);
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////
    // ２画面
    //////////////////////////////////////////////////////////////////////////
    else {
        int x;
        if(this == gLDir)
            x = 0;
        else
            x = maxx / 2; 

        int line = 0;
        mbox(dstack_exist, x, maxx/2-1, maxy-2-dstack_exist-gViewHookLineNum-jobs_exist);

        char path[PATH_MAX];
        VALUE path_original;
        if(gLDir == this)
            path_original = rb_gv_get("view_path_ldir");
        else
            path_original = rb_gv_get("view_path_rdir");

        if(path_original == Qnil) {
            strcpy(path, mPath);
            strcat(path, mMask);
        }
        else {
            strcpy(path, RSTRING(path_original)->ptr);
        }

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
        char tmp[PATH_MAX];
        if(kanji_convert(path, tmp, PATH_MAX, gKanjiCodeFileName, gKanjiCode) != -1) {
            strcpy(path, tmp);
        }
#endif

        const int len = strlen(path);
        if(len < maxx/2-5) {
            if(mActive) mattron(kCABold);
            mmvprintw(0 + dstack_exist, x+2, "%s", path);
            if(mActive) mattroff();
        }
        else {
            if(gKanjiCode == kUtf8) {
                char buf[PATH_MAX];

                str_cut3(path, maxx/2-5, buf, PATH_MAX);

                if(mActive) mattron(kCABold);
                mmvprintw(0 + dstack_exist, x+2, "%s", buf);
                if(mActive) mattroff();
            }
            else {
                bool kanji[PATH_MAX];
                for(int i=0; i<len; i++) {
                    if(is_kanji(path[i])) {
                        kanji[i] = true;
                        i++;
                        kanji[i] = false;
                    }
                    else {
                        kanji[i] = false;
                    }
                }

                char buf[PATH_MAX];
                if(kanji[len-(maxx/2-5)-1]) {
                    int i;
                    for(i=len-(maxx/2-5); i<len; i++) {
                        buf[i-len+(maxx/2-5)] = path[i];
                    }
                    buf[i-len+(maxx/2-5)] = 0;
                    buf[0] = ' ';
                }
                else {
                    int i;
                    for(i=len-(maxx/2-5); i<len; i++) {
                        buf[i-len+(maxx/2-5)] = path[i];
                    }
                    buf[i-len+(maxx/2-5)] = 0;
                }

                if(mActive) mattron(kCABold);
                mmvprintw(0 + dstack_exist, x+2, "%s", buf);
                if(mActive) mattroff();
            }
        }


        for(int i=mScrollTop;
                i-mScrollTop<maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist
                        && i<vector_size(mFiles);
                i++)
            {
                int attr = 0;
                sFile* file = (sFile*)vector_item(mFiles, i);
                
                if(gColor) {
                    char tmp[PATH_MAX];

                    if(this == gLDir) {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(0, %d) then color = item[1]; break; end end; color", i);
                    }
                    else {
                        sprintf(tmp, "color = 0; $file_color.each do |item| if item[0] =~ file_name(1, %d) then color = item[1]; break; end end; color", i);
                    }

                    int error;
                    VALUE color = rb_eval_string_protect(tmp, &error);

                    attr = NUM2INT(color);
                }

                if(mCursor == i && mActive) {
                     attr |= kCAReverse;
                }
        
                if(S_ISDIR(file->mStat.st_mode)) {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorDir;
                     }
                     else {
                         if(gBoldDir) attr |= kCABold;
                     }
                }
                else if(gExecutiveFileBold
                         &&(file->mStat.st_mode&S_IXUSR
                            || file->mStat.st_mode&S_IXGRP
                            || file->mStat.st_mode&S_IXGRP))
                {
                     if(gColor) {
                         if(!file->mMark) attr |= gColorExe;
                     }
                     else {
                         if(gBoldExe) attr |= kCABold;
                     }
                }
                else if(S_ISLNK(file->mLStat.st_mode)) {
                    if(gColor && !file->mMark) attr |= gColorLink;
                }

                char buf[1024];
                make_file_stat(file, buf);

                int name_len;
                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    name_len = maxx/2-2-2-strlen(buf);
                }
                else {
                    name_len = maxx/2-2-5-2-strlen(buf);
                }

                char fname[1024];
                char* ext;
                char dot;
                make_file_name(file, fname, &ext, &dot, name_len);

                if(file->mMark) {
                    if(gColor)
                        attr |= gColorMark;
                    else
                        attr != kCABold;
                }
                
                mattron(attr);

                if(file->mMark) {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, x+1, "*");
                }
                else {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, x+1, " ");
                }

                if(S_ISDIR(file->mStat.st_mode) || !gViewFnameDivideExt) {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, x+2, "%s%s", fname,buf);
                }
                else {
                    mmvprintw(i-mScrollTop + 1 + dstack_exist, x+2, "%s%c%-4s%s", fname, dot, ext,buf);
                }
                FREE(ext);
                
                mattroff();
        }

        char size[256];
        MakeSizeStr2(size, MarkFileSize());
        
        mmvprintw(maxy - kMaxYMinus+1-gViewHookLineNum-jobs_exist, x + 2
                    , "(%d/%d)-%sbytes", MarkFileNum(), vector_size(mFiles)-1, size);
        
        if(mActive) {
            if(gOptionPageViewWay == Qtrue) {
                const int p = (((float)mCursor+1)/((float)vector_size(mFiles)))*100;
                mprintw("-(%3d%%)", p);
            }
            else {
                const int cur_page = mCursor/(maxy-5) + 1;
                const int max_page = vector_size(mFiles)/(maxy-5) + 1;

                mprintw("-(%d/%d)", cur_page, max_page);
            }
        }
    }

    /// draw gDirStack ///
    if(dstack_exist) {
        const int width = maxx / 5;
        int j = 0;
        for(int i=0; i<vector_size(gDirStack); i++) {
            char* item = (char*)vector_item(gDirStack, i);
            
            char item2[256];
            strcpy(item2, "");
            const int len2 = strlen(item);
            for(int k=len2-2; k>=0; k--) {
                if(item[k] == '/') {
                    int l;
                    for(l=k+1; l<len2-1; l++) {
                        item2[l-k-1] = item[l];
                    }
                    item2[l-k-1] = 0;
                    break;
                }
            }
            
            if(j > 4) break;
           /* 
            char buf[256];
            buf[0] = '[';
            buf[1] = '%';
            sprintf(buf + 2, "-%ds]", width-2);

            char buf2[256];
            if(gKanjiCode == kUtf8)
                str_cut2(item2, width-2, buf2, 256);
            else
                cut(item2, buf2, width-2);
*/
            char buf2[256];
            
            if(gKanjiCode == kUtf8)
                str_cut2(item2, width-6, buf2, 256);
            else
                cut(item2, buf2, width-6);
            
            char buf[256];
            sprintf(buf, "[%d.%s]", j+1, buf2);

            mmvprintw(0, width * j, "%s", buf);
            j++;                        
        }
    }

 
}
