home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume4 / vms-vi-2 / part15 < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  39.6 KB

  1. Path: xanth!mcnc!gatech!cwjcc!hal!ncoast!allbery
  2. From: gregg@a.cs.okstate.edu (Gregg Wonderly)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i106: TPUVI for VMS part 15 of 17
  5. Message-ID: <8809212117.AA12240@uunet.UU.NET>
  6. Date: 27 Sep 88 22:19:22 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: gregg@a.cs.okstate.edu (Gregg Wonderly)
  9. Lines: 1504
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 4, Issue 106
  13. Submitted-by: "Gregg Wonderly" <gregg@a.cs.okstate.edu>
  14. Archive-name: vms-vi-2/Part15
  15.  
  16. $ WRITE SYS$OUTPUT "Creating ""VI.11"""
  17. $ CREATE VI.11
  18. $ DECK/DOLLARS=$$EOD$$
  19.         copy_line,
  20.         orig_pos,
  21.         last_pos,
  22.         pos,
  23.         exitnow,
  24.         olen,
  25.         this_pos,
  26.         cur_tabs;
  27.  
  28.     vi$start_pos := MARK (NONE);
  29.     pos := MARK (NONE);
  30.     nchar := vi$init_action (olen);
  31.     prog := vi$get_prog (nchar);
  32.  
  33.     IF prog <> "" THEN
  34.         vi$do_movement (prog, VI$FILTER_TYPE);
  35.  
  36.         IF (vi$endpos <> 0) THEN
  37.             POSITION (vi$endpos);
  38.             POSITION (LINE_BEGIN);
  39.             vi$endpos := MARK (NONE);
  40.             POSITION (vi$start_pos);
  41.             POSITION (LINE_BEGIN);
  42.  
  43.             IF (MARK (NONE) = vi$endpos) THEN
  44.                 MOVE_VERTICAL (1);
  45.                 vi$endpos := MARK (NONE);
  46.             ENDIF;
  47.  
  48.             POSITION (vi$endpos);
  49.  
  50.             vi$move_horizontal (-1);
  51.             era_range := CREATE_RANGE (vi$start_pos, MARK (NONE), NONE);
  52.             MOVE_HORIZONTAL (1);
  53.  
  54.             IF (era_range <> 0) THEN
  55.                 vi$undo_end := 0;
  56.                 POSITION (vi$start_pos);
  57.                 vi$save_for_undo (era_range, VI$LINE_MODE, 1);
  58.  
  59.                 POSITION (vi$start_pos);
  60.                 POSITION (LINE_BEGIN);
  61.  
  62.                 orig_pos := vi$get_undo_start;
  63.  
  64.                 IF (vi$filter_region (era_range, 0) = 0) THEN
  65.                     vi$kill_undo;
  66.                     vi$undo_end := 0;
  67.                     POSITION (pos);
  68.                     RETURN (vi$abort (0));
  69.                 ENDIF;
  70.  
  71.                 IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
  72.                     MOVE_HORIZONTAL (-1);
  73.                 ENDIF;
  74.  
  75.                 vi$undo_end := MARK (NONE);
  76.  
  77.                 vi$undo_start := vi$set_undo_start (orig_pos);
  78.                 vi$check_length (olen);
  79.             ELSE
  80.                 vi$info ("Internal error while filtering!");
  81.             ENDIF;
  82.         ELSE
  83.             vi$abort (0);
  84.         ENDIF;
  85.     ELSE
  86.         vi$abort (0);
  87.     ENDIF;
  88.  
  89. ENDPROCEDURE;
  90.  
  91. !
  92. !   Filter the region of text indicated by "region", using the command
  93. !   given in cmd_parm.
  94. !
  95. PROCEDURE vi$filter_region (region, cmd_parm)
  96.     LOCAL
  97.         cmd;
  98.  
  99.     ON_ERROR
  100.         vi$info ("ERROR filtering text!");
  101.         RETURN (0);
  102.     ENDON_ERROR;
  103.  
  104.     cmd := cmd_parm;
  105.  
  106.     IF (vi$filter_buf = 0) THEN
  107.         vi$filter_buf := vi$init_buffer ("$$filter_buffer$$", "");
  108.         IF (vi$filter_buf = 0) THEN
  109.             vi$info ("Can't create buffer, filter aborted!");
  110.             RETURN (0);
  111.         ENDIF;
  112.     ELSE
  113.         ERASE (vi$filter_buf);
  114.     ENDIF;
  115.  
  116.     IF (cmd = 0) THEN
  117.         IF (vi$read_a_line ("!", cmd) = 0) THEN
  118.             RETURN (0);
  119.         ENDIF;
  120.     ENDIF;
  121.  
  122.     vi$info_success_off;
  123.     IF (vi$filter_proc = 0) THEN
  124.         IF cmd = "!" THEN
  125.             cmd := vi$last_filter;
  126.             IF (cmd = 0) THEN
  127.                 vi$info ("No previous command to use!");
  128.                 RETURN (0);
  129.             ENDIF;
  130.         ELSE
  131.             vi$last_filter := cmd;
  132.         ENDIF;
  133.  
  134.         vi$filter_proc := CREATE_PROCESS (vi$filter_buf, cmd);
  135.  
  136.         IF (vi$filter_proc = 0) THEN
  137.             vi$info ("Can't create process, filter aborted!");
  138.             RETURN (0);
  139.         ENDIF;
  140.     ENDIF;
  141.  
  142.     SEND (region, vi$filter_proc);
  143.     IF vi$filter_proc <> 0 THEN
  144.         DELETE (vi$filter_proc);
  145.         vi$filter_proc := 0;
  146.     ENDIF;
  147.  
  148.     vi$info_success_on;
  149.  
  150.     ERASE (region);
  151.     COPY_TEXT (vi$filter_buf);
  152.     RETURN (1);
  153. ENDPROCEDURE;
  154.  
  155. !
  156. !   Shift the selected text region one SHIFT_WIDTH to the right.
  157. !
  158. PROCEDURE vi$region_right
  159.     vi$region_shift(1);
  160. ENDPROCEDURE
  161.  
  162. !
  163. !   Shift the selected text region one SHIFT_WIDTH to the left.
  164. !
  165. PROCEDURE vi$region_left
  166.     vi$region_shift (0);
  167. ENDPROCEDURE
  168.  
  169. !
  170. !   This function shifts the selected region right or left based on
  171. !   the mode passed.
  172. !
  173. !   Parameters:
  174. !       mode            0 indicates a left shift, 1 indicates right.
  175. !
  176. PROCEDURE vi$region_shift (mode)
  177.  
  178.     LOCAL
  179.         act_char,
  180.         needed,
  181.         era_range,
  182.         prog,
  183.         nchar,
  184.         copy_line,
  185.         tab_len,
  186.         oline,
  187.         nline,
  188.         state,
  189.         orig_pos,
  190.         last_pos,
  191.         exitnow,
  192.         this_pos,
  193.         cur_tabs;
  194.  
  195.     ON_ERROR;
  196.         IF state <> 0 THEN
  197.             IF (ERROR = TPU$_ENDOFBUF) AND (state = 2) THEN
  198.                 exitnow := 1;
  199.             ELSE
  200.                 orig_pos := 0;
  201.             ENDIF;
  202.         ELSE
  203.             vi$info ("Error occured during shift, at line: "+
  204.                                                         STR(ERROR_LINE));
  205.             POSITION (vi$start_pos);
  206.             RETURN;
  207.         ENDIF;
  208.     ENDON_ERROR;
  209.  
  210.     vi$start_pos := MARK (NONE);
  211.     nchar := vi$init_action (state);
  212.     state := 0;
  213.  
  214.     IF ((mode = 1) AND (ASCII (nchar) = '<')) OR
  215.                                     ((mode = 0) AND (ASCII (nchar) = '>')) THEN
  216.         RETURN;
  217.     ENDIF;
  218.  
  219.     prog := vi$get_prog (nchar);
  220.  
  221.     IF prog <> "" THEN
  222.         vi$do_movement (prog, VI$SHIFT_TYPE);
  223.  
  224.         oline := vi$cur_line_no;
  225.         IF (vi$endpos <> 0) THEN
  226.             POSITION (vi$endpos);
  227.             POSITION (LINE_BEGIN);
  228.             nline := vi$abs (vi$cur_line_no - oline);
  229.             vi$endpos := MARK (NONE);
  230.             POSITION (vi$start_pos);
  231.             POSITION (LINE_BEGIN);
  232.  
  233.             IF (MARK (NONE) = vi$endpos) THEN
  234.                 MOVE_VERTICAL (1);
  235.                 vi$endpos := MARK (NONE);
  236.             ENDIF;
  237.  
  238.             POSITION (vi$endpos);
  239.  
  240.             vi$move_horizontal (-1);
  241.             era_range := CREATE_RANGE (vi$start_pos, MARK (NONE), NONE);
  242.             MOVE_HORIZONTAL (1);
  243.  
  244.             IF (era_range <> 0) THEN
  245.                 vi$undo_end := 0;
  246.                 POSITION (vi$start_pos);
  247.                 vi$save_for_undo (era_range, vi$yank_mode, 1);
  248.  
  249.                 POSITION (vi$start_pos);
  250.                 POSITION (LINE_BEGIN);
  251.  
  252.                 orig_pos := vi$get_undo_start;
  253.  
  254.                 cur_tabs := GET_INFO (CURRENT_BUFFER, "TAB_STOPS");
  255.  
  256.                 IF (GET_INFO (cur_tabs, "TYPE") = STRING) THEN
  257.                     vi$info ("Can't shift region with uneven tabstops.");
  258.                     RETURN;
  259.                 ELSE
  260.                     tab_len := cur_tabs;
  261.                 ENDIF;
  262.  
  263.                 state := 2;
  264.                 exitnow := 0;
  265.  
  266.                 LOOP
  267.                     EXITIF MARK (NONE) = vi$endpos;
  268.                     EXITIF MARK (NONE) = END_OF (CURRENT_BUFFER);
  269.                     EXITIF (exitnow = 1);
  270.  
  271.                     copy_line := vi$current_line;
  272.  
  273.                     IF (copy_line <> "") THEN
  274.  
  275.                         ! Copy line is truncated to have no leading spaces.
  276.  
  277.                         needed := vi$vis_indent (copy_line, tab_len);
  278.  
  279.                         IF mode = 1 THEN
  280.                             needed := needed + vi$shift_width;
  281.                         ELSE
  282.                             needed := needed - vi$shift_width;
  283.                         ENDIF;
  284.  
  285.                         IF (needed < 0) THEN
  286.                             needed := 0;
  287.                         ENDIF;
  288.  
  289.                         ERASE_LINE;
  290.                         COPY_TEXT (vi$get_tabs (needed, tab_len)+copy_line);
  291.  
  292.                         MOVE_HORIZONTAL (1);
  293.                         IF (MARK (NONE) <> END_OF(CURRENT_BUFFER)) THEN
  294.                             MOVE_HORIZONTAL (-1);
  295.                             SPLIT_LINE;
  296.                         ENDIF;
  297.                     ELSE
  298.                         MOVE_VERTICAL (1);
  299.                     ENDIF;
  300.                     POSITION (LINE_BEGIN);
  301.                 ENDLOOP;
  302.  
  303.                 MOVE_HORIZONTAL (-1);
  304.                 vi$undo_end := MARK (NONE);
  305.  
  306.                 vi$undo_start := vi$set_undo_start (orig_pos);
  307.                 POSITION (vi$undo_start);
  308.                 IF (nline >= vi$report) THEN
  309.                     act_char := ">";
  310.                     IF mode = 0 THEN
  311.                         act_char := "<";
  312.                     ENDIF;
  313.                     vi$info (STR (nline) + " lines " + act_char + "'d");
  314.                 ENDIF;
  315.             ELSE
  316.                 vi$info ("Internal error while shifting!");
  317.             ENDIF;
  318.         ELSE
  319.             vi$abort (0);
  320.         ENDIF;
  321.     ELSE
  322.         vi$abort (0);
  323.     ENDIF;
  324.  
  325. ENDPROCEDURE;
  326.  
  327. !
  328. !  This procedure is called to calculate the number of spaces
  329. !  occupied on the screen by the leading white space of "line".  "tabstops"
  330. !  holds the number of spaces a tab displays as obtained with a call to
  331. !  GET_INFO (CURRENT_BUFFER, "TAB_STOPS").  Line is stripped of the leading
  332. !  space on return, and the function returns the number of spaces occupied
  333. !  on the screen.
  334. !
  335. PROCEDURE vi$vis_indent (line, tabstops)
  336.     LOCAL
  337.         idx,
  338.         cur_ch,
  339.         cnt;
  340.  
  341.     idx := 1;
  342.     cnt := 0;
  343.  
  344.     LOOP
  345.         cur_ch := SUBSTR (line, idx, 1);
  346.         EXITIF (cur_ch = "");
  347.         EXITIF (INDEX (vi$_space_tab, cur_ch) = 0);
  348.  
  349.         IF (cur_ch = " ") THEN
  350.             cnt := cnt + 1;
  351.         ELSE
  352.             cnt := cnt + (tabstops - (cnt - ((cnt / tabstops) * tabstops)));
  353.         ENDIF;
  354.  
  355.         idx := idx + 1;
  356.     ENDLOOP;
  357.  
  358.     ! Truncate the line removing the leading whitespace.
  359.  
  360.     line := SUBSTR (line, idx, LENGTH (line) - idx + 1);
  361.     RETURN (cnt);
  362. ENDPROCEDURE;
  363.  
  364. !
  365. !  This procedure builds a string with as many tabs as possible to create
  366. !  the indentation level given by "len".  "tabstops" is the number of spaces
  367. !  a tab produces on the screen.
  368. !
  369. PROCEDURE vi$get_tabs (len, tabstops)
  370.     LOCAL
  371.         tab_text,
  372.         rstr;
  373.  
  374.     rstr := "";
  375.  
  376.     ! Select the proper tabbing text based on the setting of vi$use_tabs
  377.  
  378.     tab_text := ASCII (9);
  379.     IF (vi$use_tabs = 0) THEN
  380.         tab_text := SUBSTR (vi$spaces, 1, tabstops);
  381.     ENDIF;
  382.  
  383.     LOOP
  384.         EXITIF (len = 0);
  385.         IF (len >= tabstops) THEN
  386.             len := len - tabstops;
  387.             rstr := rstr + tab_text;
  388.         ELSE
  389.             rstr := rstr + SUBSTR (vi$spaces, 1, len);
  390.             len := 0;
  391.         ENDIF;
  392.     ENDLOOP;
  393.  
  394.     RETURN (rstr);
  395. ENDPROCEDURE;
  396.  
  397. !
  398. !   This function should be used to abort the current keyboard stream.
  399. !   It will assure that a macro does not continue to operate after a
  400. !   failure.
  401. !
  402. PROCEDURE vi$abort (n)
  403.     vi$key_buf := 0;
  404.     RETURN (n);
  405. ENDPROCEDURE;
  406.  
  407. !
  408. !   Decide what the current line number is.
  409. !
  410. PROCEDURE vi$cur_line_no
  411.     LOCAL
  412.         pos,
  413.         cnt,
  414.         val,
  415.         opos;
  416.  
  417.     ON_ERROR
  418.         POSITION (pos);
  419.         IF (val > 1) THEN
  420.             val := val / 2;
  421.             cnt := cnt - val;
  422.         ELSE
  423.             POSITION (opos);
  424.             RETURN (cnt);
  425.         ENDIF;
  426.     ENDON_ERROR;
  427.  
  428.     opos := MARK (NONE);
  429.     val := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT") * 2 / 3;
  430.     IF (val = 0) THEN
  431.         val := 1;
  432.     ENDIF;
  433.     cnt := 1;
  434.     LOOP
  435.         pos := MARK (NONE);
  436.         MOVE_VERTICAL (-val);
  437.         cnt := cnt + val;
  438.     ENDLOOP;
  439. ENDPROCEDURE;
  440.  
  441. !
  442. !   Copy a buffer of keys for use later.  This routine is used mostly to
  443. !   make a copy of the last series of keystrokes from repeating when '.'
  444. !   is typed.
  445. !
  446. PROCEDURE vi$copy_keys (to_keys, from_keys)
  447.     LOCAL
  448.         pos;
  449.  
  450.     pos := MARK (NONE);
  451.     ERASE (to_keys);
  452.     POSITION (to_keys);
  453.     COPY_TEXT (from_keys);
  454.     POSITION (BEGINNING_OF (to_keys));
  455.     POSITION (pos);
  456. ENDPROCEDURE;
  457.  
  458. !
  459. !   Convert a string of characters into a buffer of key strokes.
  460. !
  461. PROCEDURE vi$str_to_keybuf (tstring, tbuf)
  462.     LOCAL
  463.         pos,
  464.         idx;
  465.  
  466.     idx := 1;
  467.     pos := MARK (NONE);
  468.     POSITION (BEGINNING_OF (tbuf));
  469.  
  470.     ! Note that a bug in TPU causes ill behavior if you try to ERASE
  471.     ! a buffer that TPU has never written anything into.
  472.  
  473.     SPLIT_LINE;
  474.     APPEND_LINE;
  475.     ERASE (tbuf);
  476.  
  477.     LOOP
  478.         EXITIF idx > LENGTH (tstring);
  479.         COPY_TEXT (STR (INT (KEY_NAME (SUBSTR (tstring, idx, 1)))));
  480.  
  481.         ! Move to EOB so next COPY_TEXT will insert a new line.
  482.  
  483.         MOVE_HORIZONTAL (1);
  484.         idx := idx + 1;
  485.     ENDLOOP;
  486.  
  487.     !  There must be 2 lines (the first should be blank) at the end of the
  488.     !  buffer to make it appear exactly as a key mapping.
  489.  
  490.     SPLIT_LINE;
  491.     SPLIT_LINE;
  492.  
  493.     POSITION (pos);
  494. ENDPROCEDURE;
  495.  
  496. !
  497. !   Save the key passed into the push back buffer.
  498. !
  499. PROCEDURE vi$push_a_key (ch)
  500.     LOCAL
  501.         pos;
  502.  
  503.     pos := MARK (NONE);
  504.     POSITION (vi$cur_keys);
  505.     COPY_TEXT (STR (INT (ch)));
  506.     MOVE_HORIZONTAL (1);
  507.     POSITION (pos);
  508. ENDPROCEDURE;
  509.  
  510. !
  511. !   Insert the buffer passed into the stream of key_board characters so
  512. !   that they act as a macro.
  513. !
  514. PROCEDURE vi$insert_macro_keys (key_buf)
  515.     LOCAL
  516.         spos,
  517.         pos;
  518.  
  519.     IF vi$push_key_buf = 0 THEN
  520.         vi$push_key_buf := vi$init_buffer ("$$push_key_buf$$", "");
  521.     ENDIF;
  522.  
  523.     pos := MARK (NONE);
  524.  
  525.     IF (vi$key_buf <> 0) THEN
  526.         IF (vi$key_buf = vi$push_key_buf) THEN
  527.             POSITION (vi$push_key_buf);
  528.             MOVE_HORIZONTAL (-1);
  529.             spos := MARK (NONE);
  530.             MOVE_HORIZONTAL (1);
  531.             SET (INSERT, CURRENT_BUFFER);
  532.             COPY_TEXT (key_buf);
  533.  
  534.             !  Remove blank line at end, and possible DEFINE_KEY mapping.
  535.  
  536.             MOVE_VERTICAL (-1);
  537.             ERASE_LINE;
  538.             MOVE_VERTICAL (-1);
  539.             ERASE_LINE;
  540.  
  541.             POSITION (spos);
  542.             MOVE_HORIZONTAL (1);
  543.         ELSE
  544.             POSITION (vi$key_buf);
  545.             spos := MARK (NONE);
  546.             ERASE (vi$push_key_buf);
  547.             POSITION (vi$push_key_buf);
  548.             SET (INSERT, CURRENT_BUFFER);
  549.             COPY_TEXT (CREATE_RANGE (spos, END_OF (vi$key_buf), NONE));
  550.  
  551.             !  Remove blank line at end, and possible DEFINE_KEY mapping.
  552.  
  553.             MOVE_VERTICAL (-1);
  554.             ERASE_LINE;
  555.             MOVE_VERTICAL (-1);
  556.             ERASE_LINE;
  557.  
  558.             COPY_TEXT (key_buf);
  559.             POSITION (BEGINNING_OF (vi$push_key_buf));
  560.             vi$key_buf := vi$push_key_buf;
  561.         ENDIF;
  562.     ELSE
  563.         ERASE (vi$push_key_buf);
  564.         POSITION (vi$push_key_buf);
  565.         SET (INSERT, CURRENT_BUFFER);
  566.         COPY_TEXT (key_buf);
  567.         vi$key_buf := vi$push_key_buf;
  568.         POSITION (BEGINNING_OF (vi$push_key_buf));
  569.     ENDIF;
  570.  
  571.     POSITION (pos);
  572. ENDPROCEDURE;
  573.  
  574. !
  575. !   Erase a the last key pushed back.
  576. !
  577. PROCEDURE vi$del_a_key
  578.     LOCAL
  579.         pos;
  580.  
  581.     pos := MARK (NONE);
  582.     POSITION (vi$cur_keys);
  583.     IF MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER) THEN
  584.         MOVE_VERTICAL (-1);
  585.         ERASE_LINE;
  586.     ENDIF;
  587.     POSITION (pos);
  588.  
  589. ENDPROCEDURE;
  590.  
  591. !
  592. !   Read a single keystroke from either the keyboard, or from the push
  593. !   back buffer if it is non-zero.
  594. !
  595. PROCEDURE vi$read_a_key
  596.  
  597.     LOCAL
  598.         read_a_key,
  599.         pos,
  600.         ch;
  601.  
  602.     read_a_key := 0;
  603.  
  604.     ! If there are no keys pushed, then read the keyboard.
  605.  
  606.     IF (vi$key_buf = 0) OR (GET_INFO (vi$key_buf, "TYPE") <> BUFFER) THEN
  607.         read_a_key := 1;
  608.         vi$m_level := 0;
  609.         IF vi$term_vt200 THEN
  610.             ch := READ_KEY;
  611.         ELSE
  612.             ch := READ_CHAR;
  613.         ENDIF;
  614.     ELSE
  615.  
  616.         ! Otherwise extract the next key from the buffer.
  617.  
  618.         pos := MARK (NONE);
  619.         POSITION (vi$key_buf);
  620.  
  621.         ! Get the key code.
  622.  
  623.         ch := INT (vi$current_line);
  624.         MOVE_VERTICAL (1);
  625.  
  626.         ! Check for the end of the buffer.
  627.  
  628.         IF (LENGTH (vi$current_line) = 0) THEN
  629.             vi$key_buf := 0;
  630.         ENDIF;
  631.  
  632.         POSITION (pos);
  633.     ENDIF;
  634.  
  635.     ! If we are not running on a VT200, then do some key translations
  636.  
  637.     IF NOT vi$term_vt200 THEN
  638.         IF ch = ASCII(27) THEN
  639.             ch := F11;
  640.         ENDIF;
  641.     ENDIF;
  642.  
  643.     ch := KEY_NAME (ch);
  644.  
  645.     ! If a key was read from the keyboard, then push it back.
  646.  
  647.     IF read_a_key THEN
  648.         vi$push_a_key (ch);
  649.     ENDIF;
  650.  
  651.     ! Save the last key read.
  652.  
  653.     vi$last_key := ch;
  654.  
  655.     ! Return the keycode of the character
  656.  
  657.     RETURN (ch);
  658. ENDPROCEDURE;
  659.  
  660. !
  661. !   Turn pasthru on, on the terminal
  662. !
  663. PROCEDURE vi$pasthru_on
  664.     LOCAL
  665.         junk;
  666.     junk := CALL_USER (vi$cu_pasthru_on, "");
  667. ENDPROCEDURE;
  668.  
  669. !
  670. !   Turn pasthru off, on the terminal
  671. !
  672. PROCEDURE vi$pasthru_off
  673.     LOCAL
  674.         junk;
  675.     junk := CALL_USER (vi$cu_pasthru_off, "");
  676. ENDPROCEDURE;
  677.  
  678. !
  679. !   Spawn with pasthru off
  680. !
  681. PROCEDURE vi$spawn (cmd)
  682.     LOCAL
  683.         junk;
  684.  
  685.     vi$pasthru_off;
  686.     IF (cmd = 0) THEN
  687.         SPAWN;
  688.     ELSE
  689.         SPAWN (cmd);
  690.     ENDIF;
  691.     vi$pasthru_on;
  692. ENDPROCEDURE
  693.  
  694. !
  695. !   Quit with pasthru off
  696. !
  697. PROCEDURE vi$quit
  698.     vi$pasthru_off;
  699.     QUIT;
  700.     vi$pasthru_on;
  701. ENDPROCEDURE
  702.  
  703. !
  704. !   Perform read_line with pasthru off
  705. !
  706. PROCEDURE vi$read_line (prompt)
  707.     LOCAL
  708.         junk;
  709.  
  710.     vi$pasthru_off;
  711.     junk := READ_LINE (prompt);
  712.     vi$pasthru_on;
  713.     RETURN (junk);
  714. ENDPROCEDURE;
  715.  
  716. !
  717. !   Initialize things by creating buffers and windows and perform other
  718. !   assorted operations.
  719. !
  720. PROCEDURE tpu$init_procedure
  721.  
  722.     LOCAL
  723.         journal_file,
  724.         default_journal_name,
  725.         aux_journal_name,
  726.         cnt,
  727.         input_file;
  728.  
  729.     !   Flag to indicate status of editor during startup.
  730.  
  731.     vi$starting_up := 1;
  732.  
  733.     vi$readonly := 0;
  734.     IF (GET_INFO (COMMAND_LINE, "READ_ONLY") = 1) THEN
  735.         vi$readonly := 1;
  736.     ENDIF;
  737.     vi$info_success_off;
  738.     SET (MESSAGE_FLAGS, 1);
  739.     SET (BELL, BROADCAST, ON);
  740.  
  741.     !   Set the variables to their initial values.
  742.  
  743.     vi$init_vars;
  744.  
  745.     !   Get some other information.
  746.  
  747.     vi$term_vt200 := GET_INFO (SCREEN, "vt200");
  748.     vi$scr_width := GET_INFO (SCREEN, "WIDTH");
  749.     vi$scr_length := GET_INFO (SCREEN, "VISIBLE_LENGTH");
  750.  
  751.     !   Create the message buffer and window.
  752.  
  753.     message_buffer := vi$init_buffer ("Messages", "");
  754.     message_window := CREATE_WINDOW (vi$scr_length - 1, 2, ON);
  755.     MAP (message_window, message_buffer);
  756.     SET (STATUS_LINE, message_window, NONE, "");
  757.     SET (MAX_LINES, message_buffer, 500);
  758.     ADJUST_WINDOW (message_window, 1, 0);
  759.     vi$mess_select (REVERSE);
  760.  
  761.     !   Command prompt area.
  762.  
  763.     command_buffer := vi$init_buffer ("Commands", "");
  764.     command_window := CREATE_WINDOW (vi$scr_length, 1, OFF);
  765.  
  766.     !   Buffer for SHOW (xxx) stuff.
  767.  
  768.     show_buffer := vi$init_buffer ("Show", "");
  769.     info_window := CREATE_WINDOW (1, vi$scr_length - 1, ON);
  770.     SET (STATUS_LINE, info_window, NONE, "");
  771.  
  772.     !   A buffer for the tags file(s).
  773.  
  774.     vi$tag_buf := vi$init_buffer ("Tags buffer", "");
  775.     vi$load_tags;
  776.     vi$dcl_buf := vi$init_buffer ("DCL buffer", "[End of DCL buffer]");
  777.     vi$info_success_off;
  778.  
  779.     !   A buffer and a window to start editing in.
  780.  
  781.     main_buffer := CREATE_BUFFER ("Main");
  782.     main_window := CREATE_WINDOW (1, vi$scr_length - 1, ON);
  783.     SET (EOB_TEXT, main_buffer, "[EOB]");
  784.     SET (STATUS_LINE, main_window, NONE, "");
  785.  
  786.     !   A buffer for wild carding and such.
  787.  
  788.     choice_buffer := vi$init_buffer ("Choices", "");
  789.  
  790.     !   A buffer for the list of files we are currently editing.
  791.  
  792.     vi$file_names := vi$init_buffer ("file_names", "");
  793.  
  794.     !   Buffer to hold last text inserted into a buffer.
  795.  
  796.     vi$last_insert := vi$init_buffer ("$$last_insert$$", "");
  797.  
  798.     !   Buffer to hold KEY_NAME values of last key sequence.
  799.  
  800.     vi$cur_keys := vi$init_buffer ("$$current_keys$$", "");
  801.  
  802.     !   Buffer to hold keys to be performed when '.' is pressed.
  803.  
  804.     vi$last_keys := vi$init_buffer ("$$last_keys$$", "");
  805.  
  806.     !   Get a buffer to hold yank and deletes that are not aimed at named
  807.     !   buffers.
  808.  
  809.     vi$temp_buf := vi$init_buffer ("$$temp_buffer$$", "");
  810.  
  811.     !   Set up some more stuff.
  812.  
  813.     SET (PROMPT_AREA, vi$scr_length, 1, BOLD);
  814.     SET (JOURNALING, 7);
  815.     SET (FACILITY_NAME, "VI");
  816.  
  817.     !   Move to the initial buffer.
  818.  
  819.     MAP (main_window, main_buffer);
  820.     POSITION (main_buffer);
  821.  
  822.     !   Get the filename to edit.
  823.  
  824.     input_file := GET_INFO (COMMAND_LINE, "FILE_NAME");
  825.     IF input_file = "" THEN
  826.         IF (GET_INFO (COMMAND_LINE, "OUTPUT")) THEN
  827.             input_file := GET_INFO (COMMAND_LINE, "OUTPUT_FILE");
  828.         ENDIF;
  829.     ENDIF;
  830.  
  831.     !   If there is an input file, then get it for editing.
  832.  
  833.     IF input_file <> "" THEN
  834.         cnt := vi$get_file (input_file);
  835.     ELSE
  836.         vi$bmode_main := vi$readonly;
  837.     ENDIF;
  838.  
  839.     ! Delete the unused main buffer if it is not used.
  840.  
  841.     IF (CURRENT_BUFFER <> main_buffer) AND (main_buffer <> 0) THEN
  842.         DELETE (main_buffer);
  843.     ENDIF;
  844.  
  845.     ! Start journaling if requested.
  846.  
  847.     IF (GET_INFO (COMMAND_LINE, "JOURNAL") = 1) THEN
  848.         aux_journal_name := GET_INFO (CURRENT_BUFFER, "FILE_NAME");
  849.  
  850.         IF aux_journal_name = "" THEN
  851.             aux_journal_name := GET_INFO (CURRENT_BUFFER, "OUTPUT_FILE");
  852.         ENDIF;
  853.  
  854.         IF aux_journal_name = 0 THEN
  855.             aux_journal_name := "";
  856.         ENDIF;
  857.  
  858.         IF aux_journal_name = "" THEN
  859.             default_journal_name := "MAIN.TJL";
  860.         ELSE
  861.             default_journal_name := ".TJL";
  862.         ENDIF;
  863.  
  864.         journal_file := GET_INFO (COMMAND_LINE, "JOURNAL_FILE");
  865.         journal_file := FILE_PARSE (journal_file, default_journal_name,
  866.                                                     aux_journal_name);
  867.         JOURNAL_OPEN (journal_file);
  868.     ENDIF;
  869.  
  870.     ! Force undefined keystrokes ("all of them") to call vi$command_mode.
  871.  
  872.     SET (UNDEFINED_KEY, "tpu$key_map_list",
  873.                                     COMPILE ("vi$command_mode (LAST_KEY)"));
  874.     SET (SELF_INSERT, "tpu$key_map_list", OFF);
  875.  
  876.     vi$info_success_on;
  877.  
  878.     ! Change PF1 so that it is NOT a shift key.
  879.  
  880.     SET (SHIFT_KEY, KEY_NAME (PF1, SHIFT_KEY));
  881.  
  882.     ! Do any user added local initialization.
  883.  
  884.     tpu$local_init;
  885.  
  886.     ! Do the INI file.
  887.  
  888.     IF FILE_SEARCH ("EXRC") = "" THEN
  889.         vi$do_file ("SYS$LOGIN:VI.INI", 0);
  890.     ELSE
  891.         vi$do_file ("EXRC", 0);
  892.     ENDIF;
  893.  
  894.     vi$do_exinit;
  895.  
  896.     ! Enable passthru on the terminal so that ^Y does 'Push screen'.
  897.  
  898.     vi$pasthru_on;
  899.  
  900.     ! Say we are no longer starting up.
  901.  
  902.     vi$starting_up := 0;
  903. ENDPROCEDURE;
  904.  
  905. !
  906. !   Process the EXINIT environment variable (Process Logical actually).
  907. !
  908. PROCEDURE vi$do_exinit
  909.     LOCAL
  910.         exinit;
  911.  
  912.     ON_ERROR
  913.         RETURN;
  914.     ENDON_ERROR;
  915.  
  916.     exinit := call_user (vi$cu_trnlnm_job, "EXINIT");
  917.     vi$do_cmd_line (exinit);
  918. ENDPROCEDURE;
  919.  
  920. !
  921. !   Load the file given in fn, into a buffer and execute the contents as
  922. !   a series of EX mode commands.  "complain" is boolean, and determines
  923. !   whether or not we complain about a non existant file.
  924. !
  925. PROCEDURE vi$do_file (rfn, complain)
  926.     LOCAL
  927.         fn,
  928.         ini_buffer,
  929.         ini_file;
  930.  
  931.     fn := rfn;
  932.     ini_file := FILE_SEARCH ("");
  933.     fn := FILE_PARSE (fn);
  934.     ini_file := FILE_SEARCH (fn);
  935.     IF (ini_file = "") THEN
  936.         IF (complain) THEN
  937.             vi$info ("Can't find file """+fn+"""!");
  938.         ENDIF;
  939.         RETURN (1);
  940.     ENDIF;
  941.  
  942.     vi$info_success_off;
  943.  
  944.     ini_buffer := CREATE_BUFFER ("VI$CMD$INI$$", ini_file);
  945.  
  946.     IF ini_buffer = 0 THEN
  947.         IF (complain) THEN
  948.             vi$info ("can't process file """+ini_file+"""!");
  949.         ENDIF;
  950.         vi$info_success_on;
  951.         RETURN(1);
  952.     ENDIF;
  953.  
  954.     vi$process_buffer (ini_buffer);
  955.     DELETE (ini_buffer);
  956.  
  957.     vi$info_success_on;
  958.     RETURN (1);
  959. ENDPROCEDURE;
  960.  
  961. !
  962. !  Execute the contents of the passed buffer as EX mode commands
  963. !
  964. PROCEDURE vi$process_buffer (buffer_parm)
  965.  
  966.     LOCAL
  967.         line,
  968.         old_pos,
  969.         cur_pos;
  970.  
  971.     old_pos := MARK (NONE);
  972.     POSITION (BEGINNING_OF (buffer_parm));
  973.  
  974.     LOOP
  975.         cur_pos := MARK (NONE);
  976.         EXITIF (cur_pos = END_OF (buffer_parm));
  977.         line := CURRENT_LINE;
  978.  
  979.         IF (LENGTH (line) > 0) AND (SUBSTR (line, 1, 1) <> '!') THEN
  980.             POSITION (old_pos);
  981.  
  982.             vi$do_cmd_line (line);
  983.  
  984.             old_pos := MARK (NONE);
  985.             POSITION (cur_pos);
  986.         ENDIF;
  987.  
  988.         MOVE_VERTICAL (1);
  989.     ENDLOOP;
  990.  
  991.     POSITION (old_pos);
  992. ENDPROCEDURE;
  993.  
  994. !
  995. !   Initialize a system/nowrite buffer.
  996. !
  997. PROCEDURE vi$init_buffer (new_buffer_name, new_eob_text)
  998.  
  999.     LOCAL
  1000.         new_buffer;         ! New buffer
  1001.  
  1002.     new_buffer := CREATE_BUFFER (new_buffer_name);
  1003.     SET (EOB_TEXT, new_buffer, new_eob_text);
  1004.     SET (NO_WRITE, new_buffer);
  1005.     SET (SYSTEM, new_buffer);
  1006.     RETURN (new_buffer);
  1007.  
  1008. ENDPROCEDURE;
  1009.  
  1010. !
  1011. !   Expand the list of filenames given in "get_file_list" and return
  1012. !   the count of names found as the function value.  The file names will
  1013. !   be in the vi$file_names buffer, one per line.
  1014. !
  1015. PROCEDURE vi$expand_file_list (get_file_list)
  1016.  
  1017.     LOCAL
  1018.         num_names,
  1019.         fres,
  1020.         fn,
  1021.         fl,
  1022.         comma_pos,
  1023.         pos;
  1024.  
  1025.     fl := get_file_list;
  1026.  
  1027.     ERASE (choice_buffer);
  1028.  
  1029.     IF (vi$file_names = 0) THEN
  1030.         vi$file_names := vi$init_buffer ("file_names", "");
  1031.     ELSE
  1032.         ERASE (vi$file_names);
  1033.     ENDIF;
  1034.  
  1035.     ! Expand the wild cards.  Note that this also eliminates non-existant
  1036.     ! files from the list of files to edit.
  1037.  
  1038.     LOOP
  1039.         ! Protect against earlier file_search.
  1040.  
  1041.         fres := FILE_SEARCH ("");
  1042.  
  1043.         EXITIF fl = "";
  1044.         comma_pos := INDEX (fl, ",");
  1045.  
  1046.         IF (comma_pos > 0) THEN
  1047.             fn := SUBSTR (fl, 1, comma_pos - 1);
  1048.             fl := SUBSTR (fl, comma_pos + 1, LENGTH (fl) - comma_pos);
  1049.         ELSE
  1050.             fn := fl;
  1051.             fl := "";
  1052.         ENDIF;
  1053.  
  1054.         LOOP
  1055.             fres := FILE_SEARCH (fn);
  1056.             EXITIF fres = "";
  1057.             vi$add_choice (fres);
  1058.         ENDLOOP;
  1059.     ENDLOOP;
  1060.  
  1061.     ! Save current position.
  1062.  
  1063.     pos := MARK (NONE);
  1064.  
  1065.     ! Save a copy of the filenames list
  1066.  
  1067.     POSITION (vi$file_names);
  1068.     COPY_TEXT (choice_buffer);
  1069.     POSITION (BEGINNING_OF (vi$file_names));
  1070.  
  1071.     ! Move back to where we were.
  1072.  
  1073.     POSITION (pos);
  1074.  
  1075.     ! Save the count of file names.
  1076.  
  1077.     num_names := GET_INFO (choice_buffer, "RECORD_COUNT");
  1078.  
  1079.     RETURN (num_names);
  1080. ENDPROCEDURE;
  1081. !
  1082. ! Put a file in the current window.  If the file is already in a buffer,
  1083. ! use the old buffer.  If not, create a new buffer.
  1084. !
  1085. ! Parameters:
  1086. !
  1087. !   file_parameter  String containing file name - input
  1088. !
  1089. PROCEDURE vi$get_file (file_parameter)
  1090.  
  1091.     LOCAL
  1092.         pos,
  1093.         obuf,
  1094.         get_file_parm,
  1095.         outfile,
  1096.         filename,
  1097.         file_read,
  1098.         get_file_name,          ! Local copy of get_file_parameter
  1099.         get_file_list,          ! Possible comma separated list
  1100.         temp_buffer_name,       ! String for buffer name based on get_file_name
  1101.         file_search_result,     ! Latest string returned by file_search
  1102.         temp_file_name,         ! First file name string returned by file_search
  1103.         loop_cnt,               ! Number of files left to process in loop
  1104.         file_cnt,               ! Actual number of files found with FILE_SEARCH
  1105.         loop_buffer,            ! Buffer currently being checked in loop
  1106.         new_buffer,             ! New buffer created if needed
  1107.         found_a_buffer,         ! True if buffer found with same name
  1108.         want_new_buffer;        ! True if file should go into a new buffer
  1109.  
  1110.     ON_ERROR
  1111.         IF ERROR = TPU$_PARSEFAIL THEN
  1112.             vi$info (FAO ("Don't understand file name: !AS", get_file_name));
  1113.             RETURN (0);
  1114.         ENDIF;
  1115.     ENDON_ERROR;
  1116.  
  1117.     obuf := CURRENT_BUFFER;
  1118.     get_file_parm := file_parameter;
  1119.     IF (get_file_parm = 0) OR (get_file_parm = "") THEN
  1120.         vi$info ("File name must be supplied!");
  1121.         RETURN (0);
  1122.     ENDIF;
  1123.  
  1124.     get_file_list := get_file_parm;
  1125.     get_file_name := get_file_parm;
  1126.     temp_file_name := 0;
  1127.  
  1128.     loop_cnt := vi$expand_file_list (get_file_list);
  1129.  
  1130.     !   If none were found, then set up to enter the loop and get a new buffer
  1131.  
  1132.     IF (loop_cnt = 0) THEN
  1133.         loop_cnt := 1;
  1134.         POSITION (BEGINNING_OF (choice_buffer));
  1135.     ELSE
  1136.         IF loop_cnt > 1 THEN
  1137.             vi$info (FAO ("!UL files to edit!", loop_cnt));
  1138.         ENDIF;
  1139.         POSITION (BEGINNING_OF (choice_buffer));
  1140.         temp_file_name := vi$current_line;
  1141.         ERASE_LINE;
  1142.     ENDIF;
  1143.  
  1144.     file_cnt := loop_cnt;
  1145.  
  1146.     LOOP
  1147.         IF (GET_INFO (obuf, "TYPE") = BUFFER) THEN
  1148.             POSITION (obuf);
  1149.         ENDIF;
  1150.  
  1151.         ! See if we already have a buffer by that name
  1152.  
  1153.         IF temp_file_name = 0 THEN
  1154.             temp_buffer_name :=
  1155.                 FILE_PARSE (get_file_name, "", "", NAME) +
  1156.                 FILE_PARSE (get_file_name, "", "", TYPE);
  1157.         ELSE
  1158.             temp_buffer_name :=
  1159.                 FILE_PARSE (temp_file_name, "", "", NAME) +
  1160.                 FILE_PARSE (temp_file_name, "", "", TYPE);
  1161.         ENDIF;
  1162.  
  1163.         IF get_file_parm <> 0 THEN
  1164.  
  1165.             !  Trim the trailing dot off.
  1166.  
  1167.             EDIT (get_file_parm, UPPER, COLLAPSE);
  1168.  
  1169.             IF (SUBSTR (get_file_parm, LENGTH(get_file_parm), 1)
  1170.                                                                 <> '.') THEN
  1171.                 IF (SUBSTR (temp_buffer_name,
  1172.                                 LENGTH(temp_buffer_name), 1) = '.') THEN
  1173.  
  1174.                     temp_buffer_name :=
  1175.                         SUBSTR (temp_buffer_name, 1,
  1176.                                                 LENGTH(temp_buffer_name)-1);
  1177.                 ENDIF;
  1178.             ENDIF;
  1179.         ENDIF;
  1180.  
  1181.         loop_buffer := GET_INFO (BUFFERS, "FIRST");
  1182.         found_a_buffer := 0;
  1183.  
  1184.         LOOP
  1185.             EXITIF loop_buffer = 0;
  1186.             IF temp_buffer_name = GET_INFO (loop_buffer, "NAME") THEN
  1187.                 found_a_buffer := 1;
  1188.                 EXITIF 1;
  1189.             ENDIF;
  1190.             loop_buffer := GET_INFO (BUFFERS, "NEXT");
  1191.         ENDLOOP;
  1192.  
  1193.         ! If there is a buffer by that name, is it the same file?
  1194.         ! We ignore version numbers to keep our sanity
  1195.  
  1196.         IF found_a_buffer THEN      ! Have a buffer with the same name
  1197.             IF temp_file_name = 0 THEN  ! No file on disk
  1198.                 IF get_file_name = GET_INFO (loop_buffer, "OUTPUT_FILE") THEN
  1199.                     want_new_buffer := 0;
  1200.                 ELSE
  1201.  
  1202.                     !   If the buffer is empty, then throw it
  1203.                     !   away.
  1204.  
  1205.                     IF (GET_INFO (loop_buffer, "RECORD_COUNT") > 0) THEN
  1206.                         want_new_buffer := 0;
  1207.                     ELSE
  1208.                         IF (temp_file_name <> 0) and (temp_file_name <> "") THEN
  1209.                             vi$info ("Buffer empty, reading file");
  1210.                             POSITION (loop_buffer);
  1211.                             vi$info (FAO ('Reading "!AS"', temp_file_name));
  1212.                             file_read := READ_FILE (temp_file_name);
  1213.  
  1214.                             IF file_read <> "" THEN
  1215.                                 SET (OUTPUT_FILE, loop_buffer, file_read);
  1216.                                 vi$status_lines (loop_buffer);
  1217.                             ENDIF;
  1218.                         ENDIF;
  1219.  
  1220.                         want_new_buffer := 2;
  1221.                         POSITION (BEGINNING_OF (loop_buffer));
  1222.                         MAP (CURRENT_WINDOW, loop_buffer);
  1223.                         obuf := loop_buffer;
  1224.                     ENDIF;
  1225.                 ENDIF;
  1226.             ELSE
  1227.  
  1228.                 ! Check to see if the same file
  1229.  
  1230.                 outfile := GET_INFO (loop_buffer, "OUTPUT_FILE");
  1231.                 filename := GET_INFO (loop_buffer, "FILE_NAME");
  1232.  
  1233.                 !  Trim version numbers off all of the names.
  1234.  
  1235.                 IF (outfile <> 0) THEN
  1236.                     outfile := FILE_PARSE (outfile, "", "", DEVICE) +
  1237.                                 FILE_PARSE (outfile, "", "", DIRECTORY) +
  1238.                                 FILE_PARSE (outfile, "", "", NAME) +
  1239.                                 FILE_PARSE (outfile, "", "", TYPE);
  1240.                 ENDIF;
  1241.  
  1242.                 IF (filename <> 0) THEN
  1243.                     filename := FILE_PARSE (filename, "", "", DEVICE) +
  1244.                                 FILE_PARSE (filename, "", "", DIRECTORY) +
  1245.                                 FILE_PARSE (filename, "", "", NAME) +
  1246.                                 FILE_PARSE (filename, "", "", TYPE);
  1247.                 ENDIF;
  1248.  
  1249.                 temp_file_name := FILE_PARSE (temp_file_name, "", "", DEVICE) +
  1250.                                 FILE_PARSE (temp_file_name, "", "", DIRECTORY) +
  1251.                                 FILE_PARSE (temp_file_name, "", "", NAME) +
  1252.                                 FILE_PARSE (temp_file_name, "", "", TYPE);
  1253.  
  1254.                 !   If the buffer is empty, then throw it away.
  1255.  
  1256.                 IF (GET_INFO (loop_buffer, "RECORD_COUNT") > 0) THEN
  1257.                     IF (outfile = temp_file_name) OR
  1258.                                             (filename = temp_file_name) THEN
  1259.                         want_new_buffer := 0;
  1260.                     ELSE
  1261.                         want_new_buffer := 1;
  1262.                     ENDIF;
  1263.                 ELSE
  1264.                     IF temp_file_name <> 0 THEN
  1265.                         vi$info ("Buffer empty, reading file");
  1266.                         POSITION (loop_buffer);
  1267.                         vi$info (FAO ('Reading "!AS"', temp_file_name));
  1268.                         file_read := READ_FILE (temp_file_name);
  1269.                         IF (file_read <> "") THEN
  1270.                             SET (OUTPUT_FILE, loop_buffer, file_read);
  1271.                             vi$status_lines (loop_buffer);
  1272.                         ENDIF;
  1273.                     ENDIF;
  1274.  
  1275.                     want_new_buffer := 2;
  1276.                     POSITION (BEGINNING_OF (loop_buffer));
  1277.                     MAP (CURRENT_WINDOW, loop_buffer);
  1278.                     obuf := loop_buffer;
  1279.                 ENDIF;
  1280.             ENDIF;
  1281.  
  1282.             IF want_new_buffer = 1 THEN
  1283.  
  1284.                 vi$info (FAO (
  1285.                             "Buffer name !AS is in use", temp_buffer_name));
  1286.  
  1287.                 temp_buffer_name :=
  1288.                     vi$read_line (
  1289.                         "Type new buffer name or press Return to cancel: ");
  1290.  
  1291.                 IF temp_buffer_name = "" THEN
  1292.                     vi$info ("No new buffer created");
  1293.                 ELSE
  1294.                     new_buffer := vi$_create_buffer (temp_buffer_name,
  1295.                                                 get_file_name, temp_file_name);
  1296.                 ENDIF;
  1297.             ELSE
  1298.                 IF (want_new_buffer = 0) and (CURRENT_BUFFER = loop_buffer) THEN
  1299.                     vi$info (FAO (
  1300.                                 "Already editing file !AS", get_file_name));
  1301.                 ELSE
  1302.                     IF (want_new_buffer = 0) THEN
  1303.                         IF (vi$check_auto_write) THEN
  1304.                             RETURN;
  1305.                         ENDIF;
  1306.                         MAP (CURRENT_WINDOW, loop_buffer);
  1307.                         obuf := loop_buffer;
  1308.                     ENDIF;
  1309.                 ENDIF;
  1310.             ENDIF;
  1311.         ELSE            ! No buffer with the same name, so create a new buffer
  1312.             new_buffer := vi$_create_buffer (temp_buffer_name, get_file_name,
  1313.                                                                 temp_file_name);
  1314.         ENDIF;
  1315.  
  1316.         IF new_buffer <> 0 THEN
  1317.             SET (EOB_TEXT, new_buffer, "[EOB]");
  1318.             SET (TAB_STOPS, new_buffer, vi$tab_amount);
  1319.         ENDIF;
  1320.  
  1321.         loop_cnt := loop_cnt - 1;
  1322.  
  1323.         EXITIF loop_cnt <= 0;
  1324.  
  1325.         POSITION (BEGINNING_OF (choice_buffer));
  1326.         temp_file_name := vi$current_line;
  1327.         ERASE_LINE;
  1328.     ENDLOOP;
  1329.  
  1330.     IF (file_cnt > 1) THEN
  1331.         vi$_first_file (0);
  1332.     ENDIF;
  1333.  
  1334.     vi$set_status_line (CURRENT_WINDOW);
  1335.     RETURN (file_cnt);
  1336. ENDPROCEDURE;
  1337.  
  1338. !
  1339. !  This procedure collects the names of all buffers that are leading
  1340. !  derivatives of "buffer_name".  The function value is the boolean
  1341. !  value telling whether or not the name matched exactly.  The other
  1342. !  parameters are return values.
  1343. !
  1344. PROCEDURE vi$choose_buffer (buffer_name, how_many_buffers,
  1345.                              possible_buffer, possible_buffer_name, loop_buffer)
  1346.  
  1347.     LOCAL
  1348.         this_buffer,            ! Current buffer
  1349.         loop_buffer_name,       ! String containing name of loop_buffer
  1350.         found_a_buffer;         ! True if buffer found with same exact name
  1351.  
  1352.     found_a_buffer := 0;
  1353.     EDIT (buffer_name, COLLAPSE);
  1354.     possible_buffer := 0;
  1355.     possible_buffer_name := 0;
  1356.     how_many_buffers := 0;
  1357.  
  1358.     ! See if we already have a buffer by that name
  1359.  
  1360.     this_buffer := CURRENT_BUFFER;
  1361.     loop_buffer := GET_INFO (BUFFERS, "FIRST");
  1362.     CHANGE_CASE (buffer_name, UPPER);   ! buffer names are uppercase
  1363.     ERASE (choice_buffer);
  1364.  
  1365.     LOOP
  1366.         EXITIF loop_buffer = 0;
  1367.         loop_buffer_name := GET_INFO (loop_buffer, "NAME");
  1368.  
  1369.         IF buffer_name = loop_buffer_name THEN
  1370.             found_a_buffer := 1;
  1371.             how_many_buffers := 1;
  1372.             EXITIF 1;
  1373.         ELSE
  1374.             IF buffer_name = SUBSTR (loop_buffer_name, 1,
  1375.                                                     LENGTH (buffer_name)) THEN
  1376.                 vi$add_choice (loop_buffer_name);
  1377.                 possible_buffer := loop_buffer;
  1378.                 possible_buffer_name := loop_buffer_name;
  1379.                 how_many_buffers := how_many_buffers + 1;
  1380.             ENDIF;
  1381.         ENDIF;
  1382.  
  1383.         loop_buffer := GET_INFO (BUFFERS, "NEXT");
  1384.     ENDLOOP;
  1385.  
  1386.     RETURN (found_a_buffer);
  1387. ENDPROCEDURE;
  1388.  
  1389. !
  1390. !   Return current line or empty string if at EOB
  1391. !
  1392. PROCEDURE vi$current_line
  1393.     IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN
  1394.         RETURN ("");
  1395.     ELSE
  1396.         RETURN (CURRENT_LINE);
  1397.     ENDIF;
  1398. ENDPROCEDURE;
  1399.  
  1400. !
  1401. !   If autowrite is active, then write the current buffer out.
  1402. !
  1403. PROCEDURE vi$check_auto_write
  1404.     LOCAL
  1405.         buf,
  1406.         win,
  1407.         owin,
  1408.         mod;
  1409.  
  1410.     mod := GET_INFO (CURRENT_BUFFER, "MODIFIED") AND
  1411.             (NOT GET_INFO (CURRENT_BUFFER, "SYSTEM")) AND
  1412.             (NOT GET_INFO (CURRENT_BUFFER, "NO_WRITE"));
  1413.  
  1414.     buf := CURRENT_BUFFER;
  1415.  
  1416.     IF mod AND vi$auto_write THEN
  1417.         IF (vi$can_write (CURRENT_BUFFER)) THEN
  1418.             vi$info ("Writing out """+GET_INFO (buf, "NAME")+"""");
  1419.             WRITE_FILE (buf);
  1420.         ELSE
  1421.             RETURN (1);
  1422.         ENDIF;
  1423.     ENDIF;
  1424.  
  1425.     IF (NOT mod) AND
  1426.             (NOT GET_INFO (CURRENT_BUFFER, "SYSTEM")) AND
  1427.             (NOT GET_INFO (CURRENT_BUFFER, "NO_WRITE")) AND
  1428.                                 (GET_INFO (buf, "RECORD_COUNT") = 0) THEN
  1429.         IF (vi$delete_empty) THEN
  1430.             vi$info ("Deleting empty buffer: "+GET_INFO (buf, "NAME"));
  1431.             MAP (CURRENT_WINDOW, message_buffer);
  1432.             owin := CURRENT_WINDOW;
  1433.             win := GET_INFO (WINDOWS, "FIRST");
  1434.             LOOP
  1435.                 EXITIF win = 0;
  1436.                 IF (GET_INFO (win, "BUFFER") = buf) THEN
  1437.                     MAP (win, message_buffer);
  1438.                     vi$set_status_line (win);
  1439.                 ENDIF;
  1440.                 win := GET_INFO (WINDOWS, "NEXT");
  1441.             ENDLOOP;
  1442.             POSITION (owin);
  1443.             DELETE (buf);
  1444.         ELSE
  1445.             vi$last_mapped := buf;
  1446.         ENDIF;
  1447.     ELSE
  1448.         vi$last_mapped := buf;
  1449.     ENDIF;
  1450.  
  1451.     RETURN (0);
  1452. ENDPROCEDURE;
  1453.  
  1454. !
  1455. !   Only perform an update if there is not a keyboard macro in progress.
  1456. !
  1457. PROCEDURE vi$update (win)
  1458.     IF (vi$key_buf = 0) AND (vi$playing_back = 0) THEN
  1459.         UPDATE (win);
  1460.     ENDIF;
  1461. ENDPROCEDURE;
  1462.  
  1463. !
  1464. !   This procedure should be envoked after a wild card edit.  It will allow
  1465. !   a list of files that have been created due to a wildcard filespec to be
  1466. !   processed sequentially.
  1467. !
  1468. PROCEDURE vi$_next_file (bang)
  1469.     LOCAL
  1470.         win,
  1471.         fn,
  1472.         pos,
  1473.         found_one,
  1474.         btype,
  1475.         bn,
  1476.         how_many_buffers,
  1477.         possible_buffer,
  1478.         possible_buffer_name,
  1479.         loop_buffer,
  1480.         line;
  1481.  
  1482.     ON_ERROR
  1483.         ! Ignore errors
  1484.     ENDON_ERROR;
  1485.  
  1486.     IF (NOT bang) AND (vi$check_auto_write) THEN
  1487.         RETURN;
  1488.     ENDIF;
  1489.  
  1490.     pos := MARK (NONE);
  1491.     win := CURRENT_WINDOW;
  1492.  
  1493.     POSITION (vi$file_names);
  1494.     IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
  1495.         MOVE_VERTICAL (1);
  1496.         IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN
  1497.             vi$info ("No more files!");
  1498.             MOVE_VERTICAL (-1);
  1499.             POSITION (win);
  1500.             RETURN (1);
  1501.         ENDIF;
  1502.     ELSE
  1503.         vi$info ("No more files!");
  1504.         POSITION (win);
  1505.         RETURN (1);
  1506.     ENDIF;
  1507.  
  1508.     fn := vi$current_line;
  1509.  
  1510.     bn := FILE_PARSE (fn, "", "", NAME);
  1511.     btype := FILE_PARSE (fn, "", "", TYPE);
  1512.  
  1513.     IF btype = "" THEN
  1514.         btype := ".";
  1515. $$EOD$$
  1516.