/* add.c - add entry to current file
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include "hook.h"
#include "terminal.h"
#include "viewfile.h"


extern int menuview_exitup;
extern int menuview_abort;


/* Read the current file's header into "buf" of size "sz".
 */
void rf_add_getheader(rf_data_t data, char *buf, size_t sz)
{
	long i, n;

	buf[0] = 0;
	buf[sz - 1] = 0;

	for (n = 0; (n < data->num_lines) &&	/* skip blank lines */
	     (data->line_pos[n].type == MFILE_LINE_BLANK); n++);

	for (i = 0; (i < 3) && (n < data->num_lines) &&
	     (data->line_pos[n].type != MFILE_LINE_DATESTAMP); i++) {
		rf_read_line(data, n);
		strncat(buf, data->linebuf, sz - 2 - strlen(buf));
		strcat(buf, "\n");
		n++;
	}
}


/* Store the addition "tmp" to file "f", with nameline "*name".
 *
 * Returns nonzero on error.
 */
int rf_store_addition(rf_data_t data, char *tmp, char *f, char **name)
{
	char buf[256];
	struct tm *p;
	time_t t;
	FILE *iptr;
	FILE *fptr;
	char *a;
	long i, n;

	if (rf_edit_lock(f))
		return (1);

	fptr = fopen(f, "a");
	if (!fptr) {
		rf_edit_unlock();
		return (1);
	}

	iptr = fopen(tmp, "r");
	if (!iptr) {
		fclose(fptr);
		rf_edit_unlock();
		return (1);
	}

	t = time(0);
	p = gmtime(&t);
	strftime(buf, 255, "%a %b %d %H:%M:%S %Y", p);

	n = data->num_lines - 1;

	if ((n >= 0) && (data->line_pos[n].type != MFILE_LINE_BLANK)) {
		fprintf(fptr, "\n");
	}

	fprintf(fptr, "Message: %08lX             (%s)\nFrom: ", t, buf);
	if (*name)
		fprintf(fptr, "%s ", *name);
	fprintf(fptr, "(%s)\n\n", current_user);

	i = 0;
	while (!feof(iptr) && !ferror(iptr)) {
		buf[0] = 0;
		fgets(buf, 255, iptr);
		a = strchr(buf, '\n');
		if (a)
			*a = 0;
		n = 0;
		while ((buf[n] == ' ') || (buf[n] == 9))
			n++;
		if (buf[n] == 0) {	    /* strip trailing blank lines */
			i++;
		} else {
			for (; i > 0; i--)
				fprintf(fptr, "\n");
			if (isupper(buf[0])) {	/* prefix Blah: with ]a */
				n = 1;
				while (islower(buf[n]))
					n++;
				if (buf[n] == ':') {
					if (strncmp(buf, "Subject:", 8) !=
					    0)
						fprintf(fptr, "\035a");
				}
			}
			fprintf(fptr, "%s\n", buf);
		}
	}

	fclose(iptr);

	fprintf(fptr, "\n");		    /* always end with a blank line */
	fclose(fptr);

	rf_edit_unlock();		    /* unlock file */

	if (!(data->flags & MENU_STATUS_BARLOG))
		bbs_hook(HOOK_LOG_ADD, data, 0);

	data->ldb_entry->last_accessed = 0;
	data->last_scanned = 0;

	rf_get_current_line(data);
	data->ldb_entry->current_line = data->num_lines;

	return (0);
}


/* Display the post-[A]ddition menu, and act on keys pressed.
 */
void
rf_postadd_menu(rf_data_t data, char *tmp, char *f, char **nameline,
		int ext)
{
	static char *menu[] = {
		"\n",
		"               [\035BA\035b] - Re-Edit\n",
		"               [\035BN\035b] - Set Nameline (\"\035CG\035B%s\035b\035CA\")\n",
		"\n",
		"           [\035BSPACE\035b] - Save and Exit\n",
		"\n",
		"               \035CR[\035BQ\035b]\035CA - Abort\n",
		"\n",
		0
	};
	char header[8192];
	char buf[256];
	char nmb[42];
	int i, c;

	rf_redraw = 1;

	do {

		if (rf_redraw) {
			t_clear();
			rf_lineout(data, -2);	/* output file title */
			rf_lineout(data, -1);
			for (i = 0; menu[i]; i++) {	/* show menu */
				sprintf(buf, menu[i], *nameline);
				t_lineout(buf, 0);
			}
			rf_redraw = 0;
		}

		c = t_getchar(1);

		bbs_hook(HOOK_KEY_PRESSED, 0, &c);

		t_checksize();

		if (menuview_exitup || menuview_abort)
			c = 'Q';

		switch (toupper(c)) {

		case 12:
			rf_redraw = 1;
			break;

		case 'A':
			header[0] = 0;
			rf_add_getheader(data, header, sizeof(header));
			mview_edit_file(tmp, 0, ext, data->title, header);
			rf_redraw = 1;
			break;

		case 'N':
			if (*nameline != nmb) {
				nmb[0] = 0;
				if (*nameline)
					strcpy(nmb, *nameline);
				*nameline = nmb;
			}
			while (t_input
			       ("Nameline (40 chars max): ", nmb,
				41) == 1);
			nmb[40] = 0;
			rf_redraw = 1;
			break;

		case ' ':
			if (!rf_store_addition(data, tmp, f, nameline)) {
				remove(tmp);
				return;
			}
			break;

		case 'Q':
			remove(tmp);
			rf_redraw = 1;
			return;

		default:
			break;
		}
	} while (1);

	/* NOT REACHED */
}


/* Add an edit to the current file. The nameline is taken from the
 * environment variable MVIEW_NAMELINE; if it is unset it is automatically
 * filled in with the current user's gecos field.
 *
 * If "rf_commentfile" is non-zero, it is used as the file to add to.
 *
 * The internal editor is used if "ext" is 0, $EDITOR if 1.
 *
 * Just returns if addition is not allowed.
 */
void rf_add_to_file(rf_data_t data, int ext)
{
	char header[8192];
	char nbuf[512];
	struct passwd *z;
	FILE *fptr;
	char *nameline;
	char *a;
	char *tmp;
	char *f;
	int e, wfd, frt;

	if (data->flags & MENU_STATUS_READONLY)
		return;
	if (!(data->flags & MENU_STATUS_ADD))
		return;

	if (bbs_hook(HOOK_CHECK_BAN, "E", 0)) {
		t_goto(0, t_rows - 1);
		t_clrtoeol();
		t_centre
		    ("\035R  *** You are banned from altering files ***  \035r");
		sleep(2);
		rf_redraw = 1;
		return;
	}

	f = (data->commentfile) ? data->commentfile : data->ldb_entry->
	    realname;

	if (rf_edit_lock(f))
		return;			    /* check we can lock file */
	rf_edit_unlock();

	nbuf[0] = 0;
	a = getenv("MVIEW_DIR");	    /* use mview dir if set */
	if (a) {
		strncpy(nbuf, a, 500);
		nbuf[500] = 0;
		strcat(nbuf, "/edit");
	} else {
		a = getenv("MVIEW_EDIT_TMP");	/* use MVIEW_EDIT_TMP instead */
		if (a) {
			strncpy(nbuf, a, 511);
			nbuf[511] = 0;
		}
	}

	frt = 0;
	if (nbuf[0] == 0) {
		tmp = (char *) malloc(strlen(P_tmpdir) + 32);
		if (!tmp)
			return;
		strcpy(tmp, P_tmpdir);
		strcat(tmp, "/mviewXXXXXX");
		wfd = mkstemp(tmp);
		if (wfd < 0) {
			free(tmp);
			return;
		}
		write(wfd, "Subject: \n", strlen("Subject: \n"));
		close(wfd);
		frt = 1;		    /* "free tmp" flag */
	} else {
		tmp = nbuf;
		fptr = fopen(tmp, "r");
		if (fptr) {
			fclose(fptr);
		} else {
			fptr = fopen(tmp, "w");
			if (!fptr)
				return;
			fprintf(fptr, "Subject: \n");
			fclose(fptr);
		}
	}

	chmod(tmp, S_IRUSR | S_IWUSR);	    /* make temp file read/write by us */

	bbs_hook(HOOK_SET_ACTION, 0,
		 (data->flags & MENU_STATUS_HIDETITLE) ? "" : data->title);

	rf_add_getheader(data, header, sizeof(header));
	e = mview_edit_file(tmp, 0, ext, data->title, header);	/* get edit */

	nameline = getenv("MVIEW_NAMELINE");

	if (!nameline) {
		z = getpwuid(getuid());
		if (z)
			nameline = z->pw_gecos;
		if (nameline) {
			a = strchr(nameline, ',');
			if (a)
				a[0] = 0;
		}
	}

	if (e == 0)
		rf_postadd_menu(data, tmp, f, &nameline, ext);
	else
		rf_redraw = 1;

	bbs_hook(HOOK_SET_ACTION, "Reading ",
		 (data->flags & MENU_STATUS_HIDETITLE) ? "" : data->title);

	if (frt)
		free(tmp);
}

/* EOF */
