! ! MMCSECINI.TPU from Martin Marietta Corp. (Canaveral Operations) ! ! Martin Marietta Aerospace (Canaveral Operations) ! Supplement to SYS$LIBRARY:EDTSECINI ! Supplement to Kalamazoo College SYS$LIBRARY:KAZSECINI ! !To activate after revisions: ! !$ EDIT/TPU/SECTION=SYS$SHARE:EDTSECINI/COMMAND=this_file.TPU ! and play with any modified commands; ! if all is OK, then ! $ COPY this_file.TPU TO SYS$SHARE:this_file.TPU ! $ COPY this_file.gbl TO SYS$SHARE:this_file.gbl ! ! Kalamazoo College Supplement to SYS$LIBRARY:EDTSECINI ! ! COPYRIGHT © 1985 BY ! Richard D. Piccard, Michael L. Penix, and Kalamazoo College, ! Kalamazoo, Michigan, to the extent not copyright by DIGITAL. ! ALL RIGHTS RESERVED ! ! ! The following copyright line appears in several ! locations throughout the code, indicating sections that ! are tightly based on DIGITAL's EDTSECINI.TPU file. ! ! ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED ! ! In those locations where the above lines appear, the ! following should be understood: ! ! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ! ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE ! INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ! COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY ! OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ! TRANSFERRED. ! !Functional 4-OCT-1985 Michael L. Penix and Richard D. Piccard ! !Enhanced: ! !18-APR-1986 DLS: add message for entry mode (ins/ovstrk) ! !21-APR-1986 DLS: add parameters to MMC$windows ! !22-APR-1986 DLS: change PF1+I to create temp_buffer ! !28-APR-1986 DLS: add ( /select ) option to substitute command ! !28-MAY-1986 DLS: add error message if invalid write/exit ! and remain in current_buffer (MMC$get_out) ! !17-JUN-1986 DLS: add new status_line format (mod. from EVE) ! !18-JUN-1986 DLS: add new tab procedure (insert spaces upon tab) ! !31-JUL-1986 DLS: extended ruler to 132 columns. ! !27-AUG-1986 DLS: added grow_window procedure, ! learn_begin (CTRL/K) / learn_end (CRTL/E) procedure, ! HELP_KEY buffer/window display. ! !06-SEP-1986 DLS: added ability to center lines of text. ! !The major vulnerabilities to changes by DIGITAL are in those variables !and procedures whose names begin with "EDT$"; they reference the !contents of DIGITAL's EDTSECINI file, which is "subject to change !without notice." ! !+ PROCEDURE TPU$local_init !- ! DO NOT CHANGE THE NAME OF THIS PROCEDURE!!!!. ! TPU local initialization procedure. Called at start-up to initialize ! variables and set up initial environment of main buffer. !- local this_buffer, ! Current buffer mode_string, ! String version of current mode direction_string, ! String version of current direction buffer_name; ! String containing name of current buffer !first initialize global variables ! !next line is space, tab, ff, lf, cr, vt edt$x_word := " "; MMC$word_delim := 'text'; MMC$indent_delim := 'indent'; ! !the ''& here forces an incremental search !see page 2-12 of the VAXTPU Ref. Manual ! MMC$sent_delim := ''& ( ('.'|'?'|'!') & ( ' ' | '" ' | ') ' | '] ' | '} ' | line_end | ('"'&line_end) | (')'&line_end) | (']'&line_end) | ('}'&line_end) )); ! MMC$parag_delim := line_begin & line_end; MMC$x_null := ''; MMC$x_whitespace := " "; MMC$ruler_mode := 'noruler'; MMC$ruler_string := "....|....1....|....2....|....3....|....4....|....5" + "....|....6....|....7....|....8....|....9....|....0....|....1" + "....|....2....|....3.."; MMC$x_spaces := ' '; MMC$x_center_spaces := ' '; MMC$x_max_buffer_name_length := 45; ! Buffer names can be any size, but ! this is the largest size that will ! show on the status line without being truncated edt$x_tab_size := 8; edt$x_tab_goal := edt$x_tab_size; edt$x_tab_set := 1; ! define_key('edt$wrap_word',key_name(' ')); edt$x_wrap_position := 132; ! MMC$buffer_nam_1 := get_info(current_buffer,"name"); MMC$window_nam_1 := current_window; ! MMC$window_size := 21; ! !now execute some statements to set up the environment ! set (screen_update,on); set (bell,broadcast,on); set (video,info_window,none); set (pad,info_window,off); set (message_flags,5); set (timer,on,"***Executing***"); set (facility_name, "MMC_TPU"); ! The lower the number below (5), the more frequent records are written ! to the journal file. The default is 10. ! set (journaling,5); MMC$define_keys; MMC$swap_delim; ! This is to set up the initial status line. if get_info (main_buffer, "mode") = insert then mode_string := "Insert "; else mode_string := "Overstrike"; endif; if get_info (main_buffer, "direction") = reverse then direction_string := "Reverse"; else direction_string := "Forward"; endif; buffer_name := get_info (current_buffer, "name"); buffer_name := buffer_name + " " + get_info (current_buffer, "file_name"); if length (buffer_name) > MMC$x_max_buffer_name_length then buffer_name := substr (buffer_name, 1, MMC$x_max_buffer_name_length); else buffer_name := buffer_name + substr (MMC$x_spaces, 1, MMC$x_max_buffer_name_length - length (buffer_name)); endif; set (status_line, current_window, reverse,""); set (status_line, current_window, bold, " Buffer: " + buffer_name + " " + mode_string + " " +direction_string); ENDPROCEDURE !+ ! Tab key procedure. Always inserts a tab, even if current mode ! is overstrike. ! PROCEDURE MMC$user_tab !- local this_mode, ! Variable for current mode tab_spaces; ! amount of spaces for TAB this_mode := get_info(current_buffer, "mode"); ! save current mode set (insert,current_buffer); ! set mode to insert tab_spaces := substr (MMC$x_spaces, 1, edt$x_tab_size); copy_Text(tab_spaces); set (this_mode,current_buffer); ! reset original mode ENDPROCEDURE !+ ! Set status line of a window to include buffer name and mode indications. ! Used primarily to indicate insert/overstrike and forward/reverse toggling. ! ! Parameters: ! this_window Window whose status line is being set - input ! PROCEDURE MMC$set_status_line (this_window) !- local this_buffer, ! Current buffer mode_string, ! String version of current mode direction_string, ! String version of current direction buffer_name; ! String containing name of current buffer this_buffer := get_info (this_window, "buffer"); ! Don't add a status line to windows without a status line or if RULER is on. if (MMC$ruler_mode = 'ruler') or (this_buffer = 0) or (get_info (this_window, "status_line") = 0) then return; endif; if get_info (this_buffer, "mode") = insert then mode_string := "Insert "; else mode_string := "Overstrike"; endif; if get_info (this_buffer, "direction") = reverse then direction_string := "Reverse"; else direction_string := "Forward"; endif; buffer_name := get_info (this_buffer, "name"); buffer_name := buffer_name + " " + get_info (current_buffer, "file_name"); if length (buffer_name) > MMC$x_max_buffer_name_length then buffer_name := substr (buffer_name, 1, MMC$x_max_buffer_name_length); else buffer_name := buffer_name + substr (MMC$x_spaces, 1, MMC$x_max_buffer_name_length - length (buffer_name)); endif; set (status_line, this_window, reverse,""); set (status_line, this_window, bold, " Buffer: " + buffer_name + " " + mode_string + " " + direction_string); ENDPROCEDURE; ! ! Update the status line in all windows mapped to the current buffer !+ PROCEDURE MMC$update_status_lines !- local this_buffer, ! Current buffer loop_window; ! Window currently being checked in loop this_buffer := current_buffer; if get_info (this_buffer, "map_count") > 1 then loop_window := get_info (window, "first"); loop exitif loop_window = 0; if get_info (loop_window, "buffer") = this_buffer then MMC$set_status_line (loop_window); endif; loop_window := get_info (window, "next"); endloop; else MMC$set_status_line (current_window); endif; ENDPROCEDURE; !+ PROCEDURE MMC$get_out !- on_error return 0; endon_error; write_file(main_buffer); set(no_write,main_buffer,ON); exit; ENDPROCEDURE !+ PROCEDURE MMC$RESTORE !- local start_mark, bizz_mark, bizz_mark_range; bizz_MARK := '^^&&^^'; start_mark := mark(none); POSITION (BEGINNING_OF (CURRENT_BUFFER)); bizz_MARK_RANGE := SEARCH(bizz_MARK,FORWARD,EXACT); if bizz_mark_range = 0 then position (start_mark); message ('***No mark found in this buffer.'); return; endif; POSITION (bizz_MARK_RANGE); ERASE (bizz_MARK_RANGE); ENDPROCEDURE !+ PROCEDURE MMC$find_buffer ( buffer_name) ! support routine for line mode !- !STOLEN FROM PAGE 21 OF EDTSECINI.TPU - V1.0 RDP 3-OCT-1985 ! ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED ! ! ! Find the buffer by name !- LOCAL upcased_name , buffer_ptr ; upcased_name := buffer_name; change_case(upcased_name,upper); buffer_ptr := get_info(buffers,'first'); loop exitif buffer_ptr = 0; exitif upcased_name = get_info(buffer_ptr,'name'); buffer_ptr := get_info(buffers,'next'); endloop; return buffer_ptr; ENDPROCEDURE !+ PROCEDURE MMC$buffer !- ! support routine for line mode(= buffer cmd) ! ! STOLEN FROM SAME PLACE Page 22 ! ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED !+ ! Process the line mode =buffer command !- LOCAL buffer_ptr , create_variable_string, term_char, file_write, file_name, buffer_name ; ! ! This is to move to a new buffer and map it to the main window. If ! the buffer does not exist, ask whether to create it with the NO_WRITE ! attribute. Get the buffer name from the command line. ! MMC$x_null := ''; buffer_name := read_line ("Enter buffer name to edit: "); if (buffer_name = MMC$x_null) then message('***No buffer specified'); return 0; endif; ! IF it exists just map to it. buffer_ptr := MMC$find_buffer(buffer_name); if buffer_ptr = 0 then MMC$x_make_buf_var := buffer_name; create_variable_string := MMC$x_make_buf_var + "_buffer := create_buffer(MMC$x_make_buf_var)"; execute (create_variable_string); ! Now get the pointer back, we know it is the last buffer in the list buffer_ptr := get_info (buffers,'last'); file_write := read_line ("Write the contents of this buffer to a file upon exit [Y/N]? "); if (index(file_write,'y') = 0) and (index(file_write,'Y') = 0) then SET (NO_WRITE, buffer_ptr, ON); else file_name := read_line("Enter name of file: "); set (ouTPUt_file,buffer_ptr,file_name); SET (NO_WRITE, buffer_ptr, OFF); endif; set(eob_text, buffer_ptr, '[End of '+buffer_name+']'); map(current_window,buffer_ptr); MMC$update_status_lines; if (index(file_write,'y') <> 0) or (index(file_write,'Y') <> 0) then read_file(file_name); endif; return 1; else map(current_window,buffer_ptr); MMC$update_status_lines; return 1; endif; ENDPROCEDURE !+ PROCEDURE MMC$main_buf ! support routine for line mode(= buffer cmd) !- !STOLEN FROM SAME PLACE Page 22 ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED ! ! Process the line mode =buffer command !- LOCAL buffer_ptr , create_variable_string, term_char, buffer_name ; ! ! This is to move to a new buffer and map it to the main window. If ! the buffer does not exist, create it with the NO_WRITE attribute. ! Get the name from the command line. ! MMC$x_null := ''; buffer_name := 'main'; ! IF it exists just map to it. buffer_ptr := MMC$find_buffer(buffer_name); if buffer_ptr = 0 then MMC$x_make_buf_var := buffer_name; create_variable_string := MMC$x_make_buf_var + "_buffer := create_buffer(MMC$x_make_buf_var)"; execute (create_variable_string); ! Now get the pointer back, we know it is the last buffer in the list buffer_ptr := get_info (buffers,'last'); SET (NO_WRITE, buffer_ptr, ON); set(eob_text, buffer_ptr, '[End of '+buffer_name+']'); endif; map(current_window,buffer_ptr); MMC$set_status_line (current_window); return 1; ENDPROCEDURE !+ PROCEDURE MMC$msg_buf ! support routine for line mode(= buffer cmd) ! ! Process the line mode =buffer command !- LOCAL buffer_ptr , create_variable_string, term_char, buffer_name ; ! ! This is to move to a new buffer and map it to the main window. If ! the buffer does not exist, create it with the NO_WRITE attribute. ! Get the name from the command line. ! MMC$x_null := ''; buffer_name := 'message'; ! IF it exists just map to it. buffer_ptr := MMC$find_buffer(buffer_name); if buffer_ptr = 0 then MMC$x_make_buf_var := buffer_name; create_variable_string := MMC$x_make_buf_var + "_buffer := create_buffer(MMC$x_make_buf_var)"; execute (create_variable_string); ! Now get the pointer back, we know it is the last buffer in the list buffer_ptr := get_info (buffers,'last'); SET (NO_WRITE, buffer_ptr, ON); set(eob_text, buffer_ptr, '[End of '+buffer_name+']'); endif; map(current_window,buffer_ptr); MMC$update_status_lines; return 1; ENDPROCEDURE !+ PROCEDURE MMC$tmp_buf ! support routine for line mode(= temp cmd) !- ! Process the line mode =temp command !- LOCAL buffer_ptr , create_variable_string, term_char, temp_window, buffer_name ; ! ! This is to move to a new buffer and map it to the main window. If ! the buffer does not exist, create it with the NO_WRITE attribute. ! MMC$x_null := ''; buffer_name := 'temp'; ! IF it exists just map to it. buffer_ptr := MMC$find_buffer(buffer_name); if buffer_ptr = 0 then MMC$x_make_buf_var := buffer_name; create_variable_string := MMC$x_make_buf_var + "_buffer := create_buffer(MMC$x_make_buf_var)"; execute (create_variable_string); ! Now get the pointer back, we know it is the last buffer in the list buffer_ptr := get_info (buffers,'last'); SET (NO_WRITE, buffer_ptr, ON); set(eob_text, buffer_ptr, '[End of '+buffer_name+']'); endif; map(current_window,buffer_ptr); MMC$update_status_lines; return 1; ENDPROCEDURE !+ PROCEDURE MMC$write_buf ! support routine for line mode(write cmd) !- ! Modified from "Edt line mode Write command" !- ! ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED ! LOCAL file_name , buffer_ptr, buffer_name, range_specifier , term_char , text_to_write ; MMC$x_null := ''; file_name := read_line("Enter file to write to: "); if (file_name = MMC$x_null) then message ('***No file specified'); return 0; endif; buffer_name := read_line("Enter buffer to write from: "); if (buffer_name = MMC$x_null) then message ('***No buffer specified'); return 0; endif; buffer_ptr := MMC$find_buffer (buffer_name); if (buffer_ptr = 0) then message ('***Specified buffer does not exist'); return 0; else write_file(buffer_ptr,file_name); return 1; endif; ENDPROCEDURE !+ PROCEDURE MMC$erase_buf !- ! Modified from "Edt line mode Write command" !- ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED LOCAL file_name , buffer_ptr, buffer_name, range_specifier , term_char , text_to_write ; MMC$x_null := ''; buffer_name := read_line("Enter buffer to erase: "); if (buffer_name = MMC$x_null) then message ('***No buffer specified'); return 0; endif; buffer_ptr := MMC$find_buffer (buffer_name); if (buffer_ptr = 0) then message ('***Specified buffer does not exist'); return 0; else erase(buffer_ptr); return 1; endif; ENDPROCEDURE !+ PROCEDURE MMC$tab_jump !- ! one might sensibly choose the command cursor_horizontal ! but that doesn't go from one line to the next and can be hanging ! out in space beyond the end of the line. !- if current_direction = forward then move_horizontal(+8) else move_horizontal(-8) endif; ENDPROCEDURE !+ PROCEDURE MMC$swap_characters !- local first; first := erase_character(-1); move_horizontal(+1); copy_text (first); ENDPROCEDURE !+ PROCEDURE MMC$show_buf !- ! based on "EDT line mode Show command" ! ! ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED !- LOCAL show_type , buf , cur_buf, pos , term_char , save_info_status, show_index ; ! SHOW BUFFER pos := current_window; cur_buf := current_buffer; erase(show_buffer); position(show_buffer); copy_text(' BUFFER NAME LINES FILE'); split_line; copy_text('------------------------------------------------------'); split_line; buf := get_info(buffers,'first'); loop exitif buf = 0; if (buf = cur_buf) then copy_text('='); else copy_text(' '); endif; copy_text(get_info(buf,'name')); copy_text(' '); ! insert a tab copy_Text(str(get_info(buf,'record_count'))); copy_text(' '); ! insert a tab copy_text(get_info(buf,'file_name')); split_line; buf := get_info(buffers,'next'); endloop; set(status_line,info_window,reverse,' '); set(width,info_window,get_info(screen,'width')); map(info_window,show_buffer); update(info_window); buf := read_line('Press RETURN to continue.',1); set(status_line,info_window,none,'Press CTRL-F to remove INFO_WINDOW and resume editing'); unmap(info_window); MMC$update_status_lines; position(pos); ENDPROCEDURE !+ PROCEDURE MMC$page_length !- local found_range; !next line's search string is a form feed character found_range := search(' ',reverse,exact); if found_range=0 then position (beginning_of(current_buffer)); else position (found_range); endif; move_horizontal(+1); move_horizontal(-current_offset); move_vertical(+66); ENDPROCEDURE !+ PROCEDURE MMC$top_parag !- local parag_top_range; move_horizontal(-2); parag_top_RANGE := SEARCH(MMC$parag_delim,reverse,EXACT); if parag_top_range = 0 then position (beginning_of(current_buffer)); else position(parag_top_range); move_vertical(+1); endif; ENDPROCEDURE !+ PROCEDURE MMC$end_parag !- local parag_end_range; move_horizontal(+1); parag_end_RANGE := SEARCH(MMC$parag_delim,forward,EXACT); if parag_end_range = 0 then position (end_of(current_buffer)); else position(parag_end_range); move_vertical(+1); endif; ENDPROCEDURE !+ PROCEDURE MMC$end_sent !- local space, space_range, non_space, non_space_range, sent_end_range; sent_end_RANGE := SEARCH(MMC$sent_delim,forward,EXACT); if sent_end_range = 0 then return; endif; position(sent_end_range); space := ''&(' ' | line_end); space_range := search(space,forward,exact); if space_range = 0 then return; endif; position(space_range); non_space := ''&(line_begin | notany (' ')); non_space_range := search(non_space,forward,exact); if non_space_range = 0 then return; endif; position(non_space_range); ENDPROCEDURE !+ PROCEDURE MMC$top_sent !- !move backward to beginning of sentence !- local non_space_range, non_space, space, space_range, start_mark, next_mark, this_mark, sent_top_range; start_mark := mark(none); move_horizontal(-5); sent_top_RANGE := SEARCH(MMC$sent_delim,reverse); if sent_top_range = 0 then position(start_mark); return; endif; position(beginning_of(sent_top_range)); space := '' & (' ' | line_end); space_range := search(space,forward); if space_range = 0 then return; endif; position(space_range); non_space_range := search(''&(line_begin | notany(' ')),forward); if non_space_range = 0 then return; endif; position(non_space_range); ENDPROCEDURE !+ PROCEDURE MMC$fill_parag !- local begin_mark, top, parag_end_range; begin_mark := mark(none); set(screen_update,off); MMC$top_parag; move_horizontal(+1); top := mark(none); parag_end_RANGE := SEARCH(MMC$parag_delim,forward,EXACT); if parag_end_range = 0 then parag_end_range := create_range(top,end_of(current_buffer),none); else position(end_of(parag_end_range)); move_horizontal(-1); parag_end_range := create_range(top,mark(none),none); endif; fill(parag_end_range,edt$x_word,1,edt$x_wrap_position); position (begin_mark); set(screen_update,on); ENDPROCEDURE !+ PROCEDURE MMC$get_key_help !- set(status_line,info_window,bold,MMC$x_null); set (status_line, info_window, reverse, " Help -- Next Screen or Prev Screen to scroll, RETURN to resume editing "); set(width,info_window,get_info(screen,'width')); map(info_window,help_buffer); erase(help_buffer); read_file('SYS$HELP:MMCSECINI.HLP'); position(beginning_of(help_buffer)); update(info_window); loop MMC$x_key_pressed := read_key; ! check for what key was pressed and execute appropriate action. ! if not a valid key, display message saying so. if (MMC$x_key_pressed = E5) or (MMC$x_key_pressed = E6) then execute (lookup_key (last_key, program)); update (info_window); else if MMC$x_key_pressed = ret_key then unmap(info_window); return; else if (MMC$x_key_pressed = PF2) or (MMC$x_key_pressed = help) then edt$keypad_help; unmap(info_window); return; else message ('***INVALID KEY PRESSED, TRY AGAIN!!!'); endif; endif; endif; endloop; ENDPROCEDURE !+ PROCEDURE MMC$swap_delim !- if (MMC$word_delim = 'text') then !next line is space, tab, ff, lf, cr, vt, and punctuation edt$x_word := " /<>[]{},.:*&!;+-_=^()\|'"; define_key ('MMC$return',ret_key,'return'); define_key ('MMC$return',enter,'return'); MMC$word_delim := 'program'; else !next line is space, tab, ff, lf, cr, vt edt$x_word := " "; define_key ('split_line',ret_key,'return'); define_key ('split_line',enter,'return'); MMC$word_delim := 'text'; endif; ENDPROCEDURE !+ PROCEDURE MMC$swap_word !- if (MMC$word_delim = 'text') then !next line is space, tab, ff, lf, cr, vt, and punctuation edt$x_word := " /<>[]{},.:*&!;+-_=^()\|'"; MMC$word_delim := 'program'; else !next line is space, tab, ff, lf, cr, vt edt$x_word := " "; MMC$word_delim := 'text'; endif; ENDPROCEDURE !+ PROCEDURE MMC$swap_indent !- if (MMC$indent_delim = 'indent') then define_key ('split_line',ret_key,'return'); MMC$indent_delim := 'noindent'; else define_key ('MMC$return',ret_key,'return'); MMC$indent_delim := 'indent'; endif; ENDPROCEDURE !+ PROCEDURE MMC$find_line !- local line_no; position(beginning_of(current_buffer)); line_no := read_line('Enter line number to find: '); move_vertical ( int (line_no) - 1); ENDPROCEDURE !+ PROCEDURE MMC$windows (passed_window) ! !- !Window control: double-window editing for use with !multi-buffer commands. ! ! F18 will return to the main_buffer & main_window ! ! F19 will query the names of buffers, establish and map ! them, and re-define PF1 + B and PF1 + M suitably. !- local window_count, buffer_name_2, window_top, delta_top, window_bottom, make_file_name_2, make_buf_var, delta_bottom, file_name_2; ! !global variables are MMC$window_nam_1 the main window ! MMC$window_nam_2 second ! MMC$buffer_nam_1 the main buffer ! MMC$buffer_nam_2 second ! window_count := passed_window; if window_count = "1" then ! here if normal usage ! ! restore standard key definitions; ! ensure that there is one mapped window, with standard size, to main ! buffer. ! MMC$window_size := 21; define_key ('MMC$buffer',Key_name('b',shift_key), "(PF1 + B) Edit a buffer."); define_key ('MMC$main_buf',key_name('m',shift_key), "(PF1 + M) Return to editing the main buffer."); ! MMC$main_buf; ! MMC$window_nam_1 := current_window; set (scrolling,current_window,on,7,7,0); window_top := get_info(current_window,"visible_top"); if window_top <> 1 then delta_top := 1 - window_top; adjust_window(current_window,delta_top,0); endif; window_bottom := get_info(current_window,"visible_bottom"); if window_bottom <> 20 then delta_bottom := 20 - window_bottom; adjust_window(current_window,0,delta_bottom); endif; refresh; return 1; else ! ! if (window_count = "2") or (window_count = "3") then ! here for dual-window usage ! ensure that there are two mapped windows, with half size, upper to ! main buffer, and lower to second buffer, each w/ status line. ! first, clean up the original file's buffer ! MMC$window_size := 10; MMC$window_nam_1 := current_window; window_top := get_info(current_window,"visible_top"); if window_top <> 1 then delta_top := 1 - window_top; adjust_window(current_window,delta_top,0); endif; window_bottom := get_info(current_window,"visible_bottom"); if window_bottom <> 11 then delta_bottom := 11 - window_bottom; adjust_window(current_window,0,delta_bottom); endif; MMC$set_status_line (current_window); ! ! now establish second window, buffer, and file ! MMC$x_null := ''; buffer_name:= MMC$x_null; if window_count = "2" then buffer_name := read_line("Enter name of second buffer: "); endif; if window_count = "3" then buffer_name := 'TEMP'; endif; if (buffer_name = MMC$x_null) then message('***No buffer specified'); MMC$windows("1"); return; endif; ! IF it exists just map to it. MMC$buffer_nam_2 := buffer_name; buffer_ptr := MMC$find_buffer(buffer_name); if buffer_ptr = 0 then if window_count = "2" then file_name_2 := read_line("Enter file for second buffer: "); else file_name_2 := read_line("Enter file for TEMP buffer: "); endif; MMC$buffer_nam_2 := create_buffer(buffer_name,file_name_2); ! Now get the pointer back, we know it is the last buffer in the list buffer_ptr := get_info (buffers,'last'); file_write := read_line ("Write the contents of this buffer to a file upon exit [Y/N]? "); if (index(file_write,'y') = 0) and (index(file_write,'Y') = 0) then SET (NO_WRITE, buffer_ptr, ON); else SET (NO_WRITE, buffer_ptr, OFF); endif; set(eob_text, buffer_ptr, '[End of '+buffer_name+']'); endif; ! ! now we have the buffer and file set up, it is second window time ! MMC$window_nam_2 := create_window(12,11,ON); map(MMC$window_nam_2,buffer_ptr); define_key ('position(MMC$window_nam_2)',Key_name('b',shift_key), "(PF1 + B) Edit buffer two."); define_key ('position(MMC$window_nam_1)',key_name('m',shift_key), "(PF1 + M) Edit buffer one."); set (scrolling,MMC$window_nam_1,on,3,3,0); set (scrolling,MMC$window_nam_2,on,3,3,0); MMC$update_status_lines; return 1; else ! here for improper response message('***Illegal, improper window specification...call computer svcs.'); return 0; endif; endif; ENDPROCEDURE !+ PROCEDURE MMC$include !- ! include a file in the current buffer !- local filename; MMC$x_null := ''; filename := read_line("Enter name of file to include in current buffer: "); if (filename = MMC$x_null) then message ('***No file specified'); return 0; else read_file(filename); endif; ENDPROCEDURE !+ PROCEDURE MMC$overstrike !- ! swaps between overstrike and insert modes !- if get_info (current_buffer, "mode") = insert then set (overstrike,current_buffer); else set (insert,current_buffer); endif; MMC$update_status_lines; ENDPROCEDURE !+ PROCEDURE MMC$switch_direction !- ! swaps between forward and reverse modes !- if get_info (current_buffer, "direction") = forward then set (reverse,current_buffer); else set (forward,current_buffer); endif; MMC$update_status_lines; ENDPROCEDURE !+ PROCEDURE MMC$forward !- set (forward,current_buffer); MMC$update_status_lines; ENDPROCEDURE !+ PROCEDURE MMC$reverse !- set (reverse,current_buffer); MMC$update_status_lines; ENDPROCEDURE !+ PROCEDURE MMC$find_beg_of_line (b_mark) !- ! to be called by edt$preserve_blanks, thereby preventing ! the dreaded word-split when the select range starts in a ! word that extends beyond the specified margin. !- local temp_pattern, temp_rang; on_error return endon_error; position (b_mark); move_horizontal (-current_offset); b_mark := mark(none); ENDPROCEDURE !+ PROCEDURE edt$preserve_blanks(flag) ! support routine for fill !- ! COPYRIGHT © 1983, 1984, 1985 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED !modified at Kalamazoo College !by including the call to MMC$find_beg_of_line !- LOCAL original_position, b_mark, e_mark, sub_range, temp_range, all_done, temp_pattern; on_error all_done:=1; ! cause exit endon_error; original_position:=mark(none); b_mark:=beginning_of(edt$x_select_range); ! skip leading spaces on first line only MMC$find_beg_of_line (b_mark); edt$skip_leading_spaces(b_mark); position(original_position); loop ! skip leading blank lines of a paragraph edt$skip_lines(b_mark); all_done:=edt$find_whiteline(b_mark,e_mark); ! start looking here exitif all_done; ! now only fill the range created between the blank lines sub_range:=create_range(b_mark,e_mark,none); ! go to line following the range position(e_mark); move_horizontal(1); move_vertical(1); ! pick up search at end of current_range b_mark:=mark(none); ! do the fill operation if flag then fill(sub_range,edt$x_word,1,edt$x_wrap_position); else fill(sub_range,edt$x_word,1,get_info(current_window,'width')); endif; exitif all_done; endloop; position(original_position); ENDPROCEDURE !+ PROCEDURE MMC$return !- ! implements autoindent a'la Apple Pascal, ! actuated when programming delimiters are used. !- local blanktab, orig_pos, first_pos, leading_blanks, dupe; ! search for first non-space or tab character ! if line is empty then search for line_end split_line; ! string next is space, tab blanktab := ''&(notany (" ") | line_end); orig_pos := mark(none); move_vertical (-1); first_pos := mark(none); leading_blanks := search (blanktab,forward,exact); if leading_blanks <> 0 then position (leading_blanks); endif; if current_offset <> 0 then move_horizontal (-1); dupe := create_range(first_pos,mark(none),none); position (orig_pos); copy_text(dupe); else position (orig_pos); endif; ENDPROCEDURE; !+ PROCEDURE MMC$datetime !gold D insert date + time !- local date_time; date_time := FAO ("!%D",0); copy_text(date_time) ; !move_horizontal( - length (date_time)); ENDPROCEDURE !+ ! EDT line mode SUBSTITUTE command !- PROCEDURE edt$line_mode_substitute ! support routine for line mode(subs cmd) !- local cp, line_length, old_index, temp_mark, remaining_line, term_char, old_string, new_string; ! ! This procedure searches and replaces a given string by a second string ! If found and more than one or global replacement requested, then the search ! and replace will continue until EOB or string-not-found. ! ! The command line reads: SUBSTITUTE /old_string/new_string/ [whole] [select] ! delimiter (edt$x_subs_term) ! string to be replaced ! delimiter (same as above) ! new string ! delimiter (same as above) ! either 'whole' if from beginning to end of buffer ! or 'select' if from beginning to end of paste_buffer ! or first occurrence in the current line ! ! Parse the rest of the line looking for old string and new string ! edit (edt$x_line, TRIM, OFF); ! Remember where we are temp_mark := mark(none); line_length := length (edt$x_line); if (edt$find_sub_delimiter (line_length, cp) = 0) then return 0; endif; old_string := substr (edt$x_line, 1, (cp - 1)); edt$x_line := substr (edt$x_line, (cp + 1), line_length); line_length := length (edt$x_line); if (edt$find_sub_delimiter (line_length, cp) = 0) then return 0; endif; new_string := substr (edt$x_line, 1, (cp - 1)); if (cp = line_length) ! There are no options then ! Just do one substitution in the current line RETURN edt$single_search_replace (old_string, new_string); else edt$x_line := substr (edt$x_line, (cp + 1), line_length); ! ! See if WHOLE or SELECT was typed, if not issue an error message ! edit (edt$x_line, TRIM, UPPER, OFF); ! Search through entire buffer and replace starting at the beginning If (INDEX ('WHOLE', edt$x_line) = 1) then position (beginning_of (current_buffer)); edt$global_search_replace (old_string, new_string); position (temp_mark); return 1; endif; If (INDEX ('SELECT', edt$x_line) = 1) then MMC$select_search_replace (old_string, new_string); position (temp_mark); return 1; endif; message ('***Invalid option for line mode SUBSTITUTE comand'); RETURN 0; ! endif; return 1; ENDPROCEDURE !+ ! Find the next delimiter in the command line !- PROCEDURE edt$find_sub_delimiter (line_length, cp) !support routine for subs cmd !- cp := 1; loop if cp > line_length then message ('***Delimiter for SUBSTITUTE could not be found'); RETURN 0; endif; exitif (substr(edt$x_line, cp, 1) = edt$x_subs_term); cp := cp + 1; endloop; return 1; ENDPROCEDURE !+ PROCEDURE edt$single_search_replace (string1, string2) !support routine for subs cmd !- ! This procedure performs a search through the current ! buffer and replaces one string with another if the ! original string is found on the current line !- LOCAL m1, r1, save_buf, temp_mark, msg_text, original_line, src_range; ! Return to caller if string not found ON_ERROR message ('***No occurrences of ' + string1 + ' found in current line'); position (save_buf); position (temp_mark); RETURN 0; ENDON_ERROR; save_buf := current_buffer; temp_mark := mark(none); ! Copy a range of text which is the current line over to a temp ! buffer if (current_offset <> 0) then move_horizontal(-current_offset) endif; m1:=mark(none); move_horizontal(length(current_line)); r1:=create_range(m1,mark(none),none); position(show_buffer); erase(show_buffer); copy_text (r1); position(beginning_of(show_buffer)); ! Search through the temp buffer src_range := SEARCH (string1, forward); ! Search returns a range if found ! If not found it never gets here, from here go back and find ! the same string in the original buffer position(save_buf); ! We know we found it so go back if (current_offset <> 0) then move_horizontal(-current_offset) endif; src_range := SEARCH (string1, forward); ! Search returns a range if found ERASE (src_range); ! Remove first string POSITION (END_OF (src_range)); ! Move to right place COPY_TEXT (string2); ! Replace with second string message('***First occurrence of ' + string1 + ' replaced with ' + string2 + ' in current line'); RETURN 1; ENDPROCEDURE !+ PROCEDURE edt$global_search_replace (string1, string2) !support routine for subs cmd !- ! This procedure performs a search through the current ! buffer and replaces one string with another !- LOCAL msg_text, src_range, replacement_count; ! Return to caller if string not found ON_ERROR msg_text := FAO ('!UL replacement!%S', replacement_count) + ' of ' + string1 + ' with ' + string2 + ' in current buffer'; MESSAGE (msg_text); RETURN 0; ENDON_ERROR; replacement_count := 0; LOOP src_range := SEARCH (string1, forward); ! Search returns a range if found ERASE (src_range); ! Remove first string POSITION (END_OF (src_range)); ! Move to right place COPY_TEXT (string2); ! Replace with second string replacement_count := replacement_count + 1; ENDLOOP; RETURN 1; ENDPROCEDURE !+ PROCEDURE MMC$select_search_replace (string1, string2) !support routine for subs cmd !- ! This procedure performs a search through the current ! select range and replaces one string with another !- LOCAL msg_text, src_range, replacement_count, start_range, end_range; ! Return to caller if string not found ON_ERROR msg_text := FAO ('!UL replacement!%S', replacement_count) + ' of ' + string1 + ' with ' + string2 + ' in select range'; MESSAGE (msg_text); RETURN 0; ENDON_ERROR; edt$select_range; if (edt$x_select_range = 0) then message('***No select active'); return 0; endif; start_range := beginning_of(edt$x_select_range); end_range := end_of(edt$x_select_Range); edt$x_select_range := 0; position(start_range); replacement_count := 0; LOOP exitif mark(none) >= end_range; ! stop search when at end of select src_range := SEARCH (string1, forward); ! Search returns a range if found exitif beginning_of (src_range) >= end_range; ! stop search when at end of select ERASE (src_range); ! Remove first string POSITION (END_OF (src_range)); ! Move to right place COPY_TEXT (string2); ! Replace with second string replacement_count := replacement_count + 1; ENDLOOP; RETURN 1; ENDPROCEDURE !+ PROCEDURE MMC$ruler !- ! swaps between RULER and NO RULER modes !- if (MMC$ruler_mode = 'ruler') then MMC$ruler_mode := 'noruler'; set (SCROLLING,current_window,on,7,7,0); MMC$update_status_lines; else MMC$ruler_mode := 'ruler'; set (SCROLLING,current_window,on,0,0,0); set (status_line,current_window,bold,MMC$ruler_string); endif; ENDPROCEDURE !+ PROCEDURE MMC$cur_column !- ! displays in message line the current column !- update (current_window); message ("***Current Column = " + str (current_column)); ENDPROCEDURE !+ ! EDT PASTE !- ! First set current mode to insert to avoid overwriting text. ! After copying the text, append the current line to the last line. ! We put an extra blank line in the paste buffer during the cut. ! This way, we can get a CUT / PASTE of text without a line terminator ! to work properly. Set current mode back to original state. !- PROCEDURE edt$paste !gold kp6 (paste selected text) LOCAL paste_text, this_mode; if (beginning_of(paste_buffer) <> end_of(paste_buffer)) then this_mode := get_info(current_buffer, "mode"); ! save current mode set (insert,current_buffer); ! set mode to insert copy_text(paste_buffer); append_line; set (this_mode,current_buffer); ! reset original mode endif; ENDPROCEDURE !+ PROCEDURE MMC$start_learn !- message ('***Hit key to learn'); MMC$x_learn_key := read_key; message ('***Enter the learn sequence (CTRL/E to end)'); learn_begin(exact); ENDPROCEDURE !+ PROCEDURE MMC$end_learn !- on_error if error = TPU$_notlearning then message ("***Nothing to remember"); return; else if error = TPU$_recurlearn then message("***Recursive learn procedure"); return; endif; endif; endon_error; MMC$x_learn_sequence := learn_end; message ('***End learn sequence! Press KEY again to repeat the sequence.'); define_key(MMC$x_learn_sequence,MMC$x_learn_key); ENDPROCEDURE !+ PROCEDURE MMC$grow_window !- LOCAL vtop,vbot,n_lines; vtop:=get_info(current_window,'visible_top'); vbot:=get_info(current_window,'visible_bottom'); n_lines:=get_info(current_window,'visible_length')-1; if n_lines=18 then message('***Can not enlarge window anymore'); return; endif; if vtop>1 then adjust_window(current_window,-1,0); else adjust_window(current_window,0,1); endif; MMC$update_status_lines; ENDPROCEDURE; !MMC$grow_window !+ PROCEDURE MMC$center_line !- local this_position, count, left_margin, right_margin, width_of_screen, this_column; this_position := mark (none); if this_position = end_of (current_buffer) then message ('***Can not center end of file'); return; endif; move_horizontal (- current_offset); loop exitif current_character = MMC$x_null; exitif index (MMC$x_whitespace, current_character) = 0; count := count + 1; move_horizontal (1); endloop; erase_character (- count); position (search (line_end, forward)); loop exitif current_offset = 0; move_horizontal (-1); exitif index (MMC$x_whitespace, current_character) = 0; erase_character (1); endloop; left_margin := get_info (current_buffer, "left_margin"); right_margin := get_info (current_buffer, "right_margin"); width_of_screen := get_info (screen, "width"); if width_of_screen = 132 then right_margin := width_of_screen; endif; if right_margin > width_of_screen then right_margin := width_of_screen; endif; this_column := get_info (current_buffer, "offset_column"); count := (((right_margin-left_margin)-this_column)/2)+left_margin; MMC$indent_line_to (count); position (this_position); ENDPROCEDURE; !+ PROCEDURE MMC$indent_line_to (which_column) !- local this_position, this_buffer; this_buffer := current_buffer; move_horizontal (- current_offset); loop exitif get_info (this_buffer, "offset_column") >= which_column; if (current_character = " ") or (current_character = ascii (9)) then move_horizontal (1); else exitif 1; endif; endloop; MMC$to_column (which_column); ENDPROCEDURE; !+ PROCEDURE MMC$to_column (which_column) !- local this_buffer, this_mode, distance; this_buffer := current_buffer; this_mode := get_info (this_buffer, "mode"); set (insert, this_buffer); loop distance := which_column - get_info (this_buffer, "offset_column"); exitif distance <= 0; if distance > length (MMC$x_center_spaces) then copy_text (MMC$x_center_spaces); else copy_text (substr (MMC$x_center_spaces, 1, distance)); endif; endloop; set (this_mode, this_buffer); ENDPROCEDURE; !+ PROCEDURE MMC$define_keys !- define_key ('edt$Line_mode',F10, "(F10) Enter EDT line mode commands."); define_key ('MMC$switch_direction',F11, "(F11) Swap between FORWARD and REVERSE modes."); define_key ('MMC$ruler',F13, "(F13) Swap between RULER and NO RULER modes."); define_key ('MMC$overstrike',F14, "(F14) Swap between INSERT and OVERSTRIKE modes."); define_key ('edt$Command',DO, "(DO) Enter TPU_Command_Line_Mode."); define_key ('spawn ("@sys$com:TPUspawn")',F17, "(F17) Spawn DCL subprocess"); define_key ('MMC$windows("1")',F18, "(F18) Set up single-window."); define_key ('MMC$windows("2")',F19, "(F19) Set up dual-window."); define_key ('spawn ("$ MAIL")',F20, "(F20) Spawn MAIL subprocess"); define_key ('MMC$forward',Kp4, "(KP4) Forward Mode"); define_key ('MMC$reverse',Kp5, "(KP5) Reverse Mode"); define_key ('MMC$overstrike',ctrl_a_key, "(CTRL/A) Swap between INSERT and OVERSTRIKE modes."); define_key ('MMC$msg_buf',ctrl_b_key, "(CTRL/B) Edit the MESSAGE buffer."); define_key ('MMC$swap_word',ctrl_d_key, "(CTRL/D) Swap definition of word for programming or text."); define_key ('MMC$end_learn',ctrl_e_key, "(CTRL/E) End the LEARN_BEGIN sequence previously initiated."); define_key ('MMC$user_tab',ctrl_i_key, "(CTRL/I) TAB key w/spaces."); define_key ('MMC$start_learn',ctrl_k_key, "(CTRL/K) Start the LEARN_BEGIN Key-Stroke sequence."); define_key ('MMC$top_parag',ctrl_n_key, "(CTRL/N) Move back one paragraph."); define_key ('MMC$end_parag',ctrl_p_key, "(CTRL/P) Move forward one paragraph."); define_key ('MMC$restore' , ctrl_r_key, "(CTRL/R) Find the marker left by CTRL/V."); define_key ('edt$delete_beg_line',ctrl_u_key, "(CTRL/U) Delete to beginning of line."); define_key ('copy_text ("^^&&^^")',ctrl_v_key, "(CTRL/V) Insert a marker to be found by CTRL/R."); define_key ('edt$line_mode',ctrl_z_key, "(CTRL/Z) Enter EDT_Command_Line_Mode."); define_key ('MMC$swap_indent',Key_name('a',shift_key), "(PF1 + A) Swap between AUTOINDENT and NOAUTOINDENT modes."); define_key ('MMC$buffer',Key_name('b',shift_key), "(PF1 + B) Edit a buffer."); define_key ('MMC$cur_column',key_name('c',shift_key), "(PF1 + C) Display Current Cursor Column"); define_key ('MMC$datetime',key_name('d',shift_key), "(PF1 + D) Insert Current Date and Time"); define_key ('MMC$get_out',key_name('E',shift_key), "(PF1 + E) Quick normal EXIT."); define_key ('MMC$write_buf',key_name('f',shift_key), "(PF1 + F) Write a buffer to a file."); define_key ('MMC$grow_window',key_name('g',shift_key), "(PF1 + G) Enlarge current window by one line."); define_key ('MMC$get_key_help',key_name('h',shift_key), "(PF1 + H) Get help on a key."); ! define_key ('MMC$windows("3")',key_name('i',shift_key), "(PF1 + I) Set up dual-window * temp_buffer."); define_key ('MMC$center_line',key_name('s',shift_key), "(PF1 + S) Center line of text."); define_key ('spawn ("@sys$com:TPUspawn")',key_name('k',shift_key), "(PF1 + K) Spawn DCL subprocess"); define_key ('MMC$find_line',key_name('l',shift_key), "(PF1 + L) Find a line by number."); define_key ('MMC$main_buf',key_name('m',shift_key), "(PF1 + M) Return to editing the main buffer."); define_key ('set (width,current_window,80)' ,key_name('n',shift_key), "(PF1 + N) Set Screen to Narrow (80)"); define_key ('MMC$write_buf',key_name('o',shift_key), "(PF1 + O) Write a buffer to a file."); define_key ('MMC$page_length',key_name('p',shift_key), "(PF1 + P) Go to bottom of current page."); define_key ('quit',key_name('Q',shift_key), "(PF1 + Q) Quit without writing file."); define_key ('MMC$swap_characters',key_name('r',shift_key), "(PF1 + R) Swap adjacent characters."); define_key ('MMC$tmp_buf',key_name('t',shift_key), "(PF1 + T) Edit the TEMP buffer."); define_key ('set (width,current_window,132)',key_name('w',shift_key), "(PF1 + W) Set Screen to Wide (132)"); ! the string is underscore, escape, semicolon define_key ('copy_text ("_;")',key_name('x',shift_key), "(PF1 + X) Insert NEC escape sequence for superscripts."); ! the string is underscore, escape, colon define_key ('copy_text ("_:")',key_name('y',shift_key), "(PF1 + Y) Insert NEC escape sequence for subscripts."); define_key ('move_vertical(-(MMC$window_size))',key_name(up,shift_key), "(PF1 + UP) Jump up one screen."); define_key ('move_vertical(+(MMC$window_size))',key_name(down,shift_key), "(PF1 + DOWN) Jump down one screen."); ! in the below command, the key in apostrophes is the DELETE character define_key ('MMC$erase_buf',key_name('',shift_key), "(PF1 + DEL) Erase a buffer."); define_key ('copy_text ("")' , key_name(ctrl_h_key,shift_key), "(PF1 + CTRL/H) Insert character, for overstrikes."); define_key ('MMC$include',key_name(ctrl_i_key,shift_key), "(PF1 + CTRL/I) Include file in current buffer."); define_key ('spawn ("$ MAIL")',key_name(ctrl_k_key,shift_key), "(PF1 + CTRL/K) Spawn MAIL subprocess"); define_key ('MMC$windows("1")',key_name(ctrl_m_key,shift_key), "(PF1 + CTRL/M) Set up single-window."); define_key ('MMC$windows("2")',key_name(ctrl_n_key,shift_key), "(PF1 + CTRL/N) Set up dual-window."); define_key ('MMC$ruler',key_name(ctrl_r_key,shift_key), "(PF1 + CTRL/R) Swap between RULER and NO RULER modes."); define_key ('MMC$write_buf',key_name(ctrl_w_key,shift_key), "(PF1 + CTRL/W) Write a buffer to a file."); ENDPROCEDURE ! !+ ! This is the code to be executed when the section is being built !- MMC$define_keys; ! bind keys !+ ! Relinguish memory taken up (unnecessarily) by the MMC$define_keys procedure. !- compile ('procedure MMC$define_keys endprocedure'); save('sys$login:MMCsecini.gbl'); quit;