!++ ! FILENAME: BUFFER_MGT.TPU ! FUNCTION: This file contains TPU procedures which allow the user to edit and ! manipulate files and buffers. ! AUTHOR: Steven K. Shapiro, (C) Copyright SKS Enterprises, Austin TX. ! All Rights Reserved. ! ! The format, structure and contents of this file are the sole ! property of Steven K. Shapiro and are copyrighted to SKS ! Enterprises, Austin Texas. ! ! The information may be freely distributed, used and modified ! provided that the information in this header block is not ! changed, altered, disturbed or modified in any way. ! ! DATE: 25-AUG-1987 Original. ! HISTORY: current. ! CONTENTS: ! evedt$get_wild_file (file_spec_str) ! eve_toggle_winum_get ! eve_first_user_buffer ! eve_prior_buffer ! eve_nxt_buffer ! eve_prv_buffer ! bufed_list_buffers(show_system) ! bufed_select_buffer ! bufed_remove_buffer ! bufed_get_the_buffer(the_name, the_buffer) ! bufed_destroy_buffer(the_name, the_buffer) ! eve_dbuffer ! eve_trim_buffer ! eve_update_file ! eve_toggle_nowrite ! eve_toggle_nomodify ! eve_mess_up ! eve_mess_down ! eve_count_page ! eve_get_line ! eve_xrecall (command_name) ! !23456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H !-- !*----------------------------------------------------------------------------*! procedure buffer_mgt_module_ident local file_date, module_vers; file_date := "-<( 1-DEC-1988 15:36:17.88 )>-"; module_vers := substr(file_date,5,2) + substr(file_date,8,3) + substr(file_date,14,2) + substr(file_date,17,5) ; return module_vers; endprocedure; !*----------------------------------------------------------------------------*! ! ! Get all the files that match the file specification. ! The file specification must be a string containing a wildcard specification. ! This is an internal procedure and may not be bound to a key. ! ! SKS 2-NOV-1988 add checking for command line switches. ! procedure evedt$get_wild_file_old (file_spec_str) ! local target_file_spec, get_file_name, ! Local copy of get_file_parameter temp_buffer_name, ! String for buffer name based on get_file_name temp_file_name, ! First file name string returned by file_search wild_find, new_buffer, u_file_count, u_file_spec, u_file_name; u_file_count := 0; target_file_spec := file_spec_str; wild_find := index(target_file_spec,'*'); u_f_buf_name := eve$x_null; u_file_spec := file_search (''); loop u_file_spec := file_search (target_file_spec); if (u_file_spec = '') then if (wild_find <> 0) AND (u_file_count = 0) then message ('no files found'); exitif u_file_spec = ''; endif; if u_f_buf_name = eve$x_null then message ('no files found'); get_file_name := target_file_spec; temp_file_name := get_file_name; temp_buffer_name := file_parse (get_file_name, eve$kt_null, eve$kt_null, name) + file_parse (get_file_name, eve$kt_null, eve$kt_null, type); evedt$x_prior_buffer := current_buffer; new_buffer := eve$create_buffer (temp_buffer_name, get_file_name, temp_file_name); if new_buffer <> 0 then set (output_file,new_buffer,get_info(new_buffer,"file_name")); set (eob_text, new_buffer, "[End of file]"); set (margins, new_buffer, eve$x_default_left_margin, get_info (current_window, eve$kt_width) - eve$x_default_right_margin); if (get_info(command_line, "read_only")) then set (no_write, new_buffer, ON); endif; eve$set_status_line (current_window); else eve_buffer (temp_buffer_name); endif; else if u_file_count = 1 then message ('Opened 1 file'); else message ('Opened '+ str(u_file_count)+ ' files'); endif; endif; exitif u_file_spec = ''; else u_file_count := u_file_count + 1; u_file_name := file_parse (u_file_spec,' ',' ',NAME); u_file_type := file_parse (u_file_spec,' ',' ',type); u_buf_name := u_file_name + u_file_type; new_buf := create_buffer (u_buf_name, u_file_spec); ! check the command line switches and set file info accordingly if new_buf <> 0 then ! /NOOUTPUT implies NO_WRITE to ON for the buffer. if not get_info (COMMAND_LINE, "output") then set (NO_WRITE, new_buf, ON); endif; ! /READ_ONLY implies NO_WRITE to ON and MODIFIABLE to OFF for the buffer. if get_info (COMMAND_LINE, "read_only") then set (NO_WRITE, new_buf, ON); set (MODIFIABLE, new_buf, OFF); endif; ! /WRITE implies NO_WRITE to OFF and MODIFIABLE to ON for the buffer. if get_info (COMMAND_LINE, "write") then set (NO_WRITE, new_buf, OFF); set (MODIFIABLE, new_buf, ON); endif; ! /MODIFY implies MODIFIABLE to ON for the buffer. if get_info (COMMAND_LINE, "modify") then set (MODIFIABLE, new_buf, ON); endif; ! /NOMODIFY implies MODIFIABLE to OFF for the buffer. if get_info (COMMAND_LINE, "nomodify") then set (MODIFIABLE, new_buf, OFF); endif; endif; if u_f_buf_name = eve$x_null then u_f_buf_name := u_buf_name; endif; endif; endloop; if u_f_buf_name <> eve$x_null then eve_buffer (u_f_buf_name); endif; endprocedure; !*----------------------------------------------------------------------------*! ! ! Get all the files that match the file specification. The file specification ! must be a string containing a wildcard specification. ! This is an internal procedure and may not be bound to a key. ! procedure evedt$get_wild_file (file_spec_str) ! local target_file_spec, ! Local copy of file_spec_str. wild_find, ! Wildcard in filename flag. new_buffer, ! Buffer to be created for the found file. search_file_spec, ! String of file returned by search. search_file_name, ! Parsed name of searched file. search_file_type, ! Parsed extension of searched file. search_file, ! Concatenated search file name & type. found_search_file, ! Found version of search_file. found_file_count; ! Number of files found. target_file_spec := file_spec_str; wild_find := index(target_file_spec,'*'); found_search_file := eve$x_null; search_file_spec := file_search (''); found_file_count := 0; ! Loop until we've found all of the files. loop search_file_spec := file_search (target_file_spec); if (search_file_spec = '') then ! No file found in search string ! Looking for wildcards, but none were ever found. if (wild_find <> 0) AND (found_file_count = 0) then message ('No files found.'); exitif search_file_spec = ''; ! Let's forget finding any more files. endif; ! We got all the files were gonna get. Let's see how many. if found_file_count = 1 then message ('Opened 1 file'); else message ('Opened '+ str(found_file_count)+ ' files'); endif; exitif search_file_spec = ''; ! Let's go home. ! Search found a file. Increment our found file counter, and get ! all of the info to create a buffer and put it in there. else found_file_count := found_file_count + 1; search_file_name := file_parse (search_file_spec,' ',' ',NAME); search_file_type := file_parse (search_file_spec,' ',' ',TYPE); search_file := search_file_name + search_file_type; created_buffer := create_buffer (search_file, search_file_spec); ! check the command line switches and set file info accordingly if created_buffer <> 0 then ! /NOOUTPUT implies NO_WRITE to ON for the buffer. if not get_info (COMMAND_LINE, "output") then set (NO_WRITE, created_buffer, ON); endif; ! /READ_ONLY implies NO_WRITE to ON and MODIFIABLE to OFF for the buffer. if get_info (COMMAND_LINE, "read_only") then set (NO_WRITE, created_buffer, ON); set (MODIFIABLE, created_buffer, OFF); endif; ! /WRITE implies NO_WRITE to OFF and MODIFIABLE to ON for the buffer. if get_info (COMMAND_LINE, "write") then set (NO_WRITE, created_buffer, OFF); set (MODIFIABLE, created_buffer, ON); endif; ! /MODIFY implies MODIFIABLE to ON for the buffer. if get_info (COMMAND_LINE, "modify") then set (MODIFIABLE, created_buffer, ON); endif; ! /NOMODIFY implies MODIFIABLE to OFF for the buffer. if get_info (COMMAND_LINE, "nomodify") then set (MODIFIABLE, created_buffer, OFF); endif; endif; ! Assign our initial found search file to the first file found. if found_search_file = eve$x_null then found_search_file := search_file; endif; endif; endloop; ! All done. We change back to the first file found in the search. if found_search_file <> eve$x_null then eve_buffer (found_search_file); endif; endprocedure; !*----------------------------------------------------------------------------*! PROCEDURE eve_toggle_winum_get ! Toggle 1/2 windows, show map, get file IF eve$x_number_of_windows <> 1 THEN eve_one_window; ELSE eve_two_windows; eve_get_file(''); ENDIF; ENDPROCEDURE; !*----------------------------------------------------------------------------*! PROCEDURE eve_first_user_buffer ! Position the cursor in the first user buffer in the list of buffers. local u_f_buf; u_f_buf := get_info (BUFFER, 'first'); LOOP u_s_flag := get_info (u_f_buf, 'system'); IF u_s_flag = 0 THEN eve_buffer(get_info (u_f_buf, 'name')); EXITIF u_s_flag = 0; ENDIF; u_f_buf := GET_INFO (BUFFER, 'next'); ENDLOOP; ENDPROCEDURE; !*----------------------------------------------------------------------------*! procedure eve_prior_buffer if ((evedt$x_prior_buffer = 0) or (get_info(evedt$x_prior_buffer, "type") <> buffer)) then message ("No Prior Buffer"); else eve_buffer(get_info(evedt$x_prior_buffer, "name")); endif; endprocedure; !*----------------------------------------------------------------------------*! procedure eve_nxt_buffer ! ! Positions the cursor in the next user buffer in the list of buffers. local u_c_buf, u_n_buf; u_c_buf := get_info (buffer, 'current'); if u_c_buf <> 0 then u_n_buf := get_info (buffer, 'next'); loop exitif (u_n_buf = 0); exitif (get_info(u_n_buf,"system") = FALSE); u_n_buf := get_info(BUFFER, "next"); endloop; if u_n_buf = 0 then message ('Wrapping buffer list forward.'); u_n_buf := get_info (buffer, 'first'); ! get first buffer loop ! same as above exitif (u_n_buf = 0); exitif (get_info(u_n_buf,"system") = FALSE); u_n_buf := get_info (buffer, 'next'); endloop; if u_n_buf = 0 ! no buf, exit then message ('no more buffers'); else eve_buffer(get_info (u_n_buf, 'name')); ! get that buffer endif; else eve_buffer(get_info (u_n_buf, 'name')); endif; else message ("No current buffer"); endif; endprocedure !*----------------------------------------------------------------------------*! ! ! Positions the cursor in the previous buffer in the list of buffers. ! When it gets to the first buffer, it will loop back to the last buffer. procedure eve_prv_buffer local u_c_buf, u_n_buf; u_c_buf := get_info (buffer, 'current'); ! current user buffer if u_c_buf <> 0 then u_n_buf := get_info (buffer, 'previous'); ! get previous buffer loop exitif (u_n_buf = 0); ! if no buffer, exit exitif (get_info(u_n_buf,"system") = FALSE); ! if system buf, exit u_n_buf := get_info (buffer, 'previous'); ! get previous buffer endloop; if u_n_buf = 0 ! if no buffer, loop then message ('Wrapping buffer list backward.'); u_n_buf := get_info (buffer, 'last'); ! get last buffer loop ! same as above exitif (u_n_buf = 0); exitif (get_info(u_n_buf,"system") = FALSE); u_n_buf := get_info (buffer, 'previous'); endloop; if u_n_buf = 0 ! no buf, exit then message ('no more buffers'); else eve_buffer(get_info (u_n_buf, 'name')); ! get that buffer endif; else eve_buffer(get_info (u_n_buf, 'name')); ! get that buffer endif; else message ("No current buffer"); ! should never happen, catastrophic fail endif; ENDPROCEDURE !*----------------------------------------------------------------------------*! ! ! The following procedure actually creates the formatted buffer list. ! It also temporarily rebinds the SELECT and REMOVE keys to routines ! that goto the buffer listed on the line the cursor is on or to ! delete it. ! ! Inputs: ! show_system Flag - causes system buffers to be listed ! PROCEDURE bufed_list_buffers(show_system) ! Build the buffer list local last_buffer, ! Used to tell when we've done the last one the_buffer, ! The buffer being listed temp; ! Used to build the record count as a string eve_buffer("LIST BUFFER"); set(system, current_buffer); set(no_write, current_buffer); erase(current_buffer); message("Collecting buffer list"); last_buffer := get_info(buffers, "last"); the_buffer := get_info(buffers, "first"); loop exitif (the_buffer = 0); if (show_system or (get_info(the_buffer, "system") = 0)) then split_line; evedt_insert_text(" "); evedt_insert_text(get_info(the_buffer, "name")); temp := fao("!6UL ", get_info(the_buffer, "record_count")); if (current_offset >= 30) then evedt_insert_text(""); else loop exitif (current_offset > 30); evedt_insert_text(" "); endloop; endif; evedt_insert_text(temp); if (get_info(the_buffer, "modified")) then evedt_insert_text("Modified "); else evedt_insert_text(" "); endif; if (get_info(the_buffer, "no_write")) then evedt_insert_text("No-write "); else evedt_insert_text(" "); endif; if not get_info (the_buffer, "modifiable") then evedt_insert_text("No-modify "); else evedt_insert_text(" "); endif; if (get_info(the_buffer, "system")) then evedt_insert_text("System "); else evedt_insert_text(" "); endif; if (get_info(the_buffer, "permanent")) then evedt_insert_text("Perm"); else evedt_insert_text(" "); endif; temp := current_line; move_horizontal (-current_offset); erase (create_range (mark (none), end_of (current_buffer), none)); edit (temp, trim_trailing); copy_text (temp); endif; exitif (the_buffer = last_buffer); the_buffer := get_info(buffers, "next"); endloop; if (evedt_defined_procedure("evedt_sort")) then message("Sorting buffer list"); execute('evedt_sort ( current_buffer , "" ); '); endif; position(beginning_of(current_buffer)); loop temp := evedt_search_quietly("", FORWARD); exitif (temp = 0); position(temp); erase(temp); evedt_insert_text(" -"); split_line; evedt_insert_text(" "); endloop; position(beginning_of(current_buffer)); evedt_insert_text(" Buffer Name Lines Attributes"); split_line; position(beginning_of(current_buffer)); move_vertical(2); move_horizontal(2); if (not bufed_x_active) then set(informational,off); evedt_key("bufed_select_buffer", period, "select buffer", "bufed_select_key"); evedt_key("bufed_remove_buffer", kp6, "remove buffer", "bufed_remove_key"); ! LK201 REMOVE & INSERT Keys evedt_key("bufed_select_buffer", e4, "select buffer", "bufed_select_key"); evedt_key("bufed_remove_buffer", e3, "remove buffer", "bufed_remove_key"); set(informational,on); endif; bufed_x_active := TRUE; message(" "); endprocedure !*----------------------------------------------------------------------------*! ! This routine is temporarily bound to the SELECT. It puts you in ! the buffer listed on the current line, and restores the original ! meanings of the SELECT and REMOVE keys. It only works in the ! "LIST BUFFERS" buffer. If it is invoked outside of that buffer, ! it restores the original bindings of the SELECT and REMOVE keys, ! and executes the code originally associated with SELECT. ! procedure bufed_select_buffer ! Goto the buffer pointed to local the_buffer, ! Pointer to the buffer the_name, ! Name of the buffer as a string the_type; ! Type of the code bound to the key if (get_info(current_buffer, "name") <> "LIST BUFFER") then message("Not in the LIST BUFFER"); set(informational,off); evedt_restore_key("bufed_select_key"); evedt_restore_key("bufed_remove_key"); set(informational,on); bufed_x_active := FALSE; the_type := get_info(bufed_select_key_pgm, "type"); if ((the_type = LEARN) or (the_type = PROGRAM) or (the_type = STRING)) then execute(bufed_select_key_pgm); endif; else if (bufed_get_the_buffer(the_name, the_buffer) <> 0) then eve_buffer(the_name); set(informational,off); evedt_restore_key("bufed_select_key"); evedt_restore_key("bufed_remove_key"); set(informational,on); bufed_x_active := FALSE; endif; endif; endprocedure; !*----------------------------------------------------------------------------*! ! This routine is temporarily bound to the REMOVE key. It deletes ! the buffer listed on the current line. It only works in the ! "LIST BUFFER" buffer. If it is struck outside of that buffer, ! it restores the original binding of the SELECT and REMOVE keys and ! and executes the program originally associated with the REMOVE key. ! The routine bufed_select_buffer also unbinds this key. ! procedure bufed_remove_buffer ! Delete the buffer pointed to local the_buffer, ! Pointer to the buffer the_name, ! Name of the buffer as a string the_type; ! Type of the code bound to the key if (get_info(current_buffer, "name") <> "LIST BUFFER") then message("Not in the LIST BUFFER"); set(informational,off); evedt_restore_key("bufed_select_key"); evedt_restore_key("bufed_remove_key"); set(informational,on); bufed_x_active := FALSE; the_type := get_info(bufed_remove_key_pgm, "type"); if ((the_type = LEARN) or (the_type = PROGRAM) or (the_type = STRING)) then execute(bufed_remove_key_pgm); endif; else if (bufed_get_the_buffer(the_name, the_buffer) <> 0) then if (bufed_destroy_buffer(the_name, the_buffer)) then move_horizontal(-current_offset); move_vertical(1); move_horizontal(-2); if (current_character = "-") then move_horizontal(-current_offset); erase_line; else move_horizontal(-current_offset); endif; erase_line; endif; endif; endif; endprocedure !*----------------------------------------------------------------------------*! ! This routine scans the line the cursor is on and if it is in the ! proper format for a buffer listing, it reurns both the name of ! the buffer and a pointer to it. ! procedure bufed_get_the_buffer(the_name, the_buffer) ! Scan a buffer line local the_start; ! A mark pointing to the buffer name. the_name := ""; the_buffer := 0; if (get_info(current_buffer, "name") <> "LIST BUFFER") then message("Not in the LIST BUFFER"); else move_horizontal(-current_offset); if (search(ANCHOR & " ", FORWARD) = 0) then message("This is not a buffer listing"); else move_horizontal(2); the_start := mark(none); move_horizontal(-2); move_vertical(1); move_horizontal(-2); if (current_character = "-") then move_horizontal(-2); else move_horizontal(32-current_offset); endif; the_name := create_range(the_start, mark(none), bold); the_name := substr(the_name, 1, length(the_name)); edit(the_name, TRIM_TRAILING, OFF); the_buffer := evedt_find_buffer(the_name); if (the_buffer = 0) then message("No such buffer: " + the_name); endif; move_horizontal(2-current_offset); endif; endif; bufed_get_the_buffer := the_buffer; endprocedure; !*----------------------------------------------------------------------------*! ! ! This routine actually destroys a specific buffer. ! ! Inputs: ! the_name The name of the buffer (display only) ! the_buffer Pointer to the buffer to destroy ! procedure bufed_destroy_buffer(the_name, the_buffer) ! Delete a buffer local answer, problem, new_buffer; bufed_destroy_buffer := FALSE; problem := ""; if ((get_info(the_buffer, "modified")) and (get_info(the_buffer, "record_count") <> 0)) then problem := "modified "; endif; if (get_info(the_buffer, "system")) then problem := problem + "system "; endif; if (problem <> "") then answer := read_line(substr(the_name, 1, 32) + " is a " + problem + "buffer. Are you sure? "); change_case (answer, lower); if ((length (answer) = 0) or (answer <> substr ("yes", 1, length (answer)))) then message("No buffer deleted."); return; endif; endif; if (current_buffer <> the_buffer) then delete(the_buffer); else new_buffer := get_info(buffers, "first"); loop exitif (new_buffer = 0); exitif ((get_info(new_buffer, "system") = FALSE) and (new_buffer <> current_buffer)); new_buffer := get_info(BUFFERS, "next"); endloop; if (new_buffer = 0) then eve_buffer("Main"); else eve_buffer(get_info(new_buffer, "name")); endif; if (get_info (the_buffer, "name") = "MAIN") then erase (the_buffer); else delete (the_buffer); endif; endif; bufed_destroy_buffer := TRUE; message("Deleted buffer " + the_name); new_buffer := get_info(BUFFERS, "first"); endprocedure; !*----------------------------------------------------------------------------*! ! procedure eve_dbuffer ! ! Delete the current buffer, and position the cursor in the prior buffer ! if one exists, otherwise position the cursor in the first user buffer ! in the buffer list that is not the current buffer, if no other user buffer ! exists create the Main buffer and position the cursor in it, if this is ! the main buffer just erase it. local this_buffer, this_buffers_name; this_buffers_name := get_info (current_buffer, "name"); this_buffer := current_buffer; eve_prior_buffer; bufed_destroy_buffer(this_buffers_name, this_buffer); endprocedure; !*----------------------------------------------------------------------------*! procedure eve_trim_buffer message (message_text(EVE$_TRIMMING )); eve$trim_buffer( current_buffer ); message (message_text(EVE$_DONETRIM )); endprocedure !*----------------------------------------------------------------------------*! PROCEDURE eve_update_file ! This procedure will erase the current buffer and then re-include the ! file that this buffer points to. This is good for use as a tool when ! looking at log files which are being updated dynamically. ! ! If the buffer has been modified, it will prompt to verify. local current_file; current_file := get_info(current_buffer,"file_name"); if get_info (current_buffer, "modified") then if eve$insist_y_n ("This buffer has been modified. Delete it ? (Y,n) ") then erase (current_buffer); eve_include_file (current_file); endif; else erase (current_buffer); eve_include_file (current_file); endif; ENDPROCEDURE; !*----------------------------------------------------------------------------*! PROCEDURE eve_toggle_nowrite if get_info (current_buffer, "no_write") then set (no_write, current_buffer, off); ! make buffer writeable on exit else set (no_write, current_buffer, on); ! set buffer to NO_WRITE mode endif; eve$set_status_line (current_window); ENDPROCEDURE; !*----------------------------------------------------------------------------*! PROCEDURE eve_toggle_nomodify if not get_info (current_buffer, "modifiable") then set (modifiable, current_buffer, on); ! make buffer modifiable else set (modifiable, current_buffer, off); ! set buffer non modifiable endif; eve$set_status_line (current_window); ENDPROCEDURE; !*----------------------------------------------------------------------------*! ! Scroll the message window up procedure eve_mess_up scroll(message_window,-1); endprocedure; !*----------------------------------------------------------------------------*! ! Scroll the message window down procedure eve_mess_down scroll(message_window,1); endprocedure; !*----------------------------------------------------------------------------*! procedure eve_count_page local repetitions; on_error message (fao ("End Of File encountered after !SL lines.", repetitions)); return; endon_error; repetitions := 0; loop exitif repetitions = 60; if current_direction = forward then move_vertical (1); else move_vertical (-1); endif; repetitions := repetitions + 1; endloop; endprocedure; !*----------------------------------------------------------------------------*! ! ! Returns the current line number. A variation on eve_what_line. procedure eve_get_line ! What line am I on? local saved_mark, ! marker - current position text_mark, ! marker - after snapping to text this_line_position, ! marker - position at start of this_line total_lines, ! integer - total lines in buffer high_line, ! integer - high line limit for binary search low_line, ! integer - low line limit for binary search low_position, ! marker - beginning of low line this_line, ! integer - line number of current guess eob_flag, ! boolean - true if at eob percent; ! integer - percent of way through buffer on_error [TPU$_CONTROLC]: eve$$restore_position (saved_mark); ! restore free cursor position eve$learn_abort; abort; [OTHERWISE]: eve$$restore_position (saved_mark); endon_error; ! Initialization saved_mark := mark (FREE_CURSOR); position (search (ANCHOR, FORWARD)); ! snap the cursor (move_vertical pads) text_mark := mark (NONE); total_lines := get_info (current_buffer, "record_count"); high_line := total_lines + 1; if text_mark = end_of (current_buffer) then if text_mark = beginning_of (current_buffer) then eve$message (EVE$_BUFEMPTY); position (saved_mark); ! no learn_abort here return (FALSE); else eob_flag := TRUE; low_line := total_lines; low_position := end_of (current_buffer); endif; else low_line := 1; low_position := beginning_of (current_buffer); endif; ! Binary search loop exitif high_line - low_line <= 1; this_line := (high_line + low_line) / 2; position (low_position); move_vertical (this_line - low_line); if mark (FREE_CURSOR) > saved_mark then high_line := this_line; else low_line := this_line; low_position := mark (FREE_CURSOR); if mark (FREE_CURSOR) = saved_mark then high_line := this_line; endif; endif; endloop; position (saved_mark); return (low_line); endprocedure; !*----------------------------------------------------------------------------*! ! ! This procedure will allow the user to recall a command by name. When the ! command key is pressed, xrecall prompts for a string to match to a previous ! command which is stored in the command buffer. If the user enters a string, ! xrecall tries to find it in the command buffer. If it finds a match, the ! command is displayed and the user may execute it by pressing RETURN. If ! xrecall cannot find a match, it aborts and tells the user what line of the ! file is current (just like EDT). If it finds a match and the user doesn't want ! that command, the up and down arrow keys may be used to scroll through the ! command buffer in an effor to find another command to execute. PROCEDURE eve_xrecall (command_name) local where_we_were, command_to_recall, location, search_string, command_text; on_error if error = tpu$_strnotfound then if which_action = 0 then return; endif; endif; endon_error; command_to_recall := command_name; where_we_were := mark (none); if command_to_recall = "" ! If they don't enter a command, ask them to. then command_to_recall := read_line ("ENTER command to recall:"); endif; if command_to_recall = "" ! If they still don't, use default recall proc. then eve_recall; return; endif; eve$$enter_command_window; edit (command_to_recall, trim); ! remove leading/trailing spaces search_string := "Command: " + command_to_recall; which_action := 1; the_command := search (search_string, reverse, no_exact); if the_command = 0 then message (fao("No command matching !AS found", command_to_recall)); eve$$exit_command_window; return; else position (the_command); command_text := current_line; which_action := 0; move_horizontal (length (current_line) - current_offset); endif; position (end_of (eve$command_buffer)); copy_text (command_text); ENDPROCEDURE;