!************************************************************************* ! * ! © Copyright 2005 Hewlett-Packard Development Company, L.P. * ! * ! Confidential computer software. Valid license from HP required for * ! possession, use or copying. Consistent with FAR 12.211 and 12.212, * ! Commercial Computer Software, Computer Software Documentation, and * ! Technical Data for Commercial Items are licensed to the U.S. * ! Government under vendor's standard commercial license. * ! * !************************************************************************* !++ ! FACILITY: ! eXtended LSE (XLSE) ! ! ABSTRACT: ! This module defines XLSE's TPU procedures and key bindings ! ! AUTHOR: ! Ward Clark, CASEE Group ! Mark E. Arsenault, Technical Language & Environments Group ! Thierry Cagnin, FYO ! ! CREATION DATE: 15-Oct-84 ! !-- PROCEDURE xlse_initialize !++ ! FUNCTIONAL DESCRIPTION: ! ! Initializes all XLSE global variables and editor defaults. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ON_ERROR ENDON_ERROR; ! Initialize all XLSE global variables. ! xlse__initialize_xlse; xlse__initialize_customize; xlse__initialize_keypad; ! Set the language of the $DEFAULTS buffer to UNKNOWN. ! LSE$DO_COMMAND( "SET LANGUAGE /BUFFER=$DEFAULTS UNKNOWN" ); ! Do special setup for a MAIL editing buffer. ! IF xlse__mail_session THEN xlse__mail_setup; ENDIF; ! Do special setup for a NOTES editing buffer. ! IF xlse__notes_session THEN xlse__notes_setup; ENDIF; ENDPROCEDURE PROCEDURE xlse__initialize_xlse xlse__bound_cursor := 1; xlse__duplicated_page := CREATE_BUFFER( "$XLSE_DUPLICATED_PAGE" ); SET( NO_WRITE, xlse__duplicated_page, ON ); SET( PERMANENT, xlse__duplicated_page ); SET( SYSTEM, xlse__duplicated_page ); xlse__erased_buffer := CREATE_BUFFER( "$XLSE_ERASED_BUFFER" ); SET( NO_WRITE, xlse__erased_buffer, ON ); SET( PERMANENT, xlse__erased_buffer ); SET( SYSTEM, xlse__erased_buffer ); xlse__erased_page := CREATE_BUFFER( "$XLSE_ERASED_PAGE" ); SET( NO_WRITE, xlse__erased_page, ON ); SET( PERMANENT, xlse__erased_page ); SET( SYSTEM, xlse__erased_page ); xlse__erased_string := 0; xlse__learn_key := ""; xlse__learn_status := ""; xlse__learn_mode := OFF; xlse__learn_count := 0; xlse__mark_buffers := ""; xlse__mail_buffer := ""; xlse__null := ""; xlse__parenthesis_range := 0; xlse__paste_buffer := EVE$FIND_BUFFER( "$PASTE" ); xlse__replace_string := ""; xlse__set_file := CREATE_BUFFER( "$XLSE_SET_FILE" ); SET( NO_WRITE, xlse__set_file ); SET( PERMANENT, xlse__set_file ); SET( SYSTEM, xlse__set_file ); xlse__symbol_value := ""; xlse__trapped_messages := CREATE_BUFFER( "$XLSE_TRAPPED_MESSAGES" ); SET( NO_WRITE, xlse__trapped_messages, ON ); SET( PERMANENT, xlse__trapped_messages ); SET( SYSTEM, xlse__trapped_messages ); xlse__undefined_language := ""; xlse__undefined_delim_opt := ""; xlse__undefined_delim_req := ""; xlse__space := " "; xlse__tab := " "; xlse__space_tab := " "; xlse__lower_case := "abcdefghijklmnopqrstuvwxyz"; xlse__upper_case := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; xlse__file_spec_chars := xlse__lower_case + xlse__upper_case + "0123456789" + ":[]<>.$_-*%;"; xlse__temp := 0; xlse__repeat_count := 1; ! ***BYPASS TPU BUG*** ENDPROCEDURE PROCEDURE xlse__initialize_customize !++ ! Initialize each user preference variable that has not been ! explicitly initialized by the XLSE user. !-- ! Let the user force insert or overstrike mode for ! commands and prompts. ! IF GET_INFO(xlse_command_entry_mode,"TYPE") = UNSPECIFIED THEN xlse_command_entry_mode := OVERSTRIKE; ! Hack to avoid compilation ! warning message on the ! preceding GET_INFO call ELSE IF xlse_command_entry_mode = INSERT THEN LSE$DO_COMMAND("SET INSERT/BUFFER=$COMMANDS"); LSE$DO_COMMAND("SET INSERT/BUFFER=$PROMPTS"); ELSE LSE$DO_COMMAND("SET OVERSTRIKE/BUFFER=$COMMANDS"); LSE$DO_COMMAND("SET OVERSTRIKE/BUFFER=$PROMPTS"); ENDIF; ENDIF; ! User initials used by XLSE_NEW_MODIFICATION to create ! a new entry in a module Modification History. ! IF GET_INFO(xlse_user_initials,"TYPE") = UNSPECIFIED THEN xlse_user_initials := ""; ENDIF; ! XLSE_REPLACE does case-sensitive replacement (ON) ! or exact replacement (OFF). ! IF GET_INFO(xlse_replace_case_sensitive,"TYPE") = UNSPECIFIED THEN xlse_replace_case_sensitive := ON; ENDIF; ! XLSE_INSERT_LINE creates a new line before the current line (ON) ! or breaks the current line (OFF), which is the default behavior ! of LSE's GOLD-KP0 key. ! IF GET_INFO(xlse_open_previous_line,"TYPE") = UNSPECIFIED THEN xlse_open_previous_line := ON; ENDIF; ENDPROCEDURE PROCEDURE xlse_align_list !++ ! FUNCTIONAL DESCRIPTION: ! ! Aligns the first non-blank character of the next line directly below ! the current cursor position. For example, this procedure can be used ! to easily align a vertical list of routine call arguments: ! ! x = routine( argument1, x = routine( argument1, ! argument2, ---> argument2, ! argument3, argument3, ! argument4 ) argument4 ) ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL indent_columns, white_space; ! Determine the indentation needed. ! indent_columns := GET_INFO( CURRENT_BUFFER, "OFFSET_COLUMN" ) - 1; ! All text from an entirely blank line. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); white_space := SEARCH_QUIETLY( (ANCHOR & SPAN(xlse__space_tab)) & LINE_END, FORWARD ); IF white_space <> 0 THEN ERASE_CHARACTER( +LENGTH(CURRENT_LINE) ) ENDIF; ! Remove any white space from the beginning of the next line. ! MOVE_VERTICAL( +1 ); white_space := SEARCH_QUIETLY( (ANCHOR & SPAN(xlse__space_tab)), FORWARD ); IF white_space <> 0 THEN ERASE(white_space) ENDIF; ! Re-indent the line using tabs and spaces. ! LOOP EXITIF indent_columns < 8; COPY_TEXT( xlse__tab ); indent_columns := indent_columns - 8; ENDLOOP; LOOP EXITIF indent_columns = 0; COPY_TEXT( xlse__space ); indent_columns := indent_columns - 1; ENDLOOP; ENDPROCEDURE PROCEDURE xlse_annotate_quotation !++ ! FUNCTIONAL DESCRIPTION: ! ! Annotates text which is being included in a response to a mail message ! or in a reply in a VAX Notes conference. The annotation takes the ! form ... ! ! xxx> quoted text ... ! ! where "xxx" is repeated from a preceding line. Thus, the annotation ! that is manually entered on the first line of a quotation can be easily ! duplicated on succeeding lines. ! ! If a region has been selected, the entire region is annotated. ! Otherwise, the current line is annotated. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL selected_lines, last_body_line; ! Determine whether there is a select region. ! selected_lines := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); IF selected_lines = 0 THEN ! No select region ! ! Verify that the cursor is positioned on a line. ! IF MARK(NONE) = END_OF(CURRENT_BUFFER) THEN MOVE_VERTICAL( +1 ); RETURN; ENDIF; ! Annotate the current line. ! xlse__annotate_current_line; ELSE ! Locate the beginning of the the line following the ! select region. ! POSITION( END_OF(selected_lines) ); IF CURRENT_OFFSET <> 0 THEN MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDIF; last_body_line := MARK(NONE); ! Flag the select region one line at a time. ! POSITION( BEGINNING_OF(selected_lines) ); selected_lines := 0; EVE$CLEAR_SELECT_POSITION; LOOP EXITIF MARK(NONE) = last_body_line; xlse__annotate_current_line; ENDLOOP; ENDIF; ENDPROCEDURE PROCEDURE xlse__annotate_current_line LOCAL save_cursor, previous_indent, current_indent, annotation, temp; ! Pickup the flag text from a preceding line. ! save_cursor := MARK(NONE); LOOP MOVE_HORIZONTAL( -CURRENT_OFFSET ); IF MARK(NONE) = BEGINNING_OF(CURRENT_BUFFER) THEN MESSAGE( "No previous line is annotated" ); POSITION( save_cursor ); ABORT ENDIF; MOVE_VERTICAL( -1 ); temp := SEARCH_QUIETLY( ANCHOR & SPAN(" "), FORWARD ); IF temp = 0 THEN temp := ""; previous_indent := ""; ELSE previous_indent := xlse__detab( SUBSTR(temp,1,255) ) ENDIF; MOVE_HORIZONTAL( LENGTH(temp) ); IF CURRENT_CHARACTER = ">" THEN annotation := SEARCH_QUIETLY( ANCHOR & SPAN(">"), FORWARD ) ELSE annotation := SEARCH_QUIETLY( ANCHOR & SCAN(">") & SPAN(">"), FORWARD ) ENDIF; EXITIF annotation <> 0; ENDLOOP; annotation := SUBSTR(annotation,1,255); ! Detab the line to be annotated because it will be shifted to the right. ! POSITION( save_cursor ); xlse_tabs_to_spaces( OFF ); ! Now annotate the line. ! POSITION( save_cursor ); MOVE_HORIZONTAL( -CURRENT_OFFSET ); temp := SEARCH_QUIETLY( ANCHOR & SPAN(" "), FORWARD ); IF temp <> 0 THEN current_indent := SUBSTR(temp,1,255); ERASE( temp ); COPY_TEXT( SUBSTR(current_indent,LENGTH(previous_indent)+1,255) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; IF LENGTH(CURRENT_LINE) = 0 THEN COPY_TEXT( previous_indent + annotation ) ELSE COPY_TEXT( previous_indent + annotation + " " ) ENDIF; ! Move to the beginning of the next line. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDPROCEDURE PROCEDURE xlse__detab( tabbed_string ) LOCAL result_string, string_index; result_string := ""; string_index := 0; LOOP string_index := string_index + 1; EXITIF string_index > LENGTH(tabbed_string); IF SUBSTR(tabbed_string,string_index,1) = " " THEN result_string := result_string + " " ELSE result_string := result_string + SUBSTR(tabbed_string,string_index,255); EXITIF 1 ENDIF; ENDLOOP; RETURN result_string ENDPROCEDURE PROCEDURE xlse_break_line !++ ! FUNCTIONAL DESCRIPTION: ! ! Performs an XLSE_ENTER_LINE (carriage return) operation, ! leaving the cursor's position unchanged. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- xlse_enter_line( "" ); LSE$DO_COMMAND( "GOTO/END LINE /REVERSE" ); ENDPROCEDURE PROCEDURE xlse_change_bars( ; bars_operation ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Manipulates the change bar commands in a RUNOFF, SDML or LaTeX ! source file: ! ! - disables existing change bars (RUNOFF or SDML) ! - shrinks existing change bars to .75pt (LaTeX only) ! - restores all change bars ! - removes all change bars ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL cb_off, cb_begin_on, cb_begin_off, cb_end_on, cb_end_off, on_count, off_count, nested_count, total_count; ! Verify that the current buffer contains an appropriate source file. ! IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") = "RUNOFF" THEN cb_off := "DISABLE"; cb_begin_on := ".BEGIN BAR"; cb_begin_off := ".! BEGIN BAR"; cb_end_on := ".END BAR"; cb_end_off := ".! END BAR"; ELSE IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") = "SDML" THEN cb_off := "DISABLE"; cb_begin_on := ""; cb_begin_off := "()"; cb_end_on := ""; cb_end_off := "()"; ELSE IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") = "LATEX" THEN cb_off := "SHRINK"; cb_begin_on := "\cbstart"; cb_begin_off := "\cbstart[.75pt]"; cb_end_on := "\cbend"; cb_end_off := "\cbend"; ELSE MESSAGE( "Change bar processing requires a RUNOFF, SDML or LaTeX source file" ); RETURN ENDIF; ENDIF; ENDIF; ! Ask the user how the change bars are to be handled. ! LOOP EXITIF (GET_INFO(bars_operation,"TYPE") = STRING) AND (bars_operation <> ""); bars_operation := EVE$PROMPT_LINE( "_Change bar action? {" + cb_off + "|RESTORE|DELETE}: ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); ENDLOOP; EDIT( bars_operation, TRIM, UPPER ); ! Disable/Shrink existing change bars. ! IF INDEX(cb_off,bars_operation) = 1 THEN off_count := xlse__cb_change( cb_begin_off, cb_begin_on ); total_count := xlse__cb_change( cb_begin_on, cb_begin_off ); IF cb_end_on <> cb_end_off THEN xlse__cb_change( cb_end_off, cb_end_on ); xlse__cb_change( cb_end_on, cb_end_off ); ENDIF; MESSAGE( FAO("!UL change bar!%S disabled (total=!UL)", total_count-off_count,total_count) ); RETURN; ENDIF; ! Restore all change bars. ! IF INDEX("RESTORE",bars_operation) = 1 THEN off_count := xlse__cb_change( cb_begin_off, cb_begin_on ); IF cb_end_on <> cb_end_off THEN xlse__cb_change( cb_end_off, cb_end_on ); ENDIF; nested_count := xlse__cb_denest( cb_begin_on, cb_end_on ); IF nested_count = 0 THEN MESSAGE( FAO("!UL change bar!%S restored",off_count) ); ELSE MESSAGE( FAO("!UL change bar!%S restored (!UL nested bar!%S removed)", off_count,nested_count) ); ENDIF; RETURN; ENDIF; ! Delete all change bars. ! IF INDEX("DELETE",bars_operation) = 1 THEN off_count := xlse__cb_change( cb_begin_off, "" ); on_count := xlse__cb_change( cb_begin_on, "" ); xlse__cb_change( cb_end_off, "" ); IF cb_end_on <> cb_end_off THEN xlse__cb_change( cb_end_on, "" ); ENDIF; MESSAGE( FAO("!UL change bars removed (active=!UL,disabled=!UL)", on_count+off_count,on_count,off_count) ); RETURN; ENDIF; ! Indicate an invalid request. ! MESSAGE( '"' + bars_operation + '" is an invalid option' ); bars_operation := ""; ENDPROCEDURE PROCEDURE xlse__cb_change( search_string, replace_string ) LOCAL save_cursor, substitute_count, found_string; ! Save the starting position and move to the beginning of the buffer. ! save_cursor := MARK(NONE); POSITION( BEGINNING_OF(CURRENT_BUFFER) ); substitute_count := 0; ! Loop until all substitutions have been made. ! LOOP ! Locate the search string. ! found_string := SEARCH_QUIETLY(search_string,FORWARD,NO_EXACT); EXITIF found_string = 0; POSITION( found_string ); ! Verify that RUNOFF commands start in column 1. ! IF (SUBSTR(search_string,1,1) = ".") AND (CURRENT_OFFSET <> 0) THEN MOVE_HORIZONTAL( +1 ); ELSE ! Increment the count of string substitutions. ! substitute_count := substitute_count + 1; ! Delete the search string. ! ERASE( found_string ); ! Determine whether string replace or delete has been requested. ! IF replace_string <> "" THEN ! Insert the replacement string in the buffer. ! COPY_TEXT( replace_string ); ELSE ! Cleanup after deleting the search string. ! xlse__cb_cleanup; ENDIF; ENDIF; ENDLOOP; ! Return to the starting position. ! POSITION( save_cursor ); ! Return the number of substitutions performed. ! RETURN substitute_count ENDPROCEDURE PROCEDURE xlse__cb_denest( begin_string, end_string ) LOCAL save_cursor, nested_count, block_level, extra_end_count, temp; ! Save the starting position and move to the beginning of the buffer. ! save_cursor := MARK(NONE); POSITION( BEGINNING_OF(CURRENT_BUFFER) ); nested_count := 0; block_level := 0; ! Loop through the buffer. ! LOOP EXITIF MARK(NONE) = END_OF(CURRENT_BUFFER); ! Locate the next beginning or ending command. ! found_begin := SEARCH_QUIETLY( begin_string, FORWARD, NO_EXACT ); found_end := SEARCH_QUIETLY( end_string, FORWARD, NO_EXACT ); EXITIF (found_begin = 0) AND (found_end = 0); IF (found_begin <> 0) AND (found_end <> 0) THEN POSITION( found_begin ); temp := MARK(NONE); POSITION( found_end ); IF LENGTH( CREATE_RANGE(BEGINNING_OF(CURRENT_BUFFER),temp,NONE) ) > LENGTH( CREATE_RANGE(BEGINNING_OF(CURRENT_BUFFER),MARK(NONE),NONE) ) THEN found_begin := 0; ELSE found_end := 0; ENDIF ENDIF; ! Process a begin-change-bar command. ! IF found_begin <> 0 THEN POSITION( found_begin ); IF (SUBSTR(begin_string,1,1) = ".") AND (CURRENT_OFFSET <> 0) THEN MOVE_HORIZONTAL( +1 ); ELSE block_level := block_level + 1; IF block_level > 1 THEN ERASE( found_begin ); nested_count := nested_count + 1; xlse__cb_cleanup; ELSE MOVE_HORIZONTAL( +1 ); ENDIF; ENDIF; ENDIF; ! Process a end-change-bar command. ! IF found_end <> 0 THEN POSITION( found_end ); IF (SUBSTR(end_string,1,1) = ".") AND (CURRENT_OFFSET <> 0) THEN MOVE_HORIZONTAL( +1 ); ELSE block_level := block_level - 1; IF block_level > 1 THEN ERASE( found_end ); xlse__cb_cleanup; ENDIF; IF block_level = 0 THEN MOVE_HORIZONTAL( +1 ); ENDIF; IF block_level < 0 THEN extra_end_count := extra_end_count + 1; ERASE( found_end ); xlse__cb_cleanup; block_level := 0; ENDIF; ENDIF; ENDIF; ENDLOOP; ! Report mismatched begin-bar and end-bar commands. ! IF block_level > 0 THEN MESSAGE( FAO("!UL !AS command!%S missing",block_level,end_string) ); ENDIF; IF extra_end_count > 0 THEN MESSAGE( FAO("!UL extraneous command!%S deleted", extra_end_count,end_string) ); ENDIF; ! Return to the starting position. ! POSITION( save_cursor ); ! Return the number of substitutions performed. ! RETURN nested_count ENDPROCEDURE PROCEDURE xlse__cb_cleanup LOCAL temp; ! If the entire line is blank, delete it. ! temp := CURRENT_LINE; EDIT( temp, TRIM ); IF temp = "" THEN ERASE_LINE; RETURN; ENDIF; ! Otherwise, delete a leading or trailing space. ! IF (SEARCH_QUIETLY((ANCHOR & LINE_BEGIN & " "), FORWARD)) <> 0 THEN ERASE_CHARACTER( 1 ); ELSE MOVE_HORIZONTAL( -1 ); IF (SEARCH_QUIETLY((ANCHOR & (" " | (" " & LINE_END))), FORWARD)) <> 0 THEN ERASE_CHARACTER( 1 ); ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse_change_case( desired_case ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Changes the case of a specified string of characters. If no select range ! has been set and the cursor is not positioned on the current search string, ! the current character is assumed. ! ! FORMAL PARAMETERS: ! ! desired_case ! Keyword option which indicates the desired case conversion: ! force to upper case (UPPER), force to lower case (LOWER), ! or change each character to the opposite case (INVERT). ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! The current select range, if any, is cancelled. !-- LOCAL selected_string, save_selected_string, CASE_KEYWORd; ! Establish the current select range, assuming the current ! character if no select range has been set. ! selected_string := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); save_selected_string := selected_string; IF selected_string = 0 THEN xlse_silent_lse( "SET SELECT_MARK" ); MOVE_HORIZONTAL( +1 ); selected_string := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); ENDIF; ! Convert the select range to the specified case. ! IF selected_string <> 0 THEN IF (save_selected_string <> 0) AND (desired_case = INVERT) THEN IF INDEX( xlse__lower_case, SUBSTR(selected_string,1,1) ) <> 0 THEN case_keyword := UPPER; ELSE case_keyword := LOWER; ENDIF; ELSE case_keyword := desired_case; ENDIF; CHANGE_CASE( selected_string, case_keyword ); ENDIF; ! RESTORE the select range in event of an INVERT. ! IF (save_selected_string <> 0) AND (desired_case = INVERT) THEN IF BEGINNING_OF(save_selected_string) = MARK(NONE) THEN POSITION( END_OF(save_selected_string) ); MOVE_HORIZONTAL( +1 ); xlse_silent_lse( "SET SELECT_MARK" ); POSITION( BEGINNING_OF(save_selected_string) ); ELSE POSITION( BEGINNING_OF(save_selected_string) ); xlse_silent_lse( "SET SELECT_MARK" ); POSITION( END_OF(save_selected_string) ); MOVE_HORIZONTAL( +1 ); ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse_combine_buffers !++ ! FUNCTIONAL DESCRIPTION: ! ! Appends the buffer in the previous window to the current buffer and ! deletes the previous buffer. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL starting_buffer, save_cursor; ! Verify that another buffer is currently visible. ! IF GET_INFO(CURRENT_BUFFER,"MAP_COUNT") = EVE$X_NUMBER_OF_WINDOWS THEN MESSAGE( "Only 1 buffer is currently visible" ); RETURN ENDIF; ! Move the cursor to the other buffer. ! starting_buffer := CURRENT_BUFFER; save_cursor := MARK(NONE); LOOP LSE$DO_COMMAND( "PREVIOUS WINDOW" ); EXITIF CURRENT_BUFFER <> starting_buffer; ENDLOOP; ! Save the previous buffer contents and then delete the buffer. ! xlse__erase_buffer( "/NOERASE" ); SET( NO_WRITE, CURRENT_BUFFER, ON ); LSE$DO_COMMAND( "DELETE BUFFER" ); ! Return to the original window. ! IF EVE$X_NUMBER_OF_WINDOWS <> 1 THEN LOOP EXITIF save_cursor = MARK(NONE); LSE$DO_COMMAND( "NEXT WINDOW" ); ENDLOOP; ENDIF; ! Append the "other" buffer to the original buffer, ! separated by a blank line. ! POSITION( END_OF(CURRENT_BUFFER) ); SPLIT_LINE; xlse_unerase_buffer; POSITION( save_cursor ); ! If the starting buffer is mapped several times, make it fill the screen. ! IF EVE$X_NUMBER_OF_WINDOWS <> 1 THEN IF GET_INFO(CURRENT_BUFFER,"MAP_COUNT") = EVE$X_NUMBER_OF_WINDOWS THEN LSE$DO_COMMAND( "CHANGE WINDOW_MODE" ); ENDIF; ENDIF ENDPROCEDURE PROCEDURE xlse_compile !++ ! FUNCTIONAL DESCRIPTION: ! ! Compiles the TPU Procedure at the current cursor position, if the current ! buffer contains TPU source. Otherwise, invokes an LSE COMPILE command. ! ! Restrictions: ! ! - The PROCEDURE and ENDPROCEDURE statements cannot be indented. ! ! - This procedure cannot compile itself since it can't delete itself. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Select appropriate compilation command based on ! the language of the current buffer. ! IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") = "TPU" THEN ! TPU: EXTEND/INDICATED ! LSE$DO_COMMAND( "EXTEND/INDICATED" ); ELSE ! All other languages: COMPILE ! LSE$DO_COMMAND( "COMPILE" ); ENDIF; ENDPROCEDURE PROCEDURE xlse_compile_modified_buffers !++ ! FUNCTIONAL DESCRIPTION: ! ! COMPILEs all modified, compile-able buffers. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL buffer_count, buffer_names, file_type, one_buffer, last_buffer, starting_buffer; buffer_names := ""; buffer_count := 0; last_buffer := GET_INFO(BUFFERS,"LAST"); one_buffer := GET_INFO(BUFFERS,"FIRST"); ! Loop thru all buffers, looking for modified user buffers. ! LOOP IF NOT GET_INFO(one_buffer,"SYSTEM") AND NOT GET_INFO(one_buffer,"NO_WRITE") AND GET_INFO(one_buffer,"MODIFIED") THEN ! Collect the names of just the COMPILE-able buffers. ! file_type := xlse__buffer_spec( one_buffer ); IF INDEX(file_type,".") <> 0 THEN file_type := SUBSTR( file_type, INDEX(file_type,".")+1, 255 ); IF (file_type = "ADA") OR (file_type = "BAS") OR (file_type = "BLI") OR (file_type = "B16") OR (file_type = "B32") OR (file_type = "B36") OR (file_type = "REQ") OR (file_type = "R16") OR (file_type = "R32") OR (file_type = "R36") OR (file_type = "C") OR (file_type = "CXX") OR (file_type = "COB") OR (file_type = "CBL") OR (file_type = "FOR") OR (file_type = "TEX") OR (file_type = "MAR") OR (file_type = "PAS") OR (file_type = "PLI") OR (file_type = "SCN") OR (file_type = "SDL") OR (file_type = "UIL") THEN buffer_names := buffer_names + GET_INFO(one_buffer,"NAME") + "@@"; buffer_count := buffer_count + 1; ENDIF; ENDIF; ENDIF; EXITIF one_buffer = last_buffer; one_buffer := GET_INFO(BUFFERS,"NEXT"); ENDLOOP; ! Compile one buffer at a time. ! IF buffer_count > 0 THEN starting_buffer := xlse__buffer_spec( CURRENT_BUFFER ); LOOP EXITIF LENGTH(buffer_names) = 0; one_buffer := SUBSTR(buffer_names,1,INDEX(buffer_names,"@@")-1); buffer_names := SUBSTR(buffer_names,LENGTH(one_buffer)+3,1000); LSE$DO_COMMAND( 'GOTO BUFFER "' + one_buffer + '"'); UPDATE( CURRENT_WINDOW ); LSE$DO_COMMAND( "COMPILE " ); ENDLOOP; LSE$DO_COMMAND( 'GOTO BUFFER "' + starting_buffer + '"' ); ENDIF; ! Report the number of buffers compiled. ! IF buffer_count = 0 THEN MESSAGE( "There are no modified, COMPILE-able buffers" ); ELSE MESSAGE( FAO("!UL buffer!%S compiled",buffer_count) ); ENDIF; ENDPROCEDURE PROCEDURE xlse_current_date !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the current date. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! current date (dd-mmm-yy) !-- LOCAL full_date, two_char; ! Get the full date as a ASCII string. ! full_date := FAO( "!11", 0 ); ! Convert the 2nd two characters of the month to lower case. ! two_char := SUBSTR(full_date,5,2); CHANGE_CASE( two_char, LOWER ); ! Convert the date into "dd-mmm-yy" format ! full_date := SUBSTR(full_date,1,4) + two_char + SUBSTR(full_date,7,1) + SUBSTR(full_date,10,2); ! a leading space from the date. ! IF SUBSTR(full_date,1,1) = " " THEN full_date := SUBSTR(full_date,2,8); ENDIF; ! the date string to the caller. ! RETURN( full_date ); ENDPROCEDURE PROCEDURE xlse_dcl_command( dcl_command ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's DCL command: ! ! - Splits the current window and puts the $CLI window in the ! upper window. ! ! - Adds a "$" to the user's command string. ! ! FORMAL PARAMETERS: ! ! dcl_command ! A DCL command, without the leading $ sign. ! ! IMPLICIT INPUTS/OUTPUTS: ! ! xlse__dcl_buffer ! Special user buffer for DCL commands and output. ! ! xlse__dcl_process ! Name of the subprocess used to execute the DCL command ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL dcl_string, save_working_msg; ! If no command was provided, ask for one. ! dcl_string := dcl_command; EDIT(dcl_string,TRIM); IF dcl_string = "" THEN dcl_string := EVE$PROMPT_LINE( "DCL $ ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); EDIT(dcl_string,TRIM); ENDIF; ! Strip a leading "$". ! IF SUBSTR(dcl_string,1,1) = "$" THEN dcl_string := SUBSTR(dcl_string,2,LENGTH(dcl_string)); EDIT(dcl_string,TRIM); ENDIF; ! Quit if the user didn't supply a command. ! IF dcl_string = "" THEN MESSAGE( "No DCL command given" ); RETURN; ENDIF; ! Map the DCL buffer into a window. ! IF GET_INFO(GET_INFO(BUFFERS,"FIND_BUFFER","$CLI"),"MAP_COUNT") = 0 THEN ! Split the current window to create a new DCL window. ! LSE$DO_COMMAND( "SPLIT WINDOW" ); LSE$DO_COMMAND( "PREVIOUS WINDOW" ); LSE$DO_COMMAND( "GOTO BUFFER $CLI" ); LSE$DO_COMMAND( "NEXT WINDOW" ); ENDIF; ! Change the "Working" message. ! save_working_msg := GET_INFO( SYSTEM, "TIMED_MESSAGE" ); SET( TIMER, ON, "Executing..." ); ! Send the DCL command to the subprocess. ! LSE$DO_COMMAND( "DCL $ " + dcl_string ); ! Restore the previous "Working" message. ! SET( TIMER, OFF, "" ); SET( TIMER, ON, save_working_msg ); ! Return to the caller. ! RETURN ENDPROCEDURE PROCEDURE xlse_delete_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's DELETE BUFFER command: ! ! - Saves the contents of the current buffer for XLSE_UNERASE_BUFFER. ! ! - Avoids two windows on the same buffer. ! ! - Calls RNF_DO_DIFF_END to delete a DIFF comparison buffer. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_cursor; IF CURRENT_BUFFER = rnf_b_diff_buf2 THEN ! Simply discard a DIFF comparison buffer. ! rnf_do_diff_end; ELSE ! Otherwise, save the current buffer contents. ! save_cursor := MARK(NONE); xlse__erase_buffer( "/NOERASE" ); POSITION( save_cursor ); ! Delete the current buffer. ! xlse__delete_buffer(); ENDIF; ENDPROCEDURE PROCEDURE xlse__delete_buffer LOCAL save_buffer, next_user_buffer; ! Don't delete the $MAIN buffer. ! IF GET_INFO(CURRENT_BUFFER,"NAME") = "$MAIN" THEN RETURN; ENDIF; ! Delete the current buffer. ! save_buffer := CURRENT_BUFFER; next_user_buffer := xlse__find_user_buffer( "NEXT" ); LSE$DO_COMMAND( 'DELETE BUFFER "' + GET_INFO(CURRENT_BUFFER,"NAME") + '"' ); IF CURRENT_BUFFER = save_buffer THEN ABORT; ENDIF; ! Avoid two windows on the same buffer. ! IF next_user_buffer <> 0 THEN LSE$DO_COMMAND( 'GOTO BUFFER "' + xlse__buffer_spec(next_user_buffer) + '"' ); ELSE IF EVE$X_NUMBER_OF_WINDOWS > 1 THEN LSE$DO_COMMAND( "DELETE WINDOW" ); ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse_duplicate_line !++ ! FUNCTIONAL DESCRIPTION: ! ! Duplicates the current line. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL save_cursor, this_line; ! Save the starting position. ! save_cursor := MARK(NONE); ! Duplicate the current line. ! this_line := CURRENT_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); SPLIT_LINE; MOVE_VERTICAL( -1 ); COPY_TEXT( this_line ); ! Return to the starting position. ! POSITION( save_cursor ); ENDPROCEDURE PROCEDURE xlse_duplicate_page !++ ! FUNCTIONAL DESCRIPTION: ! ! Duplicates the current page. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL save_cursor, add_page_break, save_input_mode; ! Save the starting position. ! save_cursor := MARK(NONE); ! Move the current page contents into the $XLSE_DUPLICATED_PAGE ! system buffer. ! IF xlse__current_character <> " " THEN xlse__goto_page( REVERSE ); ENDIF; IF xlse__current_character = " " THEN add_page_break := 0; ELSE add_page_break := 1; ENDIF; xlse_silent_lse( "SET SELECT_MARK" ); xlse__goto_page( FORWARD ); xlse_silent_lse( "CUT /NOERASE /BUFFER=$XLSE_DUPLICATED_PAGE" ); ! Insert a copy of the current page at the end of the current page. ! save_input_mode := eveplus_set_mode( INSERT ); IF add_page_break THEN COPY_TEXT( " " ); ENDIF; LSE$DO_COMMAND( "PASTE /BUFFER=$XLSE_DUPLICATED_PAGE" ); ! Return to the starting position. ! POSITION( save_cursor ); ENDPROCEDURE PROCEDURE xlse_enter_line( enter_line_qualifier ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's ENTER LINE command: ! ! -- Does SET INDENTATION CURSOR if the cursor precedes the ! first non-blank character; otherwise, does SET INDENTATION CURRENT. ! ! -- Performs automatic indentation. ! ! -- Mimics wrap-mode automatic insertion of comment characters. ! ! FORMAL PARAMETERS: ! ! enter_line_qualifier ! Optional qualifier for the ENTER LINE command. ! ! ROUTINE VALUE: ! ! None !-- LOCAL auto_comment_mode, auto_comment_indent, first_chars, last_chars, indent_string; ! Avoid messages. ! ON_ERROR [TPU$_NOEOBSTR] : ; ! Cannot return string at end of buffer [TPU$_STRNOTFOUND] : ; ! String not found ENDON_ERROR; ! Set the automatic indentation point to the first printing character ! of the current line. ! first_chars := SUBSTR( CURRENT_LINE, 1, CURRENT_OFFSET ); EDIT( first_chars, TRIM ); IF first_chars = "" THEN LSE$DO_COMMAND( "SET INDENTATION CURSOR" ); ELSE LSE$DO_COMMAND( "SET INDENTATION CURRENT" ); ENDIF; ! Determine whether automatic commenting is appropriate, that is, ! whether the current line starts with a line comment character. ! first_chars := CURRENT_LINE; EDIT( first_chars, TRIM_LEADING ); IF (CURRENT_OFFSET < (INDEX(CURRENT_LINE,first_chars) + LENGTH(xlse__comment_line))) OR (INDEX(first_chars,xlse__comment_line) <> 1) THEN auto_comment_mode := 0; ELSE auto_comment_mode := 1; last_chars := SUBSTR( first_chars, LENGTH(xlse__comment_line)+1, LENGTH(first_chars) ); EDIT( last_chars, TRIM_LEADING ); auto_comment_indent := SUBSTR( first_chars, 1, LENGTH(first_chars)-LENGTH(last_chars) ); ENDIF; ! Begin a new line. If wrap mode is set and the cursor is past the ! right margin, two ENTER LINE commands will be needed. ! IF xlse__wrap_mode(CURRENT_BUFFER) AND (CURRENT_COLUMN > GET_INFO(CURRENT_BUFFER,"RIGHT_MARGIN")+1) THEN LSE$DO_COMMAND( "ENTER LINE" ); ENDIF; LSE$DO_COMMAND( "ENTER LINE" + enter_line_qualifier ); ! Automatically indent the new line, unless WRAP mode has ! has already resulted in indentation. ! IF (CURRENT_OFFSET = 0) AND (GET_INFO(CURRENT_BUFFER,"LANGUAGE") <> "FORTRAN") THEN LSE$DO_COMMAND( "ENTER TAB" ); ENDIF; ! Mimic automatic commenting done by wrap-mode. ! IF (auto_comment_mode AND (enter_line_qualifier <> "/NOCOMMENT")) THEN indent_string := SUBSTR(CURRENT_LINE,1,CURRENT_OFFSET); EDIT( indent_string, TRIM ); IF LENGTH(indent_string) = 0 THEN COPY_TEXT( auto_comment_indent ); ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse_enter_replace !++ ! FUNCTIONAL DESCRIPTION: ! ! Prompt the user for replacement string and performs the ! first string replacement. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- xlse__replace_string := EVE$PROMPT_LINE( "_Replace with: ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); xlse_replace ENDPROCEDURE PROCEDURE xlse_erase_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Removes all contents of the current buffer. ! ! Erased buffer contents can be reinserted (in any buffer) using ! the XLSE_UNERASE_BUFFER procedure. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Verify that the buffer can be erased. ! xlse__modifiable_buffer; ! Erase and save the contents of the current buffer. ! xlse__erase_buffer( "/ERASE" ); ENDPROCEDURE PROCEDURE xlse__erase_buffer( cut_option ) ! Move the current buffer contents into the ! $XLSE_ERASED_BUFFER system buffer. ! POSITION( BEGINNING_OF(CURRENT_BUFFER) ); xlse_silent_lse( "SET SELECT_MARK" ); POSITION( END_OF(CURRENT_BUFFER) ); xlse_silent_lse( "CUT /BUFFER=$XLSE_ERASED_BUFFER" + cut_option ); ENDPROCEDURE PROCEDURE xlse_erase_page !++ ! FUNCTIONAL DESCRIPTION: ! ! Removes all contents of the current page. ! ! Erased page contents can be reinserted using the ! XLSE_UNERASE_PAGE procedure. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Verify that the buffer can be modified. ! xlse__modifiable_buffer; ! Move the current page contents into the $XLSE_ERASED_PAGE system buffer. ! IF xlse__current_character <> " " THEN xlse__goto_page( REVERSE ); ENDIF; xlse_silent_lse( "SET SELECT_MARK" ); xlse__goto_page( FORWARD ); xlse_silent_lse( "CUT /ERASE /BUFFER=$XLSE_ERASED_PAGE" ); ENDPROCEDURE PROCEDURE xlse_erase_string !++ ! FUNCTIONAL DESCRIPTION: ! ! Erases the current selected string (from a SEARCH or SET SELECT_MARK ! command). ! ! An erased string can be reinserted using the XLSE_UNERASE_STRING procedure. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! The current select range, if any, is cancelled. !-- LOCAL selected_string; ! Determine whether a string has been selected. ! selected_string := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); IF selected_string = 0 THEN ! Indicate that no string has been erased. ! MESSAGE( "No string has been indicated" ); xlse__erased_string := 0; ELSE ! Erase the current string and save the string. ! xlse__erased_string := SUBSTR( selected_string, 1, 255 ); ERASE( selected_string ); selected_string := 0; EVE$CLEAR_SELECT_POSITION; ENDIF; ENDPROCEDURE PROCEDURE xlse_exit !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's EXIT command: ! ! o Disabled in $BUFFERS buffer. ! ! o In DECwindows mode ... ! ! - Does a WRITE of the current buffer if it has been modified. ! ! - Does a DELETE BUFFER. ! ! - Does not EXIT. ! ! o In CCT mode ... ! ! - Does an END REVIEW if a Review session is active. ! ! - Clears the message window. ! ! - EXITs the editor. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Don't exit from the $BUFFERS buffer. ! IF GET_INFO(CURRENT_BUFFER,"NAME") = "$BUFFERS" THEN MESSAGE( "EXIT ignored from the $BUFFERS buffer" ); ABORT; ENDIF; ! Do separate processing in DECwindows and CCT mode. ! IF GET_INFO(SCREEN,"DECWINDOWS") THEN xlse__exit_decwindows(); ELSE xlse__exit_cct(); ENDIF; ENDPROCEDURE PROCEDURE xlse__exit_decwindows ! Don't do anything from the $MAIN buffer. ! IF GET_INFO(CURRENT_BUFFER,"NAME") = "$MAIN" THEN MESSAGE( "EXIT ignored from the $MAIN buffer" ); ABORT; ENDIF; ! Write out the current buffer if it has been modified. ! IF GET_INFO(CURRENT_BUFFER,"MODIFIED") THEN LSE$DO_COMMAND( "WRITE" ); ENDIF; ! Delete the current buffer. ! LSE$DO_COMMAND( "DELETE BUFFER" ); ENDPROCEDURE PROCEDURE xlse__exit_cct ! Terminate a visible REVIEW session. ! IF GET_INFO(GET_INFO(BUFFERS,"FIND_BUFFER","$REVIEW"),"MAP_COUNT") > 0 THEN LSE$DO_COMMAND( "END REVIEW" ); ENDIF; ! Turn off the "Working" message. ! SET( TIMER, OFF, "" ); ! Clear the message buffer. ! ERASE( message_buffer ); UPDATE( MESSAGE_WINDOW ); ! Don't display a temporary MAIL or NOTES file message. ! IF xlse__mail_session OR xlse__notes_session THEN SET( SUCCESS, OFF ); ENDIF; ! Terminate this editing session. ! LSE$DO_COMMAND( "EXIT" ) ENDPROCEDURE PROCEDURE xlse_expand !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's EXPAND command: ! ! - Limits the search for a placeholder to just the expanded text. ! ! - Backs up a single character when the cursor is positioned after a ! statement separator (e.g., ";" in BLISS). ! ! This allows program statements to be more easily added to existing ! source code. For example, adding an IF statement becomes the ! following: ! ! IF;^E ! ! - Backs up over any number of punctuation characters in ! text-oriented "languages" (e.g., TEXT, SDML). ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! None ! ! IMPLICIT OUTPUTS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL expand_start, expand_end, expand_key; ON_ERROR ENDON_ERROR; ! Remember the starting position. ! expand_start := MARK(NONE); ! If the current line is an overview line, ! simply do a vanilla EXPAND. ! IF LSE$IS_OVERVIEW THEN LSE$DO_COMMAND( "EXPAND" ); RETURN; ENDIF; ! Backup over statement separators. ! LOOP MOVE_HORIZONTAL( -1 ); IF INDEX(xlse__statement_separator,CURRENT_CHARACTER) = 0 THEN MOVE_HORIZONTAL( +1 );; EXITIF 1; ENDIF; EXITIF LENGTH(xlse__statement_separator) <= 1; ENDLOOP; ! Determine the limits of template expansion for placeholder search testing. ! expand_end := MARK(NONE); MOVE_HORIZONTAL( -CURRENT_OFFSET ); IF MARK(NONE) = BEGINNING_OF(CURRENT_BUFFER) THEN expand_start := 0; ELSE MOVE_VERTICAL( -1 ); expand_start := MARK(NONE); ENDIF; POSITION( expand_end ); ! Temporarily redefine the XLSE_EXPAND key to be just an EXPAND ! so that LSE will let it be used to select a menu item. ! expand_key := LAST_KEY; IF expand_key = CTRL_E_KEY THEN UNDEFINE_KEY( CTRL_E_KEY ); LSE$DO_COMMAND( "DEFINE KEY CTRL_E_KEY EXPAND" ); ELSE UNDEFINE_KEY( KEY_NAME("`") ); LSE$DO_COMMAND( 'DEFINE KEY "`" EXPAND' ); ENDIF; ! Invoke an EXPAND command. ! LSE$DO_COMMAND( "EXPAND" ); ! Restore the XLSE_EXPAND key definitions. ! IF expand_key = CTRL_E_KEY THEN UNDEFINE_KEY( CTRL_E_KEY ); LSE$DO_COMMAND( 'DEFINE KEY CTRL_E_KEY "DO/TPU xlse_expand"' ); ELSE UNDEFINE_KEY( KEY_NAME("`") ); LSE$DO_COMMAND( 'DEFINE KEY "`" "DO/TPU xlse_expand"' ); ENDIF; ! Limit the implicit NEXT PLACEHOLDER command to the expanded text. ! IF expand_start <> 0 THEN IF LENGTH( CREATE_RANGE(expand_start,MARK(NONE),NONE) ) > LENGTH( CREATE_RANGE(expand_start,expand_end,NONE) ) THEN POSITION( expand_end ); MESSAGE( "No placeholder in expanded text" ); ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse_fill( fill_qualifiers ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's FILL command: ! ! - Ensures correct recognition of DCL comments (because XLSE's ! definition of the DCL language has "$" treated as a comment ! character). ! ! FORMAL PARAMETERS: ! ! fill_qualifiers ! String of qualifier text to be added to the FILL command. ! ! ROUTINE VALUE: ! ! None !-- IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") <> "DCL" THEN LSE$DO_COMMAND( "FILL " + fill_qualifiers ); ELSE LSE$DO_COMMAND( "MODIFY LANGUAGE DCL /COMMENT=NOLINE" ); LSE$DO_COMMAND( "FILL " + fill_qualifiers ); LSE$DO_COMMAND( 'MODIFY LANGUAGE DCL /COMMENT=LINE="$"' ); ENDIF; ENDPROCEDURE PROCEDURE xlse_find_symbol !++ ! FUNCTIONAL DESCRIPTION: ! ! Prompts the user for a FIND/SYMBOL command. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LSE$DO_COMMAND( "FIND " + EVE$PROMPT_LINE("_FIND ", EVE$$X_PROMPT_TERMINATORS, xlse__null) ); ENDPROCEDURE PROCEDURE xlse_free_scroll !++ ! FUNCTIONAL DESCRIPTION: ! ! Starts buffer scrolling. This continuous scroll terminates ! when any key is pressed. The key which terminates the scrolling ! is not processed. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL starting_row, scroll_limit, ignore_key; ! Move to the beginning of the current line. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); UPDATE( CURRENT_WINDOW ); ! Start continuous scrolling. ! SCROLL( CURRENT_WINDOW ); ! Eliminate scrolling "bounce" if the cursor starts beyond the ! scrolling portion of the current window. ! starting_row := GET_INFO( CURRENT_WINDOW, "CURRENT_ROW" ) - GET_INFO( CURRENT_WINDOW, "ORIGINAL_TOP" ) + 1; scroll_limit := GET_INFO( CURRENT_WINDOW, "SCROLL_TOP" ); IF (starting_row < scroll_limit) AND (CURRENT_DIRECTION = FORWARD) THEN CURSOR_VERTICAL( scroll_limit - starting_row ); ENDIF; scroll_limit := GET_INFO( CURRENT_WINDOW, "ORIGINAL_LENGTH" ) - GET_INFO( CURRENT_WINDOW, "SCROLL_BOTTOM" ); IF GET_INFO(CURRENT_WINDOW,"STATUS_LINE") <> 0 THEN scroll_limit := scroll_limit - 1; ENDIF; IF (starting_row > scroll_limit) AND (CURRENT_DIRECTION = REVERSE) THEN CURSOR_VERTICAL( scroll_limit - starting_row ); ENDIF; ! Continue free scrolling until the user types a ! character (which is ignored). ! ignore_key := READ_KEY; ENDPROCEDURE PROCEDURE xlse_find_mark( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the cursor to the "next" unnamed marker. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the next marker (FORWARD) ! or the previous marker (REVERSE). ! ! ROUTINE VALUE: ! ! None !-- LOCAL buffer_name, current_number, max_number, new_number, marker_found; marker_found := 0; ! Get the "normalized" name of the current buffer. ! buffer_name := xlse__normalized_buffer_name; ! Exit if no markers have been set. ! IF INDEX(xlse__mark_buffers,buffer_name) = 0 THEN MESSAGE( "No markers set in this buffer" ); RETURN ENDIF; ! Find the next marker that is currently defined. ! current_number := xlse__get_value( "lse__current_" + buffer_name ); max_number := xlse__get_value( "lse__max_" + buffer_name ); new_number := current_number; LOOP ! Select a new marker number. ! IF direction = FORWARD THEN new_number := new_number + 1; ELSE new_number := new_number - 1; ENDIF; ! Adjust the marker number if it goes beyond the upper or lower limits. ! IF new_number > max_number THEN new_number := 1 ENDIF; IF new_number <= 0 THEN new_number := max_number ENDIF; ! Determine whether the marker is still defined. ! EXECUTE( "xlse__temp := GET_INFO(LSE$$MARK_" + xlse__mark_name(buffer_name) + "_" + STR(new_number) + ",'TYPE')" ); IF xlse__temp = MARKER THEN marker_found := 1; ! Ignore markers at the current position. ! EXECUTE( "xlse__temp := LSE$$MARK_" + xlse__mark_name(buffer_name) + "_" + STR(new_number) ); EXITIF xlse__temp <> MARK(NONE); ENDIF; ! Avoid an infinite loop if all marker have been checked. ! IF new_number = current_number THEN IF marker_found = 0 THEN MESSAGE( "No markers set in this buffer" ) ELSE MESSAGE( "No more markers in this buffer" ) ENDIF; RETURN ENDIF; ENDLOOP; ! Save the new current marker number. ! EXECUTE( "lse__current_" + buffer_name + ":=" + STR(new_number) ); ! Position the cursor at the specified marker. ! POSITION( xlse__temp ); ENDPROCEDURE PROCEDURE xlse__mark_name( name_string ) IF LENGTH(name_string) <= 18 THEN RETURN name_string ELSE RETURN SUBSTR(name_string,LENGTH(name_string)-17,18) ENDIF; ENDPROCEDURE PROCEDURE xlse_goto_end_of_comment( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Positions the cursor at the last line of a major comment block ! (i.e., a line consisting of a comment character followed by ! two hyphens). ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the search direction ! (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! ROUTINE VALUE: ! ! None !-- LOCAL comment_pattern, save_cursor, temp; ! Save the starting cursor position. ! save_cursor := MARK(NONE); ! Turn off screen updating until the final position is found. ! SET( SCREEN_UPDATE, OFF ); ! Search for the end of a major comment block. ! xlse__goto_end_of_comment( direction, save_cursor ); ! If the cursor did not move, search again. ! IF MARK(NONE) = save_cursor THEN IF direction = FORWARD THEN MOVE_VERTICAL(1) ELSE MOVE_VERTICAL(-1) ENDIF; xlse__goto_end_of_comment( direction, save_cursor ); ENDIF; ! Position the end of the comment block at the top of the window. ! SET( SCREEN_UPDATE, ON ); xlse__top_of_window; ENDPROCEDURE PROCEDURE xlse_goto_file( default_qualifiers ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's GOTO FILE command: ! ! - The file-name and file-type default to the name of the current buffer. ! ! - A wildcard file-spec can be specified, in which case all ! matching files are loaded into separate buffers. ! ! - A file containing a list of file-specs can be specified (@setname). ! ! - Automatically sets special margins for a Pure-Text file. ! ! This procedure prompts the user for the file(s) to be edited. ! ! FORMAL PARAMETERS: ! ! default_qualifiers ! Default "/READ", "/WRITE", "/[NO]MODIFY" and/or "/CREATE" ! qualifiers for the GOTO FILE command. ! ! IMPLICIT INPUTS: ! ! Name of the current buffer ! ! ROUTINE VALUE: ! ! None !-- LOCAL file_spec, qualifiers; ! Ask the user for a file-spec. ! file_spec := EVE$PROMPT_LINE( "_Edit file: ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); ! Strip any qualifier string off the user's response. ! IF INDEX(file_spec,"/") = 0 THEN qualifiers := ""; ELSE qualifiers := SUBSTR( file_spec, INDEX(file_spec,"/"), 255 ); CHANGE_CASE( qualifiers, UPPER ); file_spec := SUBSTR( file_spec, 1, INDEX(file_spec,"/")-1 ); ENDIF; ! Merge default and explicit qualifiers. ! IF (INDEX(qualifiers,"/R") = 0) AND (INDEX(qualifiers,"/W") = 0) THEN IF INDEX(default_qualifiers,"/READ") <> 0 THEN qualifiers := "/READ" + qualifiers; ENDIF; IF INDEX(default_qualifiers,"/WRITE") <> 0 THEN qualifiers := "/WRITE" + qualifiers; ENDIF; ENDIF; IF (INDEX(default_qualifiers,"/CREATE") <> 0) AND (INDEX(default_qualifiers,"/NOCREATE") = 0) THEN qualifiers := "/CREATE" + qualifiers; ENDIF; IF INDEX(default_qualifiers,"/MODIFY") <> 0 THEN qualifiers := "/MODIFY" + qualifiers; ENDIF; IF INDEX(default_qualifiers,"/NOMODIFY") <> 0 THEN qualifiers := "/NOMODIFY" + qualifiers; ENDIF; ! Invoke a GOTO FILE command, using the buffer name as the default spec. ! xlse__iterate_command( "GOTO FILE"+qualifiers, file_spec, xlse__buffer_spec(CURRENT_BUFFER) ); ENDPROCEDURE PROCEDURE xlse_goto_indicated_file( default_qualifiers ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's GOTO FILE command: ! ! - A /INDICATED operation is simulated by picking up the file name ! and file type at the current position. ! ! - A wildcard file-spec can be specified, in which case all ! matching files are loaded into separate buffers. ! ! - A file containing a list of file-specs can be specified (@setname). ! ! - Automatically sets special margins for a Pure-Text file. ! ! FORMAL PARAMETERS: ! ! default_qualifiers ! Default "/READ", "/WRITE", "/[NO]MODIFY" and/or "/CREATE" ! qualifiers for the GOTO FILE command. ! ! IMPLICIT INPUTS: ! ! Name of the current buffer ! ! ROUTINE VALUE: ! ! None !-- LOCAL file_spec, save_cursor; ! Pickup an indicated file-spec, if one exists. ! file_spec := xlse__current_file_spec; IF file_spec = "" THEN MESSAGE( "Current position is not on a file-spec" ); RETURN ENDIF; ! Split the current window and do the GOTO FILE in the lower pane. ! save_cursor := MARK(NONE); LSE$DO_COMMAND( "SPLIT WINDOW" ); xlse__iterate_command( "GOTO FILE"+default_qualifiers, file_spec, xlse__buffer_spec(CURRENT_BUFFER) ); ! Restore the original window state if GOTO FILE failed. ! IF MARK(NONE) = save_cursor THEN LSE$DO_COMMAND( "DELETE WINDOW" ); ENDIF; ENDPROCEDURE PROCEDURE xlse_goto_page( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves to the beginning of a buffer page. ! ! This procedure differs from LSE's GOTO PAGE command in three ways: ! ! - A page is boundary is a buffer line that begins or ends ! with a form-feed. LSE simply searches for a form-feed. ! ! - The top of the page is positioned near the top of the ! window. LSE positions the top of the page at a random ! location in the window. ! ! - On a workstation, the window is refreshed instead of being ! scrolled. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the search direction ! (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! ROUTINE VALUE: ! ! None !-- ! Fail with a message if the cursor is already at the edge of ! the current buffer. ! IF (direction = FORWARD) AND (MARK(NONE) = END_OF(CURRENT_BUFFER)) THEN MESSAGE( "Attempt to move past the end of buffer " + GET_INFO(CURRENT_BUFFER,"NAME") ); RETURN ENDIF; IF (direction = REVERSE) AND (MARK(NONE) = BEGINNING_OF(CURRENT_BUFFER)) THEN MESSAGE( "Attempt to move past the beginning of buffer " + GET_INFO(CURRENT_BUFFER,"NAME") ); RETURN ENDIF; ! Move to the next page boundary. ! xlse__goto_page( direction ); ! Position the page boundary at the top of the window. ! xlse__top_of_window; ENDPROCEDURE PROCEDURE xlse_goto_screen( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the view on the current buffer forward or backward, leaving ! only two lines of the current view in the new view. ! ! This procedure differs from LSE's GOTO SCREEN command in two ways: ! ! - The initial position of the cursor within the scrolling ! region does not affect the number of lines moved. ! ! - On a workstation, the window is refreshed instead of being ! scrolled. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the search direction ! (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! ROUTINE VALUE: ! ! None !-- LOCAL window_row, window_size, window_delta, scroll_delta; ! Warn the user on an attempt to move past the edge of the buffer. ! ON_ERROR IF direction = FORWARD THEN MESSAGE( "Attempt to move past the end of buffer " + GET_INFO(CURRENT_BUFFER,"NAME") ); ELSE MESSAGE( "Attempt to move past the beginning of buffer " + GET_INFO(CURRENT_BUFFER,"NAME") ); ENDIF; ENDON_ERROR; ! Determine window attributes. ! window_row := GET_INFO(CURRENT_WINDOW,"CURRENT_ROW") - GET_INFO(CURRENT_WINDOW,"VISIBLE_TOP") + 1; window_size := GET_INFO(CURRENT_WINDOW,"VISIBLE_LENGTH"); IF GET_INFO(CURRENT_WINDOW,"STATUS_LINE") <> 0 THEN window_size := window_size - 1; ENDIF; ! Turn off workstation scrolling. ! IF xlse__workstation THEN SET( SCROLLING, CURRENT_WINDOW, OFF, GET_INFO(CURRENT_WINDOW,"SCROLL_TOP"), GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM"), GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ENDIF; ! Force full-screen movement by moving the cursor to the edge ! of the scrolling region and then simulating GOTO SCREEN. ! MOVE_HORIZONTAL(-CURRENT_OFFSET); IF direction = FORWARD THEN scroll_delta := GET_INFO(CURRENT_WINDOW,"SCROLL_TOP") + 1 - window_row; IF scroll_delta < 0 THEN scroll_delta := 0; ENDIF; window_delta := window_size - GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM") - window_row; MOVE_VERTICAL( window_delta + window_size - 2 ); ELSE scroll_delta := window_size - window_row - GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM"); IF scroll_delta > 0 THEN scroll_delta := 0; ENDIF; window_delta := GET_INFO(CURRENT_WINDOW,"SCROLL_TOP") - window_row + 1; MOVE_VERTICAL( window_delta - window_size + 2 ); ENDIF; ! Update the current window. ! UPDATE( CURRENT_WINDOW ); ! Restore the relative cursor screen position, with an adjustment ! in case the original position was outside the scrolling region. ! MOVE_VERTICAL( -window_delta + scroll_delta ); ! Turn on workstation scrolling. ! IF xlse__workstation THEN SET( SCROLLING, CURRENT_WINDOW, ON, GET_INFO(CURRENT_WINDOW,"SCROLL_TOP"), GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM"), GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ENDIF; ENDPROCEDURE PROCEDURE xlse_goto_top_bottom !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves to beginning or end of the current buffer, based on the ! current direction. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- IF CURRENT_DIRECTION = FORWARD THEN POSITION( END_OF(CURRENT_BUFFER) ) ELSE POSITION( BEGINNING_OF(CURRENT_BUFFER) ); SET(FORWARD,CURRENT_BUFFER); LSE$SET_STATUS_LINE( CURRENT_WINDOW ) ENDIF ENDPROCEDURE PROCEDURE xlse_insert_line !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts a blank line before the current line. ! If the cursor is at the beginning of a line, it moves to the ! beginning of the inserted blank line. ! Otherwise, the cursor does not move. ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! xlse_open_previous_line ! Indicates whether to open a previous line (ON) or break the current ! line (OFF), which is the behavior of LSE's GOLD-KP0 key. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_cursor; ! Test the current position within a line. ! IF (CURRENT_OFFSET = 0) OR (xlse_open_previous_line <> ON) THEN ! At beginning of line - simply insert a null line and move to it. ! SPLIT_LINE; MOVE_HORIZONTAL( -1 ); ELSE ! Save the starting position within a line. ! save_cursor := MARK(NONE); ! Move to the beginning of the line and insert a blank line. ! MOVE_HORIZONTAL(-CURRENT_OFFSET); SPLIT_LINE; ! Return to the starting position. ! POSITION( save_cursor ); ENDIF; ENDPROCEDURE PROCEDURE xlse_insert_placeholder !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts a language-specific "TBS" (to be specified) placeholder ! at the current position. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL before_placeholder, after_placeholder; ! Turn off screen updating until the placeholder is inserted. ! SET( SCREEN_UPDATE, OFF ); ! Insert a language-independent alias name. ! COPY_TEXT( " TBS" ); after_placeholder := MARK(NONE); ! Mark the space before the alias name. ! MOVE_HORIZONTAL( -4 ); before_placeholder := MARK(NONE); ! Expand the TBS token. ! MOVE_HORIZONTAL( 4 ); LSE$DO_COMMAND( "EXPAND" ); ! Delete the space before the inserted placeholder. ! POSITION( before_placeholder ); ERASE_CHARACTER( 1 ); ! Set the indentation level at the beginning of the text on the current ! line. This corrects for the incorrect indentation that is set by ! EXPANDing a TBS token at the beginning of a line. !- LSE$DO_COMMAND( "SET INDENT CURRENT" ); ! Move the cursor past the placeholder. ! POSITION( after_placeholder ); ! Turn screen updating back on, and update the current window. ! SET( SCREEN_UPDATE, ON ); UPDATE( CURRENT_WINDOW ); ENDPROCEDURE PROCEDURE xlse_join_lines !++ ! FUNCTIONAL DESCRIPTION: ! ! Joins the current buffer line with the next buffer line, ! leaving a single space between the actual text from the two lines. ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! None ! ! IMPLICIT OUTPUTS: ! ! None ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! None !-- LOCAL join_comments, white_space, bypass_bug; ! Determine whether the current line includes a comment character. ! IF xlse__comment_line <> "" THEN IF INDEX( CURRENT_LINE, xlse__comment_line ) <> 0 THEN join_comments := "YES" ENDIF; ENDIF; ! Remove any white-space from the end of the current line. ! MOVE_HORIZONTAL(-CURRENT_OFFSET); MOVE_HORIZONTAL(+LENGTH(CURRENT_LINE)); COPY_TEXT(" "); MOVE_HORIZONTAL(-CURRENT_OFFSET); white_space := SEARCH_QUIETLY( (SPAN(xlse__space_tab) & LINE_END), FORWARD ); POSITION(white_space); ERASE(white_space); ! Remove any white-space from the beginning of the next line. ! white_space := SEARCH_QUIETLY( (ANCHOR & SPAN(xlse__space_tab)), FORWARD ); IF white_space <> 0 THEN ERASE(white_space) ENDIF; ! Remove comment characters and additional white space ! if two comment lines are being joined. ! IF join_comments = "YES" THEN ! white_space := SEARCH_QUIETLY( (ANCHOR & xlse__comment_line), FORWARD ); bypass_bug := xlse__comment_line; white_space := SEARCH_QUIETLY( (ANCHOR & bypass_bug), FORWARD ); IF white_space <> 0 THEN ERASE(white_space); white_space := SEARCH_QUIETLY( (ANCHOR & SPAN(xlse__space_tab)), FORWARD ); IF white_space <> 0 THEN ERASE(white_space) ENDIF; ENDIF; ENDIF; ! Separate the text from the two lines by a single space. ! COPY_TEXT(" "); ENDPROCEDURE PROCEDURE xlse_learn( exact_option ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Initiates a keystroke "learn mode" that is compatible with the ! LSE V2 LEARN command. ! ! FORMAL PARAMETERS: ! ! exact_option ! An EXACT or NO_EXACT option to be passed to TPU's LEARN_BEGIN built-in. ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! Changes the current buffer status line to bold and underline for the ! duration of learn mode. !-- LOCAL learn_sequence, temp; ON_ERROR ENDON_ERROR; ! Determine whether this is beginning of learn mode or the end. ! IF xlse__learn_mode = OFF THEN ! Ask the user for the key to be bound to the learn sequence. ! LOOP MESSAGE( "Press the key to be defined (F7 - F9) " ); xlse__learn_key := READ_KEY; IF (xlse__learn_key = F10) OR (xlse__learn_key = CTRL_Z_KEY) THEN RETURN; ENDIF; EXITIF (xlse__learn_key = F7) OR (xlse__learn_key = F8) OR (xlse__learn_key = F9); MESSAGE( "Only key F7, F8 or F9 can be defined" ); ENDLOOP; ! Warn the user that learn mode is active with a message. ! IF exact_option = EXACT THEN MESSAGE( "Learn mode is active -- press " + xlse__xlate_key(xlse__learn_key) + " to end" ) ELSE MESSAGE( "Learn mode is active (text input NOT saved) -- press " + xlse__xlate_key(xlse__learn_key) + " to end" ) ENDIF; ! Bold and underline the status line. ! xlse__learn_status := GET_INFO( CURRENT_WINDOW, "STATUS_LINE" ); SET( STATUS_LINE, CURRENT_WINDOW, BOLD, xlse__learn_status ); SET( STATUS_LINE, CURRENT_WINDOW, UNDERLINE, xlse__learn_status ); ! Allow the user to terminate the learn sequence by pressing ! either the XLSE learn key or the key begin defined. ! UNDEFINE_KEY( xlse__learn_key ); DEFINE_KEY( "xlse_learn('')", xlse__learn_key, "learning in progress" ); ! Initiate learn mode. ! LEARN_BEGIN( exact_option ); xlse__learn_mode := ON; xlse__learn_count := xlse__learn_count + 1; ELSE ! Save the current learn sequence. ! learn_sequence := LEARN_END; IF learn_sequence = 0 THEN RETURN ENDIF; xlse__learn_mode := OFF; ! Return the current status line to simply reverse-video. ! SET( STATUS_LINE, CURRENT_WINDOW, NONE, xlse__learn_status ); SET( STATUS_LINE, CURRENT_WINDOW, REVERSE, xlse__learn_status ); ! Bind the learn sequence to the specified key. ! UNDEFINE_KEY( xlse__learn_key ); DEFINE_KEY( learn_sequence, xlse__learn_key, "Learn sequence #"+STR(xlse__learn_count) ); MESSAGE( "Learn sequence #" + STR(xlse__learn_count) + " bound to " + xlse__xlate_key(xlse__learn_key) ); ENDIF; ENDPROCEDURE PROCEDURE xlse_line_in_error( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Performs a NEXT ERROR or PREVIOUS ERROR operation, skipping any errors that ! are on the same source line as the current error. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the direction to move through the ! $REVIEW buffer (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! ROUTINE VALUE: ! ! None !-- LOCAL source_line, save_cursor, duplicate_error; ! Start by moving to the $REVIEW buffer. ! LSE$DO_COMMAND( "GOTO REVIEW" ); IF INDEX(GET_INFO(CURRENT_BUFFER,"NAME"),"$REVIEW") <> 1 THEN RETURN ENDIF; ! Pickup the current source line number. ! source_line := SUBSTR(CURRENT_LINE,1,11); save_cursor := MARK(NONE); ! Skip to the 1st error on a line other than the current line. ! IF direction = FORWARD THEN ! Skip to the next line in error. ! LOOP MOVE_VERTICAL( +1 ); duplicate_error := SEARCH_QUIETLY( LINE_BEGIN & "Line", FORWARD, EXACT ); IF duplicate_error <> 0 THEN POSITION( duplicate_error ); IF source_line <> SUBSTR(CURRENT_LINE,1,11) THEN LSE$DO_COMMAND( "GOTO REVIEW" ); RETURN ENDIF; ELSE MOVE_VERTICAL( -1 ); EXITIF 1; ENDIF; ENDLOOP; ELSE ! Skip to the previous line in error. ! LOOP MOVE_VERTICAL( -1 ); duplicate_error := SEARCH_QUIETLY( LINE_BEGIN & "Line", REVERSE, EXACT ); IF duplicate_error <> 0 THEN POSITION( duplicate_error ); EXITIF source_line <> SUBSTR(CURRENT_LINE,1,11); ELSE MOVE_VERTICAL( +1 ); EXITIF 1; ENDIF; ENDLOOP; IF duplicate_error <> 0 THEN source_line := SUBSTR(CURRENT_LINE,1,11); LOOP MOVE_VERTICAL( -1 ); duplicate_error := SEARCH_QUIETLY( LINE_BEGIN & source_line, REVERSE, EXACT ); IF duplicate_error <> 0 THEN POSITION( duplicate_error ); ELSE MOVE_VERTICAL( +1 ); LSE$DO_COMMAND( "GOTO REVIEW" ); RETURN ENDIF; ENDLOOP; ENDIF; ENDIF; ! Return to the starting position if another line in error cannot be found. ! MESSAGE( "No more source lines in error" ); POSITION( save_cursor ); LSE$DO_COMMAND( "GOTO REVIEW" ); ENDPROCEDURE PROCEDURE xlse_match_parenthesis( highlight_mode ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the cursor to the character which matches the "parenthesis" ! character at the current position. The pairs of characters are ! supported by this procedure: ! ! ( ) [ ] { } < > | & ! ! NOTE: The unusual "|&" pair of characters are used in VAX DOCUMENT ! tag definitions. ! ! FORMAL PARAMETERS: ! ! highlight_mode ! Indicates how the parenthesized region should be highlighted: ! NONE, BOLD, BLINK, REVERSE, UNDERLINE. ! ! ROUTINE VALUE: ! ! None !-- LOCAL match_index, match_character, match_range, save_cursor, search_direction, nest_count, same_character, same_range; ! Use the current parenthesis character to select a matching ! character and direction. ! same_character := CURRENT_CHARACTER; match_index := INDEX( "()[]{}<>|&", same_character ); IF match_index = 0 THEN MESSAGE( '"' + same_character + '" is not a parenthesis character' ); RETURN ENDIF; match_character := SUBSTR( ")(][}{><&|", match_index, 1 ); IF (match_index-2*(match_index/2)) = 1 THEN search_direction := FORWARD; ELSE search_direction := REVERSE; ENDIF; ! Search for a matching parenthesis character. ! nest_count := 1; save_cursor := MARK(NONE); LOOP IF search_direction = FORWARD THEN MOVE_HORIZONTAL( +1 ); ELSE MOVE_HORIZONTAL( -1 ); ENDIF; match_range := SEARCH_QUIETLY( match_character, search_direction ); IF match_range = 0 THEN MESSAGE( 'No match for "' + same_character + '" can be found' ); POSITION( save_cursor ); RETURN ENDIF; match_range := CREATE_RANGE( MARK(NONE), BEGINNING_OF(match_range), NONE ); same_range := SEARCH_QUIETLY( same_character, search_direction ); IF same_range = 0 THEN same_range := match_range; ELSE same_range := CREATE_RANGE( MARK(NONE), BEGINNING_OF(same_range), NONE); ENDIF; IF (LENGTH(match_range) <= LENGTH(same_range)) THEN nest_count := nest_count - 1; EXITIF nest_count = 0; IF search_direction = FORWARD THEN POSITION( END_OF(match_range) ); ELSE POSITION( match_range ); ENDIF; ELSE nest_count := nest_count + 1; IF search_direction = FORWARD THEN POSITION( END_OF(same_range) ); ELSE POSITION( same_range ); ENDIF; ENDIF; ENDLOOP; ! Move the cursor to the matching character and highlight the ! parenthesized range. ! IF search_direction = FORWARD THEN POSITION( END_OF(match_range) ); ELSE POSITION( match_range ); ENDIF; xlse__parenthesis_range := CREATE_RANGE( save_cursor, MARK(NONE), highlight_mode ); ENDPROCEDURE PROCEDURE xlse_modification_remark !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts the current modification remark in the current ! modification history entry. ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! SYS$SCRATCH:REMARK.TXT ! Contains a single line modification remark. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_cursor, remark_range; ! Locate the modification remark placeholder. ! save_cursor := MARK(NONE); MOVE_HORIZONTAL( -CURRENT_OFFSET ); remark_range := SEARCH_QUIETLY( "modification-remark", FORWARD ); IF remark_range = 0 THEN MESSAGE( "Cannot locate MODIFICATION-HISTORY placeholder" ); POSITION( save_cursor ); RETURN; ENDIF; ! Read the current remark into the $PASTE buffer. ! POSITION( xlse__paste_buffer ); ERASE( xlse__paste_buffer ); SET( SUCCESS, OFF ); READ_FILE( "SYS$SCRATCH:REMARK.TXT" ); SET( SUCCESS, ON ); ! Paste the current remark on top of the remark placeholder. ! POSITION( remark_range ); LSE$DO_COMMAND( "PASTE" ); ERASE( xlse__paste_buffer ); ENDPROCEDURE PROCEDURE xlse_new_modification !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts a new modification history entry at the end of the ! first comment block containing "Modification History" ! or "Modified by". ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! XLSE_USER_INITIALS ! String of user initials to be automatically inserted into the ! modification history entry. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_cursor, temp; ! Turn off screen updating until the modification line is setup. ! SET( SCREEN_UPDATE, OFF ); ! Go to the beginning of the current buffer. ! save_cursor := MARK(NONE); POSITION( BEGINNING_OF(CURRENT_BUFFER) ); ! Search forward to the modification history header. ! temp := SEARCH_QUIETLY( ("Modification History:" | "Modified by:"), FORWARD ); IF temp = 0 THEN POSITION( save_cursor ); SET( SCREEN_UPDATE, ON ); MESSAGE( "New modification history entry cannot be added" ); RETURN; ENDIF; ! Move to the end of the comment block. ! POSITION( temp ); SET( FORWARD, CURRENT_BUFFER ); LSE$SET_STATUS_LINE( CURRENT_WINDOW ); xlse__goto_end_of_comment( CURRENT_DIRECTION, save_cursor ); ! Insert a modification history entry template. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); COPY_TEXT( "new_modification" ); LSE$DO_COMMAND( "ENTER LINE" ); MOVE_HORIZONTAL( -1 ); LSE$DO_COMMAND( "EXPAND" ); ! Insert the user's initials, if they're known. ! IF xlse_user_initials <> "" THEN MOVE_HORIZONTAL( -CURRENT_OFFSET ); temp := SEARCH_QUIETLY( "your-initials", FORWARD ); IF temp <> 0 THEN POSITION( temp ); temp := xlse_user_initials; IF LENGTH(temp) < 3 THEN temp := temp + SUBSTR(" ",1,3-LENGTH(temp)); ENDIF; COPY_TEXT( temp ); ENDIF; ENDIF; ! Insert the current date into the modification entry. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); temp := SEARCH_QUIETLY( "modification-date", FORWARD ); IF temp <> 0 THEN POSITION( temp ); temp := xlse_current_date; IF LENGTH(temp) = 8 THEN temp := " " + temp; ENDIF; COPY_TEXT( temp ); ENDIF; ! Locate the "modification-id" placeholder. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); temp := SEARCH_QUIETLY( "modification-id", FORWARD ); IF temp <> 0 THEN POSITION( temp ); ENDIF; ! Turn screen updating back on, and update the current window. ! SET( SCREEN_UPDATE, ON ); xlse__bottom_of_window; ENDPROCEDURE PROCEDURE xlse_next_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Maps the "next" buffer into the current window, skipping ! buffers that are mapped into another window. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL user_buffer; user_buffer := xlse__find_user_buffer( "NEXT" ); IF user_buffer = 0 THEN MESSAGE( "No more user buffers" ); ELSE LSE$DO_COMMAND( 'GOTO BUFFER "' + xlse__buffer_spec(user_buffer) + '"' ); ENDIF; ENDPROCEDURE PROCEDURE xlse_next_window !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the cursor down one window, stopping at the bottom window. ! ! If there is only one window, this procedure splits the screen into two ! windows and maps the next user buffer into the bottom window. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL user_buffer; ! If there is more than one window, simply move the cursor ! down one window (stopping at the bottom). ! IF EVE$X_NUMBER_OF_WINDOWS > 1 THEN IF CURRENT_WINDOW = LSE$BOTTOM_WINDOW THEN MESSAGE( "Already positioned in the bottom window" ); ELSE LSE$DO_COMMAND( "NEXT WINDOW" ); ENDIF; RETURN; ENDIF; ! If there is another user buffer, change into two window mode and map ! the current buffer into the top window and the next user buffer into ! the bottom window. ! user_buffer := xlse__find_user_buffer( "NEXT" ); IF user_buffer = 0 THEN MESSAGE( "No more user buffers" ); ELSE LSE$DO_COMMAND( "CHANGE WINDOW_MODE" ); LSE$DO_COMMAND( 'GOTO BUFFER "' + xlse__buffer_spec(user_buffer) + '"' ); ENDIF; ENDPROCEDURE PROCEDURE xlse_previous_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Maps the "previous" buffer into the current window, skipping ! buffers that are mapped into another window. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL user_buffer; user_buffer := xlse__find_user_buffer( "PREVIOUS" ); IF user_buffer = 0 THEN MESSAGE( "No more user buffers" ); ELSE LSE$DO_COMMAND( 'GOTO BUFFER "' + xlse__buffer_spec(user_buffer) + '"' ); ENDIF; ENDPROCEDURE PROCEDURE xlse_previous_window !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the cursor up one window, stopping at the top window. ! ! If there is only one window, this procedure splits the screen into two ! windows and maps the previous user buffer into the top window. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL user_buffer; ! If there is more than one window, simply move the cursor ! up one window (stopping at the top). ! IF EVE$X_NUMBER_OF_WINDOWS > 1 THEN IF CURRENT_WINDOW = LSE$TOP_WINDOW THEN MESSAGE( "Already positioned in the top window" ); ELSE LSE$DO_COMMAND( "PREVIOUS WINDOW" ); ENDIF; RETURN; ENDIF; ! If there is another user buffer, change into two window mode and map ! the current buffer into the bottom window and the previous user buffer ! into the top window. ! user_buffer := xlse__find_user_buffer( "PREVIOUS" ); IF user_buffer = 0 THEN MESSAGE( "No more user buffers" ); ELSE LSE$DO_COMMAND( "CHANGE WINDOW_MODE" ); LSE$DO_COMMAND( "PREVIOUS WINDOW" ); LSE$DO_COMMAND( 'GOTO BUFFER "' + xlse__buffer_spec(user_buffer) + '"' ); ENDIF; ENDPROCEDURE PROCEDURE xlse_quit !++ ! FUNCTIONAL DESCRIPTION: ! ! Erases message buffer and QUITs the current editing session. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Turn off the "Working" message. ! SET( TIMER, OFF, "" ); ! Erase the message buffer. ! SET( INFORMATIONAL, ON ); ERASE( message_buffer ); UPDATE( MESSAGE_WINDOW ); ! Discard an unwanted MAIL message. ! IF xlse__mail_session THEN LSE$DO_COMMAND( "GOTO BUFFER " + xlse__mail_buffer ); LSE$DO_COMMAND( "SET NOWRITE" ); LSE$DO_COMMAND( "SET NOMODIFY" ); ENDIF; ! Discard an unwanted NOTES buffer. ! IF xlse__notes_session THEN LSE$DO_COMMAND( "SET NOWRITE" ); LSE$DO_COMMAND( "SET NOMODIFY" ); ENDIF; ! Terminate the editing session. ! LSE$DO_COMMAND( "QUIT" ) ENDPROCEDURE PROCEDURE xlse_quote_lse_body !++ ! FUNCTIONAL DESCRIPTION: ! ! Indents and quotes all or part of the template body of an LSE token ! or LSE placeholder definition. ! ! If a region has been selected, the entire region is quoted. ! Otherwise, only the current line is quoted. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL selected_lines, last_body_line; ! Determine whether there is a select region. ! selected_lines := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); IF selected_lines = 0 THEN ! No select region - quote the current line. ! IF MARK(NONE) <> END_OF(CURRENT_BUFFER) THEN xlse__quote_current_line; ENDIF; ELSE ! Locate the beginning of the the line following the select region. ! POSITION( END_OF(selected_lines) ); IF CURRENT_OFFSET <> 0 THEN MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDIF; last_body_line := MARK(NONE); ! Quote the select region one line at a time. ! POSITION( BEGINNING_OF(selected_lines) ); selected_lines := 0; EVE$CLEAR_SELECT_POSITION; LOOP EXITIF MARK(NONE) = last_body_line; xlse__quote_current_line; ENDLOOP; ENDIF; ENDPROCEDURE PROCEDURE xlse__quote_current_line LOCAL line_image, line_index, line_length; ON_ERROR ENDON_ERROR; ! Trim trailing spaces and tabs from the line. ! line_image := CURRENT_LINE; EDIT( line_image, TRIM_TRAILING ); line_length := LENGTH( line_image ); IF line_length < LENGTH(CURRENT_LINE) THEN MOVE_HORIZONTAL( -CURRENT_OFFSET+line_length ); ERASE_CHARACTER( LENGTH(CURRENT_LINE)-line_length ); ENDIF; ! Double any quotation marks in the line. ! line_index := line_length; LOOP EXITIF line_index = 0; IF SUBSTR(line_image,line_index,1) = '"' THEN MOVE_HORIZONTAL( -CURRENT_OFFSET+line_index-1 ); COPY_TEXT( '"' ); ENDIF; line_index := line_index - 1; ENDLOOP; ! Indent and quote the line. ! line_length := LENGTH( CURRENT_LINE ); MOVE_HORIZONTAL( -CURRENT_OFFSET ); COPY_TEXT(' "'); MOVE_HORIZONTAL( line_length ); COPY_TEXT('"'); ! Move to the beginning of the next line. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDPROCEDURE PROCEDURE xlse_read_file !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's READ FILE command: ! ! - The file-name and file-type default to the name of the current buffer. ! ! - The cursor is positioned at the beginning of the inserted file(s). ! ! - A wildcard file-spec can be specified, in which case all ! matching files are inserted into the current buffer. ! ! - A file containing a list of file-specs can be specified (@setname). ! ! This procedure prompts the user for the file(s) to be inserted. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_input_mode, save_cursor, file_spec; ! Save the starting position. ! save_cursor := xlse__cursor_position; ! Ask the user for a file-spec. ! file_spec := EVE$PROMPT_LINE( "_Insert file: ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); ! Force insert mode. ! save_input_mode := eveplus_set_mode( INSERT ); ! Read the file into the current buffer. ! xlse__iterate_command( "READ", file_spec, xlse__buffer_spec(CURRENT_BUFFER) ); ! Restore the starting position and input mode. ! xlse__restore_cursor( save_cursor ); eveplus_set_mode( save_input_mode ); ENDPROCEDURE PROCEDURE xlse_replace !++ ! FUNCTIONAL DESCRIPTION: ! ! Replaces the search string at the current location with the ! current replacement string, maintaining the case of the search ! string (i.e. case-sensitive replacement). ! ! FORMAL PARAMETERS: ! ! None ! ! IMPLICIT INPUTS: ! ! xlse_replace_case_sensitive ! Indicates case-sensitive (ON) or exact (OFF) replacement. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_input_mode, old_string, new_string, state, i; ! Verify that a SEARCH preceded this replacement. ! IF EVE$X_FOUND_RANGE = 0 THEN MESSAGE(" No previous search"); ABORT; ENDIF; IF MARK(NONE) <> BEGINNING_OF( EVE$X_FOUND_RANGE ) THEN MESSAGE( "Not at start of search string" ); ABORT; ENDIF; ! Verify that a replacement string has been specified. ! IF xlse__replace_string = 0 THEN MESSAGE( "No replacement string defined" ); ABORT; ENDIF; ! Make local copies of the search (old) and replacement (new) strings. ! old_string := SUBSTR( EVE$X_FOUND_RANGE, 1, LENGTH(EVE$X_FOUND_RANGE) ); new_string := xlse__replace_string; ! Adjust the case of replacement string to match the search string. ! IF xlse_replace_case_sensitive = ON THEN new_string := xlse__match_case( old_string, new_string ); ENDIF; ! Do the replacement. ! ERASE( EVE$X_FOUND_RANGE ); save_input_mode := eveplus_set_mode( INSERT ); COPY_TEXT( new_string ); eveplus_set_mode( save_input_mode ); ! Clear the current search string so that this function cannot ! be re-executed without doing another search. ! EVE$X_FOUND_RANGE := 0; ENDPROCEDURE PROCEDURE xlse_replace_and_search !++ ! FUNCTIONAL DESCRIPTION: ! ! Replaces the current search string with the current replacement string ! and then move to the next occurrence of the search string. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! LOCAL ! ***BYPASS TPU BUG*** ! xlse__repeat_count; ! ***BYPASS TPU BUG*** ! Terminate on any error. ! ON_ERROR [TPU$_STRNOTFOUND] : MESSAGE( "No more strings to replace" ); [OTHERWISE] : MESSAGE( ERROR_TEXT ); RETURN; ENDON_ERROR; ! Save the current repeat count and set it to 1 so that the ! following SEARCH command is only performed once. ! xlse__repeat_count := EVE$X_REPEAT_COUNT; EVE$X_REPEAT_COUNT := 1; ! Replace the search string at the current position. ! xlse_replace; ! Find the next occurrence of the search string. ! EVE_FIND( EVE$X_TARGET ); ! Restore the repeat count. ! EVE$X_REPEAT_COUNT := xlse__repeat_count; ENDPROCEDURE PROCEDURE xlse_review !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's REVIEW command: ! ! - Executes a GOTO REVIEW if a Review session has been started; ! otherwise, simply executes a REVIEW command. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL review_buffer; ! If a Review session is already active, a GOTO REVIEW ! will cause the $REVIEW buffer to be displayed. ! review_buffer := GET_INFO( BUFFER, "FIND_BUFFER", "$REVIEW" ); IF review_buffer <> 0 THEN IF GET_INFO(review_buffer,"RECORD_COUNT") > 0 THEN LSE$DO_COMMAND( "GOTO REVIEW" ); RETURN; ENDIF; ENDIF; ! Otherwise, REVIEW the current buffer. ! LSE$DO_COMMAND( "REVIEW" ); ENDPROCEDURE PROCEDURE xlse_search_indicated !++ ! FUNCTIONAL DESCRIPTION: ! ! Augments LSE's SEARCH command: ! ! - supports "search for the current select range" or ! "indicated word" ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL selected_string, search_string; ! Pickup the current select region or indicated word. ! IF EVE$X_SELECT_POSITION <> 0 THEN ! Pickup the current select range. ! selected_string := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); search_string := SUBSTR( selected_string, 1, LENGTH(selected_string) ); selected_string := 0; EVE$CLEAR_SELECT_POSITION; IF LENGTH(search_string) = 0 THEN MESSAGE( "Can't search -- nothing selected" ); RETURN ENDIF; ELSE ! Pickup the current word. ! IF CURRENT_CHARACTER = "" THEN MESSAGE( "Can't search -- no word at the current cursor position" ); RETURN; ENDIF; search_string := EVE$CURRENT_WORD; IF GET_INFO( search_string, "TYPE" ) <> RANGE THEN MESSAGE( "Can't search -- no word at the current cursor position" ); RETURN; ENDIF; search_string := SUBSTR( search_string, 1, LENGTH(search_string) ); EDIT( search_string, TRIM_TRAILING ); ENDIF; ! Invoke an EVE search. ! IF EVE_FIND( search_string ) THEN EVE$POSITION_IN_MIDDLE( EVE$X_FOUND_RANGE ) ENDIF; ENDPROCEDURE PROCEDURE xlse_set_mark !++ ! FUNCTIONAL DESCRIPTION: ! ! Sets an "unnamed" marker, which can later be located using ! XLSE_GOTO_MARK. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL buffer_name, new_number; ! Get the "normalized" name of the current buffer. ! buffer_name := xlse__normalized_buffer_name; ! Calculate a new marker number. ! IF INDEX(xlse__mark_buffers,buffer_name) = 0 THEN xlse__mark_buffers := xlse__mark_buffers + "/" + buffer_name; new_number := 1; ELSE new_number := xlse__get_value( "lse__max_" + buffer_name ) + 1; ENDIF; ! Set the new marker. ! LSE$DO_COMMAND( "SET MARK " + xlse__mark_name(buffer_name) + "_" + STR(new_number) ); ! Save the marker values for the current buffer. ! EXECUTE( "lse__max_" + buffer_name + ":=" + STR(new_number) ); EXECUTE( "lse__current_" + buffer_name + ":=" + STR(new_number) ); ENDPROCEDURE PROCEDURE xlse_show_symbol( ; symbol_name ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Displays the type and value of one or more TPU symbols. ! ! FORMAL PARAMETERS: ! ! symbol_name ! Symbol name string. ! ! ROUTINE VALUE: ! ! None !-- LOCAL list_of_procs, list_of_variables, one_name, symbol_type, temp; ! Avoid messages. ! ON_ERROR [TPU$_NONAMES] : ; ! There are no names matching the one requested [TPU$_MULTIPLENAMES] : ;! There is more than one name matching, ... ENDON_ERROR; ! Prompt for a symbol name if none was specified. ! LOOP EXITIF (GET_INFO(symbol_name,"TYPE") = STRING) AND (symbol_name <> ""); symbol_name := EVE$PROMPT_LINE( "_Symbol name: ", EVE$$X_PROMPT_TERMINATORS, xlse__null ); ENDLOOP; EDIT( symbol_name, TRIM ); ! Get a list of all names that match the prefix string. ! list_of_procs := EXPAND_NAME(symbol_name,PROCEDURES); list_of_variables := EXPAND_NAME(symbol_name,VARIABLES); IF (list_of_procs = "") AND (list_of_variables = "") THEN MESSAGE( "No symbol named " + symbol_name ); ENDIF; ! Loop until all variable names have been displayed. ! list_of_procs := list_of_procs + " "; LOOP ! Remove one name from the list. ! EXITIF LENGTH(list_of_procs) <= 1; temp := INDEX(list_of_procs," "); one_name := SUBSTR(list_of_procs,1,temp-1); list_of_procs := SUBSTR(list_of_procs,temp+1,LENGTH(list_of_procs)); ! Display the procedure information. ! MESSAGE( one_name + " (procedure)" ); ENDLOOP; ! Loop until all variable names have been displayed. ! list_of_variables := list_of_variables + " "; LOOP ! Remove one name from the list. ! EXITIF LENGTH(list_of_variables) <= 1; temp := INDEX(list_of_variables," "); one_name := SUBSTR(list_of_variables,1,temp-1); list_of_variables := SUBSTR(list_of_variables, temp+1, LENGTH(list_of_variables)); ! Determine the type and value of the symbol. ! EXECUTE( "xlse__symbol_value := " + one_name ); temp := GET_INFO(xlse__symbol_value,"TYPE"); symbol_type := 0; xlse__symbol_value := 0; IF temp = INTEGER THEN EXECUTE( "xlse__symbol_value := STR(" + one_name + ")" ); symbol_type := "integer"; ENDIF; IF temp = STRING THEN EXECUTE( "xlse__symbol_value := " + one_name ); symbol_type := "string"; ENDIF; IF temp = UNSPECIFIED THEN symbol_type := "unspecified" ENDIF; IF temp = BUFFER THEN symbol_type := "buffer" ENDIF; IF temp = WINDOW THEN symbol_type := "window" ENDIF; IF temp = MARKER THEN symbol_type := "marker" ENDIF; IF temp = RANGE THEN symbol_type := "range" ENDIF; IF temp = PATTERN THEN symbol_type := "pattern" ENDIF; IF temp = PROGRAM THEN symbol_type := "program" ENDIF; IF temp = PROCESS THEN symbol_type := "process" ENDIF; IF temp = LEARN THEN symbol_type := "learn" ENDIF; IF symbol_type = 0 THEN symbol_type := "unknown" ENDIF; ! Display the variable information. ! IF xlse__symbol_value = 0 THEN MESSAGE( one_name + " (" + symbol_type + ")" ); ELSE MESSAGE( one_name + " (" + symbol_type + ") = " + xlse__symbol_value ); ENDIF; ENDLOOP; ENDPROCEDURE PROCEDURE xlse_silent_lse( lse_command ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Silently executes a single LSE command, trapping and discarding ! all messages. ! ! FORMAL PARAMETERS: ! ! lse_command ! String to be executed. ! ! IMPLICIT INPUTS: ! ! xlse__trapped_messages ! Buffer to collect messages. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_message_buffer; ! Temporarily replace the standard message buffer. ! save_message_buffer := MESSAGE_BUFFER; MESSAGE_BUFFER := xlse__trapped_messages; ! Execute the LSE command. ! LSE$DO_COMMAND( lse_command ); ! Discard any messages generated by the LSE command. ! ERASE( xlse__trapped_messages ); ! Restore the standard message buffer. ! MESSAGE_BUFFER := save_message_buffer; ! Return to the caller. ! RETURN; ENDPROCEDURE PROCEDURE xlse_silent_tpu( tpu_statement ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Silently executes a single TPU statement, trapping and discarding ! all messages. ! ! FORMAL PARAMETERS: ! ! tpu_statement ! String to be executed. ! ! IMPLICIT INPUTS: ! ! xlse__trapped_messages ! Buffer to collect messages. ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_message_buffer; ! Temporarily replace the standard message buffer. ! save_message_buffer := MESSAGE_BUFFER; MESSAGE_BUFFER := xlse__trapped_messages; ! Execute the TPU statement. ! EXECUTE( tpu_statement ); ! Discard any messages generated by the TPU statement. ! ERASE( xlse__trapped_messages ); ! Restore the standard message buffer. ! MESSAGE_BUFFER := save_message_buffer; ! Return to the caller. ! RETURN; ENDPROCEDURE PROCEDURE xlse_spaces_to_tabs( entire_line_option, log_option ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Replaces sequences of spaces with tab characters. ! ! If a region has been selected, the entire region is processed. ! Otherwise, only the current line is processed and the cursor moves to ! the beginning of the next line. ! ! WARNING: This procedure assumes that tabs have been set every "n" ! characters, where "n" can be any number. ! ! FORMAL PARAMETERS: ! ! entire_line_option ! Indicates whether all spaces in the entire line should be scanned (ON) ! or just the leading spaces (OFF). ! ! log_option ! Indicates whether to report the number of tabs replaced (ON or OFF). ! ! ROUTINE VALUE: ! ! None !-- LOCAL selected_lines, save_cursor, ! beginning cursor position save_input_mode, ! initial insert/overstrike mode retab_count, ! number of tabs inserted last_body_line; ! Initialization ! save_cursor := MARK(NONE); save_input_mode := eveplus_set_mode( INSERT ); ! Determine whether there is a select region. ! selected_lines := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); IF selected_lines = 0 THEN ! No select region ! ! Verify that the cursor is positioned on a line. ! IF MARK(NONE) = END_OF(CURRENT_BUFFER) THEN MOVE_VERTICAL( +1 ); RETURN; ENDIF; ! Retab the current line and move to the next line. ! IF entire_line_option = ON THEN retab_count := xlse__retab_current_line; ELSE retab_count := xlse__pretab_current_line; ENDIF; MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ELSE ! Locate the beginning of the the line following the select region. ! POSITION( END_OF(selected_lines) ); IF CURRENT_OFFSET <> 0 THEN MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDIF; last_body_line := MARK(NONE); ! Retab the select region one line at a time. ! POSITION( BEGINNING_OF(selected_lines) ); selected_lines := 0; EVE$CLEAR_SELECT_POSITION; LOOP EXITIF MARK(NONE) = last_body_line; IF entire_line_option = ON THEN retab_count := retab_count + xlse__retab_current_line; ELSE retab_count := retab_count + xlse__pretab_current_line; ENDIF; MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDLOOP; ! Return to the starting position. ! POSITION( save_cursor ); ENDIF; ! Restore the initial state of the buffer. ! eveplus_set_mode( save_input_mode ); ! Report how many tabs have been inserted. ! IF log_option = ON THEN MESSAGE( FAO("!UL tab!%S inserted",retab_count) ); ENDIF; ENDPROCEDURE PROCEDURE xlse__retab_current_line LOCAL tab_interval, ! interval between tab stops detab_count, ! number of existing tabs retab_count, ! number of tabs inserted detabbed_line, ! detabbed image of the current line tab_position, ! tab position being evaluated counter; ! loop counter ! Initialization ! tab_interval := GET_INFO(CURRENT_BUFFER,"TAB_STOPS"); retab_count := 0; ! Start by detabbing the current line, ! remembering the original number of tabs. ! detab_count := xlse__detab_current_line; ! Save an image of the detabbed line. ! detabbed_line := CURRENT_LINE; ! Scan the line from right to left so that any changes to the ! current line in the buffer are to the right of the "cursor". ! tab_position := (LENGTH(detabbed_line) / tab_interval) * tab_interval; LOOP EXITIF tab_position = 0; ! If there is a space at a tab position, ! it can be replaced by a tab character. ! IF SUBSTR(detabbed_line,tab_position,1) = xlse__space THEN MOVE_HORIZONTAL( -CURRENT_OFFSET + tab_position ); ERASE_CHARACTER( -1 ); COPY_TEXT( xlse__tab ); ! Count the number of tabs inserted. ! retab_count := retab_count + 1; ! Delete up to "interval-1" spaces that precede the new tab. ! MOVE_HORIZONTAL( -1 ); counter := 0; LOOP counter := counter + 1; EXITIF counter >= tab_interval; MOVE_HORIZONTAL( -1 ); EXITIF CURRENT_CHARACTER <> xlse__space; ERASE_CHARACTER( +1 ); ENDLOOP; ENDIF; ! Backup one tab position, and repeat. ! tab_position := tab_position - tab_interval; ENDLOOP; ! Return the number of tabs inserted into the line. ! RETURN retab_count - detab_count; ENDPROCEDURE PROCEDURE xlse__pretab_current_line LOCAL tab_interval, ! interval between tab stops detab_count, ! number of existing tabs retab_count, ! number of tabs inserted spaces_needed; ! number of spaces need to replace a tab ! Initialization ! tab_interval := GET_INFO(CURRENT_BUFFER,"TAB_STOPS"); retab_count := 0; ! Start by detabbing the current indentation, ! remembering the original number of tabs. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); detab_count := 0; LOOP IF CURRENT_CHARACTER = xlse__tab THEN ERASE_CHARACTER( 1 ); detab_count := detab_count + 1; spaces_needed := tab_interval - (CURRENT_OFFSET - tab_interval * (CURRENT_OFFSET/tab_interval)); COPY_TEXT( FAO("!#* ",spaces_needed) ); ELSE IF CURRENT_CHARACTER = xlse__space THEN MOVE_HORIZONTAL( +1 ); ELSE EXITIF 1; ENDIF; ENDIF; ENDLOOP; ! Retab only the indentation of the current line. ! MOVE_HORIZONTAL( -CURRENT_OFFSET ); LOOP EXITIF SEARCH_QUIETLY(ANCHOR & FAO("!#* ",tab_interval),FORWARD) = 0; ERASE_CHARACTER( +tab_interval ); COPY_TEXT( xlse__tab ); retab_count := retab_count + 1; ENDLOOP; ! Return the number of tabs inserted into the line. ! RETURN retab_count - detab_count; ENDPROCEDURE PROCEDURE xlse_tabs_to_spaces( log_option ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Replaces tab characters with spaces. ! ! If a region has been selected, the entire region is processed. ! Otherwise, only the current line is processed and the cursor moves to ! the beginning of the next line. ! ! WARNING: This procedure assumes that tabs have been set every "n" ! characters, where "n" can be any number. ! ! FORMAL PARAMETERS: ! ! log_option ! Indicates whether to report the number of tabs replaced (ON or OFF). ! ! ROUTINE VALUE: ! ! None !-- LOCAL selected_lines, save_cursor, ! beginning cursor position save_input_mode, ! initial insert/overstrike mode detab_count, ! number of tabs replaced last_body_line; ! Initialization ! save_cursor := MARK(NONE); save_input_mode := eveplus_set_mode( INSERT ); ! Determine whether there is a select region. ! selected_lines := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); IF selected_lines = 0 THEN ! No select region ! ! Verify that the cursor is positioned on a line. ! IF MARK(NONE) = END_OF(CURRENT_BUFFER) THEN MOVE_VERTICAL( +1 ); RETURN; ENDIF; ! Detab the current line and move to the next line. ! detab_count := xlse__detab_current_line; MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ELSE ! Locate the beginning of the the line following the select region. ! POSITION( END_OF(selected_lines) ); IF CURRENT_OFFSET <> 0 THEN MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDIF; last_body_line := MARK(NONE); ! Detab the select region one line at a time. ! POSITION( BEGINNING_OF(selected_lines) ); selected_lines := 0; EVE$CLEAR_SELECT_POSITION; LOOP EXITIF MARK(NONE) = last_body_line; detab_count := detab_count + xlse__detab_current_line; MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( +1 ); ENDLOOP; ! Return to the starting position. ! POSITION( save_cursor ); ENDIF; ! Restore the initial state of the buffer. ! eveplus_set_mode( save_input_mode ); ! Report how many tabs have been replaced. ! IF log_option = ON THEN MESSAGE( FAO("!UL tab!%S replaced",detab_count) ); ENDIF; ENDPROCEDURE PROCEDURE xlse__detab_current_line LOCAL tab_interval, ! interval between tab stops detab_count, ! number of tabs removed tab_index, ! displacement of 1st tab in the current line spaces_needed; ! number of spaces needed to replace a tab character ! Initialization ! tab_interval := GET_INFO(CURRENT_BUFFER,"TAB_STOPS"); detab_count := 0; ! Loop until all tabs have been removed. ! LOOP tab_index := INDEX(CURRENT_LINE,xlse__tab); IF tab_index = 0 THEN RETURN detab_count; ENDIF; ! Delete the tab character. ! MOVE_HORIZONTAL( -CURRENT_OFFSET + tab_index - 1); ERASE_CHARACTER( 1 ); ! Insert an equivalent number of spaces. ! spaces_needed := tab_interval - (CURRENT_OFFSET - tab_interval * (CURRENT_OFFSET/tab_interval)); COPY_TEXT( FAO("!#* ",spaces_needed) ); ! Count the number of tabs removed. ! detab_count := detab_count + 1; ENDLOOP; ENDPROCEDURE PROCEDURE xlse_toggle_tabs !++ ! FUNCTIONAL DESCRIPTION: ! ! Toggles GRAPHIC_TABS mode for the current window. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- IF GET_INFO(CURRENT_WINDOW,"TEXT") = GRAPHIC_TABS THEN SET( TEXT, CURRENT_WINDOW, BLANK_TABS ) ELSE SET( TEXT, CURRENT_WINDOW, GRAPHIC_TABS ) ENDIF ENDPROCEDURE PROCEDURE xlse_toggle_width !++ ! FUNCTIONAL DESCRIPTION: ! ! Toggles the screen width between narrow format (80 characters) and ! wide format (132 characters). ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- IF get_info(get_info(window,"CURRENT"),"WIDTH") = 80 THEN LSE$DO_COMMAND( "SET SCREEN WIDTH=132" ) ELSE LSE$DO_COMMAND( "SET SCREEN WIDTH=80" ) ENDIF ENDPROCEDURE PROCEDURE xlse_unerase_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts the most recently erased buffer contents into the current ! buffer, leaving the cursor positioned at the beginning of the ! inserted text. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_input_mode, save_cursor; ! Verify that a buffer has been erased. ! IF xlse__erased_buffer = 0 THEN MESSAGE( "No buffer has been erased" ); RETURN ENDIF; ! Save the starting position. ! save_cursor := xlse__cursor_position; ! Force insert mode. ! save_input_mode := eveplus_set_mode( INSERT ); ! Insert the erased buffer contents into the current buffer. ! LSE$DO_COMMAND( "PASTE /BUFFER=$XLSE_ERASED_BUFFER" ); ! Restore the starting position and input mode. ! xlse__restore_cursor( save_cursor ); eveplus_set_mode( save_input_mode ); ENDPROCEDURE PROCEDURE xlse_unerase_page !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts the most recently erased page contents into the current ! buffer, leaving the cursor positioned at the beginning of the ! inserted text. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_input_mode, save_cursor; ! Verify that a page has been erased. ! IF xlse__erased_page = 0 THEN MESSAGE( "No page has been erased" ); RETURN ENDIF; ! Save the starting position. ! save_cursor := xlse__cursor_position; ! Force insert mode. ! save_input_mode := eveplus_set_mode( INSERT ); ! Insert the erased page contents into the current buffer. ! LSE$DO_COMMAND( "PASTE /BUFFER=$XLSE_ERASED_PAGE" ); ! Restore the starting position and input mode. ! xlse__restore_cursor( save_cursor ); eveplus_set_mode( save_input_mode ); ENDPROCEDURE PROCEDURE xlse_unerase_string !++ ! FUNCTIONAL DESCRIPTION: ! ! Inserts the most recently erased string into the current ! buffer, leaving the cursor positioned at the beginning of the ! inserted text. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_input_mode, save_cursor; ! Verify that a string has been erased. ! IF xlse__erased_string = 0 THEN MESSAGE( "No string has been erased" ); RETURN ENDIF; ! Save the starting position. ! save_cursor := xlse__cursor_position; ! Force insert mode. ! save_input_mode := eveplus_set_mode( INSERT ); ! Insert the erased string contents into the current buffer. ! COPY_TEXT( xlse__erased_string ); ! Restore the starting position and input mode. ! xlse__restore_cursor( save_cursor ); eveplus_set_mode( save_input_mode ); ENDPROCEDURE PROCEDURE xlse_write_modified_buffers !++ ! FUNCTIONAL DESCRIPTION: ! ! WRITEs all modified buffers. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL buffer_count, one_buffer, last_buffer; buffer_count := 0; last_buffer := GET_INFO(BUFFERS,"LAST"); one_buffer := GET_INFO(BUFFERS,"FIRST"); ! Loop thru all buffers, WRITEing out modified user buffers. ! LOOP IF NOT GET_INFO(one_buffer,"SYSTEM") AND NOT GET_INFO(one_buffer,"NO_WRITE") AND GET_INFO(one_buffer,"MODIFIED") THEN LSE$DO_COMMAND( 'WRITE /BUFFER="' + GET_INFO(one_buffer,"NAME") + '"' ); buffer_count := buffer_count + 1; ENDIF; EXITIF one_buffer = last_buffer; one_buffer := GET_INFO(BUFFERS,"NEXT"); ENDLOOP; ! Report the number of buffers written. ! IF buffer_count = 0 THEN MESSAGE( "There are no modified buffers" ); ELSE MESSAGE( FAO("!UL buffer!%S written",buffer_count) ); ENDIF; ENDPROCEDURE !++ ! XLSE Support Procedures !-- PROCEDURE xlse__bottom_of_window !++ ! FUNCTIONAL DESCRIPTION: ! ! Positions the current line of the current buffer at the bottom of ! the current window (last line of the scrolling region). ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_scroll_amount, save_scroll_top, one_line_scroll, multi_line_scroll, window_size; ! Determine window attributes. ! IF xlse__workstation THEN one_line_scroll := OFF; ELSE one_line_scroll := ON; ENDIF; IF GET_INFO(SCREEN,"SCROLL") THEN multi_line_scroll := ON; ELSE multi_line_scroll := OFF; ENDIF; window_size := GET_INFO(CURRENT_WINDOW,"VISIBLE_LENGTH"); IF GET_INFO(CURRENT_WINDOW,"STATUS_LINE") <> 0 THEN window_size := window_size - 1; ENDIF; ! Save the window scrolling attributes. ! save_scroll_top := GET_INFO( CURRENT_WINDOW, "SCROLL_TOP" ); ! Shrink the window scrolling region to a single line. ! SET( SCROLLING, CURRENT_WINDOW, one_line_scroll, window_size - GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM") - 1, GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM"), GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ! Force the current line into the bottom (single) line of ! the window scrolling region. ! UPDATE( CURRENT_WINDOW ); ! Restore the original window scrolling region. ! SET( SCROLLING, CURRENT_WINDOW, multi_line_scroll, save_scroll_top, GET_INFO(CURRENT_WINDOW,"SCROLL_BOTTOM"), GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ENDPROCEDURE PROCEDURE xlse__buffer_spec( one_buffer ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the file-spec portion of a buffer name, discarding an additional ! text, for example , "(LIBRARY ELEMENT)". ! ! FORMAL PARAMETERS: ! ! one_buffer ! Buffer variable which identifies a specific buffer. ! ! ROUTINE VALUE: ! ! string ! File-spec portion of a buffer name. !-- LOCAL buffer_name, end_of_spec; buffer_name := GET_INFO( one_buffer, "NAME" ); end_of_spec := INDEX( buffer_name, " " ); IF end_of_spec = 0 THEN RETURN buffer_name ELSE RETURN SUBSTR(buffer_name,1,end_of_spec-1) ENDIF ENDPROCEDURE PROCEDURE xlse__comment_line !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the comment character(s) for a single line comment. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! comment character(s) corresponding to the current language !-- LOCAL current_language; ! Determine the language type of the current buffer. ! current_language := GET_INFO(CURRENT_BUFFER,"LANGUAGE"); ! Select comment characters based on the language. ! IF (current_language = "BASIC") OR (current_language = "BLISS") OR (current_language = "CDU") OR (current_language = "DATATRIEVE") OR (current_language = "LSE") OR (current_language = "MMS") OR (current_language = "MESSAGE") OR (current_language = "SCAN") OR (current_language = "TEXT") OR (current_language = "TPU") OR (current_language = "UIL") THEN RETURN "!" ENDIF; IF current_language = "ADA" THEN RETURN "--" ENDIF; IF (current_language = "C") OR (current_language = "CXX") OR (current_language = "PLI") THEN RETURN "**" ENDIF; IF current_language = "COBOL" THEN RETURN "*" ENDIF; IF current_language = "DCL" THEN RETURN "$!" ENDIF; IF current_language = "FORTRAN" THEN RETURN "C" ENDIF; IF current_language = "MACRO" THEN RETURN ";" ENDIF; IF (current_language = "MAKE") OR (current_language = "SCRIPT") THEN RETURN "#" ENDIF; IF current_language = "PASCAL" THEN RETURN "|" ENDIF; IF current_language = "RUNOFF" THEN RETURN ".!" ENDIF; IF current_language = "SDL" THEN RETURN "{" ENDIF; IF current_language = "SDML" THEN RETURN "" ENDIF; IF current_language = "SPITBOL" THEN RETURN ";*" ENDIF; IF current_language = "TABLE" THEN RETURN "" ENDIF; IF current_language = "LATEX" THEN RETURN "%" ENDIF; ! Assume a "!" for all other languages. ! RETURN "!"; ENDPROCEDURE PROCEDURE xlse__current_character !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the current character, unless the current position is at the ! end of a line or buffer. ! ! This procedure differs from the CURRENT_CHARACTER builtin in that no ! error is reported at the end of a buffer. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! current character -or- "" !-- ON_ERROR ENDON_ERROR; RETURN CURRENT_CHARACTER ENDPROCEDURE PROCEDURE xlse__current_file_spec !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the file-spec, if any, at the current buffer position. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! file-spec or a null string !-- LOCAL selected_string, file_spec; ! Determine how the user has indicated the file-spec. ! IF EVE$X_SELECT_POSITION <> 0 THEN ! Pickup the file-spec from the selected range. ! selected_string := EVE$SELECTION( FALSE, TRUE, FALSE, FALSE, TRUE ); file_spec := SUBSTR( selected_string, 1, LENGTH(selected_string) ); selected_string := 0; EVE$CLEAR_SELECT_POSITION; RETURN file_spec; ELSE ! Span the file-spec characters starting at the current position. ! file_spec := SEARCH_QUIETLY( (ANCHOR & SPAN(xlse__file_spec_chars)), FORWARD); IF file_spec = 0 THEN RETURN "" ELSE RETURN SUBSTR(file_spec,1,LENGTH(file_spec)) ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse__double_quotes( subject_string ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Doubles each quotation mark in a string. ! ! FORMAL PARAMETERS: ! ! subject_string ! String to be converted. ! ! ROUTINE VALUE: ! ! result string !-- LOCAL temp_string, result_string, temp; temp_string := subject_string; result_string := ""; LOOP temp := INDEX(temp_string,'"'); IF temp = 0 THEN RETURN result_string + temp_string ENDIF; result_string := result_string + SUBSTR(temp_string,1,temp-1) + '""'; temp_string := SUBSTR(temp_string,temp+1,LENGTH(temp_string)); ENDLOOP; ENDPROCEDURE PROCEDURE xlse__find_user_buffer( search_direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Searches the list of user buffers for the next (or previous) buffer ! that is not already mapped into a window. ! ! FORMAL PARAMETERS: ! ! search_direction ! Indicates whether to search for the "NEXT" user buffer or ! the "PREVIOUS" user buffer. ! ! ROUTINE VALUE: ! ! 0 ! Indicates that there are no unmapped user buffers. ! ! buffer-variable ! User buffer which is not mapped to a window. !-- LOCAL starting_buffer, last_buffer, one_buffer; ! Determine the end of the buffer list. ! IF search_direction = "NEXT" THEN last_buffer := GET_INFO(BUFFERS,"LAST"); ELSE last_buffer := GET_INFO(BUFFERS,"FIRST"); ENDIF; ! Start with the current buffer. ! starting_buffer := GET_INFO(BUFFERS,"CURRENT"); one_buffer := starting_buffer; ! Loop thru the list of all buffers (user and system). ! LOOP IF one_buffer = last_buffer THEN IF search_direction = "NEXT" THEN one_buffer := GET_INFO(BUFFERS,"FIRST"); ELSE one_buffer := GET_INFO(BUFFERS,"LAST"); ENDIF; ELSE one_buffer := GET_INFO(BUFFERS,search_direction) ENDIF; ! Return if the entire list has been searched. ! IF one_buffer = starting_buffer THEN RETURN 0 ENDIF; ! Skip a buffer that is already mapped to a window. ! IF GET_INFO(one_buffer,"MAP_COUNT") = 0 THEN ! Skip a "$MAIN" buffer that the user hasn't touched. ! IF xlse__buffer_spec( one_buffer ) = "$MAIN" THEN EXITIF GET_INFO(one_buffer,"MODIFIED"); EXITIF GET_INFO(one_buffer,"RECORD_COUNT") <> 0; ELSE ! Skip a system buffer. ! EXITIF GET_INFO(one_buffer,"SYSTEM") = 0; ENDIF; ENDIF; ENDLOOP; ! Return a user buffer variable. ! RETURN one_buffer ENDPROCEDURE PROCEDURE xlse__get_value( variable_name ) !++ ! FUNCTIONAL DESCRIPTION: ! ! XLSE__GET_VALUE returns the value of a variable. ! ! FORMAL PARAMETERS: ! ! variable_name ! Name of a TPU variable. ! ! ROUTINE VALUE: ! ! value of the variable !-- EXECUTE( "xlse__temp := " + variable_name ); RETURN xlse__temp; ENDPROCEDURE PROCEDURE xlse__goto_end_of_comment( direction, save_cursor ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves to the end of a major comment block. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the search direction ! (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! save_cursor ! The buffer position to be assumed in the event of a search failure. ! ! ROUTINE VALUE: ! ! None ! ! SIDE EFFECTS: ! ! Screen updating is forced on in the event of a search failure. !-- LOCAL comment_pattern, comment_range, temp; ! Setup the end-of-comment search pattern. ! IF GET_INFO(CURRENT_BUFFER,"LANGUAGE") = "SDL" THEN comment_pattern := "" & ("{--" | "/*--"); ELSE comment_pattern := xlse__comment_line + "--"; ENDIF; ! Loop until an actual end-of-comment is found. ! LOOP comment_range := SEARCH_QUIETLY( comment_pattern, direction ); IF comment_range = 0 THEN SET( SCREEN_UPDATE, ON ); POSITION( save_cursor ); MESSAGE( "Cannot find the end of a major comment block" ); ABORT; ENDIF; POSITION( comment_range ); temp := CURRENT_LINE; EDIT( temp, TRIM ); EXITIF LENGTH(temp) = LENGTH(comment_range); IF direction = FORWARD THEN MOVE_VERTICAL(1) ELSE MOVE_VERTICAL(-1) ENDIF; ENDLOOP; ENDPROCEDURE PROCEDURE xlse__goto_page( direction ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves to the beginning of a buffer page. ! ! FORMAL PARAMETERS: ! ! direction ! An option which indicates the search direction ! (FORWARD, REVERSE, or CURRENT_DIRECTION). ! ! ROUTINE VALUE: ! ! None !-- LOCAL ff_range; ! Block "Cannot return a string at end of buffer" error. ! ON_ERROR [TPU$_NOEOBSTR] : ; ENDON_ERROR; ! Loop until an actual page boundary is found. ! LOOP ! Move one character if the cursor is positioned on a form-feed. ! IF MARK(NONE) <> END_OF(CURRENT_BUFFER) THEN IF CURRENT_CHARACTER = " " THEN IF direction = FORWARD THEN MOVE_HORIZONTAL( +1 ); ELSE MOVE_HORIZONTAL( -1 ); ENDIF; ENDIF; ENDIF; ! Find the next form-feed. ! ff_range := SEARCH_QUIETLY( " ", direction ); IF ff_range <> 0 THEN POSITION( ff_range ); ELSE ! If a page cannot be found in the specified direction, ! simply go to the edge of the buffer. ! IF direction = FORWARD THEN POSITION( END_OF(CURRENT_BUFFER) ); ELSE POSITION( BEGINNING_OF(CURRENT_BUFFER) ); ENDIF; ENDIF; ! Exit if an actual page boundary has been found. ! EXITIF (CURRENT_OFFSET = 0) OR (CURRENT_OFFSET = LENGTH(CURRENT_LINE)-1 ); ENDLOOP; ENDPROCEDURE PROCEDURE xlse__iterate_command( lse_command, file_spec, default_spec ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Iterates an LSE command over a wildcard file name or ! a predefined set of names. ! ! FORMAL PARAMETERS: ! ! lse_command ! LSE command to be iteratively executed. ! ! file_spec ! A simple file-spec, a wildcard file-spec, or a reference ! to a predefined set of names (@setname). ! ! default_spec ! A default file-name and file-type. ! ! ROUTINE VALUE: ! ! None !-- LOCAL upper_file_spec, set_spec, full_set_spec, user_buffer_position, one_file_spec, comment_index; ! Abort with a message if no file was specified. ! IF file_spec = "" THEN MESSAGE( "No file specified" ); ABORT; ENDIF; ! Determine the type of file-spec provided. ! upper_file_spec := file_spec; EDIT( upper_file_spec, UPPER ); IF SUBSTR(file_spec,1,1) <> "@" THEN ! Iterate over a simple file-spec (which may include wildcards). ! xlse__iterate_over_files( lse_command, upper_file_spec, default_spec ); ELSE ! Loop thru a set of file-specs (which may include wildcards). ! set_spec := SUBSTR(file_spec,2,255); EDIT( set_spec, UPPER ); IF (INDEX(set_spec,"*") <> 0) OR (INDEX(set_spec,"%") <> 0) THEN MESSAGE( "Set file-spec cannot include wildcards" ); ABORT; ENDIF; full_set_spec := FILE_SEARCH( set_spec, ".SET" ); IF full_set_spec = "" THEN MESSAGE( set_spec + " set file cannot be opened" ); ABORT; ENDIF; ! Save the starting location. ! user_buffer_position := MARK(NONE); ! Read the set file into the $XLSE_SET_FILE buffer. ! ERASE( xlse__set_file ); POSITION( xlse__set_file ); SET( SUCCESS, OFF ); READ_FILE( full_set_spec ); SET( SUCCESS, ON ); ! Loop thru the set file in the iterate buffer. ! POSITION( BEGINNING_OF(CURRENT_BUFFER) ); LOOP EXITIF MARK(NONE) = END_OF(CURRENT_BUFFER); ! Pickup the current line in the set file and ! eliminate everything but the file-spec. ! one_file_spec := SUBSTR(CURRENT_LINE,1,255); comment_index := INDEX(one_file_spec,"!"); IF comment_index <> 0 THEN one_file_spec := SUBSTR(one_file_spec,1,comment_index-1); ENDIF; EDIT( one_file_spec, UPPER, TRIM ); ! Skip set lines that don't include a file-spec. ! IF one_file_spec <> "" THEN ! Iterate over a simple file-spec (which may include wildcards). ! POSITION( user_buffer_position ); xlse__iterate_over_files( lse_command, one_file_spec, default_spec ); ! Save the position in the user's buffer. ! user_buffer_position := MARK(NONE); ENDIF; ! Move to the next line in the set file. ! POSITION( xlse__set_file ); MOVE_VERTICAL( +1 ); ENDLOOP; ! Move to the final user buffer position. ! POSITION( user_buffer_position ); ENDIF; ENDPROCEDURE procedure mhg$check_read_only(a_buffer) local rw, filename; filename := get_info(a_buffer,"file_name"); rw := call_user(1,filename); IF (rw <> '1') AND (rw <> '0') THEN message( rw ); ENDIF; IF (rw <> '1') THEN ! set buffer readonly if no priv or error msg set(MODIFIABLE, a_buffer, OFF); set(NO_WRITE, a_buffer); ENDIF; eve$set_status_line(current_window); endprocedure; PROCEDURE xlse__iterate_over_files( lse_command, file_spec, default_spec ) LOCAL one_found, mhg_check_access, one_file; ON_ERROR [TPU$_PARSEFAIL] : ; ENDON_ERROR; ! Determine whether a wildcard file-spec was provided. ! IF (INDEX(file_spec,"*") = 0) AND (INDEX(file_spec,"%") = 0) THEN ! Simple file-spec ! mhg_check_access := 1; one_file := FILE_SEARCH( file_spec, default_spec ); IF one_file = "" THEN mhg_check_access := 0; one_file := FILE_PARSE( file_spec, default_spec ); IF one_file = "" THEN MESSAGE( '"' + file_spec + '" is an invalid file specification' ); ABORT; ENDIF; ENDIF; ! Execute the command for one file. ! LSE$DO_COMMAND( lse_command + " " + one_file ); if mhg_check_access = 1 then mhg$check_read_only(current_buffer); endif; ELSE ! Wildcard file-spec. ! one_found := 0; LOOP one_file := FILE_SEARCH( file_spec, default_spec ); EXITIF one_file = ""; one_found := 1; ! Execute the command for one file. ! LSE$DO_COMMAND( lse_command + " " + one_file ); mhg$check_read_only(current_buffer); ENDLOOP; ! Warn the user if no files were found. ! IF one_found = 0 THEN one_file := FILE_PARSE( file_spec, default_spec ); IF one_file = "" THEN MESSAGE( '"' + file_spec + '" is an invalid file specification' ); ELSE MESSAGE( "No files found for " + one_file ); ENDIF; ABORT; ENDIF; ENDIF; ENDPROCEDURE PROCEDURE xlse__mail_session !++ ! FUNCTIONAL DESCRIPTION: ! ! Determines whether LSE was invoked from MAIL to create a MAIL message ! (e.g., SEND/EDIT). ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! 1 = MAIL session ! 0 = not a MAIL session !-- ! Use the output file-spec to determine whether this ! is a MAIL editing session. ! IF INDEX(GET_INFO(COMMAND_LINE,"OUTPUT_FILE"),"SYS$SCRATCH:MAIL_") = 1 THEN RETURN 1 ELSE RETURN 0 ENDIF; ENDPROCEDURE PROCEDURE xlse__mail_setup !++ ! FUNCTIONAL DESCRIPTION: ! ! Sets up a MAIL editing session when Callable LSE is invoked from ! VAX/VMS MAIL. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL input_file_name; ! MAIL provides an input file in response to the following commands: ! ! SEND/EDIT filename ! REPLY/EDIT ! FORWARD/EDIT ! IF GET_INFO(CURRENT_BUFFER,"NAME") <> "$MAIN" THEN ! If this a REPLY command, create an empty buffer for the reply. ! ! Unfortunately, MAIL makes it impossible to tell the difference ! between a REPLY and FORWARD command. ! input_file_name := GET_INFO(COMMAND_LINE,"FILE_NAME"); IF ((INDEX(input_file_name,"SYS$SCRATCH:MAIL_") = 1) ! VMS V5 AND (INDEX(input_file_name,"_EDIT.TMP") <> 0)) ! VMS V5 OR (INDEX(input_file_name,"SYS$SCRATCH:MAIL1_") = 1) ! VMS V4.7 THEN ! Make the initial buffer unmodifiable. ! LSE$DO_COMMAND( "SET NOWRITE" ); LSE$DO_COMMAND( "SET NOMODIFY" ); ! Create a new buffer in a separate window. ! LSE$DO_COMMAND( "CHANGE WINDOW_MODE" ); CREATE_BUFFER( "$MAIN" ); LSE$DO_COMMAND( "GOTO BUFFER $MAIN" ); SET( OUTPUT_FILE, CURRENT_BUFFER, GET_INFO(COMMAND_LINE,"OUTPUT_FILE") ); ENDIF; ! Clear the "read from" message. ! ERASE( message_buffer ); ENDIF; ! Set the primary editing buffer to TEXT language mode. ! LSE$DO_COMMAND( "SET LANGUAGE TEXT" ); ! Save the name of the primary MAIL editing buffer (for XLSE_QUIT). ! xlse__mail_buffer := GET_INFO( CURRENT_BUFFER, "NAME" ); ENDPROCEDURE PROCEDURE xlse__match_case( pattern_string, subject_string ) !++ ! FUNCTIONAL DESCRIPTION: ! ! XLSE__MATCH_CASE forces the case of a subject string to match the case ! of a pattern string. ! ! FORMAL PARAMETERS: ! ! pattern_string ! A string whose upper/lower case is to be matched. ! ! subject_string ! The string to be converted. ! ! IMPLICIT INPUTS: ! ! xlse__lower_case ! String of all lower case alphabetic characters. ! ! xlse__upper_case ! String of all upper case alphabetic characters. ! ! ROUTINE VALUE: ! ! Subject string whose case has been converted to match the pattern string. !-- LOCAL new_string, lower_pattern, upper_pattern, char_index, one_char; ! Initialization ! new_string := subject_string; lower_pattern := pattern_string; CHANGE_CASE( lower_pattern, LOWER ); upper_pattern := pattern_string; CHANGE_CASE( upper_pattern, UPPER ); ! Return the subject string unchanged if the pattern string ! does not contain any alphabetic characters. ! IF lower_pattern = upper_pattern THEN RETURN subject_string; ENDIF; ! Test the pattern string for all lower case. ! IF pattern_string = lower_pattern THEN CHANGE_CASE( new_string, LOWER ); RETURN new_string; ENDIF; ! Test the pattern string for all upper case. ! IF pattern_string = upper_pattern THEN CHANGE_CASE( new_string, UPPER ); RETURN new_string; ENDIF; ! Find the first alphabetic character in the pattern string. ! char_index := 0; LOOP char_index := char_index + 1; ! Return a lower case string if the first character is lower case. ! IF INDEX( xlse__lower_case, SUBSTR(pattern_string,char_index,1) ) <> 0 THEN CHANGE_CASE( new_string, LOWER ); RETURN new_string; ENDIF; ! Stop searching if an upper case character is found. ! IF INDEX( xlse__upper_case, SUBSTR(pattern_string,char_index,1) ) <> 0 THEN EXITIF 1; ENDIF; ENDLOOP; ! Force the first character of the result string to upper case. ! CHANGE_CASE( new_string, LOWER ); char_index := 0; LOOP char_index := char_index + 1; ! Return the subject string unchanged if it contains no ! alphabetic character. ! IF char_index > LENGTH(new_string) THEN RETURN new_string; ENDIF; ! Return a lower case string if the first character is lower case. ! one_char := SUBSTR( new_string, char_index, 1 ); IF INDEX( xlse__lower_case, one_char ) <> 0 THEN CHANGE_CASE( one_char, UPPER ); new_string := SUBSTR(new_string,1,char_index-1) + one_char + SUBSTR(new_string,char_index+1,LENGTH(new_string)); RETURN new_string; ENDIF; ENDLOOP; ENDPROCEDURE PROCEDURE xlse__modifiable_buffer !++ ! FUNCTIONAL DESCRIPTION: ! ! Aborts with a message if the current buffer cannot be modified. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- IF GET_INFO(CURRENT_BUFFER,"MODIFIABLE") <> 1 THEN MESSAGE( "Attempt to change unmodifiable buffer " + GET_INFO(CURRENT_BUFFER,"NAME") ); ABORT; ENDIF; ENDPROCEDURE PROCEDURE xlse__normalized_buffer_name !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the name of the current buffer, with the following ! transformations: ! ! ø "." replaced by "_" ! ø "." replaced by "_" ! ø special suffix (e.g., "(LIBRARY ELEMENT)") is discarded ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! Normalized buffer name string !-- LOCAL normalized_name; ! Get the name of the current buffer. ! normalized_name := xlse__buffer_spec( CURRENT_BUFFER ); ! Replace "-" and "." with "_". ! TRANSLATE( normalized_name, "__", "-." ); ! Return the normalized name to the caller. ! RETURN normalized_name ENDPROCEDURE PROCEDURE xlse__notes_session !++ ! FUNCTIONAL DESCRIPTION: ! ! Determines whether LSE was invoked from NOTES to create a note ! (e.g., REPLY command). ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! 1 = NOTES session ! 0 = not a NOTES session !-- ! Use the output file-spec to determine whether this ! is a NOTES editing session. ! IF INDEX(GET_INFO(COMMAND_LINE,"OUTPUT_FILE"),"SYS$SCRATCH:NOTES_") = 1 THEN RETURN 1 ELSE RETURN 0 ENDIF; ENDPROCEDURE PROCEDURE xlse__notes_setup !++ ! FUNCTIONAL DESCRIPTION: ! ! Sets up a NOTES editing session when Callable LSE is invoked from ! VAX Notes. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! If NOTES provided an initial file, special setup is called for. ! IF GET_INFO(CURRENT_BUFFER,"NAME") <> "$MAIN" THEN ! Clear the "read from" message. ! ERASE( message_buffer ); ! Determine the type of supplied text. ! IF xlse__notes_forward THEN ! Put a FORWARDed note at the end of the buffer. ! COPY_TEXT( " [text]" ); SPLIT_LINE; SPLIT_LINE; MOVE_VERTICAL( -2 ); MOVE_HORIZONTAL( 5 ); ELSE IF xlse__notes_reply THEN ! Make a REPLY/EXTRACT buffer unmodifiable. ! LSE$DO_COMMAND( "SET NOWRITE" ); LSE$DO_COMMAND( "SET NOMODIFY" ); ! Create a new note buffer in a separate window. ! LSE$DO_COMMAND( "CHANGE WINDOW_MODE" ); CREATE_BUFFER( "$MAIN" ); LSE$DO_COMMAND( "GOTO BUFFER $MAIN" ); SET( OUTPUT_FILE, CURRENT_BUFFER, GET_INFO(COMMAND_LINE,"OUTPUT_FILE") ); ENDIF; ENDIF; ENDIF; ! Set the primary editing buffer to TEXT language mode. ! LSE$DO_COMMAND( "SET LANGUAGE TEXT" ); ENDPROCEDURE PROCEDURE xlse__notes_forward LOCAL output_spec; output_spec := GET_INFO(COMMAND_LINE,"OUTPUT_FILE"); IF INDEX(output_spec,"SYS$SCRATCH:NOTES_") = 0 THEN RETURN 0 ENDIF; IF INDEX(output_spec,"_MAIL") = 0 THEN RETURN 0 ENDIF; RETURN 1; ENDPROCEDURE PROCEDURE xlse__notes_reply LOCAL input_spec, output_spec; input_spec := GET_INFO(COMMAND_LINE,"FILE_NAME"); output_spec := GET_INFO(COMMAND_LINE,"OUTPUT_FILE"); ! Test for a Notes V1 reply. ! IF INDEX(CURRENT_LINE,"< Note ") = 1 THEN RETURN 1; ENDIF; ! Test for a Notes V2 reply. ! IF INDEX(input_spec,"SYS$SCRATCH:NOTES_") = 0 THEN RETURN 0 ENDIF; IF INDEX(output_spec,"SYS$SCRATCH:NOTES_") = 0 THEN RETURN 0 ENDIF; IF INDEX(input_spec,"_EDIT") = 0 THEN RETURN 0 ENDIF; IF INDEX(output_spec,"_EDIT1") = 0 THEN RETURN 0 ENDIF; RETURN 1; ENDPROCEDURE PROCEDURE xlse__restore_cursor( cursor_position ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Moves the cursor to a "saved" position. ! ! FORMAL PARAMETERS: ! ! cursor_position ! Former cursor position or 0 (beginning of buffer). ! ! ROUTINE VALUE: ! ! None !-- IF cursor_position = 0 THEN POSITION( BEGINNING_OF(CURRENT_BUFFER) ) ELSE POSITION( cursor_position ); MOVE_HORIZONTAL(1) ENDIF ENDPROCEDURE PROCEDURE xlse__cursor_position !++ ! FUNCTIONAL DESCRIPTION: ! ! XLSE__CURSOR_POSITION returns the current position. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! current buffer position or 0 (beginning of the buffer) !-- IF MARK(NONE) = BEGINNING_OF(CURRENT_BUFFER) THEN xlse__cursor_position := 0 ELSE MOVE_HORIZONTAL(-1); xlse__cursor_position := MARK(NONE); MOVE_HORIZONTAL(1) ENDIF ENDPROCEDURE PROCEDURE xlse__statement_separator !++ ! FUNCTIONAL DESCRIPTION: ! ! Returns the statement separator (or terminator) character ! for current buffer. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! statement separator character corresponding to the current language !-- LOCAL current_language; ! Determine the language type of the current buffer. ! current_language := GET_INFO(CURRENT_BUFFER,"LANGUAGE"); ! Determine appropriate separator character based on the type of buffer. ! IF (current_language = "ADA") OR (current_language = "BLI") OR (current_language = "C") OR (current_language = "CXX") OR (current_language = "PASCAL") OR (current_language = "PLI") OR (current_language = "SDL") OR (current_language = "SPITBOL") OR (current_language = "TPU") THEN RETURN ";" ENDIF; IF current_language = "SDML" THEN RETURN ".,:;!?)""" ENDIF; ! Otherwise, return no separator character. ! RETURN ""; ENDPROCEDURE PROCEDURE xlse__top_of_window !++ ! FUNCTIONAL DESCRIPTION: ! ! Positions the current line of the current buffer at the top of ! the current window (1st line of the scrolling region). ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- LOCAL save_scroll_bottom, one_line_scroll, multi_line_scroll, window_size; ! Determine window attributes. ! IF xlse__workstation THEN one_line_scroll := OFF; ELSE one_line_scroll := ON; ENDIF; IF GET_INFO(SCREEN,"SCROLL") THEN multi_line_scroll := ON; ELSE multi_line_scroll := OFF; ENDIF; window_size := GET_INFO(CURRENT_WINDOW,"VISIBLE_LENGTH"); IF GET_INFO(CURRENT_WINDOW,"STATUS_LINE") <> 0 THEN window_size := window_size - 1; ENDIF; ! Save the window scrolling attributes. ! save_scroll_bottom := GET_INFO( CURRENT_WINDOW, "SCROLL_BOTTOM" ); ! Shrink the window scrolling region to a single line. ! SET( SCROLLING, CURRENT_WINDOW, one_line_scroll, GET_INFO(CURRENT_WINDOW,"SCROLL_TOP"), window_size - GET_INFO(CURRENT_WINDOW,"SCROLL_TOP") - 1, GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ! Force the current line into the top (single) line of ! the window scrolling region. ! UPDATE( CURRENT_WINDOW ); ! Restore the original window scrolling region. ! SET( SCROLLING, CURRENT_WINDOW, multi_line_scroll, GET_INFO(CURRENT_WINDOW,"SCROLL_TOP"), save_scroll_bottom, GET_INFO(CURRENT_WINDOW,"SCROLL_AMOUNT") ); ENDPROCEDURE PROCEDURE xlse__workstation !++ ! FUNCTIONAL DESCRIPTION: ! ! Determines whether XLSE is being run on a µVAX Workstation. ! ! NOTE: This procedure uses the visible screen size to make this ! determination. That is, if the screen size is greater than 25 lines, ! it assumes a workstation. ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! 0 = not a workstation ! 1 = is a workstation !-- RETURN (GET_INFO(SCREEN,"DECWINDOWS")) OR (GET_INFO(SCREEN,"VISIBLE_LENGTH") > 25) ENDPROCEDURE PROCEDURE xlse__wrap_mode( buffer_variable ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Determines whether wrap mode is set for the specified buffer. ! ! FORMAL PARAMETERS: ! ! buffer_variable ! Buffer to be interrogated. ! ! ROUTINE VALUE: ! ! 0 ! Wrap mode is not set. ! ! 1 ! Wrap mode is set. !-- LOCAL language; language := GET_INFO( buffer_variable, "LANGUAGE" ); IF (language = "C") OR (language = "CXX") OR (language = "RUNOFF") OR (language = "SDML") OR (language = "TEXT") THEN RETURN 1; ELSE RETURN 0; ENDIF; ENDPROCEDURE PROCEDURE xlse__xlate_key( tpu_key_number ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Translates a TPU key number into an ASCII key name. ! ! NOTE: This procedure is currently limited to keys F6 - F20. ! ! FORMAL PARAMETERS: ! ! tpu_key_number ! Key number. ! ! ROUTINE VALUE: ! ! ASCII key name !-- IF tpu_key_number = F6 THEN RETURN "F6" ENDIF; IF tpu_key_number = F7 THEN RETURN "F7" ENDIF; IF tpu_key_number = F8 THEN RETURN "F8" ENDIF; IF tpu_key_number = F9 THEN RETURN "F9" ENDIF; IF tpu_key_number = F10 THEN RETURN "F10" ENDIF; IF tpu_key_number = F11 THEN RETURN "F11" ENDIF; IF tpu_key_number = F12 THEN RETURN "F12" ENDIF; IF tpu_key_number = F13 THEN RETURN "F13" ENDIF; IF tpu_key_number = F14 THEN RETURN "F14" ENDIF; IF tpu_key_number = F15 THEN RETURN "F15" ENDIF; IF tpu_key_number = F16 THEN RETURN "F16" ENDIF; IF tpu_key_number = F17 THEN RETURN "F17" ENDIF; IF tpu_key_number = F18 THEN RETURN "F18" ENDIF; IF tpu_key_number = F19 THEN RETURN "F19" ENDIF; IF tpu_key_number = F20 THEN RETURN "F20" ENDIF; RETURN "UNKNOWN-KEY" ENDPROCEDURE PROCEDURE tpu$local_init !++ ! FUNCTIONAL DESCRIPTION: ! ! TPU Initialization Procedure ! ! FORMAL PARAMETERS: ! ! None ! ! ROUTINE VALUE: ! ! None !-- ! Perform XLSE initialization. ! xlse_initialize; ENDPROCEDURE