/********************************************************************
 *                                                                  *
 *      CRISP - Custom Reduced Instruction Set Programmers Editor   *
 *                                                                  *
 *      (C) Paul Fox, 1989, 1990, 1991                              *
 *                                                                  *
 *                                                                  *
 *    Please See COPYLEFT notice.                                   *
 *                                                                  *
 ********************************************************************/

# include	"crisp.h"

# define	WINDOW_WIDTH	66 
int	kbd_help,
	help_level; 

void	
main()
{	extern int top_keyboard;

	keyboard_push();
	keyboard_typeables();
	kbd_help = inq_keyboard();
	assign_to_key("^G", "objects routines");
	assign_to_key("<Esc>", "help_esc");
	assign_to_key("<Keypad-minus>", "help_k_minus");
	copy_keyboard(top_keyboard, 
			"search_prev",
			"home", "end", "up", "down", "page_down", "page_up");
	keyboard_pop(1);
}
void
help_esc()
{
	while (help_level > 0) {
		-- help_level;
		exit();
		} 
}
void
help_k_minus()
{
	message("");
	-- help_level;
	exit();
}
list help_menu = {
	"Keyboard Summary    ",		"kbd_summary",
	"Macro Library     =>",		"message \"Not yet implemented\"",
	"Macro Primitives  =>",		"help_usage",
	"Explain macro     =>",		"explain",
	"User Guide        =>",		"ninfo \"user\"",
	"Programmers Guide =>",		"ninfo \"prog\"",
	"Config Guide      =>",		"ninfo \"config\"",
	};
void
help()
{
	int	users_buf;
	int	cur_keyboard;
	
	users_buf = inq_buffer();
	cur_keyboard = inq_keyboard();
	
	select_list("Help Menu", "", 2, help_menu, SEL_CENTER);
}
void
help_key_sum()
{
	assign_to_key("<Alt-H>", "help_keyboard_summary_help");
	assign_to_key("<Alt-K>", "help_key_list");
}
void
help_keyboard_summary_help()
{
	string cmd, arg;
	int i;
	extern int top_line;
	
	cmd = trim(ltrim(read()));
	cmd = ltrim(substr(cmd, index(cmd, ">") + 1));

	/*----------------------------------------
	/*   Now extract any argument if there is
	/*   one.
	/*----------------------------------------*/
	
	if (i = index(cmd, " ")) {
		arg = substr(cmd, i + 1);
		cmd = substr(cmd, 1, i - 1);
		}
	top_line += 2;
	explain(cmd);
	top_line -= 2;
}
list help_usage_list = {
	"Arithmetic Ops",	"help_section \"arith\"",
	"Buffers",		"help_section \"buffer\"",
	"Debugging",		"help_section \"debug\"",
	"Environment",		"help_section \"env\"",
	"Files",		"help_section \"file\"",
	"Floating Point",	"help_section \"float\"",
	"Keyboard",		"help_section \"kbd\"",
	"Lists",		"help_section \"list\"",
	"Macro Primitives",	"help_section \"macro\"",
	"Miscellaneous",	"help_section \"misc\"",
	"Movement",		"help_section \"movement\"",
	"Process Management",	"help_section \"proc\"",
	"Scrap",		"help_section \"scrap\"",
	"Screen",		"help_section \"screen\"",
	"Search & Translate",	"help_section \"search\"",
	"String Manipulation",	"help_section \"string\"",
	"Variable Declaration", "help_section \"var\"",
	"Windows",		"help_section \"window\""
	};
void
help_usage()
{
	select_list("Macro Subjects", "", 2, help_usage_list, SEL_CENTER);
}

void
help_section(string sec_name)
{
	string	filename, 
		message_string,
		cmd;
	int	win,
		buf,
		curbuf,
		curwin,
		width,
		ret;

	curbuf = inq_buffer();
	curwin = inq_window();

	filename = getenv("BHELP") + "/obj/" + sec_name + ".sec";

	buf = create_buffer("Index", filename, 1);
	set_buffer(buf);
	width = inq_line_length() + 1;
	if (width < 10)
		width = 10;
 
	message_string = "";
	win = sized_window(inq_lines() + 1, width, message_string);
	++ help_level;
	ret = select_buffer(buf, win, SEL_CENTER, 
		NULL, NULL, 1);

	cmd = trim(ltrim(read()));
	delete_buffer(buf);
	set_buffer(curbuf);
	set_window(curwin);
	attach_buffer(curbuf);
	if (ret < 0)
		return;
	explain(cmd);
}
void
explain()
{
	string	filename, 
		cmd;
	list	lst;
	int	win,
		buf, ibuf,
		curbuf,
		curwin;

	curbuf = inq_buffer();
	curwin = inq_window();
	get_parm(0, cmd, "Explain: ");
	cmd = trim(ltrim(compress(cmd)));
	if (cmd == "") {
		message("");
		return;
		}

	/***********************************************/
	/*   Edit  the  index  file to see which file  */
	/*   this entry is located in.		       */
	/***********************************************/
	filename = getenv("BHELP") + "/obj/prim.000";
	ibuf = create_buffer("explain-buf", filename, TRUE);
	set_buffer(ibuf);
	top_of_buffer();
	if (re_search(NULL, "^" + quote_regexp(cmd) + ":") <= 0) {
		error("Sorry, %s not yet available.", cmd);
		set_buffer(curbuf);
		delete_buffer(ibuf);
		return;
		}
	lst = split(trim(read()), ": ", 1);
	delete_buffer(ibuf);
	filename = getenv("BHELP") + "/" + lst[1];
	buf = create_buffer(cmd, filename, TRUE);
	set_buffer(buf);
	/***********************************************/
	/*   Delete   everything   before  and  after  */
	/*   this entry.			       */
	/***********************************************/
	goto_line(lst[3] + 1);
	drop_anchor(MK_LINE);
	end_of_buffer();
	delete_block();
	if (lst[2] != 1) {
		top_of_buffer();
		drop_anchor(MK_LINE);
		goto_line(lst[2] - 1);
		delete_block();
		}
	top_of_buffer();
	tabs(4);
	win = sized_window(inq_lines() + 1, inq_line_length() + 2, "");
	set_window(win);
	attach_buffer(buf);
	keyboard_push(kbd_help);
	++ help_level;
	message("");
	process();
	keyboard_pop(1);

	delete_window();
	delete_buffer(buf);
	set_buffer(curbuf);
	set_window(curwin);
}
void
help_display(string filename, string title, string section)
{
	int	curwin,
		curbuf,
		win,
		line,
		buf;

	filename = getenv("BHELP") + "/" + filename;
	curwin = inq_window();
	curbuf = inq_buffer();

	buf = create_buffer(title, filename, 1);
	set_buffer(buf);
	win = sized_window(inq_lines() + 1, WINDOW_WIDTH, "");
	set_window(win);
	attach_buffer(buf);
	if (section != "") {
		re_search(NULL, "<" + quote_regexp(section));
		inq_position(line);
		set_top_left(line);
		}

	keyboard_push(kbd_help);
	++ help_level;
	message("Type <Ctrl-G> to see section headings.");
	process();
	keyboard_pop(1);

	delete_window();
	delete_buffer(buf);

	set_window(curwin);
	set_buffer(curbuf);
}
void
kbd_summary()
{	int	i;
	string	key;
	list	l_bookmarks;
	list	l_buffers;
	list	l_marks;
	list	l_deletes;
	list	l_misc;
	list	l_window;
	list	l_searches;
	list	l_moves;
	int	buf, cur_buf, win;
	list	klist;
	int	klen;
	extern int users_buf, cur_keyboard;
	string	macro_name;

	message("Generating keyboard summary..."); 
	klist = key_list(cur_keyboard, NULL, users_buf);
	klen = length_of_list(klist);
	for (i = 0; i < klen; i += 2) {
		key = klist[i+1];
		macro_name = klist[i];
		if (index(key, "bookmark")) {
			if (key == "drop_bookmark 0") {
				l_bookmarks += "drop_bookmark";
				l_bookmarks += macro_name;
				}
			else if (index(key, "drop_bookmark") <= 0) {
				l_bookmarks += key;
				l_bookmarks += macro_name;
				}
			}
		else if (index(key, "mark") || key == "cut" || 
		     index(key, "copy") || index(key, "paste") || 
		     index(key, "block")) {
		     	switch (key) {
			  case "mark 2":
			  	l_marks += "column mark";
				break;
			  case "mark 3":
			  	l_marks += "line mark";
				break;
			  default:
				l_marks += key;
				break;
			  }
			l_marks += macro_name;
			}
		else if (index(key, "buffer") || index(key, "file")) {
			l_buffers = h_append(l_buffers, macro_name, key);
			}
		else if (index(key, "window") || index(key, "edge")) {
			l_window += key;
			l_window += macro_name;
			}
		else if (index(key, "delete")) {
			l_deletes = h_append(l_deletes, macro_name, key);
			}
		else if (index(key, "search") || index(key, "translate") || 
			index(key, "find")) {
			l_searches = h_append(l_searches, macro_name, key);
			}
		else if (index(key, "goto") || index(key, "up") || index(key, "down")
			|| index(key, "left") || index(key, "right") || 
			index(key, "home") || index(key, "end"))  {
			l_moves += key;
			l_moves += macro_name;
			}
		else {
			l_misc = h_append(l_misc, macro_name, key);
			}
		}
		
	message(int_to_key(ALT_H) + " for help; " + int_to_key(ALT_K) + " for key list");
	cur_buf = inq_buffer();
	buf = create_buffer("Command-Summary", NULL, 1);
	set_buffer(buf);
	
	/***********************************************/
	/*   Now insert the lists into the buffer.     */
	/***********************************************/
	if (length_of_list(l_moves))
		h_insert_list("Movement", l_moves);
	if (length_of_list(l_deletes))
		h_insert_list("Deletions", l_deletes);
	if (length_of_list(l_searches))
		h_insert_list("Search & Translates", l_searches);
	if (length_of_list(l_buffers))
		h_insert_list("Files & Buffers", l_buffers);
	if (length_of_list(l_marks))
		h_insert_list("Markers & Regions", l_marks);
	if (length_of_list(l_window))
		h_insert_list("Windows", l_window);
	if (length_of_list(l_bookmarks))
		h_insert_list("Bookmarks", l_bookmarks);
	if (length_of_list(l_misc))
		h_insert_list("Miscellaneous", l_misc);

	/***********************************************/
	/*   Pretify  the  macro  names  so they look  */
	/*   more english-like.			       */
	/***********************************************/
	top_of_buffer();
	re_translate(SF_GLOBAL, "objects ", "");
	top_of_buffer();
	re_translate(SF_GLOBAL, "_", " ");

	win = sized_window(inq_lines(buf), inq_line_length(buf), "");
	select_buffer(buf, win, SEL_NORMAL, help_key_sum());
	delete_buffer(buf);
	set_buffer(cur_buf);
	attach_buffer(cur_buf);
		
}
list
h_append(list lst, string key, string mac)
{	int	i;
	string	s;

	if ((i = re_search(NULL, "<" + quote_regexp(mac) + ">", lst)) >= 0) {
		s = lst[i+1];
		s += ", " + key;
		lst[i+1] = s;
		}
	else {
		lst += mac;
		lst += key;
		}
	return lst;
}
void
h_insert_list(string title, list l)
{	int	i;
	string	s;
 	string	s1;

	insert("***** " + upper(title) + " *****\n");
	drop_anchor(MK_LINE);
	for (i = 0; i < length_of_list(l); i += 2) {
		s1 = l[i];
		if (substr(s1, 1, 8) == "objects ")
			s1 = substr(s1, 9);
		sprintf(s, "%-21s %s\n", s1, l[i+1]);
		insert(s);
		}
	up();
	sort_buffer();
	raise_anchor();
	down();
	insert("\n");
}
/**********************************************************************/
/*   Macro  to  do  context-sensitive help. We get passed the string  */
/*   to lookup and see if its in the index file.		      */
/**********************************************************************/
void
cshelp(string dir, string str)
{	string	file;
	int	curbuf;
	int	curwin;
	int	buf, buf1, win;
	int	len;
		
	if (getenv("BHELP") == "") {
		error("BHELP environment variable not setup.");
		return;
		}
	/***********************************************/
	/*   Remember  the  buffer and window we came  */
	/*   from.				       */
	/***********************************************/
	curbuf = inq_buffer();
	curwin = inq_window();
	
	/***********************************************/
	/*   Read  the  index  file and see if we can  */
	/*   find a matching string.		       */
	/***********************************************/
	file = getenv("BHELP") + "/" + dir + "/INDEX";
	buf = create_buffer(file, file, TRUE);
	set_buffer(buf);
	
	/***********************************************/
	/*   Remove trailing newline.		       */
	/***********************************************/
	len = strlen(str);
	if (substr(str, len) == "\n")
		str = substr(str, 1, len - 1);
	/***********************************************/
	/*   Attempt  to  be  intelligent  and remove  */
	/*   anything  on  the right hand side of the  */
	/*   menu item.				       */
	/***********************************************/
	str = ltrim(str);
	if (substr(str, strlen(str) - 1) == "=>")
		str = substr(str, 1, strlen(str) - 2);
	else if (re_search(NULL, "  ", str) > 0)
		str = substr(str, 1, re_search(NULL, "  ", str) - 1);
	str = trim(str);
	if (re_search(NULL, "^" + quote_regexp(str) + ":\\c") <= 0) {
		/***********************************************/
		/*   Dont        print       errors       for  */
		/*   context-sensitive  help  because we have  */
		/*   a  prompt  on  the status line so theres  */
		/*   nowhere to print out message.	       */
		/***********************************************/
		if (dir == "cshelp")
			beep();
		else
			message("Sorry, no help for this topic.");
		delete_buffer(buf);
		set_buffer(curbuf);
		return;
		}
	/***********************************************/
	/*   Get the actual filename.		       */
	/***********************************************/
	file = getenv("BHELP") + "/obj/" +
		ltrim(trim(read())) + ".hlp";
	buf1 = create_buffer(file, file, TRUE);
	set_buffer(buf1);
	delete_buffer(buf);
	win = sized_window(inq_lines() + 1, inq_line_length() + 1, 
		"<Esc> to exit.");
	select_buffer(buf1, win);
	delete_buffer(buf1);
	
	set_buffer(curbuf);
	set_window(curwin);
	attach_buffer(curbuf);
}
/**********************************************************************/
/*   Macro  to  display  all key assignments (except the self-insert  */
/*   ones).							      */
/**********************************************************************/
void
help_key_list()
{
	list	lst;
	int	i, cur_buf, buf, win, len;
	extern int users_buf, cur_keyboard;
	extern int top_line;
	
	message("Generating key list..."); 
	lst = key_list(cur_keyboard, NULL, users_buf);
	len = length_of_list(lst);
	
	cur_buf = inq_buffer();
	buf = create_buffer("Key List", NULL, 1);
	set_buffer(buf);
	for (i = 0; i < len; i += 2) {
		insert(lst[i]);
		move_abs(0, 20);
		insert(lst[i+1]);
		insert("\n");
		}
	delete_line();
	sort_buffer();
	top_line++;
	win = sized_window(inq_lines(buf), inq_line_length(buf), "");
	select_buffer(buf, win, SEL_NORMAL, help_key_sum());
	delete_buffer(buf);
	set_buffer(cur_buf);
	attach_buffer(cur_buf);
	top_line--;
}
