/********************************************************************
 *                                                                  *
 *      CRISP - Custom Reduced Instruction Set Programmers Editor   *
 *                                                                  *
 *      (C) Paul Fox, 1989                                          *
 *                                                                  *
 *    Please See COPYLEFT notice.                                   *
 *                                                                  *
 ********************************************************************/
# include	"crisp.h"

# define	GREP_COMMAND	"egrep"	/* Faster than normal grep. */

int	grep_buf,
	grep_line_no = 1,
	spell_buf,
	spell_line_no;
string	grep_old_file;

void
main()
{

	grep_buf = create_buffer("GREP-Buffer", NULL, 0);
}
/*
/*   Macro to report how many words in current buffer, and
/*   display average word length.
/**/
void
wc()
{
	string	tmp_file,
		buf;
	int	curbuf,
		tmp_buf,
		num_words,
		num_chars;

	save_position();

	top_of_buffer();
	drop_anchor(MK_LINE);
	end_of_buffer();

	sprintf(tmp_file, "/tmp/gr.wc%d", getpid());
	write_block(tmp_file);
	sprintf(buf, "wc -wc %s", tmp_file);
	message("Counting number of words...");
	tmp_buf = perform_unix_command(buf, "wc-buffer");

	curbuf = inq_buffer();
	set_buffer(tmp_buf);
	end_of_buffer();
	beginning_of_line();
	re_search(NULL, "[0-9]");
	num_words = atoi (read());
	re_search(NULL, " \\c[0-9]");
	num_chars = atoi (read());

	message("Words: %d Avg. len: %d", num_words, num_chars / num_words);

	remove(tmp_file);
	
	set_buffer(curbuf);
	delete_buffer(tmp_buf);
	attach_buffer(curbuf);
	restore_position();
}
/*
/*   Macro to perform a grep and display buffers at location
/*   of matched strings.
/**/
void
grep()
{
	string	buf,
		pattern,
		msg,
		files;
	int	curbuf,
		grep_win,
		num_lines;

	curbuf = inq_buffer();

	get_parm(0, pattern, "GREP pattern: ");
	pattern = trim (ltrim(pattern));
	if (pattern == "")
		return;
	get_parm(1, files, "GREP files: ");

	sprintf(buf, "%s -n %s %s /dev/null </dev/null", GREP_COMMAND, pattern, files);
	message("Locating text...");
	assign_to_key("<Ctrl-N>", "grep_next");
	assign_to_key("<Ctrl-P>", "grep_prev");
	grep_buf = perform_unix_command(buf, "GREP-Buffer", grep_buf);
	message("");

	set_buffer(grep_buf);
	end_of_buffer();
	insert("\n");
	top_of_buffer();
	num_lines = inq_lines();
	/*----------------------------------------
	/*   Dont let autosave and the exit code know
	/*   we changed the buffer.
	/*----------------------------------------*/
	set_buffer_flags(~ BF_CHANGED);
	set_buffer(curbuf);

	if (num_lines <= 1) {
		error("No matching lines found.");
		return;
		}

	msg = int_to_key(ALT_E) + " to edit, <Enter> to select, <Esc> to quit.";
	grep_win = sized_window(num_lines, -1, msg);

	grep_line_no = select_buffer(grep_buf, grep_win, NULL,
		assign_to_key("<Alt-E>", "grep_edit"),
		NULL,
		"help_display \"features/grep.hlp\" \"Help on Grep Window\"", 
		NULL, FALSE);
	if (grep_line_no < 0)
		return;

	grep_display();
}
void
grep_edit()
{
	string	answer;
	
	raise_anchor();
	while (1) {
		message("Type <Esc> to terminate translate mode.");
		select_editable();
		answer = prompt_ync("GREP translate/continue/abort ? ", "tca");
		if (answer != "c")
			break;
		}
	if (answer == "t")
		grep_translate();
	
}
string
prompt_ync(string msg, string responses)
{
	string	answer;
	
	answer = "9";
	while (index(responses, answer) == 0) {
		get_parm(NULL, answer, msg, 1);
		answer = lower(answer);
		}
	return answer;
}
void
grep_translate()
{
	int	line,
		i, j,
		buf,
		line_no;
	string	lbuf,
		filename;
	
	buf = inq_buffer();
	top_of_buffer();
	line = 1;
	
	while (line < inq_lines()) {
		lbuf = read();
		i = index(lbuf, ":");
		filename = substr(lbuf, 1, i - 1);
		lbuf = substr(lbuf, i + 1);
		j = index(lbuf, ":");
		line_no = atoi(substr(lbuf, 1, j - 1));
		lbuf = substr(lbuf, j + 1);
		edit_file(filename);
		move_abs(line_no, 0);
		delete_line();
		insert(lbuf);
		message("File='%s' line=%d", filename, line_no);
		set_buffer(buf);
		++ line;
		down();
		}
	attach_buffer(buf);
}

void
grep_next()
{
	++ grep_line_no;
	grep_display();
}
void
grep_prev()
{
	-- grep_line_no;
	grep_display();
}
void
grep_display()
{
	string	text,
		filename;
	int	lines,
		colon,
		curbuf,
		line_no;

	curbuf = inq_buffer();
	set_buffer(grep_buf);
	lines = inq_lines();

	if (grep_line_no < 1 || grep_line_no >= lines) {
		grep_line_no = 1;
		message("No more matching lines.");
		return;
		}
	move_abs(grep_line_no, 1);
	text = read();

	colon = index(text, ":");
	filename = substr(text, 1, colon - 1);
	line_no = atoi(substr(text, colon + 1));
	if (filename == grep_old_file)
		set_buffer(curbuf);
	else {
		edit_file(filename);
		top_of_buffer();
		grep_old_file = filename;
		}
	move_abs(line_no, 1);
	message("<Ctrl-P> previous match, <Ctrl-N> next match.");
}
/*
/*   Macro to perform spell on the current buffer, and then allow user
/*   to move from word to word. Note that spell checking is done with
/*   BRITISH spelling.
/**/
void
spell()
{
	string	tmp_file,
		buf,
		mydict;
	int	curbuf,
		num_lines;

	curbuf = inq_buffer();

	top_of_buffer();
	drop_anchor(MK_LINE);
	end_of_buffer();

	sprintf(tmp_file, "/tmp/gr.sp%d", getpid());
	write_block(tmp_file);
	
	/******************************************************
	 *    If  user  has  a private dictionary, then use   *
	 *    that.    Private    dictionary    is   either   *
	 *    specified  by  BDICT  env variable or we look   *
	 *    in $HOME/mydict.				      *
	 ******************************************************/
	mydict = getenv("BDICT");
	if (mydict == "") {
		sprintf(mydict, "%s/mydict", getenv("HOME"));
		if (!exist(mydict))
			mydict = "";
		}
	if (mydict != "")
		sprintf(buf, "spell -b +%s %s", mydict, tmp_file);
	else
		sprintf(buf, "spell -b %s", tmp_file);
	message("Checking for mis-spelled words...");
	spell_buf = perform_unix_command(buf, "wc-buffer");

	remove(tmp_file);

	set_buffer(spell_buf);
	end_of_buffer();
	insert("\n");
	top_of_buffer();
	num_lines = inq_lines();
	set_buffer(curbuf);

	if (num_lines <= 1) {
		error("No spelling mistakes.");
		return;
		}

	spell_line_no = 0;

	assign_to_key("<Ctrl-N>", "spell_next");
	assign_to_key("<Ctrl-P>", "spell_prev");
	spell_next();

}
void
spell_next()
{
	while (spell_display(spell_line_no + 1) >= 0)
		continue;
}
void
spell_prev()
{
	while (spell_display(spell_line_no - 1) >= 0)
		continue;
}
/*
/*   macro to display next incorrect word on screen and allow
/*   user to type in a correction.
/*
/*   macro returns -1 if an error occurs;
/*		0 user doesnt want to correct word
/*		1 user corrected word.
/**/
int
spell_display(int word_no)
{
	int	curbuf;
	string	word,
		new_word,
		buf;

	if (word_no <= 0)
		word_no = 1;

	curbuf = inq_buffer();

	/*
	/*   Read next word from list.
	/**/
	set_buffer(spell_buf);
	goto_line(word_no);
	spell_line_no = word_no;
	word = trim(ltrim(compress(read())));
	set_buffer(curbuf);

	if (word == "") {
		message("No further words to correct.");
		return -1;
		}

	/*
	/*   Now get word onto screen and let user decide to translate
	/*   word.
	/**/
	top_of_buffer();
	sprintf(buf, "Correct '%s': ", word);
	message("Searching for '%s'...", word);
	re_search(SF_NOT_REGEXP, word);
	drop_anchor(MK_NORMAL);
	right(strlen(word));
	set_center_of_window();
	refresh();

	if (get_parm(NULL, new_word, buf, NULL, word) <= 0) {
		message("<Ctrl-N>/<Ctrl-P> checks next or previous word.");
		left(strlen(word));
		raise_anchor();
		return -1;
		}

	message("");
	left(strlen(word));
	raise_anchor();

	if (new_word == "" || new_word == word)
		return 0;
	translate(word, new_word, NULL, 0, 1);
	return 0;
}
