/* $Cambridge: hermes/src/prayer/cmd/cmd.c,v 1.3 2008/09/16 09:59:55 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2008 */
/* See the file NOTICE for conditions of use and distribution. */

#include "prayer_session.h"

#include "cmd.h"

static struct cmd session_cmds[] = {
    {"abook_add", cmd_abook_add},
    {"abook_compose", cmd_abook_compose},
    {"abook_compose2", cmd_abook_compose2},
    {"abook_export", cmd_abook_export},
    {"abook_import", cmd_abook_import},
    {"abook_list", cmd_abook_list},
    {"abook_lookup", cmd_abook_lookup},
    {"abook_lookup_add", cmd_abook_lookup_add},
    {"abook_save", cmd_abook_save},
    {"abook_search", cmd_abook_search},
    {"abook_sort", cmd_abook_sort},
    {"abook_take", cmd_abook_take},
    {"abook_update", cmd_abook_update},
    {"abook_xfer", cmd_abook_xfer},
    {"action_stub", cmd_action_stub},
    {"add_address", cmd_add_address},
    {"aggregate", cmd_aggregate},
    {"aggregate_tmp", cmd_aggregate_tmp},
    {"attachments", cmd_attachments},
    {"block", cmd_block},
    {"change", cmd_change},
    {"check_cookie", cmd_check_cookie},
    {"checkpoint", cmd_checkpoint},
    {"compose", cmd_compose},
    {"compose1", cmd_compose1},
    {"copy", cmd_copy},
    {"copy_msg", cmd_copy_msg},
    {"create", cmd_create},
    {"delete", cmd_delete},
    {"detach", cmd_detach},
    {"dictionary", cmd_dictionary},
    {"dir_check", cmd_dir_check},
    {"disp_delete", cmd_disp_delete},
    {"disp_mark", cmd_disp_mark},
    {"disp_undelete", cmd_disp_undelete},
    {"disp_unmark", cmd_disp_unmark},
    {"display", cmd_display},
    {"download", cmd_download},
    {"download_xfer", cmd_download_xfer},
    {"error", cmd_error},
    {"exit", cmd_exit},
    {"expunge", cmd_expunge},
    {"expunge1", cmd_expunge1},
    {"favourites", cmd_favourites},
    {"filter", cmd_filter},
    {"filter_mbox", cmd_filter_mbox},
    {"filter_select", cmd_filter_select},
    {"folders", cmd_folders},
    {"forward", cmd_forward},
    {"forward1", cmd_forward1},
    {"fullname", cmd_fullname},
    {"hdrs", cmd_hdrs},
    {"help", cmd_help},
    {"include", cmd_include},
    {"init", cmd_init},
    {"list", cmd_list},
    {"list_sort", cmd_list_sort},
    {"logout", cmd_logout},
    {"manage", cmd_manage},
    {"mark", cmd_mark},
    {"passwd", cmd_passwd},
    {"preferred", cmd_preferred},
    {"prefs", cmd_prefs},
    {"printable", cmd_printable},
    {"quota", cmd_quota},
    {"rawdisplay", cmd_rawdisplay},
    {"redirect", cmd_redirect},
    {"rename", cmd_rename},
    {"rename_item", cmd_rename_item},
    {"reply", cmd_reply},
    {"reply1", cmd_reply1},
    {"reply2", cmd_reply2},
    {"restart", cmd_restart},
    {"resume", cmd_resume},
    {"rm", cmd_rm},
    {"rm1", cmd_rm1},
    {"roles_entry", cmd_roles_entry},
    {"roles_list", cmd_roles_list},
    {"search", cmd_search},
    {"send", cmd_send},
    {"sieve", cmd_sieve},
    {"sizes", cmd_sizes },
    {"spam", cmd_spam},
    {"spell", cmd_spell},
    {"subscribe", cmd_subscribe},
    {"transfer", cmd_transfer},
    {"undelete", cmd_undelete},
    {"unmark", cmd_unmark},
    {"unsubscribe", cmd_unsubscribe},
    {"upload_exit", cmd_upload_exit},
    {"upload_select", cmd_upload_select},
    {"upload_xfer", cmd_upload_xfer},
    {"vacation", cmd_vacation},
    {"vaclog", cmd_vaclog},
    {"welcome", cmd_welcome},
    {"zoom", cmd_zoom},
    {NIL, NIL}
};

static unsigned long session_cmd_count = 0L;
static unsigned long session_cmd_maxlen = 0L;

/* cmd_dispatch_init() ***************************************************
 *
 * Initialise dispatch tables.
 ************************************************************************/

void cmd_dispatch_init(void)
{
    struct cmd *cmd = session_cmds;
    unsigned long len;
    unsigned long maxlen = 0;

    session_cmd_count = 0;

    while (cmd[0].cmd && cmd[0].fn) {
        if ((len = strlen(cmd[0].cmd)) > maxlen)
            maxlen = len;

        if (cmd[1].cmd && cmd[1].fn) {
            if (strcmp(cmd[0].cmd, cmd[1].cmd) > 0)
                log_fatal("cmd.c: cmd array sorted incorrectly at %s\n",
                          cmd[0].cmd);
        }
        session_cmd_count++;
        cmd++;
    }

    session_cmd_maxlen = maxlen;
}

/* ====================================================================== */

/* cmd_dispatch() ********************************************************
 *
 * Dispatch a command
 *   session
 *      text: Command to dispatch
 ************************************************************************/

BOOL cmd_dispatch(struct session *session, char *text)
{
    struct cmd *cmd;
    unsigned long first, last, middle;
    int rc;

    cmd = session_cmds;
    first = 0;
    last = session_cmd_count;

    /* Binary chop */
    while (first < last) {
        middle = (first + last) / 2;
        rc = strcmp(cmd[middle].cmd, text);

        if (rc == 0) {
            /* Record command that we are about to run */
            (cmd[middle].fn) (session);
            session_record_last_cmd(session, text);
            return (T);
        }
        if (rc < 0)
            first = middle + 1;
        else
            last = middle;
    }
    /* Not found */
    return (NIL);
}
