;**
;**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;**		Written by Dave Nanian and Michael Strickman.
;**
;**		Revision history:
;**		-----------------
;**		27 November 1985		Fixed bug that didn't allow moving back up
;**									to the top of the menu.
;**

;**
;**		menus.m:
;**
;**		This file implements a simple pop-up menu facility that is
;**	currently used by help.  The menus are in a fairly strange format
;**	described below:
;**
;**		1st line of file: ";" is the delimiter.
;**
;**			lx;by;rx;ty;Bottom_Line_Message
;**
;**		Where lx, by, rx and ty are the corners of the menu window, and
;**	Bottom_Line_Message is the message displayed in the bottom line.
;**	This control line is deleted when the menu is displayed.
;**
;**		The following lines have the following format:
;**
;**			Menu Text (spaces or tabs...) ;Routine_To_Call<;Parm_1;Parm_2>
;**
;**		The items in "<>" are optional.  Note that the window should
;**	not be wide enough to show the Routine_To_Call, etc.
;**

;**
;**		_menu_process:
;**
;**		Creates a pop-up menu, and allows the user to choose from the
;**	selections within.
;**

(macro _menu_process
	(
		(string			file
							menu_title
							_menu_dir
		)
		(int				orig_buffer
							menu_buffer
							lx
							by
							rx
							ty
							_menu_level
		)
		(global			_menu_level
							_menu_dir
		)
		(returns 1)

		(if (== _menu_level 0)
			(get_parm 2 _menu_dir)
		)
		(if (&& (&& (get_parm 0 file) (get_parm 1 menu_title)) (exist (+ _menu_dir file)))
			(
				(message "Creating menu...")
				(= menu_buffer (create_buffer menu_title (+ _menu_dir file) 1))
				(= orig_buffer (inq_buffer))
				(set_buffer menu_buffer)

				(if (_menu_parse lx by rx ty file)
					(
						(++ _menu_level)
						(delete_line)
						(create_window lx by rx ty file)
						(attach_buffer menu_buffer)
						(_highlight_line)

						(keyboard_push)
						(assign_to_key "%#80" "_menu_down")
						(assign_to_key "%#72" "_menu_up")
						(assign_to_key "#13" "_menu_pick")
						(assign_to_key "#27" "_menu_exit")
						(assign_to_key "#18989" "_exit")
						(refresh)
						(message "Select an item with the return key.")

						(process)

						(raise_anchor)
						(delete_window)
						(keyboard_pop)
						(-- _menu_level)
					)
				;else
					(error "Invalid menu format.")
				)
				(if (! (inq_views menu_buffer))
					(delete_buffer menu_buffer)
				)
				(set_buffer orig_buffer)

				(if (! _menu_level)
					(
						(call_registered_macro 1)
						(message "")
						(returns 0)
					)
				)
			)
		)
	)
)

;**
;**		_hilight_line:
;**
;**		Highlights the current menu line using marked areas.
;**

(macro _highlight_line
	(
		(move_rel 0 100)

		(if (inq_marked)
			(raise_anchor)
		)
		(drop_anchor)
		(move_rel 0 -100)
	)
)

;**
;**		_menu_exit:
;**
;**		If called during menu processing, all menu levels are exited.
;**

(macro _menu_exit
	(
		(int		curr_level)

		(= curr_level _menu_level)

		(while curr_level
			(
				(exit)
				(-- curr_level)
			)
		)
	)
)

;**
;**		_menu_down:
;**
;**		Moves the current selection down, not allowing the user to go past
;**	the bottom of the menu.
;**

(macro _menu_down
	(
		(down)

		(if (inq_position)
			(up)
		;else
			(_highlight_line)
		)
	)
)

;**
;**		_menu_up:
;**
;**		Moves the current selection up.
;**

(macro _menu_up
	(
		(int			line)

		(inq_position line)

		(if (!= line 1)
			(
				(up)
				(_highlight_line)
			)
		)
	)
)

;**
;**		_menu_pick:
;**
;**		Processes the menu line that is selected when the user presses
;**	return.
;**

(macro _menu_pick
	(
		(string			cmd_name
							arg_1
							arg_2
		)
		(= arg_2 (read))
		(= arg_2 (substr arg_2 (+ (index arg_2 "\;") 1)))
		(= arg_2 (substr arg_2 1 (- (strlen arg_2) 1)))

		(if (! (_menu_to_semi arg_2 cmd_name))
			(= cmd_name arg_2)
		;else
			(_menu_to_semi arg_2 arg_1)
		)
		(execute_macro cmd_name arg_1 arg_2)
		(message "Select an item with the return key.")
	)
)

(macro _menu_parse
	(
		(string		file_line
						curr_str
		)
		(int			ret_code)

		(= ret_code 1)
		(= file_line (read))
		(= file_line (substr file_line 1 (- (strlen file_line) 1)))

		(*= ret_code (_menu_to_semi file_line curr_str))
		(put_parm 0 (atoi curr_str))
		(*= ret_code (_menu_to_semi file_line curr_str))
		(put_parm 1 (atoi curr_str))
		(*= ret_code (_menu_to_semi file_line curr_str))
		(put_parm 2 (atoi curr_str))
		(*= ret_code (_menu_to_semi file_line curr_str))
		(put_parm 3 (atoi curr_str))

		(while (== (index file_line " ") 1)
			(= file_line (substr file_line 2))
		)
		(put_parm 4 file_line)
		(returns ret_code)
	)
)

;**
;**		_menu_to_semi:
;**
;**		This routine is used by help and the menu routines to parse
;**	the menu and file descriptor lines.
;**

(macro _menu_to_semi
	(
		(string		source
						result
		)
		(int			loc)

		(get_parm 0 source)

		(= loc (index source "\;"))

		(if loc
			(
				(= result (substr source 1 (- loc 1)))
				(put_parm 1 result)
				(= source (substr source (+ loc 1)))
				(put_parm 0 source)
				(returns 1)
			)
		;else
			(returns 0)
		)
	)
)
