#include "args.h"

#include "config.h"
/*
 * Copyright (c) 1986, 2014 by The Trustees of Columbia University in
 * the City of New York.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  + Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  + Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 *  + Neither the name of Columbia University nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 */

#ifndef lint
static const char *rcsid = "$Header: /usr/local/src/mm/mm-0.94/mm/RCS/browse.c,v 1.1 2005/05/28 22:27:50 beebe Exp $";
#endif

#include "mm.h"
#include "parse.h"
#include "cmds.h"

static int browse_body ARGS((void));
static int browse_copy ARGS((void));
static int browse_delete ARGS((void));
static int browse_dispatch ARGS((int c));
static int browse_flag ARGS((void));
static int browse_getchar ARGS((void));
static int browse_header ARGS((void));
static int browse_help ARGS((void));
static int browse_keyword ARGS((void));
static int browse_next ARGS((void));
static int browse_prev ARGS((void));
static int browse_quit ARGS((void));
static int browse_reply ARGS((void));
static int browse_switch ARGS((void));

extern int browse_pause, browse_clear_screen;

#define B_FORWARD 1
#define B_BACKWARD 2
#define B_STAY 3
#define B_QUIT 4
#define CS (cf->sequence)
#define PS (cf->prev_sequence)
#undef RS				/* HP-UX already defined this */
#define RS (cf->read_sequence)

#define CSfirst (sequence_first(CS))
#define CSlast (sequence_last(CS))
#define CSinverted (sequence_inverted(CS))
#define PSfirst (sequence_first(PS))
#define PSlast (sequence_last(PS))
#define PSinverted (sequence_inverted(PS))
#define RSfirst (sequence_first(RS))
#define RSlast (sequence_last(RS))
#define RSinverted (sequence_inverted(RS))

int browse_direction = B_FORWARD;

static struct browse_cmds {
    char cmd;
    int (*fctn)();
    const char *hlpstr;
} browse_cmds[] = {
    { ' ', browse_body, 	"see the next message" },
    { 'n', browse_next,		"go to next message" },
    { 'p', browse_prev,		"go to previous message" },
    { 'q', browse_quit,		"quit browsing" },
    { 's', browse_switch,	"switch direction of browsing" },
    { '?', browse_help,		"print this out" },
    { '\f', browse_header,	"redisplay the header" },
    { '\n', browse_body,	"see the message" },
    { 'c', browse_copy,		"copy to a file" },
    { 'r', browse_reply,	"reply to the message" },
    { 'd', browse_delete,	"delete this message" },
    { 'f', browse_flag,		"flag this message" },
    { 'k', browse_keyword,	"add a keyword to this message" },
    { '\0', nil, nil },
};

void
#if HAVE_STDC
cmd_browse(int n)
#else /* K&R style */
cmd_browse(n)
int n;
#endif /* HAVE_STDC */
{
    if (!check_cf (O_RDWR))
	return;

    if (!(mode & MM_READ)) {
	parse_sequence ("unseen", NULL, NULL);
	copy_sequence (cf->read_sequence, cf->sequence); /* XXX */
	check_mark();			/* can we mark things? */

	if (sequence_start (cf->read_sequence)) {
	    mode |= MM_BROWSE;
	}
    }
    else {
	confirm();
	mode |= MM_BROWSE;
    }
}
int
browse_message(VOID)
{
    int c;

    browse_header();
    c = browse_getchar();
    return(browse_dispatch(c));
}
static int
browse_header(VOID)
{
    message *m = &cf->msgs[cf->current];
    char *from = htext("from", m->text);
    char *subj = htext("subject",m->text);

    if (browse_clear_screen == SET_YES)
	cmcls();			/* clear the screen */
    else
	printf("\n");

    header_summary (cf->current, stdout, 1); /* 1 => browse format */

    printf("--%lu chars;  More?--", m->size);
    safe_free(from);
    safe_free(subj);
    return(B_STAY);
}
static int
browse_body(VOID)
{
    if (clear_screen)			/* user normally want this? */
	cmcls();
    else
	printf("\n");

    if (!display_message(stdout, &cf->msgs[cf->current], false,
			 only_type_headers, dont_type_headers) ||
	browse_pause == SET_YES)
    {
	if (browse_clear_screen == SET_YES) {
	    printf("---Hit any key to continue---");
	    browse_getchar();
	}
    }
    change_flag(cf->current, CMD_MARK);
    return(B_FORWARD);
}
static int
browse_next(VOID)
{
    return(B_FORWARD);
}
static int
browse_prev(VOID)
{
    return(B_BACKWARD);
}
static int
browse_switch(VOID)
{
    sequence_inverted(CS) = !sequence_inverted(CS);
    return(B_FORWARD);
}
static int
browse_quit(VOID)
{
    cmxputc('\n');
    return(B_QUIT);
}
static int
browse_help(VOID)
{
    int i;
    printf("\n");
    for(i = 0; browse_cmds[i].fctn != nil; i++) {
	if (browse_cmds[i].cmd < ' ' || browse_cmds[i].cmd == '\177')
	    printf("'^%c'", browse_cmds[i].cmd ^ 0100);
	else
	    printf(" '%c'", browse_cmds[i].cmd);
	printf(" -- %s\n", browse_cmds[i].hlpstr);
    }

    if (browse_clear_screen == SET_YES) {
	printf("---Hit any key to continue---");
	browse_getchar();
    }
    return(B_STAY);
}

static int
#if HAVE_STDC
browse_dispatch(int c)
#else /* K&R style */
browse_dispatch(c)
int c;
#endif /* HAVE_STDC */
{
    int ret = -1;
    int r,i;
    for(i = 0; browse_cmds[i].fctn != nil; i++)
	if (browse_cmds[i].cmd == c) {
	    ret = (*browse_cmds[i].fctn)();
	    break;
	}
    switch(ret) {
    case B_STAY:
	break;
    case B_FORWARD:
	if (sequence_next(CS) == 0)
	    mode &= ~MM_BROWSE;
	break;
    case B_BACKWARD:
	sequence_inverted(CS) = !sequence_inverted(CS);
	r = sequence_next(CS);
	sequence_inverted(CS) = !sequence_inverted(CS);
	if (r == 0)
	    mode &= ~MM_BROWSE;
	break;
    case B_QUIT:
	mode &= ~MM_BROWSE;
	break;
    default:
	fflush(cmcsb._cmoj);
	fprintf(stderr,"\n\007Invalid command\n");
	printf("--%lu chars;  More?--", cf->msgs[cf->current].size);
	return(browse_dispatch(browse_getchar()));
    }
    return (0);
}
static int
browse_copy(VOID)
{
    int doprev = false;

    cmseteof();
    if (cmseter ()) {			/* errors return here */
	if (cmcsb._cmerr == CMxEOF) {
	    return CMxEOF;
	}
	else
	    doprev = true;
    }

    prompt("Copy to: ");
    if (doprev) {
	doprev = false;
	prevcmd();
    }
    cmsetrp();
    cmd_copy(CMD_COPY);
    return(B_FORWARD);
}
static int
browse_reply(VOID)
{
    cmxnl();
    do_reply(cf->current, reply_all, reply_include_me);
    return(B_FORWARD);
}

static int
browse_getchar(VOID)
{
    int c = getchar();
    cmechx(c);
    return(c);
}
static int
browse_delete(VOID)
{
    check_mark();
    change_flag(cf->current, CMD_DELETE);
    return(B_FORWARD);
}
static int
browse_flag(VOID)
{
    check_mark();
    change_flag(cf->current, CMD_FLAG);
    return(B_STAY);
}
static int
browse_keyword(VOID) {
    int doprev = false;

    check_mark();
    cmseteof();
    if (cmseter ()) {			/* errors return here */
	if (cmcsb._cmerr == CMxEOF) {
	    return CMxEOF;
	}
	else
	    doprev = true;
    }

    prompt("Keyword: ");
    if (doprev) {
	doprev = false;
	prevcmd();
    }
    cmsetrp();
    do_keyword();
    return(B_STAY);
}
