/* listed.c - edit a listed directory
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "viewmenu.h"
#include "terminal.h"

extern int menuview_abort;


/* Prompt the user, with text "intro", to select one of the menu entries to
 * operate on.
 *
 * Returns the menu index of the selected entry, or -1 if [Q] was pressed.
 */
int menuview_listed__getentry(menudata_t data, char *intro)
{
	int c, n, i;
	char a[2];

	strcpy(data->buf, intro);
	strcat(data->buf, " [\035B");

	a[1] = 0;
	n = 0;

	for (i = 0; i < data->menu->num_entries; i++) {
		if (data->menu->menu[i].key) {
			a[0] = data->menu->menu[i].key;
			strcat(data->buf, a);
			n++;
		}
	}

	if (n < 1)
		return (-1);		    /* no entries to select */

	strcat(data->buf, "\035b] [\035BQ\035b]:Quit");

	menuview_wipe_footer(data);
	t_goto(0, t_rows - 1);
	t_centre(data->buf);

	do {
		if (menuview_abort)
			return (-1);
		c = toupper(t_getchar(1));
		if (c == 'Q')
			return (-1);
		if (c == 12) {
			rf_redraw = 1;
			c = 0;
		}
		if (rf_redraw) {
			menuview_wipe_footer(data);
			t_goto(0, t_rows - 1);
			t_centre(data->buf);
			rf_redraw = 0;
		}
		for (i = 0; (i < data->menu->num_entries)
		     && (toupper(data->menu->menu[i].key) != toupper(c));
		     i++);
		if (i < data->menu->num_entries)
			return (i);
	} while (1);
}


/* Report an error.
 */
void menuview_edit__error(menudata_t data)
{
	strcpy(data->buf, "\035R *** ");
	strcat(data->buf, strerror(errno));
	strcat(data->buf, " *** \035r");
	menuview_wipe_footer(data);
	t_goto(0, t_rows - 1);
	t_centre(data->buf);
	sleep(2);
}


/* Allow the user to add a file to the current directory.
 *
 * Menu files (.mn) and ACL files (.acl) will be created only group-readable;
 * all other files will be created group writeable as well.
 */
void menuview_listed__addfile(menudata_t data)
{
	char buf[80];
	char *a;
	int fd;
	int group_readonly = 0;

	a = strrchr(data->menu->filename, '/');
	if (!strcmp(a, "/.")) {
		a--;
		while ((a > data->menu->filename) && (*a != '/'))
			a--;
		if ((a < data->menu->filename) || (*a != '/'))
			a = 0;
	}

	if (!a)
		return;

	buf[0] = 0;
	while (t_input("Name of new file: ", buf, sizeof(buf) - 1) == 1);

	if (buf[0] == 0)
		return;
	if (strchr(buf, '/'))
		return;			    /* no directory changing */

	strncpy(data->buf, data->menu->filename, sizeof(data->buf) - 128);
	strcat(data->buf, "/");
	strcat(data->buf, buf);
	if (!strchr(buf, '.'))
		strcat(data->buf, ".cm");

	a[0] = '/';

	a = strrchr(buf, '.');
	if ((a) && (!strcmp(a, ".mn")))
		group_readonly = 1;	    /* menu file */
	if ((a) && (!strcmp(a, ".acl")))
		group_readonly = 1;	    /* ACL file */

	fd = open(data->buf, O_WRONLY | O_CREAT | O_EXCL,
		  S_IRUSR | S_IWUSR);
	if (fd < 0) {
		menuview_edit__error(data);
	} else {
		fchmod(fd,
		       S_IRUSR | S_IWUSR | S_IRGRP | ((group_readonly) ? 0
						      : S_IWGRP));
		close(fd);
	}
}


/* Allow the user to add a subdirectory to the current directory.
 */
void menuview_listed__addmenu(menudata_t data)
{
	struct stat sb;
	char buf[80];
	char *a;
	int n;

	a = strrchr(data->menu->filename, '/');
	if (!strcmp(a, "/.")) {
		a--;
		while ((a > data->menu->filename) && (*a != '/'))
			a--;
		if ((a < data->menu->filename) || (*a != '/'))
			a = 0;
	}

	if (!a)
		return;

	buf[0] = 0;
	while (t_input("Name of new directory: ", buf, sizeof(buf) - 1) ==
	       1);

	if (buf[0] == 0)
		return;
	if (strchr(buf, '/'))
		return;			    /* no directory changing */

	strncpy(data->buf, data->menu->filename, sizeof(data->buf) - 128);
	strcat(data->buf, "/");
	strcat(data->buf, buf);

	a[0] = '/';

	if (!stat(data->buf, &sb)) {
		menuview_wipe_footer(data);
		t_goto(0, t_rows - 1);
		t_centre("\035R *** File already exists *** \035r");
		sleep(2);
		return;
	}

	n = mkdir(data->buf, S_IRWXU | S_IRWXG);
	if (!n)
		chmod(data->buf, S_IRWXU | S_IRWXG);

	if (n)
		menuview_edit__error(data);
}


/* Allow the user to remove a file from the current directory.
 */
void menuview_listed__delfile(menudata_t data)
{
	struct stat sb;
	char *a;
	int n, c;

	n = menuview_listed__getentry(data, "Select entry to delete");
	if (n < 0)
		return;

	if (stat(data->menu->menu[n].filename, &sb)) {
		menuview_edit__error(data);
		return;
	}

	a = strrchr(data->menu->menu[n].filename, '/');
	if (!strcmp(a, "/.")) {
		a[0] = 0;
		while ((a > data->menu->menu[n].filename) && (*a != '/'))
			a--;
	}

	if (a)
		a++;
	else
		a = data->menu->menu[n].filename;

	strcpy(data->buf, "Delete \"\035B");
	strncat(data->buf, a, sizeof(data->buf) - strlen(data->buf));
	strcat(data->buf, "\035b\". Are you sure? [\035BYNQ\035b]");

	menuview_wipe_footer(data);
	t_goto(0, t_rows - 1);
	t_centre(data->buf);

	do {
		if (menuview_abort)
			return;
		c = toupper(t_getchar(1));
		if (c == 'Q')
			return;
		if (c == 'N')
			return;
		if (c == 12) {
			rf_redraw = 1;
			c = 0;
		}
		if (rf_redraw) {
			menuview_wipe_footer(data);
			t_goto(0, t_rows - 1);
			t_centre(data->buf);
			rf_redraw = 0;
		}
	} while (c != 'Y');

	if (S_ISDIR(sb.st_mode)) {
		n = rmdir(data->menu->menu[n].filename);
	} else {
		n = remove(data->menu->menu[n].filename);
	}

	if (n)
		menuview_edit__error(data);
}


/* Allow the user to rename a file in the current directory.
 */
void menuview_listed__rename(menudata_t data)
{
	struct stat sb;
	char buf[80];
	char *a;
	int n;

	n = menuview_listed__getentry(data, "Select entry to rename");
	if (n < 0)
		return;

	a = strrchr(data->menu->menu[n].filename, '/');
	if ((a) && (!strcmp(a, "/."))) {
		a--;
		while ((a > data->menu->menu[n].filename) && (*a != '/'))
			a--;
		if ((a < data->menu->menu[n].filename) || (*a != '/'))
			a = 0;
	}

	if (!a)
		return;

	a[0] = 0;

	buf[0] = 0;
	while (t_input("Rename to: ", buf, sizeof(buf) - 1) == 1);

	if (buf[0] == 0)
		return;
	if (strchr(buf, '/'))
		return;			    /* no directory changing */

	strncpy(data->buf, data->menu->menu[n].filename,
		sizeof(data->buf) - 128);
	strcat(data->buf, "/");
	strcat(data->buf, buf);

	a[0] = '/';

	if (!stat(data->buf, &sb)) {
		menuview_wipe_footer(data);
		t_goto(0, t_rows - 1);
		t_centre("\035R *** File already exists *** \035r");
		sleep(2);
		return;
	}

	n = rename(data->menu->menu[n].filename, data->buf);

	if (n)
		menuview_edit__error(data);
}


/* Allow the user to edit the current directory's contents.
 */
void menuview_edit_listed(menudata_t data)
{
	int c;

	strcpy(data->buf, "[\035BA\035b]:Add File  "
	       "[\035BM\035b]:Add Dir  "
	       "[\035BD\035b]:Delete  "
	       "[\035BR\035b]:Rename  " "[\035BQ\035b]:Exit");
	menuview_wipe_footer(data);
	t_goto(0, t_rows - 1);
	t_centre(data->buf);

	do {
		if (menuview_abort)
			return;
		c = toupper(t_getchar(1));
		if (c == 'Q')
			return;
		if (c == 12) {
			rf_redraw = 1;
			c = 0;
		}
		if (rf_redraw) {
			menuview_wipe_footer(data);
			t_goto(0, t_rows - 1);
			t_centre(data->buf);
			rf_redraw = 0;
		}
	} while ((c != 'A') && (c != 'M') && (c != 'D') && (c != 'R'));

	switch (c) {
	case 'A':
		menuview_listed__addfile(data);
		break;
	case 'M':
		menuview_listed__addmenu(data);
		break;
	case 'D':
		menuview_listed__delfile(data);
		break;
	case 'R':
		menuview_listed__rename(data);
		break;
	}
}

/* EOF */
