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

/**********************************************************************/
/*   Following  list  is  a  list  of  prompts  on  the command line  */
/*   together  with  the  functions  to  call  to handle the bad key  */
/*   being pressed at these prompts.				      */
/**********************************************************************/
list	compl_list = quote_list(
		"Edit file:",			"compl_file",
		"File to read:",		"compl_file",
		"Go to bookmark:",		"compl_bookmark",
		"Load keystroke file:",		"compl_keylib",
		"Cut to named scrap:",		"compl_scrap",
		"Copy to named scrap:",		"compl_scrap",
		"Paste named scrap:",		"compl_scrap"
		);
/**********************************************************************/
/*   The  following  list  is  used  to  handle abbreviations at the  */
/*   Command:  prompt  where  the  user  is  typing in a multi-token  */
/*   command line.						      */
/**********************************************************************/
list	compl_commands = quote_list(
		"cd",				"compl_cd"
		);

string	hist_last_response;
int	hist_buf,
	hist_no,
	hist_line,
	hist_last_line;

void
main()
{
	hist_buf = create_buffer("History-Buffer", NULL, 1);
}
void
_prompt_begin()
{
	int	curbuf,
		msg_level;
	string	curr_msg;
	

	curr_msg = inq_message();
	if (index(curr_msg, ":"))
		curr_msg = substr(curr_msg, 1, index(curr_msg, ":"));
	curbuf = inq_buffer();
	set_buffer(hist_buf);
	hist_no = -1;
	top_of_buffer();
	msg_level = inq_msg_level();
	set_msg_level(3);

	if (re_search(NULL, "<### " + quote_regexp(curr_msg) + " ###$") <= 0) {
		end_of_buffer();
		insert("### " + curr_msg + " ###\n");
		hist_last_line = -1;
		inq_position(hist_line);
		set_buffer(curbuf);
		set_msg_level(msg_level);
		return;
		}

	down();
	inq_position(hist_line);
	if (re_search(NULL, "<### * ###$") <= 0) {
		hist_last_line = inq_lines();
		hist_last_line -= hist_line;
		}
	else {
		inq_position(hist_last_line);
		hist_last_line -= 2;
		}
	goto_line(hist_line);
	set_buffer(curbuf);
	attach_buffer(curbuf);
	set_msg_level(msg_level);
}
string
_bad_key()
{
	string	line;
	int	curbuf,
		key_pressed;
	int	do_push_back = TRUE;

	curbuf = inq_buffer();
	key_pressed  = read_char();

	switch (key_pressed) {
	  case key_to_int("<Up>"):
		++hist_no;
	  case key_to_int("<Down>"):
		--hist_no;
	  case key_to_int("<Alt-L>"):
		return hist_last_response;
	  case key_to_int("<Tab>"):
		line = completion(inq_cmd_line(), inq_message());
		if (line != "") {
			if (do_push_back)
				push_back(key_to_int("<End>"));
			return line;
			}
		return inq_cmd_line();
	  }


	if (read(1) == "#" || hist_last_line < 0) {
		return "";
		}


	if (hist_no < 0)
		hist_no = hist_last_line - 1;
	if (hist_no < 0) {
		beep();
		return 0;
		}
	if (hist_no >= hist_last_line)
		hist_no = 0;
	set_buffer(hist_buf);
	move_rel(hist_no);
	line = trim(read());
	goto_line(hist_line);

	set_buffer(curbuf);

	return line;
}
void
_prompt_end()
{
	int	curbuf,
		line;
	string	cmd;

	if (inq_message() == "Command cancelled.")
		return;

	curbuf = inq_buffer();
	cmd = inq_cmd_line();
	if (strlen(cmd) > 2)
		hist_last_response = cmd;
	set_buffer(hist_buf);
	inq_position(line);

	if (strlen(cmd) > 1) {
		insert(cmd + "\n");
		if (re_search(NULL, "<#|{" + quote_regexp(cmd) + "$}") > 0) {
			if (read(1) != "#")
				delete_line();
			}
		}
	set_buffer(curbuf);
	attach_buffer(curbuf);
}
string
completion(string word, string prompt)
{
	int	len,
		n,
		ret,
		match_count;
	list	cmd_list,
		match_list;
	string	arg;
	
	if ((n = index(prompt, ":")) > 0) {
		prompt = substr(prompt, 1, n);
		if ((n = re_search(SF_NOT_REGEXP, prompt, compl_list)) >= 0)
			return execute_macro(compl_list[n+1], word);
		/***********************************************/
		/*   If  its  the  command  prompt then check  */
		/*   the  first  command  word  to  see if we  */
		/*   have a special handler.		       */
		/***********************************************/
		if (prompt == "Command:") {
			n = index(word, " ");
			if (n)
				arg = ltrim(substr(word, 1, n - 1));
			else
				arg = trim(ltrim(word));
			if ((n = re_search(NULL, "^" + quote_regexp(arg) + "$", 
			     compl_commands)) >= 0)
				return execute_macro(compl_commands[n+1], word);
			}
		}
	len = strlen(word);
	if (len == 0) {
		beep();
		return "";
		}

	match_count = -1;
	word = "<" + word;

	cmd_list = command_list();
	n = re_search(SF_IGNORE_CASE, word, cmd_list);
	while (n >= 0) {
		match_list[++match_count] = cmd_list[n];
		n = re_search(SF_IGNORE_CASE, word, cmd_list, n+1);
		}

	if (match_count < 0) {
		beep();
		return "";
		}

	if (match_count == 0)
		ret = 0;
	else {
		ret = select_list("Abbreviations", "", 1, match_list, TRUE,
			"help_display \"features/abbrev.hlp\" \"Help on Abbreviations\"");
		refresh();
		}

	if (ret < 0) {
		return "";
		}
	return match_list[ret - 1];
}
/**********************************************************************/
/*   Function called when we need to do filename completion.	      */
/**********************************************************************/
string
compl_file(string file)
{	extern int do_push_back;
	file = select_file(ltrim(file), NULL, FALSE);
	if (file != "")
		do_push_back = FALSE;

	return file;
}

/**********************************************************************/
/*   Function to display the bookmark popup.			      */
/**********************************************************************/
string
compl_bookmark(string str)
{	int	curbuf, curwin;
	int	buf, i, len, ret, win, width;
	list	bk_list;
	string	name, s;
	
	curbuf = inq_buffer();
	curwin = inq_window();
	
	bk_list = bookmark_list();
	len = length_of_list(bk_list);
	if (len <= 0)
		return "";
	buf = create_buffer("Bookmarks", NULL, TRUE);
	set_buffer(buf);
	for (i = 0; i < len; i += 4) {
		inq_names(NULL, NULL, name, bk_list[i+1]);
		/***********************************************/
		/*   Get the line where the bookmark is.       */
		/***********************************************/
		set_buffer(bk_list[i+1]);
		save_position();
		move_abs(bk_list[i+2], 1);
		s = trim(ltrim(read()));
		restore_position();
		set_buffer(buf);
		if (strlen(s) > 35)
			s = substr(s, 1, 32) + "...";
		sprintf(str, "%2d. %-14s %5d %5d: %s\n",
			bk_list[i], name, bk_list[i+2], bk_list[i+3], s);
		insert(str);
		}
	delete_line();
	sort_buffer();
	width = inq_line_length();
	if (width < 48)
		width = 48;
	win = sized_window(inq_lines()+1, width,
		"<Alt-D> to delete; <Enter> to select bookmark");
	ret = select_buffer(buf, win, SEL_NORMAL,
		book_keys());
	if (ret >= 0) {
		beginning_of_line();
		ret = atoi(read(6));
		}
	delete_buffer(buf);
	set_buffer(curbuf);
	set_window(curwin);
	attach_buffer(curbuf);
	refresh();
	if (ret >= 0) {
		push_back(key_to_int("<Enter>"));
		return "" + ret;
		}
		
	return "";
}
void
book_keys()
{
	assign_to_key("<Alt-D>", "book_delete");
}
void
book_delete()
{	int	ret;

	beginning_of_line();
	ret = atoi(read(6));
	delete_bookmark(ret);
	delete_line();
}
/**********************************************************************/
/*   Function  to  handle  the  user  typing the 'cd' command at the  */
/*   Command:  prompt.  Allow user to use the select_file() macro to  */
/*   complete the directory name.				      */
/**********************************************************************/
string
compl_cd(string cmd)
{
	int	n;
	string	file;
	extern int do_push_back;
	
	if ((n = index(cmd, " ")) != 0)
		cmd = ltrim(trim(substr(cmd, n + 1)));
	else
		cmd = "";
	file = select_file(cmd, NULL, TRUE);
	if (file != "")
		do_push_back = FALSE;
	return "cd " + file;
}
/**********************************************************************/
/*   Macro  called  when  user  hits  <Alt-H>  at  a  prompt  on the  */
/*   command  line.  Popup  a  help  window telling him/her what the  */
/*   options are.						      */
/**********************************************************************/
void
prompt_help()
{	string	msg = inq_message();
	int	i;
	
	if ((i = index(msg, ":")) > 0)
		msg = substr(msg, 1, i-1);
	cshelp("cshelp", msg);
	refresh();
}
