!************************************************************************* ! * ! © 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. * ! * !************************************************************************* !++ ! ! Abstract: ! Implements the DIFF, NEXT_DIFF and END_DIFF commands. ! ! Author: ! R. Neil Faiman, TLE Group ! W. Ward Clark, MEMEX Project ! Jeff E. Nelson, XLSE user ! ! Creation Date: 25-Sep-88 ! !-- !++ ! RNF_CREATE_WORK_SUBPROCESS will establish the subprocess RNF_S_WORK and ! the buffer RNF_B_WORK if they don't already exist. !-- procedure rnf_create_work_subprocess IF GET_INFO(rnf_s_work, "type") = unspecified THEN rnf_b_work := CREATE_BUFFER("RNF_WORK"); SET(eob_text, rnf_b_work, ""); SET(no_write, rnf_b_work); SET(system, rnf_b_work); rnf_s_work := CREATE_PROCESS(rnf_b_work, "$ set noon"); SEND("$ delete:==delete", rnf_s_work); ! disregard user symbols ENDIF; ERASE(rnf_b_work); endprocedure !++ ! RNF_FIX_POSITION_IN_WINDOW forces the line containing the current position ! to appear on a particular row of the current window. If XROW is positive, ! it is the row number. If it is negative, it is the row count from the ! bottom of the window. If it is 0, the line will appear in the middle ! of the window. !-- procedure rnf_fix_position_in_window( xrow ) local disp_row, window_size, save_scroll_top, save_scroll_bottom, save_scroll_amount, ix; IF EVE$X_REPEAT_COUNT <> tpu$k_unspecified THEN ix := GET_INFO (EVE$X_REPEAT_COUNT, "last"); IF ix <> tpu$k_unspecified THEN IF EVE$X_REPEAT_COUNT {ix} > 1 THEN return; ENDIF; ENDIF; ENDIF; save_scroll_top := GET_INFO(current_window, "scroll_top"); save_scroll_bottom := GET_INFO(current_window, "scroll_bottom"); save_scroll_amount := GET_INFO(current_window, "scroll_amount"); window_size := GET_INFO(current_window, "visible_length"); IF GET_INFO(current_window, "status_line") <> "" THEN window_size := window_size - 1; ENDIF; if eve$x_decwindows_active then if get_info( current_window, 'scroll_bar', HORIZONTAL ) <> 0 then window_size := window_size - 1; endif; endif; IF xrow > 0 THEN disp_row := xrow; else IF xrow < 0 THEN disp_row := window_size + xrow + 1; ELSE disp_row := (window_size + 1) / 2; ENDIF; ENDIF; IF disp_row <= save_scroll_top THEN disp_row := save_scroll_top + 1; ENDIF; IF disp_row > window_size - save_scroll_bottom THEN disp_row := window_size - save_scroll_bottom; ENDIF; SET(scrolling, current_window, on, disp_row - 1, window_size - disp_row, 0); UPDATE(current_window); SET(scrolling, current_window, on, save_scroll_top, save_scroll_bottom, save_scroll_amount); endprocedure !++ ! RNF_DO_DIFF will find differences between the current buffer and a ! specified file (by default, the previous version of the file in the ! buffer - this assumes the buffer has been modified and represents ! the next version). !-- procedure rnf_do_diff( ; comparison_spec ) LOCAL save_cursor, original_file, comparison_file, comparison_name, diff1_begin, diff1_end, diff1_previous, diff2_begin, diff2_end, diff2_previous, temp; !+ ! Terminate a previous DIFF session. !- rnf_do_diff_end; !+ ! Save information about the current buffer. !- rnf_b_diff_buf1 := current_buffer; save_cursor := MARK(NONE); original_file := GET_INFO(rnf_b_diff_buf1, "file_name"); !+ ! Get the file specification of the comparison file. !- IF GET_INFO(comparison_spec,"TYPE") = UNSPECIFIED THEN IF original_file <> "" THEN comparison_file := original_file; ELSE MESSAGE("Comparison file not specified"); ABORT; ENDIF; ELSE IF original_file <> "" THEN comparison_file := FILE_PARSE( comparison_spec, "", original_file ); ENDIF; ENDIF; !+ ! Verify that the comparison file actually exists. !- temp := FILE_SEARCH(""); temp := FILE_SEARCH(comparison_file); IF temp = "" THEN MESSAGE("Comparison file " + comparison_file + " not found"); abort; ENDIF; comparison_file := temp; ! Set up for the comparison. MESSAGE("Beginning comparison..."); rnf_create_work_subprocess; !+ ! Write out the current buffer into a temporary file. !- current_buffer_file := "SYS$SCRATCH:" + STR( GET_INFO(rnf_s_work,"PID") ) + ".TMP"; WRITE_FILE( rnf_b_diff_buf1, current_buffer_file ); !+ ! Do the comparison, and verify that it produced some differences. !- SEND( "DIFFERENCES " + current_buffer_file + " " + comparison_file + " /MERGE=1", rnf_s_work ); !+ ! Delete the temporary copy of the current buffer. !- SEND( "DELETE "+current_buffer_file+";*", rnf_s_work ); POSITION( BEGINNING_OF(rnf_b_work) ); !+ ! Skip the first line if it contains the DIFFERENCES command. ! The next is the first line of output. (JEN 92/02/05) !- IF SUBSTR(current_line,1,11) = "DIFFERENCES" THEN MOVE_VERTICAL(1); ENDIF; !+ ! Report any errors from the comparison. !- IF current_character = "%" THEN POSITION( save_cursor ); MESSAGE(current_line); abort; ENDIF; IF current_line <> "************" THEN POSITION( save_cursor ); MESSAGE("No differences"); abort; ENDIF; !+ ! Find a buffer containing the comparison file, if there is one. ! Otherwise, create a new buffer. !- rnf_b_diff_buf2 := GET_INFO(buffers, "first"); LOOP IF rnf_b_diff_buf2 = 0 THEN temp := 0; LOOP comparison_name := FILE_PARSE(comparison_file, "", "", name) + FILE_PARSE(comparison_file, "", "", type) + FILE_PARSE(comparison_file, "", "", version); IF temp <> 0 THEN comparison_name := comparison_name + "-" + STR(temp); ENDIF; rnf_b_diff_buf2 := GET_INFO(buffers, "first"); LOOP EXITIF rnf_b_diff_buf2 = 0; EXITIF GET_INFO(rnf_b_diff_buf2, "name") = comparison_name; rnf_b_diff_buf2 := GET_INFO(buffers, "next"); ENDLOOP; EXITIF rnf_b_diff_buf2 = 0; temp := temp + 1; ENDLOOP; rnf_b_diff_buf2 := CREATE_BUFFER( comparison_name, comparison_file); LSE$DO_COMMAND( "SET READ_ONLY /BUFFER=" + comparison_name ); LSE$DO_COMMAND( "SET NOMODIFY /BUFFER=" + comparison_name ); EXITIF 1; ENDIF; EXITIF(GET_INFO(rnf_b_diff_buf2, "file_name") = comparison_file) and (not GET_INFO(rnf_b_diff_buf2, "modified")); rnf_b_diff_buf2 := GET_INFO(buffers, "next"); ENDLOOP; !+ ! Prepare to mark the difference regions in the two buffers. !- diff1_previous := 1; diff2_previous := 1; POSITION( rnf_b_diff_buf1 ); POSITION( BEGINNING_OF(rnf_b_diff_buf1) ); POSITION( rnf_b_diff_buf2 ); POSITION( BEGINNING_OF(rnf_b_diff_buf2) ); rnf_r_diff_1a := 0; rnf_r_diff_1b := 0; POSITION( BEGINNING_OF(rnf_b_work) ); !+ ! Skip the first line if it contains the DIFFERENCES command. ! The next is the first line of output. (JEN 92/02/05) !- IF SUBSTR(current_line,1,11) = "DIFFERENCES" THEN MOVE_VERTICAL(1); ENDIF; !+ ! Scan the formatted differences listing in the work buffer. !- LOOP EXITIF current_character <> "*"; rnf_n_diff_count := rnf_n_diff_count + 1; MOVE_VERTICAL(2); !+ ! Pickup the beginning and ending line numbers ! for the current buffer. !- IF current_character = "*" THEN diff1_begin := 0; diff1_end := 0; ELSE temp := SUBSTR( current_line, 1, 5 ); EDIT( temp, TRIM ); diff1_begin := INT(temp); LOOP temp := SUBSTR( current_line, 1, 5 ); EDIT( temp, TRIM ); diff1_end := INT(temp); MOVE_VERTICAL( 1 ); EXITIF current_character = "*"; ENDLOOP; ENDIF; MOVE_VERTICAL(2); !+ ! Pickup the beginning and ending line numbers ! for the comparison file. !- IF current_character = "*" THEN diff2_begin := 0; diff2_end := 0; ELSE temp := SUBSTR( current_line, 1, 5 ); EDIT( temp, TRIM ); diff2_begin := INT(temp); LOOP temp := SUBSTR( current_line, 1, 5 ); EDIT( temp, TRIM ); diff2_end := INT(temp); MOVE_VERTICAL( 1 ); EXITIF current_character = "*"; ENDLOOP; ENDIF; MOVE_VERTICAL( 1 ); !+ ! Create a difference range in the current buffer. !- POSITION( rnf_b_diff_buf1 ); IF diff1_begin = 0 THEN POSITION( END_OF(current_buffer) ); EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "a := CREATE_RANGE(MARK(NONE),MARK(NONE),NONE)" ); ELSE MOVE_VERTICAL( diff1_begin - diff1_previous ); rnf_x_temp := MARK(NONE); MOVE_VERTICAL( diff1_end - diff1_begin + 1 ); MOVE_HORIZONTAL(-1); EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "a := CREATE_RANGE(rnf_x_temp,MARK(NONE),NONE)" ); MOVE_HORIZONTAL( 1 ); ENDIF; diff1_previous := diff1_end + 1; !+ ! Create a difference range in the comparison buffer. !- POSITION( rnf_b_diff_buf2 ); IF diff2_begin = 0 THEN POSITION( END_OF(current_buffer) ); EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "b := CREATE_RANGE(MARK(NONE),MARK(NONE),NONE)" ); ELSE MOVE_VERTICAL( diff2_begin - diff2_previous ); rnf_x_temp := MARK(NONE); MOVE_VERTICAL( diff2_end - diff2_begin + 1 ); MOVE_HORIZONTAL(-1); EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "b := CREATE_RANGE(rnf_x_temp,MARK(NONE),NONE)" ); MOVE_HORIZONTAL( 1 ); ENDIF; diff2_previous := diff2_end + 1; POSITION( rnf_b_work ); ENDLOOP; POSITION( save_cursor ); !+ ! Go into two-window mode, and display the two buffers, with the ! cursors at the start of the first difference regions. !- xlse_diff_window( rnf_b_diff_buf2 ); POSITION( rnf_r_diff_1b ); rnf_r_diff_b := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_1b), END_OF(rnf_r_diff_1b), UNDERLINE ); rnf_fix_position_in_window( 1 ); xlse_diff_window( rnf_b_diff_buf1 ); POSITION( rnf_r_diff_1a ); rnf_r_diff_a := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_1a), END_OF(rnf_r_diff_1a), UNDERLINE ); rnf_fix_position_in_window( 1 ); !+ ! Report the number of differences found. !- MESSAGE(FAO("!SL difference!%S found", rnf_n_diff_count)); endprocedure !++ ! RNF_DO_DIFF_END ends a DIFF session. !-- procedure rnf_do_diff_end IF GET_INFO(rnf_n_diff_count, "type") = unspecified THEN rnf_n_diff_count := 0; ENDIF; IF rnf_n_diff_count = 0 THEN return; ENDIF; LOOP EXITIF rnf_n_diff_count = 0; EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "a := 0" ); EXECUTE( "rnf_r_diff_" + STR(rnf_n_diff_count) + "b := 0" ); rnf_n_diff_count := rnf_n_diff_count - 1; ENDLOOP; rnf_r_diff_a := 0; rnf_r_diff_b := 0; !+ ! Delete the buffer and window (if any) containing the comparison file. !- IF (GET_INFO(rnf_b_diff_buf2,"MAP_COUNT") > 0) AND (EVE$X_NUMBER_OF_WINDOWS > 1) THEN xlse_diff_window( rnf_b_diff_buf2 ); LSE$DO_COMMAND( "DELETE WINDOW" ); ENDIF; LSE$DO_COMMAND( "DELETE BUFFER " + GET_INFO(rnf_b_diff_buf2,"NAME") ); ENDPROCEDURE !++ ! RNF_DO_DIFF_NEXT moves to the next difference. !-- procedure rnf_do_diff_next local save_cursor, mchar, xpos, n; IF rnf_n_diff_count = 0 THEN MESSAGE("No DIFFERENCES session is active"); ABORT; ENDIF; save_cursor := MARK(NONE); IF current_buffer = rnf_b_diff_buf1 THEN mchar := "a"; ELSE IF current_buffer = rnf_b_diff_buf2 THEN mchar := "b"; ELSE POSITION( rnf_b_diff_buf1 ); mchar := "a"; ENDIF; ENDIF; xpos := MARK(NONE); POSITION( save_cursor ); n := 1; LOOP IF n > rnf_n_diff_count THEN MESSAGE("No next difference"); ABORT; ENDIF; EXECUTE( "rnf_x_temp := BEGINNING_OF(rnf_r_diff_" + STR(n) + mchar + ")" ); EXITIF rnf_x_temp > xpos; n := n + 1; ENDLOOP; !+ ! Go into two-window mode, and display the two buffers, with the ! cursors at the start of the selected difference regions. !- xlse_diff_window( rnf_b_diff_buf2 ); EXECUTE( "rnf_r_diff_b := rnf_r_diff_" + STR(n) + "b" ); rnf_r_diff_b := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_b), END_OF(rnf_r_diff_b), UNDERLINE ); POSITION( rnf_r_diff_b ); rnf_fix_position_in_window( 1 ); xlse_diff_window( rnf_b_diff_buf1 ); EXECUTE( "rnf_r_diff_a := rnf_r_diff_" + STR(n) + "a" ); rnf_r_diff_a := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_a), END_OF(rnf_r_diff_a), UNDERLINE ); POSITION( rnf_r_diff_a ); rnf_fix_position_in_window( 1 ); endprocedure !++ ! RNF_DO_DIFF_PREV moves to the next difference. !-- procedure rnf_do_diff_prev local save_cursor, mchar, xpos, n; IF rnf_n_diff_count = 0 THEN MESSAGE("No DIFFERENCES session is active"); ABORT; ENDIF; save_cursor := MARK(NONE); IF current_buffer = rnf_b_diff_buf1 THEN mchar := "a"; ELSE IF current_buffer = rnf_b_diff_buf2 THEN mchar := "b"; ELSE POSITION( rnf_b_diff_buf1 ); mchar := "a"; ENDIF; ENDIF; xpos := MARK(NONE); POSITION( save_cursor ); n := rnf_n_diff_count; LOOP IF n = 0 THEN MESSAGE("No previous difference"); ABORT; ENDIF; EXECUTE( "rnf_x_temp := BEGINNING_OF(rnf_r_diff_" + STR(n) + mchar + ")"); EXITIF rnf_x_temp < xpos; n := n - 1; ENDLOOP; ! Go into two-window mode, and display the two buffers, with the cursors ! at the start of the selected difference regions. xlse_diff_window( rnf_b_diff_buf2 ); EXECUTE( "rnf_r_diff_b := rnf_r_diff_" + STR(n) + "b" ); rnf_r_diff_b := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_b), END_OF(rnf_r_diff_b), UNDERLINE ); POSITION( rnf_r_diff_b ); rnf_fix_position_in_window( 1 ); xlse_diff_window( rnf_b_diff_buf1 ); EXECUTE( "rnf_r_diff_a := rnf_r_diff_" + STR(n) + "a" ); rnf_r_diff_a := CREATE_RANGE( BEGINNING_OF(rnf_r_diff_a), END_OF(rnf_r_diff_a), UNDERLINE ); POSITION( rnf_r_diff_a ); rnf_fix_position_in_window( 1 ); endprocedure PROCEDURE xlse_diff_window( diff_buffer ) !++ ! FUNCTIONAL DESCRIPTION: ! ! Positions in the window containing a specific DIFF buffer. ! ! If the buffer is not mapped into a window, the current window is ! split and the buffer is mapped into the upper half of the split ! (à la REVIEW). ! ! FORMAL PARAMETERS: ! ! diff_buffer ! DIFF buffer variable ! ! ROUTINE VALUE: ! ! None !-- !+ ! Determine whether the desired buffer is already visible. !- IF GET_INFO(diff_buffer,"MAP_COUNT") > 0 THEN !+ ! The buffer is already mapped to a current window. !- IF CURRENT_BUFFER = diff_buffer THEN RETURN; ENDIF; POSITION( LSE$TOP_WINDOW ); LOOP EXITIF CURRENT_BUFFER = diff_buffer; LSE$DO_COMMAND( "NEXT WINDOW" ); ENDLOOP; ELSE !+ ! Create a new window and map the buffer into it. !- LSE$DO_COMMAND( "SPLIT WINDOW" ); LSE$DO_COMMAND( "PREVIOUS WINDOW" ); LSE$DO_COMMAND( "GOTO BUFFER " + GET_INFO(diff_buffer,"NAME") ); ENDIF; !+ ! Return to the caller. !- RETURN; ENDPROCEDURE