#include "main.h"

char *ubar = "_____________________________________________________________________________________________________________________________________________________________________________________________________";


extern int size;
extern int alignment;
unsigned long file_end();

save_changes()
{
	char ch;
	if (!dirty)
		return;
	wmove(status_window, 0, COLS - 20);
	if (ronly)
		waddstr(status_window, "File is Read-Only.");
	else
		waddstr(status_window, "Save changes? (Y/n)");
	wclrtoeol(status_window);
	wrefresh(status_window);
	while ((ch != 'y') && (ch != 'n')) {
		ch = wgetch(status_window);
		if ((ch == 'Y') || (ch == ''))
			ch = 'y';
		if (ch == 'N')
			ch = 'n';
	}
	if ((ch == 'y') && (!ronly)) {
		(void) fseek(view_file, daddr, 0);
		(void) fwrite(buffer, 1, size, view_file);
	}
	dirty = 0;	
	wmove(status_window, 0, COLS - 20);
	wclrtoeol(status_window);
	wrefresh(status_window);
}

confirm(message)
char *message;
{
	char	ch;
	int	rc = 0;

	wmove(status_window, 0, COLS - strlen(message) - 1);
	waddstr(status_window, message);
	wclrtoeol(status_window);
	wrefresh(status_window);
	while ((ch != 'y') && (ch != 'n')) {
		ch = wgetch(status_window);
		if ((ch == 'Y') || (ch == ''))
			ch = 'y';
		if (ch == 'N')
			ch = 'n';
	}
	wmove(status_window, 0, COLS - 20);
	wclrtoeol(status_window);
	wrefresh(status_window);
	if (ch == 'y')
		return(1);
	else
		return(0);
}

int get_jump(start)
int start;
{
	char ch = ' ';
	char str[10];
	int index;
	unsigned long retval;
	WINDOW *jump_window;
	jump_window = newwin(2, 35, 0, COLS - 35);
	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	waddstr(jump_window, "Goto address:");
	wrefresh(jump_window);

	for (index = 0; index < 10; index++)
		str[index] = '\0';

	index = 0;
	while (ch != '') {
		wmove(jump_window, 0, 20);
		waddstr(jump_window, str);
		wrefresh(jump_window);
		ch = wgetch(jump_window);
		if ((index > 0) && ((ch == 8) || (ch == 127))) {
			index -= 1;
			str[index] = ' ';
			wmove(jump_window, 0, 20);
			waddstr(jump_window, str);
			str[index] = '\0';
		}

		if ((ch >= 'A') && (ch <= 'F'))
			ch += 'a' - 'A';

		if ((index < 8) &&
		    (((ch >= '0') && (ch <= '9')) ||
		     ((ch >= 'a') && (ch <= 'f')))) {
			str[index] = ch;
			index++;
		}
	}
	str[index] = '\0';
	retval = start;
	if (index != 0) {
		(void) sscanf(str, "%x", &retval);
		if (retval > file_end())
			retval = start;
	}

	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	delwin(jump_window);
	return(retval);
}

int find_hex(start, direction)
int start;
int direction;
{
	char	ch;
	char	str[MAXLEN];
	int	index;
	int	index2;
	int	temp;
	int	temp2;
	char	search_for[MAXLEN];
	WINDOW	*jump_window;

	if (direction)
		ch = '<';
	else
		ch = '>';

	(void) sprintf(out_string, "%c Hex to find:", ch);
	ch = ' ';

	jump_window = newwin(1, 39, 0, COLS - 39);
	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	waddstr(jump_window, out_string);
	wrefresh(jump_window);

	for (index = 0; index < MAXLEN; index++)
		str[index] = '\0';

	index = 0;
	while (ch != '') {
		wmove(jump_window, 0, 15);
		waddstr(jump_window, str);
		wrefresh(jump_window);
		ch = wgetch(jump_window);
		if ((index > 0) && ((ch == 8) || (ch == 127))) {
			if (str[index] == '?')
				str[--index] = ' ';
			str[--index] = ' ';
			wmove(jump_window, 0, 15);
			waddstr(jump_window, str);
			str[index] = '\0';
		}

		if ((index < MAX_HEX * 2) && (ch == '?') &&
		    !(index & 1) && (index > 0)) {
			str[index++] = '?';
			str[index++] = '?';
		}

		if ((ch >= 'A') && (ch <= 'F'))
			ch += 'a' - 'A';

		if ((index < MAX_HEX * 2) &&
		    (((ch >= '0') && (ch <= '9')) ||
		     ((ch >= 'a') && (ch <= 'f'))))
			str[index++] = ch;

		if (ch == '') {
			index = 0;
			str[index] = '\0';
			wmove(jump_window, 0, 0);
			waddstr(jump_window, out_string);
			wclrtoeol(jump_window);
		}

		if (ch == ESC) {
			index = 0;
			ch = '';
		}
	}
	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	delwin(jump_window);

	str[index] = '\0';
	if (index != 0) {
		global_type = 1;
		global_direction = direction;
		if (index & 1) {
			index++;
			temp = str[0];
			for (index2 = 1; index2 < index; index2++) {
				temp2 = str[index2];
				str[index2] = temp;
				temp = temp2;
			}
			str[index2] = temp;
			str[0] = '0';
		}

		global_num = index / 2;
		out_string[0] = '\0';

		for (index2 = 0; index2 < global_num; index2++) {
			if ((str[2 * index2] == '?') || (str[2 * index2 + 1] == '?'))
				global_special[index] = 1;
			else {
				(void) sscanf(str + (2 * index2), "%02x", &local_search[index2]);
				global_special[index] = 0;
			}
			(void) sprintf(out_string, "%02x", local_search[index2]);
			strcat(search_for, out_string);
			global_search[index2] = (char) local_search[index2];
		}
		return(generic_search(start, global_direction));
	}
	return(start);
}

int find_str(start, direction)
int start;
int direction;
{
	char	ch;
	char	str[MAXLEN];
	int	index;
	char	out_string[256];
	WINDOW *jump_window;

	if (direction)
		ch = '<';
	else
		ch = '>';

	(void) sprintf(out_string, "%c String to find:", ch);
	ch = ' ';

	jump_window = newwin(1, COLS - 32, 0, 32);
	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	waddstr(jump_window, out_string);
	wrefresh(jump_window);

	for (index = 0; index < MAXLEN; index++)
		str[index] = '\0';

	index = 0;
	while (ch != '') {
		wmove(jump_window, 0, 18);
		waddstr(jump_window, str);
		wrefresh(jump_window);
		ch = wgetch(jump_window);
		if ((index > 0) && ((ch == 8) || (ch == 127))) {
			index -= 1;
			str[index] = ' ';
			wmove(jump_window, 0, 18);
			waddstr(jump_window, str);
			str[index] = '\0';
		}
		if ((index < MAXLEN-1) && (ch != 8) &&
		    (ch != 127) && (ch != '') ) {
			str[index] = ch;
			index++;
		}
		if (ch == '') {
			index = 0;
			str[index] = '\0';
			wmove(jump_window, 0, 0);
			waddstr(jump_window, out_string);
			wclrtoeol(jump_window);
		}

		if (ch == ESC) {
			index = 0;
			ch = '';
		}
	}
	str[index] = '\0';

	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	delwin(jump_window);

	if (index) {
		global_type	 = 0;
		global_num	 = index;
		global_direction = direction;
		(void) strcpy(global_search, str);
		for (index=0; index < global_num; index++)
			if (str[index] == '?')
				global_special[index] = 1;
			else
				global_special[index] = 0;
		return(generic_search(start, global_direction));
	}
	return(start);
}

/* This is the search routine for all forward and backward searches.
	Buffer is moved less the full size of the thing we are searching
	for in order to make sure it isn't split between a block.
*/
int generic_search(start, direction)
unsigned long start;
int direction;
{
	int	index;
	long	retval;
	long	buf_last;
	long	cur_pos;
	long	end;
	char	search_for[MAXLEN];
	char 	cdir;
	int	wrapped;
	WINDOW	*jump_window;

	found = 0;

	if (global_num == 0)
		return(start);

	global_direction = direction;
	wmove(status_window, 0, 0);
	(void) sprintf(out_string, "[%08x-%08x]", start, start);
	waddstr(status_window, out_string);
	wrefresh(status_window);

	jump_window = newwin(1, COLS - 30, 0, 30);

	if (global_type) {
		(void) sprintf(search_for, "0x%02x", local_search[0]);
		for (index = 1; index < global_num; index++)
			if (global_special[index])
				strcat(search_for, "??");
			else {
				(void) sprintf(out_string, "%02x", local_search[index]);
				strcat(search_for, out_string);
			}
	} else
		(void) sprintf(search_for, "\"%s\"", global_search);

	if (direction)
		cdir = '<';
	else
		cdir = '>';
	(void) sprintf(out_string, "Searching %c for %s", cdir, search_for);
	wmove(jump_window, 0, 0);
	waddstr(jump_window, out_string);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	end = file_end();

	searching = 1;

	if (direction) {  /* Backward Search */
	    buf_last = start - max_buf_size;
	    if (buf_last < 0)
		buf_last += end;

	    buf_read(buf_last, buffer, max_buf_size);

	    cur_pos = max_buf_size - 4;
	    while (!found) {
		nope:
		cur_pos--;
/*
		if ((buf_last + cur_pos) == start) {
			daddr = !daddr;
			break;
		}
*/
		if (cur_pos < 0) {
			(void) sprintf(out_string, "%08x", buf_last);
			wmove(status_window, 0, 1);
			waddstr(status_window, out_string);
			wrefresh(status_window);

			buf_last = buf_last - max_buf_size + global_num;
			if ((buf_last <= start - max_buf_size) && (wrapped))
				break;
			else if (buf_last >= start - max_buf_size)
				wrapped = 1;
			buf_read(buf_last, buffer, max_buf_size);
			if (buf_last < 0)
				buf_last += end;
			cur_pos = max_buf_size - global_num;
		}
		if (global_search[0] == buffer[cur_pos]) {
			for (index = 1; index < global_num; index++)
				if ((global_search[index] != buffer[cur_pos + index]) &&
				   !(global_special[index]))
					goto nope;
			found = 1;
			daddr = !retval;
			retval = cur_pos + buf_last;
			if (retval > end)
				retval -= end;
		}
	    }
	} else {   /* Forward Search */
	    buf_last = start;

	    buf_read(buf_last, buffer, max_buf_size);
	    cur_pos = 4;

	    while (!found) {
		nope2:
/*
		if ((cur_pos + buf_last) == start) {
			daddr = !daddr;
			break;
		}
*/

		if (cur_pos > (max_buf_size - global_num)) {
			if (wdismode)
			    (void) sprintf(out_string, "%8d", buf_last);
			else
			    (void) sprintf(out_string, "%08x", buf_last);
			wmove(status_window, 0, 1);
			waddstr(status_window, out_string);
			wrefresh(status_window);

			cur_pos = 0;
			buf_last += (max_buf_size - global_num);

			if ((buf_last >= start + max_buf_size) && (wrapped))
				break;
			else if (buf_last <= start + max_buf_size)
				wrapped = 1;

			if (buf_last >= end)
				buf_last = 0;

			buf_read(buf_last, buffer, max_buf_size);
		} else
			cur_pos++;

		if (global_search[0] == buffer[cur_pos]) {
			for (index = 1; index < global_num; index++)
				if ((global_search[index] != buffer[cur_pos + index]) &&
				   !(global_special[index]))
					goto nope2;
			found = 1;
			daddr = !retval;
			retval = cur_pos + buf_last;
			if (retval > end)
				retval -= end;
		}
	    }

	}

	if (!found)
	    retval = start;

	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);
	delwin(jump_window);
	searching = 0;
	return(retval);
}

buf_read(pos, buffer, size)
int pos;
char *buffer;
int size;
{
	unsigned long end;
	end = file_end();
	if (pos < 0) {  /* block wrap back */
		(void) fseek(view_file, end + pos, 0);
		(void) fread(buffer, 1, -pos, view_file);
		(void) fseek(view_file, 0, 0);
		(void) fread(buffer - pos, 1, pos + size, view_file);
	} else if (pos + size > end) {  /* block wrap over */
		(void) fseek(view_file, pos, 0);
		(void) fread(buffer, 1, end - pos, view_file);
		(void) fseek(view_file, 0, 0);
		(void) fread(buffer + end - pos, 1, size + pos - end, view_file);
	} else {
		(void) fseek(view_file, pos, 0);
		(void) fread(buffer, 1, size, view_file);
	}
}

set_mark(addr)
int addr;
{
	char ch;
	int index;

	ch = wgetch(status_window);
	for (index = 0; index < MARKS; index++)
		if (markchar[index] == ch) {
			markpos[index] = addr;
			return;
		}
	markchar[marks]	= ch;
	markpos[marks]	= addr;
	marks = (marks + 1) % MARKS;
}

get_mark(start)
int start;
{
	char	ch;
	int	index;

	ch = wgetch(status_window);
	for (index = 0; index < MARKS; index++)
		if (markchar[index] == ch)
			return(markpos[index]);
	return(start);
}

unsigned long file_end()
{
	static end = -1;
	static type = 0;
	struct stat buf;

	if (type)
		return(end);
	else
		(void) fstat(fileno(view_file), &buf);

	if (type = (buf.st_mode & S_IFCHR))
		return(end = device_end());
	else
		return(buf.st_size + 4 - (buf.st_size % 4));
}

device_end()
{
	unsigned int size = 512;
	int smsize = 0;
	int integer;

	while (1) {
		fseek(view_file, size, 0);
		if (fread(&integer, 1, 1, view_file))
			size <<= 1;
		else
			break;
	}

	size >>= 1;
	smsize = size >> 1;

	while (smsize > 128) {
		smsize >>= 1;
		fseek(view_file, size + smsize, 0);
		if (fread(&integer, 1, 1, view_file))
			size += smsize;
	}

	if (size & 128)
		size += 128;

	return(size);
}

edit_hex(addr)
int addr;
{
	char	ch = ' ';
	char	str[EDIT_STRLEN];
	int	index;
	WINDOW	*jump_window;

	jump_window = newwin(1, 50, 0, COLS - 50);
	wmove(jump_window, 0, 0);
	sprintf(out_string, "Alter hex %08x to:", ibuffer[addr]);
	waddstr(jump_window, out_string);
	wrefresh(jump_window);

	(void) sprintf(str, "%x", ibuffer[addr]);
	index = strlen(str);

	while (ch != '') {
		wmove(jump_window, 0, 26);
		waddstr(jump_window, str);
		wrefresh(jump_window);
		ch = wgetch(jump_window);
		if ((index > 0) && ((ch == 8) || (ch == 127))) {
			if (str[index] == '?')
				str[--index] = ' ';
			str[--index] = ' ';
			wmove(jump_window, 0, 26);
			waddstr(jump_window, str);
			str[index] = '\0';
		}

		if ((ch >= 'A') && (ch <= 'F'))
			ch += 'a' - 'A';

		if ((index < EDIT_STRLEN) &&
		    (((ch >= '0') && (ch <= '9')) ||
		     ((ch >= 'a') && (ch <= 'f'))))
			str[index++] = ch;

		if (ch == '') {
			index = 0;
			str[index] = '\0';
			wmove(jump_window, 0, 26);
			wclrtoeol(jump_window);
		}
	}

	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	delwin(jump_window);

	str[index] = '\0';

	if (index != 0)
		(void) sscanf(str, "%x", &ibuffer[addr]);
}

edit_mem_string(addr)
int addr;
{
	int	rc;
	char	*string;
	string	= (char *) malloc(EDIT_STRLEN);
	mem_to_string(addr * 4, string);

	if (rc = edit_string(string))
		if (rc == 2)
			string_to_mem(addr * 4, string, 1);
		else
			string_to_mem(addr * 4, string, 0);
}

edit_string(string)
char *string;
{
	char	ch	= ' ';
	char	ch2;
	WINDOW	*jump_window;
	char	*prevstr;
	char	*origstr;
	char	*temp;
	int	index	= 0;
	int	index2;
	int	slen;
	int	origlen;
	int	emode = -1;
	int	rc = 0;

/* must take into account that string length can be greater
   then the maximum displayable area on the screen. */
	/* original copy of string */
	origstr	= (char *) malloc(EDIT_STRLEN);
	strcpy(origstr, string);

	/* edit updated copy of string */
	prevstr	= (char *) malloc(EDIT_STRLEN);
	strcpy(prevstr, string);

	origlen	    = strlen(string);
	index	    = origlen - 1;

	jump_window = newwin(1, COLS - 31, 0, 20);
	wmove(jump_window, 0, 0);
	sprintf(out_string, "Alter: ");
	waddstr(jump_window, out_string);

	while ((ch != '') && (ch != '')) {
	    slen = strlen(string);
	    wstandout(jump_window);
	    wmove(jump_window, 0, 7);
	    if (slen <= origlen) {
		sprintf(out_string, "%s", string);
		waddstr(jump_window, out_string);
		sprintf(out_string, "%.*s", origlen - strlen(out_string), ubar);
		waddstr(jump_window, out_string);
		wstandend(jump_window);
		sprintf(out_string, "%.*s", EDIT_STRLEN - origlen, ubar);
		waddstr(jump_window, out_string);
	    } else {
		sprintf(out_string, "%.*s", origlen, string);
		waddstr(jump_window, out_string);
		wstandend(jump_window);
		sprintf(out_string, "%s", string + origlen);
		waddstr(jump_window, out_string);
		sprintf(out_string, "%.*s", EDIT_STRLEN - slen, ubar);
		waddstr(jump_window, out_string);
	    }
	    wmove(jump_window, 0, index + 7);
	    wrefresh(jump_window);

	    ch = wgetch(jump_window);

	    switch(ch) {
		case '':
		    index = 0;
		    break;
		case '':
		    index = slen + emode;
		    break;
		case 8:
		case 127:
		    if (emode) {
			    if (index > 0)
				index--;
			    break;
		    }
		    strcpy(prevstr, string);
		    if (index > 0) {
			index--;
			for (index2 = index; index2 < slen; index2++)
				string[index2] = string[index2 + 1];
		    }
		    break;
		case '':
		    if (index > 0)
		        index--;
		    break;
		case 10:  /* ^J */
		case '':
		    if (index < slen)
			index++;
		    break;
		case '':
		case '':
		    break;
		case '':
		    strcpy(prevstr, string);
		    index = 0;
		    string[index] = '\0';
		    wmove(jump_window, 0, 7);
		    wclrtoeol(jump_window);
		    break;
		case '':
		case 3:
		    goto quit;
		    break;
		case ESC:
		    emode = -1;
		    if (index > slen - 1)
			index--;
		    break;
		default:
		    if (emode) {
			switch(ch) {
			    case 'a':
				strcpy(prevstr, string);
				emode = 0;
				if (index < slen)
				    index++;
				break;
			    case 'A':
				strcpy(prevstr, string);
				emode = 0;
				index = slen;
				break;
			    case 'c':
				emode = 0;
			    case 'd':
				strcpy(prevstr, string);
				ch2 = wgetch(jump_window);
				if (ch2 == 'w')
				    delword(string + index, slen);
				else if (ch2 == 't') {
				    ch2 = wgetch(jump_window);
				    for (index2 = index + 1; index2 < slen;
					index2++)
					if (string[index2] == ch2) {
					    delchars(string + index, index2 -
						     index, slen);
					    break;
					}
				}
				if (index > strlen(string) - 1)
					index = strlen(string) - 1;
				break;
			    case 'H':
				help_me_str();
				touchwin(jump_window);
				touchwin(main_window);
				wrefresh(jump_window);
				wrefresh(main_window);
				break;
			    case 'h':
			    case 'k':
				if (index > 0)
				    index--;
				break;
			    case 'I':
				index = 0;
			    case 'i':
				strcpy(prevstr, string);
				emode = 0;
				break;
			    case 'j':
			    case 'l':
			    case ' ':
				if (index < slen - 1)
				    index++;
				break;
			    case 'r':
			    case 's':
				strcpy(prevstr, string);
				string[index] = wgetch(jump_window);
				break;
			    case 't':
			    case 'T':
				ch2 = wgetch(jump_window);
				for (index2 = index + 1; index2 < slen;index2++)
					if (string[index2] == ch2) {
						index = index2 - 1;
						break;
					}
				break;
			    case 'u':
				temp	= prevstr;
				prevstr	= string;
				string	= temp;
				break;
			    case 'U':
				temp	= prevstr;
				prevstr	= string;
				string	= temp;
				strcpy(string, origstr);
				break;
			    case 'x':
				strcpy(prevstr, string);
				for (index2 = index; index2 < slen;index2++)
					string[index2] = string[index2 + 1];
				if (index == slen - 1)
					index--;
				break;
			    case '0':
			    case '^':
				index = 0;
				break;
			    case '$':
				index = slen;
				break;
			}
			break;
		    }
		    if (ch == '')
			ch = wgetch(jump_window);
		    if (slen == EDIT_STRLEN)
			break;
		    for (index2 = slen; index2 > index; index2--)
			string[index2] = string[index2 - 1];
		    string[slen + 1] = '\0';
		    string[index++] = ch;
		    ch = ' ';
		    break;
	    }
	}

	if (ch == '')
		rc = 2;
	else
		rc = 1;

	quit:

	wmove(jump_window, 0, 0);
	wclrtoeol(jump_window);
	wrefresh(jump_window);

	delwin(jump_window);

	return(rc);
}

delword(string, slen)
char	*string;
int	slen;
{
	int index;
	for (index = 1; index < slen; index++)
		if (strchr(",<.>/?;:'\"`~[{]}=+-_\\|!@#$%^&*()", string[index]))
			break;
	delchars(string, index, slen);
}

delchars(string, index, slen)
char	*string;
int	index;
int	slen;
{
	int index2;
	for (index2 = index; index2 <= slen; index2++)
		string[index2 - index] = string[index2];
}

mem_to_string(addr, string)
int addr;
char *string;
{
    char	ch;
    int		strpos = 0;
    int		index;

    for (index = 0; strpos < EDIT_STRLEN - 2; index++) {
	ch = buffer[addr + index];
	if (((ch >= 'a') && (ch <= 'z')) ||
	    ((ch >= 'A') && (ch <= 'Z')) ||
	    (strchr("[]{},./<>?;'`:\"~", ch)))
		string[strpos++] = ch;
	else switch(ch) {
	    case '\0':  goto mem_to_string_done;
	    case '\m':  string[strpos++] = '\\';
			string[strpos++] = 'm';
			break;
	    case '\t':  string[strpos++] = '\\';
			string[strpos++] = 't';
			break;
	    case '\r':  string[strpos++] = '\\';
			string[strpos++] = 'r';
			break;
	    case '\\':  string[strpos++] = '\\';
			string[strpos++] = '\\';
			break;
	    default:
			if ((ch > 0) && (ch <= 26)) {
				string[strpos++] = '^';
				string[strpos++] = ch + 'A' - 1;
			} else
				string[strpos++] = ch;
	}
    }
    mem_to_string_done:
    string[strpos] = '\0';
}

	
/*
	if (((buffer[addr + index] >= 'a') && (buffer[addr + index] <= 'z')) ||
	    ((buffer[addr + index] >= ' ') && (buffer[addr + index] <= 'Z')) ||
	    (strchr("[]{},./<>?;'`:\"~", buffer[addr + index])))
		string[strpos++] = buffer[addr + index];
	else switch(buffer[addr + index]) {
*/

string_to_mem(addr, string, type)
int	addr;
char	*string;
int	type;
{
	int	index;
	int	mempos = 0;
	char	ch;

	for (index = 0; index < strlen(string) + type; index++, mempos++) {
	    switch (string[index]) {
		case '\\':
		    index++;
		    switch (string[index]) {
			case '0':
			    ch = 0;
			    break;
			case 'm':
			case 'M':
			    ch = '\m';
			    break;
			case 't':
			case 'T':
			    ch = '\t';
			    break;
			case 'r':
			case 'R':
			    ch = '\r';
			    break;
			case '\\':
			    ch = '\\';
			    break;
		    }
		    break;
		case '^':
		    index++;
		    if ((string[index] >= 'A') && (string[index] <= 'Z'))
			    ch = string[index] - 'A';
		    else if ((string[index] >= 'A') && (string[index] <= 'Z'))
			    ch = string[index] - 'a';
		    else {
			    index--;
			    ch = '^';
		    }
		    break;
		default:
		    ch = string[index];
	    }
	    buffer[addr + mempos] = ch;
	}
}

edit_mode()
{
	wmove(status_window, 0, COLS - 10);

	waddch(status_window, '0' + alignment);
	if (ronly)
		waddstr(status_window, "R");
	else
		waddstr(status_window, "W");

	waddstr(status_window, " ");

	if (mode == STRING)
		waddstr(status_window, "Str");
	else
		waddstr(status_window, "   ");
	switch (wdismode) {
	    case 0:
		waddstr(status_window, "Hex");
		break;
	    case 1:
		waddstr(status_window, "Dec");
		break;
	    case 2:
		waddstr(status_window, "Flt");
		break;
	    case 3:
		waddstr(status_window, "Dbl");
		break;
	}

	touchwin(status_window);
	wrefresh(status_window);
}

void sigint()
{
	if (searching) {
		found = 1;
		return;
	} else {
		de_init();
		exit(0);
	}
}

void sigquit()
{
	de_init();
	exit(0);
}

extern char *filename;
extern unsigned long last_viewed;

void sigwinch()
{
	struct winsize buf;

	de_init();

	ioctl(1, TIOCGWINSZ, &buf);
	COLS  = buf.ws_col;
	LINES = buf.ws_row;

	init();

	wmove(status_window, 0, 20);
	(void) sprintf(out_string, "of %s\n", filename);
	waddstr(status_window, out_string);
	last_viewed = caddr;

	show_addr(caddr, 0);
	update_cursor(ON);
	wrefresh(main_window);
	edit_mode();
}

write_file(first, last, type)
int first;
int last;
int type;
{
	int	index;
	char	name[128];
	char	tmp[128];
	char	*buf;
	int	size;
	FILE	*out_file;

	size = last - first;
	if (size > 65536) {
		if (wdismode)
			sprintf(tmp, "Write %d Kbytes?  (Y/n)", size / 1024);
		else
			sprintf(tmp, "Write %08x Kbytes?  (Y/n)", size / 1024);
		if (!confirm(tmp))
			return(0);
	}
	
	top:
	strcpy(name, "output");

	buf = (char *) malloc(last - first);
	if (edit_string(name)) {
		if (type) {
			out_file = fopen(name, "a+");
			if (out_file == NULL)
				out_file = fopen(name, "w");
		} else
			out_file = fopen(name, "w");
		if (out_file == NULL) {
			sprintf(tmp, "Unable to open %s for writing.  Another?", name);
			if (confirm(tmp))
				goto top;
			else
				return(0);
		}
		fseek(view_file, first, 0);
		fread(buf, size, 1, view_file);
		fwrite(buf, size, 1, out_file);
		fclose(out_file);
	}
	wmove(status_window, 0, 30);
	if (wdismode)
		sprintf(tmp, "%d bytes %d-8d written", size, first, last);
	else
		sprintf(tmp, "%08x bytes %08x-%08x written", size, first, last);
	waddstr(status_window, tmp);
	wclrtoeol(status_window);
	wrefresh(status_window);
	return(1);
}

write_mark(start, type)
int start;
int type;
{
	char	ch;
	int	index;
	int	temp;
	int	end;

	if (MARKS == 0) {
		wmove(status_window, 0, 30);
		waddstr(status_window, "No marks set, press return");
		wclrtoeol(status_window);
		wrefresh(status_window);
		while (wgetch(status_window) != '');
		wmove(status_window, 0, 30);
		wclrtoeol(status_window);
		wrefresh(status_window);
		return;
	}
	wmove(status_window, 0, 30);
	waddstr(status_window, "pick end mark");
	wclrtoeol(status_window);
	wrefresh(status_window);
	ch = wgetch(status_window);
	wmove(status_window, 0, 30);
	wclrtoeol(status_window);
	wrefresh(status_window);

	for (temp = 0; temp < MARKS; temp++)
		if (markchar[temp] == ch) {
			end = markpos[temp];
			break;
		}

	if (temp == MARKS) {
		wmove(status_window, 0, 30);
		waddstr(status_window, "Mark ");
		waddch(status_window, ch);
		waddstr(status_window, " unknown, press return");
		wclrtoeol(status_window);
		wrefresh(status_window);
		while (wgetch(status_window) != '');
		wmove(status_window, 0, 30);
		wclrtoeol(status_window);
		wrefresh(status_window);
		return;
	}
	
	if (end < start) {
		temp = start;
		start = end;
		end = temp;
	} else if (start == end) {
		wmove(status_window, 0, 30);
		waddstr(status_window, "Can't write 0 bytes, press return");
		wclrtoeol(status_window);
		wrefresh(status_window);
		while (wgetch(status_window) != '');
		wmove(status_window, 0, 30);
		wclrtoeol(status_window);
		wrefresh(status_window);
		return;
	}

	write_file(start, end, type);
}
