/* $Id: menu.c,v 1.3 2002/03/17 09:18:23 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <string.h>
#include "config.h"
#include "pttstruct.h"
#include "common.h"
#include "perm.h"
#include "modes.h"
#include "proto.h"
extern int usernum;
extern int talkrequest;
extern char *fn_register;
extern char currboard[];        /* name of currently selected board */
extern int currmode;
extern unsigned int currstat;
extern char reset_color[];
extern userinfo_t *currutmp;
extern char *BBSName;
extern int b_lines;             /* Screen bottom line number: t_lines-1 */

/* help & menu processring */
static int refscreen = NA;
extern char *boardprefix;
extern struct utmpfile_t *utmpshm;

int egetch() {
    int rval;

    while(1) {
        rval = igetkey();
        if(talkrequest) {
            talkreply();
            refscreen = YEA;
            return rval;
        }
        if(rval != Ctrl('L'))
            return rval;
        redoscr();
    }
}

extern userec_t cuser;
extern char *fn_board;
extern char board_hidden_status;

void showtitle(char *title, char *mid) {
    char    buf[40], numreg[50];
    int     nreg, spc = 0, pad, bid;
    boardheader_t   bh;
    static  char    lastboard[16] = {0};

    spc = strlen(mid);
    if(title[0] == 0)
        title++;
    else if(currutmp->mailalert) {
        mid = "\033[41;5m   �l�t�ӫ��a�o   " TITLE_COLOR;
        spc = 22;
    } else if(HAS_PERM(PERM_SYSOP) && (nreg = dashs(fn_register)/163) > 10) {
	sprintf(numreg, "\033[41;5m  ��%03d/%03d���f��  " TITLE_COLOR,
		nreg,
		(int)dashs("register.new.tmp") / 163);
        mid = numreg;
        spc = 22;
    }
    spc = 66 - strlen(title) - spc - strlen(currboard);
    if(spc < 0)
        spc = 0;
    pad = 1 - (spc & 1);
    memset(buf, ' ', spc >>= 1);
    buf[spc] = '\0';
    
    clear();
    prints(TITLE_COLOR "�i%s�j%s\033[33m%s%s%s\033[3%s�m",
           title, buf, mid, buf, " " + pad,
           currmode & MODE_SELECT ? "6m�t�C" : currmode & MODE_ETC ? "5m��L" :
           currmode & MODE_DIGEST ? "2m��K" : "7m�ݪO");

    if( strcmp(currboard, lastboard) ){ /* change board */
	if( currboard[0] != 0 &&
	    (bid = getbnum(currboard)) > 0 &&
	    (get_record(fn_board, &bh, sizeof(bh), bid) != -1) ){
	    board_hidden_status = ((bh.brdattr & BRD_HIDE) &&
				   (bh.brdattr & BRD_POSTMASK));
	    strncpy(lastboard, currboard, sizeof(lastboard));
	}
    }
    
    if( board_hidden_status )
	prints("\033[32m%s", currboard);
    else
	prints("%s", currboard);
    prints("\033[3%dm�n\033[0m\n", currmode & MODE_SELECT ? 6 :
	   currmode & MODE_ETC ? 5 : currmode & MODE_DIGEST ? 2 : 7);
}

/* �ʵe�B�z */
#define FILMROW 11
static unsigned char menu_row = 12;
static unsigned char menu_column = 20;
static char mystatus[160];

static int u_movie() {
    cuser.uflag ^= MOVIE_FLAG;
    return 0;
}

void movie(int i) {
    extern struct pttcache_t *ptt;
    static short history[MAX_HISTORY];
    static char myweek[] = "�Ѥ@�G�T�|����";
    const char *msgs[] = {"����", "���}", "�ޱ�", "����","�n��"};
    time_t now = time(NULL);
    struct tm *ptime = localtime(&now);

    if((currstat != CLASS) && (cuser.uflag & MOVIE_FLAG) &&
       !ptt->busystate && ptt->max_film > 0) {
        if(currstat == PSALE) {
            i = PSALE;
            reload_money();
        } else {
            do {
                if(!i)
                    i = 1 + (int)(((float)ptt->max_film *
                                   rand()) / (RAND_MAX + 1.0));

                for(now = ptt->max_history; now >= 0; now--)
                    if(i == history[now]) {
                        i = 0;
                        break;
                    }
            } while(i == 0);
        }

        memcpy(history, &history[1], ptt->max_history * sizeof(short));
        history[ptt->max_history] = now = i;

        if(i == 999)       /* Goodbye my friend */
            i = 0;

        move(1, 0);
        clrtoline(1 + FILMROW); /* �M���W���� */
        Jaky_outs(ptt->notes[i], 11); /* �u�L11��N�n */
        outs(reset_color);
    }
    i = ptime->tm_wday << 1;
    sprintf(mystatus, "\033[34;46m[%d/%d �P��%c%c %d:%02d]\033[1;33;45m%-14s"
            "\033[30;47m �ثe�{�̦� \033[31m%d\033[30m�H, �ڬO\033[31m%-12s"
            "\033[30m[����]\033[31m%s\033[0m",
            ptime->tm_mon + 1, ptime->tm_mday, myweek[i], myweek[i + 1],
            ptime->tm_hour, ptime->tm_min, currutmp->birth ?
            "�ͤ�n�Ыȭ�" : ptt->today_is,
            utmpshm->number, cuser.userid, msgs[currutmp->pager]);
    outmsg(mystatus);
    refresh();
}

static int show_menu(commands_t *p) {
    register int n = 0;
    register char *s;
    const char *state[4]={"�Υ\\��", "�w�h��", "�۩w��", "SHUTUP"};
    char buf[80];

    movie(currstat);

    move(menu_row, 0);
    while((s = p[n].desc)) {
        if(HAS_PERM(p[n].level)) {
            sprintf(buf, s + 2, state[cuser.proverb % 4]);
            prints("%*s  (\033[1;36m%c\033[0m)%s\n", menu_column, "", s[1],
                   buf);
        }
        n++;
    }
    return n - 1;
}

void domenu(int cmdmode, char *cmdtitle, int cmd, commands_t cmdtable[]) {
    int lastcmdptr;
    int n, pos, total, i;
    int err;
    int chkmailbox();
    static char cmd0[LOGIN];

    if(cmd0[cmdmode])
        cmd = cmd0[cmdmode];

    setutmpmode(cmdmode);

    showtitle(cmdtitle, BBSName);

    total = show_menu(cmdtable);

    outmsg(mystatus);
    lastcmdptr = pos = 0;

    do {
        i = -1;
        switch(cmd) {
        case Ctrl('C'):
            cal();
            i = lastcmdptr;
            refscreen = YEA;
            break;
        case Ctrl('I'):
            t_idle();
            refscreen = YEA;
            i = lastcmdptr;
            break;
        case Ctrl('N'):
            New();
            refscreen = YEA;
            i = lastcmdptr;
            break;
        case Ctrl('A'):
            if(mail_man() == FULLUPDATE)
                refscreen = YEA;
            i = lastcmdptr;
            break;
        case KEY_DOWN:
            i = lastcmdptr;
        case KEY_HOME:
        case KEY_PGUP:
            do {
                if(++i > total)
                    i = 0;
            } while(!HAS_PERM(cmdtable[i].level));
            break;
        case KEY_END:
        case KEY_PGDN:
            i = total;
            break;
        case KEY_UP:
            i = lastcmdptr;
            do {
                if(--i < 0)
                    i = total;
            } while(!HAS_PERM(cmdtable[i].level));
            break;
        case KEY_LEFT:
        case 'e':
        case 'E':
            if(cmdmode == MMENU)
                cmd = 'G';
            else if((cmdmode == MAIL) && chkmailbox())
                cmd = 'R';
            else
                return;
        default:
            if((cmd == 's'  || cmd == 'r') &&
               (currstat == MMENU || currstat == TMENU || currstat == XMENU)) {
                if(cmd == 's')
                    ReadSelect();
                else
                    Read();
                refscreen = YEA;
                i = lastcmdptr;
                break;
            }

            if(cmd == '\n' || cmd == '\r' || cmd == KEY_RIGHT) {
                move(b_lines, 0);
                clrtoeol();

                currstat = XMODE;

                if((err = (*cmdtable[lastcmdptr].cmdfunc) ()) == QUIT)
                    return;
                currutmp->mode = currstat = cmdmode;

                if(err == XEASY) {
                    refresh();
                    safe_sleep(1);
                } else if(err != XEASY + 1 || err == FULLUPDATE)
                    refscreen = YEA;

                if(err != -1)
                    cmd = cmdtable[lastcmdptr].desc[0];
                else
                    cmd = cmdtable[lastcmdptr].desc[1];
                cmd0[cmdmode] = cmdtable[lastcmdptr].desc[0];
            }

            if(cmd >= 'a' && cmd <= 'z')
                cmd &= ~0x20;
            while(++i <= total)
                if(cmdtable[i].desc[1] == cmd)
                    break;
        }

        if(i > total || !HAS_PERM(cmdtable[i].level))
            continue;

        if(refscreen) {
            showtitle(cmdtitle, BBSName);

            show_menu(cmdtable);

            outmsg(mystatus);
            refscreen = NA;
        }
        cursor_clear(menu_row + pos, menu_column);
        n = pos = -1;
        while(++n <= (lastcmdptr = i))
            if(HAS_PERM(cmdtable[n].level))
                pos++;

        cursor_show(menu_row + pos, menu_column);
    } while(((cmd = egetch()) != EOF) || refscreen);

    abort_bbs(0);
}
/* INDENT OFF */

/* administrator's maintain menu */
static commands_t adminlist[] = {
    {m_user, PERM_ACCOUNTS,           "UUser          �ϥΪ̸��"},
    {search_user_bypwd, PERM_SYSOP,   "SSearch User   �S���j�M�ϥΪ�"},
    {search_user_bybakpwd,PERM_SYSOP, "OOld User data �d�\\�ƥ��ϥΪ̸��"},
    {m_board, PERM_SYSOP,             "BBoard         �]�w�ݪO"},
    {m_register, PERM_SYSOP,          "RRegister      �f�ֵ��U����"},
    {cat_register, PERM_SYSOP,        "CCatregister   �L�k�f�֮ɥΪ�"},
    {x_file, PERM_SYSOP|PERM_VIEWSYSOP,     "XXfile         �s��t���ɮ�"},
    {give_money, PERM_SYSOP|PERM_VIEWSYSOP, "GGivemoney     ���]��"},
#ifdef  HAVE_MAILCLEAN
    {m_mclean, PERM_SYSOP,            "MMail Clean    �M�z�ϥΪ̭ӤH�H�c"},
#endif
#ifdef  HAVE_REPORT
    {m_trace, PERM_SYSOP,             "TTrace         �]�w�O�_�O��������T"},
#endif
    {NULL, 0, NULL}
};

/* mail menu */
static commands_t maillist[] = {
    {m_new, PERM_READMAIL,      "RNew           �\\Ū�s�i�l��"},
    {m_read, PERM_READMAIL,     "RRead          �h�\\��Ū�H���"},
    {m_send, PERM_BASIC,        "RSend          �����H�H"},
    {main_bbcall, PERM_LOGINOK, "BBBcall        \033[1;31m�q�ܯ���\033[m"},
    {x_love, PERM_LOGINOK,      "PPaper         \033[1;32m���Ѳ��;�\033[m "},
    {mail_list, PERM_BASIC,     "RMail List     �s�ձH�H"},
    {setforward, PERM_LOGINOK,"FForward       \033[32m�]�w�H�c�۰���H\033[m"},
    {m_sysop, 0,                "YYes, sir!     �ԴA����"},
    {m_internet, PERM_INTERNET, "RInternet      �H�H�� Internet"},
    {mail_mbox, PERM_INTERNET,  "RZip UserHome  ��Ҧ��p�H��ƥ��]�^�h"},
    {built_mail_index, PERM_LOGINOK, "SSavemail      ��H��Ϧ^��"},
    {mail_all, PERM_SYSOP,      "RAll           �H�H���Ҧ��ϥΪ�"},
    {NULL, 0, NULL}
};

/* Talk menu */
static commands_t talklist[] = {
    {t_users, 0,            "UUsers         ������Ѥ�U"},
    {t_pager, PERM_BASIC,   "PPager         �����I�s��"},
    {t_idle, 0,             "IIdle          �o�b"},
    {t_query, 0,            "QQuery         �d�ߺ���"},
    {t_qchicken, 0,         "WWatch Pet     �d���d��"},
    {t_talk, PERM_PAGE,     "TTalk          ��H���"},
    {t_chat, PERM_CHAT,     "CChat          ��a���{����h"},
#ifdef HAVE_MUD
    {x_mud, 0,              "VVrChat        \033[1;32m������~��Ѽs��\033[m"},
#endif
    {t_display, 0,          "DDisplay       ��ܤW�X�����T"},
    {NULL, 0, NULL}
};

/* name menu */
static int t_aloha() {
    friend_edit(FRIEND_ALOHA);
    return 0;
}

static int t_special() {
    friend_edit(FRIEND_SPECIAL);
    return 0;
}

static commands_t namelist[] = {
    {t_override, PERM_LOGINOK,"OOverRide      �n�ͦW��"},
    {t_reject, PERM_LOGINOK,  "BBlack         �a�H�W��"},
    {t_aloha,PERM_LOGINOK,    "AALOHA         �W���q���W��"},
#ifdef POSTNOTIFY
    {t_post,PERM_LOGINOK,     "NNewPost       �s�峹�q���W��"},
#endif
    {t_special,PERM_LOGINOK,  "SSpecial       ��L�S�O�W��"},
    {NULL, 0, NULL}
};

/* User menu */
static commands_t userlist[] = {
    {u_info, PERM_LOGINOK,          "IInfo          �]�w�ӤH��ƻP�K�X"},
    {calendar, PERM_LOGINOK,          "CCalendar      �ӤH��ƾ�"},
    {u_editcalendar, PERM_LOGINOK,    "CCalendarEdit  �s��ӤH��ƾ�"},
    {u_loginview, PERM_LOGINOK,     "LLogin View    ��ܶi���e��"},
    {u_ansi, 0, "AANSI          ���� ANSI \033[36m�m\033[35m��\033[37m/"
     "\033[30;47m��\033[1;37m��\033[m�ҥ�"},
    {u_movie, 0,                    "MMovie         �����ʵe�ҥ�"},
#ifdef  HAVE_SUICIDE
    {u_kill, PERM_BASIC,            "IKill          �۱��I�I"},
#endif
    {u_editplan, PERM_LOGINOK,      "QQueryEdit     �s��W����"},
    {u_editsig, PERM_LOGINOK,       "SSignature     �s��ñ�W��"},
#if HAVE_FREECLOAK
    {u_cloak, PERM_LOGINOK,           "CCloak         �����N"},
#else
    {u_cloak, PERM_CLOAK,           "CCloak         �����N"},
#endif
    {u_register, PERM_BASIC,        "RRegister      ��g�m���U�ӽг�n"},
    {u_list, PERM_SYSOP,            "UUsers         �C�X���U�W��"},
    {NULL, 0, NULL}
};

/* XYZ tool menu */
static commands_t xyzlist[] = {
#ifdef  HAVE_LICENSE
    {x_gpl, 0,       "LLicense       GNU �ϥΰ���"},
#endif
#ifdef HAVE_INFO
    {x_program, 0,   "PProgram       ���{���������P���v�ŧi"},
#endif
    {x_boardman,0,   "MMan Boards    �m�ݪ���ذϱƦ�]�n"},
//  {x_boards,0,     "HHot Boards    �m�ݪ��H��Ʀ�]�n"},
    {x_history, 0,   "HHistory       �m�ڭ̪������n"},
    {x_note, 0,      "NNote          �m�IJ��W���y�����n"},
    {x_login,0,      "SSystem        �m�t���n���i�n"},
    {x_week, 0,      "WWeek          �m���g���Q�j�������D�n"},
    {x_issue, 0,     "IIssue         �m����Q�j�������D�n"},
    {x_today, 0,     "TToday         �m����W�u�H���έp�n"},
    {x_yesterday, 0, "YYesterday     �m�Q��W�u�H���έp�n"},
    {x_user100 ,0,   "UUsers         �m�ϥΪ̦ʤj�Ʀ�]�n"},
    {x_birth, 0,     "BBirthday      �m����جP�j�[�n"},
    {p_sysinfo, 0,   "XXload         �m�d�ݨt�έt���n"},
    {NULL, 0, NULL}
};

/* Ptt money menu */
static commands_t moneylist[] = {
    {p_give, 0,         "00Give        ����L�H��"},
    {save_violatelaw, 0,"11ViolateLaw  ú�@��"},
#if !HAVE_FREECLOAK
    {p_cloak, 0,        "22Cloak       ���� ����/�{��   $19  /��"},
#endif
    {p_from, 0,         "33From        �Ȯɭק�G�m     $49  /��"},
    {ordersong,0,       "44OSong       �ڮ�ʺA�I�q��   $200 /��"},
    {p_exmail, 0,       "55Exmail      �ʶR�H�c         $1000/��"},
    {NULL, 0, NULL}
};

static int p_money() {
    domenu(PSALE, "��tt�q�c��", '0', moneylist);
    return 0;
};

static commands_t jceelist[] = {
    {x_90,PERM_LOGINOK,	     "0090 JCEE     �i90�Ǧ~�פj���p�۬d�]�t�Ρj"},
    {x_89,PERM_LOGINOK,	     "1189 JCEE     �i89�Ǧ~�פj���p�۬d�]�t�Ρj"},
    {x_88,PERM_LOGINOK,      "2288 JCEE     �i88�Ǧ~�פj���p�۬d�]�t�Ρj"},
    {x_87,PERM_LOGINOK,      "3387 JCEE     �i87�Ǧ~�פj���p�۬d�]�t�Ρj"},
    {x_86,PERM_LOGINOK,      "4486 JCEE     �i86�Ǧ~�פj���p�۬d�]�t�Ρj"},
    {NULL, 0, NULL}
};

static int m_jcee() {
    domenu(JCEE, "��tt�d�]�t��", '0', jceelist);
    return 0;
}

static int forsearch();
static int playground();

/* Ptt Play menu */
static commands_t playlist[] = {
#if HAVE_JCEE
    {m_jcee, PERM_LOGINOK,   "JJCEE        �i �j���p�Ҭd�]�t�� �j"},
#endif
    {note, PERM_LOGINOK,     "NNote        �i ���y���� �j"},
    {x_weather,0 ,           "WWeather     �i ��H�w�� �j"},
    {x_stock,0 ,             "SStock       �i �ѥ��污 �j"},
#ifdef HAVE_BIG2
    {x_big2, 0,              "BBig2        �i �����j�ѤG �j"},
#endif
#ifdef HAVE_MJ
    {x_mj, PERM_LOGINOK,     "QQkmj        �i �������±N �j"},
#endif
#ifdef  HAVE_BRIDGE
    {x_bridge, PERM_LOGINOK, "OOkBridge    �i ���P�v�� �j"},
#endif
#ifdef HAVE_GOPHER
    {x_gopher, PERM_LOGINOK, "GGopher      �i �a����Ʈw �j"},
#endif
#ifdef HAVE_TIN
    {x_tin, PERM_LOGINOK,    "NNEWS        �i ���ڷs�D �j"},
#endif
#ifdef BBSDOORS
    {x_bbsnet, PERM_LOGINOK, "BBBSNet      �i ��L BBS�� �j"},
#endif
#ifdef HAVE_WWW
    {x_www, PERM_LOGINOK,    "WWWW Browser �i �L�L�L �j"},
#endif
    {forsearch,PERM_LOGINOK, "SSearchEngine�i\033[1;35m ��tt�j�M�� \033[m�j"},
    {topsong,PERM_LOGINOK,   "TTop Songs   �i\033[1;32m�ڮ��I�q�Ʀ�]\033[m�j"},
    {p_money,PERM_LOGINOK,   "PPay         �i\033[1;31m ��tt�q�c�� \033[m�j"},
    {chicken_main,PERM_LOGINOK, "CChicken     "
     "�i\033[1;34m ��tt�i���� \033[m�j"},
    {playground,PERM_LOGINOK, "AAmusement   �i\033[1;33m ��tt�C�ֳ� \033[m�j"},
    {NULL, 0, NULL}
};

static commands_t plist[] = {

/*    {p_ticket_main, PERM_LOGINOK,"00Pre         �i �`�ξ� �j"},
      {alive, PERM_LOGINOK,        "00Alive       �i  �q����  �j"},
*/
    {ticket_main, PERM_LOGINOK,  "11Gamble      �i ��tt��� �j"},
    {guess_main, PERM_LOGINOK,   "22Guess number�i �q�Ʀr   �j"},
    {othello_main, PERM_LOGINOK, "33Othello     �i �¥մ�   �j"},
//    {dice_main, PERM_LOGINOK,    "44Dice        �i ����l   �j"},
    {vice_main, PERM_LOGINOK,    "44Vice        �i �o����� �j"},
    {g_card_jack, PERM_LOGINOK,  "55Jack        �i �³ǧJ �j"},
    {g_ten_helf, PERM_LOGINOK,   "66Tenhalf     �i �Q�I�b �j"},
    {card_99, PERM_LOGINOK,      "77Nine        �i �E�Q�E �j"},
    {NULL, 0, NULL}
};

static int playground() {
    domenu(AMUSE, "��tt�C�ֳ�",'1',plist);
    return 0;
}

static commands_t slist[] = {
    {x_dict,0,                   "11Dictionary  "
     "�i\033[1;33m ����j�r�� \033[m�j"},
    {main_railway, PERM_LOGINOK,  "33Railway     "
     "�i\033[1;32m �������d�� \033[m�j"},
    {NULL, 0, NULL}
};

static int forsearch() {
    domenu(SREG, "��tt�j�M��", '1', slist);
    return 0;
}

/* main menu */

static int admin() {
    domenu(ADMIN, "�t��@", 'X', adminlist);
    return 0;
}

static int Mail() {
    domenu(MAIL, "�q�l�l��", 'R', maillist);
    return 0;
}

static int Talk() {
    domenu(TMENU, "��ѻ���", 'U', talklist);
    return 0;
}

static int User() {
    domenu(UMENU, "�ӤH�]�w", 'A', userlist);
    return 0;
}

static int Xyz() {
    domenu(XMENU, "�u��{��", 'M', xyzlist);
    return 0;
}

static int Play_Play() {
    domenu(PMENU, "�����C�ֳ�", 'A', playlist);
    return 0;
}

static int Name_Menu() {
    domenu(NMENU, "�զ⮣��", 'O', namelist);
    return 0;
}

commands_t cmdlist[] = {
    {admin,PERM_SYSOP|PERM_VIEWSYSOP, "00Admin       �i �t��@�� �j"},
    {Announce, 0,                     "AAnnounce     �i ��ؤ��G�� �j"},
    {Boards, 0,                       "FFavorite     �i �� �� �̷R �j"},
    {root_board, 0,                   "CClass        �i ���հQ�װ� �j"},
    {Mail, PERM_BASIC,                "MMail         �i �p�H�H��� �j"},
    {Talk, 0,                         "TTalk         �i �𶢲�Ѱ� �j"},
    {User, 0,                         "UUser         �i �ӤH�]�w�� �j"},
    {Xyz, 0,                          "XXyz          �i �t�Τu��� �j"},
    {Play_Play,0,                     "PPlay         �i �C�ֳ�/�j�Ǭd�]�j"},
    {Name_Menu,PERM_LOGINOK,          "NNamelist     �i �s�S�O�W�� �j"},
    {Goodbye, 0,                      "GGoodbye       ���}�A�A���K�K"},
    {NULL, 0, NULL}
};