?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE VIRTUAL TERMINAL PROTOCOL INTERFACE' ??

MODULE iim$vtp_interface;
{ PURPOSE: }
{   This VIRTUAL TERMINAL PROTOCOL (VTP) interface provides externally declared procedures }
{   which are used to access CDCNET. }
{ DESIGN:  }
{   The VTP interface procedures make calls to NAMVE to send and receive on CDCNET. }
{   Input received from NAMVE/CDCNET is queued until specifically requested by the procedure }
{   which is using the VTP interface. }

?? PUSH (LISTEXT := ON) ??
*copyc i#move
*copyc amt$file_identifier
*copyc amt$local_file_name
*copyc clp$get_time_string
*copyc pmp$get_job_names
*copyc bat$task_file_table
*copyc bav$last_tft_entry
*copyc bav$task_file_table
*copyc clp$get_system_file_id
*copyc clc$standard_file_names
*copyc ife$error_codes
*copyc jmt$timesharing_signal
*copyc nae$application_interfaces
*copyc nae$namve_conditions
*copyc nat$data_fragments
*copyc oss$task_shared
*copyc osp$i_await_activity
*copyc ost$activity_status
*copyc ost$status
*copyc ost$wait
*copyc pmp$wait
*copyc amp$flush
*copyc iik$vt_keypoints
*copyc iip$st_put
*copyc iit$vt_attributes
*copyc iit$vt_attribute_descriptions
*copyc iit$vt_attribute_kinds
*copyc iit$vt_change_error_codes
*copyc iit$vt_connections
*copyc iit$vt_input_information
*copyc iit$vt_message_types
*copyc iit$vt_octet_header
*copyc iit$vt_output_information
*copyc iit$vt_timeout
*copyc iiv$interactive_terminated
*copyc iiv$xt_xterm_downline
*copyc iiv$xt_xterm_upline
*copyc oss$job_pageable
*copyc oss$job_paged_literal
*copyc oss$task_shared
*copyc syv$job_initialization_complete
?? POP ??

*copyc amp$open
*copyc amp$close
*copyc ifp$st_fap_control
*copyc iip$vt_validate_file_identifier
*copyc iip$xt_check_upline
*copyc iip$xt_open_downline_messages
*copyc iip$xt_open_upline_messages
*copyc iiv$interactive_terminated
*copyc i#move
*copyc i#ptr
*copyc jmp$detach_timesharing_job
*copyc jmp$is_xterm_job
*copyc nap$check_data_available
*copyc nap$await_data_available
*copyc nap$se_clear_request
*copyc nap$se_receive_data
*copyc nap$se_send_data
*copyc nap$se_synchronize
*copyc nap$se_synchronize_confirm
*copyc osp$append_status_integer
*copyc osp$set_status_abnormal
*copyc osp$format_message
*copyc osv$job_pageable_heap
*copyc osv$task_shared_heap
*copyc pmp$log_ascii
*copyc pmp$log


?? NEWTITLE := 'STATIC VARIABLES', EJECT ??

  VAR
    char_length: [STATIC, oss$job_pageable] integer,
    connections_head: [STATIC, oss$job_pageable] ^iit$vt_connection := NIL,
    connections_tail: [STATIC, oss$job_pageable] ^iit$vt_connection := NIL,
    file_id_is_valid: [STATIC, oss$job_pageable] boolean,
    ordinal_char: [STATIC, oss$job_pageable] string (10),
    queue_type_from_message: [STATIC, READ, oss$job_paged_literal] iit$vt_queue_type_from_message :=
        [iic$vt_output, iic$vt_input, iic$vt_change, iic$vt_change, iic$vt_change, iic$vt_indications,
        iic$vt_status, iic$vt_status, iic$vt_status, iic$vt_start_stop_comm, iic$vt_start_stop_comm_resp,
        iic$vt_start_stop_comm, iic$vt_start_stop_comm_resp, iic$vt_change, iic$vt_version, iic$vt_create,
        iic$vt_create_status, iic$vt_create_status, iic$vt_delete, iic$vt_status, iic$vt_status,
        iic$vt_status, iic$vt_create, iic$vt_create_status, iic$vt_create_status];

?? TITLE := '[XDCL] iip$vt_create_attribute_octets', EJECT ??

  PROCEDURE [XDCL] iip$vt_create_attribute_octets
    (    attributes: iit$vt_attributes;
     VAR buffer: ^SEQ ( * );
     VAR data_length: nat$data_length);

{ Purpose:  Create octets from an iit$vt_attributes array.

{ Design:   Each element in the iit$vt_attributes array is an AN/AV
{           (attribute-number/attribute-value) group.  This procedure
{           creates one or more 8-bit bytes (called octets) from each
{           AN/AV group, stores these octets in an adaptable sequence
{           and returns a pointer to this sequence as well as the
{           total byte size of all the octets it created.

    CONST
      vtc_multiple_octet_number = 128,
      vtc_multiple_octet_number_dflt = 2,
      vtc_single_octet = FALSE,
      vtc_multiple_octet = TRUE,
      vtc_octet_header_fill = 0,
      vtc_site_defined_code_set_dflt = 3;

    CONST
      iic$vt_max_octet_size = 143;

    TYPE
      vtt_input_output_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$input_output_mode,
      recend,
      vtt_input_editing_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$input_editing_mode,
      recend,
      vtt_transp_char_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$trans_character_mode,
      recend,
      vtt_transp_for_char_single_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_transp_for_char_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 1 .. 4,
      recend,
      vtt_transp_term_char_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_transp_term_char_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 1 .. 4,
      recend,
      vtt_transp_timeout_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$trans_timeout_mode,
      recend,
      vtt_transp_len_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$trans_length_mode,
      recend,
      vtt_transp_mess_len_sing_oct = record
        header: iit$vt_octet_header,
        attribute: 0 .. 255,
      recend,
      vtt_transp_mess_len_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 2 .. 2,
        attribute: 0 .. 32767,
      recend,
      vtt_partial_char_forward_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_atten_char_act_oct = record
        header: iit$vt_octet_header,
        attribute: ift$attention_character_action,
      recend,
      vtt_break_key_action_oct = record
        header: iit$vt_octet_header,
        attribute: ift$break_key_action,
      recend,
      vtt_input_block_size_sing_oct = record
        header: iit$vt_octet_header,
        attribute: 20 .. 255,
      recend,
      vtt_input_block_size_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 2 .. 2,
        attribute: ift$input_block_size,
      recend,
      vtt_store_nul_del_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_store_back_char_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_network_ctl_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_cancel_line_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_end_line_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_begin_line_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_backspace_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_end_partial_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_attention_char_oct = record
        header: iit$vt_octet_header,
        attribute: char,
      recend,
      vtt_page_length_oct = record
        header: iit$vt_octet_header,
        attribute: ift$page_length,
      recend,
      vtt_page_width_oct = record
        header: iit$vt_octet_header,
        attribute: ift$page_width,
      recend,
      vtt_hold_page_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_hold_page_over_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_fold_line_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_end_out_seq_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_end_out_seq_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. 4,
      recend,
      vtt_carr_ret_seq_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_carr_ret_seq_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. 2,
      recend,
      vtt_line_feed_seq_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_line_feed_seq_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. 2,
      recend,
      vtt_form_feed_seq_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_form_feed_seq_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. 7,
      recend,
      vtt_end_page_action_oct = record
        header: iit$vt_octet_header,
        attribute: ift$end_page_action,
      recend,
      vtt_carr_ret_delay_sing_oct = record
        header: iit$vt_octet_header,
        attribute: 0 .. 255,
      recend,
      vtt_carr_ret_delay_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 2 .. 2,
        attribute: 0 .. 999,
      recend,
      vtt_line_feed_delay_sing_oct = record
        header: iit$vt_octet_header,
        attribute: 0 .. 255,
      recend,
      vtt_line_feed_delay_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 2 .. 2,
        attribute: 0 .. 999,
      recend,
      vtt_form_feed_delay_sing_oct = record
        header: iit$vt_octet_header,
        attribute: 0 .. 255,
      recend,
      vtt_form_feed_delay_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 2 .. 2,
        attribute: 0 .. 3000,
      recend,
      vtt_end_line_position_oct = record
        header: iit$vt_octet_header,
        attribute: ift$end_line_positioning,
      recend,
      vtt_end_partial_position_oct = record
        header: iit$vt_octet_header,
        attribute: ift$end_partial_positioning,
      recend,
      vtt_char_flow_control_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_function_key_class_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_function_key_class_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. ifc$max_function_key_class_size,
      recend,
      vtt_terminal_model_sing_oct = record
        header: iit$vt_octet_header,
        attribute: string (1),
      recend,
      vtt_terminal_model_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. ifc$max_terminal_model_size,
      recend,
      vtt_code_set_oct = record
        header: iit$vt_octet_header,
        attribute: ift$code_set,
      recend,
      vtt_code_set_name_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. ifc$max_code_set_name_size,
        site_defined_code_set : 3 .. 3,
      recend,
      vtt_parity_type_oct = record
        header: iit$vt_octet_header,
        attribute: ift$parity,
      recend,
      vtt_echoplex_oct = record
        header: iit$vt_octet_header,
        attribute: boolean,
      recend,
      vtt_status_action_oct = record
        header: iit$vt_octet_header,
        attribute: ift$status_action,
      recend,
      vtt_transp_protocol_mode_oct = record
        header: iit$vt_octet_header,
        attribute: ift$trans_protocol_mode,
      recend,
      vtt_control_code_rep_none_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. 0,
      recend,
      vtt_control_code_rep_mult_oct = record
        header: iit$vt_octet_header,
        octet_number: 0 .. ifc$total_substitution_count * 2 - 2,
      recend,
      vtt_control_code_rep_ext_oct = record
        header: iit$vt_octet_header,
        octet_length: packed record
          multiple_attribute_length_octet: boolean,
          fill_0: 0..1F(16),
          attribute_length_octet_number: 1 .. 2,
        recend,
        octet_number: 0 .. 0FFFF(16),
      recend;


    VAR
      input_output_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_input_output_mode_oct :=
            [[vtc_single_octet, iic$vt_input_output_mode], *],
      input_editing_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_input_editing_mode_oct :=
            [[vtc_single_octet, iic$vt_input_editing_mode], *],
      transp_char_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_char_mode_oct :=
            [[vtc_single_octet, iic$vt_trans_character_mode], *],
      transp_for_char_single_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_for_char_single_oct :=
            [[vtc_single_octet, iic$vt_trans_forward_character], *],
      transp_for_char_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_for_char_mult_oct :=
            [[vtc_multiple_octet, iic$vt_trans_forward_character], vtc_multiple_octet_number_dflt],
      transp_term_char_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_term_char_sing_oct :=
            [[vtc_single_octet, iic$vt_trans_term_character], *],
      transp_term_char_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_term_char_mult_oct :=
            [[vtc_multiple_octet, iic$vt_trans_term_character], vtc_multiple_octet_number_dflt],
      transp_protocol_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_protocol_mode_oct :=
            [[vtc_single_octet, iic$vt_trans_protocol_mode], *],
      transp_timeout_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_timeout_mode_oct :=
            [[vtc_single_octet, iic$vt_trans_timeout_mode], *],
      transp_len_mode_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_len_mode_oct :=
            [[vtc_single_octet, iic$vt_trans_length_mode], *],
      transp_mess_len_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_mess_len_sing_oct :=
            [[vtc_single_octet, iic$vt_trans_message_length], *],
      transp_mess_len_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_transp_mess_len_mult_oct :=
            [[vtc_multiple_octet, iic$vt_trans_message_length], vtc_multiple_octet_number_dflt, *],
      control_code_rep_none_oct: [STATIC, READ, oss$job_paged_literal] vtt_control_code_rep_none_oct :=
            [[vtc_multiple_octet, iic$vt_control_code_replacement], *],
      control_code_rep_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_control_code_rep_mult_oct :=
            [[vtc_multiple_octet, iic$vt_control_code_replacement],
              vtc_multiple_octet_number_dflt],
      control_code_rep_ext_oct: [STATIC, READ, oss$job_paged_literal] vtt_control_code_rep_ext_oct :=
            [[vtc_multiple_octet, iic$vt_control_code_replacement],
              [vtc_multiple_octet, 0, vtc_multiple_octet_number_dflt],
              vtc_multiple_octet_number],
      partial_char_forward_oct: [STATIC, READ, oss$job_paged_literal] vtt_partial_char_forward_oct :=
            [[vtc_single_octet, iic$vt_partial_char_forwarding], *],
      atten_char_act_oct: [STATIC, READ, oss$job_paged_literal] vtt_atten_char_act_oct :=
            [[vtc_single_octet, iic$vt_attention_char_action], *],
      break_key_action_oct: [STATIC, READ, oss$job_paged_literal] vtt_break_key_action_oct :=
            [[vtc_single_octet, iic$vt_break_key_action], *],
      input_block_size_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_input_block_size_sing_oct :=
            [[vtc_single_octet, iic$vt_input_block_size], *],
      input_block_size_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_input_block_size_mult_oct :=
            [[vtc_multiple_octet, iic$vt_input_block_size], vtc_multiple_octet_number_dflt, *],
      store_nul_del_oct: [STATIC, READ, oss$job_paged_literal] vtt_store_nul_del_oct :=
            [[vtc_single_octet, iic$vt_store_nuls_dels], *],
      store_back_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_store_back_char_oct :=
            [[vtc_single_octet, iic$vt_store_backspace_char], *],
      network_ctl_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_network_ctl_char_oct :=
            [[vtc_single_octet, iic$vt_network_command_char], *],
      cancel_line_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_cancel_line_char_oct :=
            [[vtc_single_octet, iic$vt_cancel_line_character], *],
      end_line_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_line_char_oct :=
            [[vtc_single_octet, iic$vt_end_line_character], *],
      begin_line_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_begin_line_char_oct :=
            [[vtc_single_octet, iic$vt_begin_line_character], *],
      backspace_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_backspace_char_oct :=
            [[vtc_single_octet, iic$vt_backspace_character], *],
      end_partial_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_partial_char_oct :=
            [[vtc_single_octet, iic$vt_end_partial_character], *],
      attention_char_oct: [STATIC, READ, oss$job_paged_literal] vtt_attention_char_oct :=
            [[vtc_single_octet, iic$vt_attention_character], *],
      page_length_oct: [STATIC, READ, oss$job_paged_literal] vtt_page_length_oct :=
            [[vtc_single_octet, iic$vt_page_length], *],
      page_width_oct: [STATIC, READ, oss$job_paged_literal] vtt_page_width_oct :=
            [[vtc_single_octet, iic$vt_page_width], *],
      hold_page_oct: [STATIC, READ, oss$job_paged_literal] vtt_hold_page_oct :=
            [[vtc_single_octet, iic$vt_hold_page], *],
      hold_page_over_oct: [STATIC, READ, oss$job_paged_literal] vtt_hold_page_over_oct :=
            [[vtc_single_octet, iic$vt_hold_page_over], *],
      fold_line_oct: [STATIC, READ, oss$job_paged_literal] vtt_fold_line_oct :=
            [[vtc_single_octet, iic$vt_fold_line], *],
      end_out_seq_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_out_seq_sing_oct :=
            [[vtc_single_octet, iic$vt_end_output_sequence], *],
      end_out_seq_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_out_seq_mult_oct :=
            [[vtc_multiple_octet, iic$vt_end_output_sequence], vtc_multiple_octet_number_dflt],
      carr_ret_seq_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_carr_ret_seq_sing_oct :=
            [[vtc_single_octet, iic$vt_carriage_return_sequence], *],
      carr_ret_seq_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_carr_ret_seq_mult_oct :=
            [[vtc_multiple_octet, iic$vt_carriage_return_sequence], vtc_multiple_octet_number_dflt],
      line_feed_seq_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_line_feed_seq_sing_oct :=
            [[vtc_single_octet, iic$vt_line_feed_sequence], *],
      line_feed_seq_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_line_feed_seq_mult_oct :=
            [[vtc_multiple_octet, iic$vt_line_feed_sequence], vtc_multiple_octet_number_dflt],
      form_feed_seq_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_form_feed_seq_sing_oct :=
            [[vtc_single_octet, iic$vt_form_feed_sequence], *],
      form_feed_seq_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_form_feed_seq_mult_oct :=
            [[vtc_multiple_octet, iic$vt_form_feed_sequence], vtc_multiple_octet_number_dflt],
      end_page_action_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_page_action_oct :=
            [[vtc_single_octet, iic$vt_end_page_action], *],
      carr_ret_delay_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_carr_ret_delay_sing_oct :=
            [[vtc_single_octet, iic$vt_carriage_return_delay], *],
      carr_ret_delay_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_carr_ret_delay_mult_oct :=
            [[vtc_multiple_octet, iic$vt_carriage_return_delay], vtc_multiple_octet_number_dflt, *],
      line_feed_delay_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_line_feed_delay_sing_oct :=
            [[vtc_single_octet, iic$vt_line_feed_delay], *],
      line_feed_delay_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_line_feed_delay_mult_oct :=
            [[vtc_multiple_octet, iic$vt_line_feed_delay], vtc_multiple_octet_number_dflt, *],
      form_feed_delay_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_form_feed_delay_sing_oct :=
            [[vtc_single_octet, iic$vt_form_feed_delay], *],
      form_feed_delay_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_form_feed_delay_mult_oct :=
            [[vtc_multiple_octet, iic$vt_form_feed_delay], vtc_multiple_octet_number_dflt, *],
      end_line_position_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_line_position_oct :=
            [[vtc_single_octet, iic$vt_end_line_positioning], *],
      end_partial_position_oct: [STATIC, READ, oss$job_paged_literal] vtt_end_partial_position_oct :=
            [[vtc_single_octet, iic$vt_end_partial_positioning], *],
      char_flow_control_oct: [STATIC, READ, oss$job_paged_literal] vtt_char_flow_control_oct :=
            [[vtc_single_octet, iic$vt_character_flow_control], *],
      function_key_class_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_function_key_class_sing_oct :=
            [[vtc_single_octet, iic$vt_function_key_class], *],
      function_key_class_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_function_key_class_mult_oct :=
            [[vtc_multiple_octet, iic$vt_function_key_class], vtc_multiple_octet_number_dflt],
      terminal_model_sing_oct: [STATIC, READ, oss$job_paged_literal] vtt_terminal_model_sing_oct :=
            [[vtc_single_octet, iic$vt_terminal_model], *],
      terminal_model_mult_oct: [STATIC, READ, oss$job_paged_literal] vtt_terminal_model_mult_oct :=
            [[vtc_multiple_octet, iic$vt_terminal_model], vtc_multiple_octet_number_dflt],
      code_set_oct: [STATIC, READ, oss$job_paged_literal] vtt_code_set_oct :=
            [[vtc_single_octet, iic$vt_code_set], *],
      code_set_name_oct: [STATIC, READ, oss$job_paged_literal] vtt_code_set_name_oct :=
            [[vtc_multiple_octet, iic$vt_code_set], vtc_multiple_octet_number_dflt,
            vtc_site_defined_code_set_dflt],
      parity_type_oct: [STATIC, READ, oss$job_paged_literal] vtt_parity_type_oct :=
            [[vtc_single_octet, iic$vt_parity], *],
      echoplex_oct: [STATIC, READ, oss$job_paged_literal] vtt_echoplex_oct :=
            [[vtc_single_octet, iic$vt_echoplex], *],
      status_action_oct: [STATIC, READ, oss$job_paged_literal] vtt_status_action_oct :=
            [[vtc_single_octet, iic$vt_status_action], *];

    VAR
      input_output_mode_oct_ptr: ^vtt_input_output_mode_oct,
      input_editing_mode_oct_ptr: ^vtt_input_editing_mode_oct,
      transp_char_mode_oct_ptr: ^vtt_transp_char_mode_oct,
      transp_for_char_single_oct_ptr: ^vtt_transp_for_char_single_oct,
      transp_for_char_mult_oct_ptr: ^vtt_transp_for_char_mult_oct,
      transp_term_char_sing_oct_ptr: ^vtt_transp_term_char_sing_oct,
      transp_term_char_mult_oct_ptr: ^vtt_transp_term_char_mult_oct,
      transp_protocol_mode_oct_ptr: ^vtt_transp_protocol_mode_oct,
      transp_timeout_mode_oct_ptr: ^vtt_transp_timeout_mode_oct,
      transp_len_mode_oct_ptr: ^vtt_transp_len_mode_oct,
      transp_mess_len_sing_oct_ptr: ^vtt_transp_mess_len_sing_oct,
      transp_mess_len_mult_oct_ptr: ^vtt_transp_mess_len_mult_oct,
      control_code_rep_none_oct_ptr: ^vtt_control_code_rep_none_oct,
      control_code_rep_mult_oct_ptr: ^vtt_control_code_rep_mult_oct,
      control_code_rep_ext_oct_ptr: ^vtt_control_code_rep_ext_oct,
      partial_char_forward_oct_ptr: ^vtt_partial_char_forward_oct,
      atten_char_act_oct_ptr: ^vtt_atten_char_act_oct,
      break_key_action_oct_ptr: ^vtt_break_key_action_oct,
      input_block_size_sing_oct_ptr: ^vtt_input_block_size_sing_oct,
      input_block_size_mult_oct_ptr: ^vtt_input_block_size_mult_oct,
      store_nul_del_oct_ptr: ^vtt_store_nul_del_oct,
      store_back_char_oct_ptr: ^vtt_store_back_char_oct,
      network_ctl_char_oct_ptr: ^vtt_network_ctl_char_oct,
      cancel_line_char_oct_ptr: ^vtt_cancel_line_char_oct,
      end_line_char_oct_ptr: ^vtt_end_line_char_oct,
      begin_line_char_oct_ptr: ^vtt_begin_line_char_oct,
      backspace_char_oct_ptr: ^vtt_backspace_char_oct,
      end_partial_char_oct_ptr: ^vtt_end_partial_char_oct,
      attention_char_oct_ptr: ^vtt_attention_char_oct,
      page_length_oct_ptr: ^vtt_page_length_oct,
      page_width_oct_ptr: ^vtt_page_width_oct,
      hold_page_oct_ptr: ^vtt_hold_page_oct,
      hold_page_over_oct_ptr: ^vtt_hold_page_over_oct,
      fold_line_oct_ptr: ^vtt_fold_line_oct,
      end_out_seq_sing_oct_ptr: ^vtt_end_out_seq_sing_oct,
      end_out_seq_mult_oct_ptr: ^vtt_end_out_seq_mult_oct,
      carr_ret_seq_sing_oct_ptr: ^vtt_carr_ret_seq_sing_oct,
      carr_ret_seq_mult_oct_ptr: ^vtt_carr_ret_seq_mult_oct,
      line_feed_seq_sing_oct_ptr: ^vtt_line_feed_seq_sing_oct,
      line_feed_seq_mult_oct_ptr: ^vtt_line_feed_seq_mult_oct,
      form_feed_seq_sing_oct_ptr: ^vtt_form_feed_seq_sing_oct,
      form_feed_seq_mult_oct_ptr: ^vtt_form_feed_seq_mult_oct,
      end_page_action_oct_ptr: ^vtt_end_page_action_oct,
      carr_ret_delay_sing_oct_ptr: ^vtt_carr_ret_delay_sing_oct,
      carr_ret_delay_mult_oct_ptr: ^vtt_carr_ret_delay_mult_oct,
      line_feed_delay_sing_oct_ptr: ^vtt_line_feed_delay_sing_oct,
      line_feed_delay_mult_oct_ptr: ^vtt_line_feed_delay_mult_oct,
      form_feed_delay_sing_oct_ptr: ^vtt_form_feed_delay_sing_oct,
      form_feed_delay_mult_oct_ptr: ^vtt_form_feed_delay_mult_oct,
      end_line_position_oct_ptr: ^vtt_end_line_position_oct,
      end_partial_position_oct_ptr: ^vtt_end_partial_position_oct,
      char_flow_control_oct_ptr: ^vtt_char_flow_control_oct,
      terminal_model_sing_oct_ptr: ^vtt_terminal_model_sing_oct,
      terminal_model_mult_oct_ptr: ^vtt_terminal_model_mult_oct,
      function_key_class_sing_oct_ptr: ^vtt_function_key_class_sing_oct,
      function_key_class_mult_oct_ptr: ^vtt_function_key_class_mult_oct,
      code_set_oct_ptr: ^vtt_code_set_oct,
      code_set_name_oct_ptr: ^vtt_code_set_name_oct,
      parity_type_oct_ptr: ^vtt_parity_type_oct,
      echoplex_oct_ptr: ^vtt_echoplex_oct,
      status_action_oct_ptr: ^vtt_status_action_oct;

    VAR
      i: integer,
      j: integer,
      k: integer,
      control_code_replacement_value: ^array [1 .. *]
        OF ift$control_code_rep_char,
      original_control_code_set: ^array[1 .. *] OF char,
      original_control_code_set_size: 1 .. 2 * ifc$total_substitution_count,
      string_attribute: ^string ( * );

*copyc ift$terminal_connection_types
*copyc ift$terminal_attribute_types
*copyc iit$vt_attribute_descriptions
*copyc iit$vt_attribute_kinds

?? EJECT ??


    FOR i := 1 TO UPPERBOUND (attributes) DO
      CASE attributes [i].kind OF

      = iic$vt_input_output_mode =
        data_length := data_length + #SIZE (input_output_mode_oct);
        NEXT input_output_mode_oct_ptr IN buffer;
        input_output_mode_oct_ptr^ := input_output_mode_oct;
        input_output_mode_oct_ptr^.attribute := attributes [i].input_output_mode;

      = iic$vt_input_editing_mode =
        data_length := data_length + #SIZE (input_editing_mode_oct);
        NEXT input_editing_mode_oct_ptr IN buffer;
        input_editing_mode_oct_ptr^ := input_editing_mode_oct;
        input_editing_mode_oct_ptr^.attribute := attributes [i].input_editing_mode;

      = iic$vt_trans_character_mode =
        data_length := data_length + #SIZE (transp_char_mode_oct);
        NEXT transp_char_mode_oct_ptr IN buffer;
        transp_char_mode_oct_ptr^ := transp_char_mode_oct;
        transp_char_mode_oct_ptr^.attribute := attributes [i].trans_character_mode;

      = iic$vt_trans_forward_character =
        IF attributes [i].trans_forward_character.size = 1 THEN
          data_length := data_length + #SIZE (transp_for_char_single_oct);
          NEXT transp_for_char_single_oct_ptr IN buffer;
          transp_for_char_single_oct_ptr^ := transp_for_char_single_oct;
          transp_for_char_single_oct_ptr^.attribute := attributes [i].trans_forward_character.value;
        ELSE
          data_length := data_length + #SIZE (transp_for_char_mult_oct) +
                attributes [i].trans_forward_character.size;
          NEXT transp_for_char_mult_oct_ptr IN buffer;
          transp_for_char_mult_oct_ptr^ := transp_for_char_mult_oct;
          NEXT string_attribute: [attributes [i].trans_forward_character.size] IN buffer;
          string_attribute^ := attributes [i].trans_forward_character.value;
          transp_for_char_mult_oct_ptr^.octet_number := attributes [i].trans_forward_character.size;
        IFEND;

      = iic$vt_trans_term_character =
        IF attributes [i].trans_terminate_character.size = 1 THEN
          data_length := data_length + #SIZE (transp_term_char_sing_oct);
          NEXT transp_term_char_sing_oct_ptr IN buffer;
          transp_term_char_sing_oct_ptr^ := transp_term_char_sing_oct;
          transp_term_char_sing_oct_ptr^.attribute := attributes [i].trans_terminate_character.value;
        ELSE
          data_length := data_length + #SIZE (transp_term_char_mult_oct) +
                attributes [i].trans_terminate_character.size;
          NEXT transp_term_char_mult_oct_ptr IN buffer;
          transp_term_char_mult_oct_ptr^ := transp_term_char_mult_oct;
          NEXT string_attribute: [attributes [i].trans_terminate_character.size] IN buffer;
          string_attribute^ := attributes [i].trans_terminate_character.value;
          transp_term_char_mult_oct_ptr^.octet_number := attributes [i].trans_terminate_character.size;
        IFEND;

      = iic$vt_trans_timeout_mode =
        data_length := data_length + #SIZE (transp_timeout_mode_oct);
        NEXT transp_timeout_mode_oct_ptr IN buffer;
        transp_timeout_mode_oct_ptr^ := transp_timeout_mode_oct;
        transp_timeout_mode_oct_ptr^.attribute := attributes [i].trans_timeout_mode;

      = iic$vt_trans_length_mode =
        data_length := data_length + #SIZE (transp_len_mode_oct);
        NEXT transp_len_mode_oct_ptr IN buffer;
        transp_len_mode_oct_ptr^ := transp_len_mode_oct;
        transp_len_mode_oct_ptr^.attribute := attributes [i].trans_length_mode;

      = iic$vt_trans_message_length =
        IF attributes [i].trans_message_length <= 255 THEN
          data_length := data_length + #SIZE (transp_mess_len_sing_oct);
          NEXT transp_mess_len_sing_oct_ptr IN buffer;
          transp_mess_len_sing_oct_ptr^ := transp_mess_len_sing_oct;
          transp_mess_len_sing_oct_ptr^.attribute := attributes [i].trans_message_length;
        ELSE
          data_length := data_length + #SIZE (transp_mess_len_mult_oct);
          NEXT transp_mess_len_mult_oct_ptr IN buffer;
          transp_mess_len_mult_oct_ptr^ := transp_mess_len_mult_oct;
          transp_mess_len_mult_oct_ptr^.attribute := attributes [i].trans_message_length;
        IFEND;

      = iic$vt_partial_char_forwarding =
        data_length := data_length + #SIZE (partial_char_forward_oct);
        NEXT partial_char_forward_oct_ptr IN buffer;
        partial_char_forward_oct_ptr^ := partial_char_forward_oct;
        partial_char_forward_oct_ptr^.attribute := attributes [i].partial_char_forwarding;

      = iic$vt_attention_char_action =
        data_length := data_length + #SIZE (atten_char_act_oct);
        NEXT atten_char_act_oct_ptr IN buffer;
        atten_char_act_oct_ptr^ := atten_char_act_oct;
        atten_char_act_oct_ptr^.attribute := attributes [i].attention_character_action;

      = iic$vt_break_key_action =
        data_length := data_length + #SIZE (break_key_action_oct);
        NEXT break_key_action_oct_ptr IN buffer;
        break_key_action_oct_ptr^ := break_key_action_oct;
        break_key_action_oct_ptr^.attribute := attributes [i].break_key_action;

      = iic$vt_input_block_size =
        IF attributes [i].input_block_size <= 255 THEN
          data_length := data_length + #SIZE (input_block_size_sing_oct);
          NEXT input_block_size_sing_oct_ptr IN buffer;
          input_block_size_sing_oct_ptr^ := input_block_size_sing_oct;
          input_block_size_sing_oct_ptr^.attribute := attributes [i].input_block_size;
        ELSE
          data_length := data_length + #SIZE (input_block_size_mult_oct);
          NEXT input_block_size_mult_oct_ptr IN buffer;
          input_block_size_mult_oct_ptr^ := input_block_size_mult_oct;
          input_block_size_mult_oct_ptr^.attribute := attributes [i].input_block_size;
        IFEND;

      = iic$vt_store_nuls_dels =
        data_length := data_length + #SIZE (store_nul_del_oct);
        NEXT store_nul_del_oct_ptr IN buffer;
        store_nul_del_oct_ptr^ := store_nul_del_oct;
        store_nul_del_oct_ptr^.attribute := attributes [i].store_nuls_dels;

      = iic$vt_store_backspace_char =
        data_length := data_length + #SIZE (store_back_char_oct);
        NEXT store_back_char_oct_ptr IN buffer;
        store_back_char_oct_ptr^ := store_back_char_oct;
        store_back_char_oct_ptr^.attribute := attributes [i].store_backspace_character;

      = iic$vt_network_command_char =
        data_length := data_length + #SIZE (network_ctl_char_oct);
        NEXT network_ctl_char_oct_ptr IN buffer;
        network_ctl_char_oct_ptr^ := network_ctl_char_oct;
        network_ctl_char_oct_ptr^.attribute := attributes [i].network_command_character;

      = iic$vt_cancel_line_character =
        data_length := data_length + #SIZE (cancel_line_char_oct);
        NEXT cancel_line_char_oct_ptr IN buffer;
        cancel_line_char_oct_ptr^ := cancel_line_char_oct;
        cancel_line_char_oct_ptr^.attribute := attributes [i].cancel_line_character;

      = iic$vt_end_line_character =
        data_length := data_length + #SIZE (end_line_char_oct);
        NEXT end_line_char_oct_ptr IN buffer;
        end_line_char_oct_ptr^ := end_line_char_oct;
        end_line_char_oct_ptr^.attribute := attributes [i].end_line_character;

      = iic$vt_begin_line_character =
        data_length := data_length + #SIZE (begin_line_char_oct);
        NEXT begin_line_char_oct_ptr IN buffer;
        begin_line_char_oct_ptr^ := begin_line_char_oct;
        begin_line_char_oct_ptr^.attribute := attributes [i].begin_line_character;

      = iic$vt_backspace_character =
        data_length := data_length + #SIZE (backspace_char_oct);
        NEXT backspace_char_oct_ptr IN buffer;
        backspace_char_oct_ptr^ := backspace_char_oct;
        backspace_char_oct_ptr^.attribute := attributes [i].backspace_character;

      = iic$vt_end_partial_character =
        data_length := data_length + #SIZE (end_partial_char_oct);
        NEXT end_partial_char_oct_ptr IN buffer;
        end_partial_char_oct_ptr^ := end_partial_char_oct;
        end_partial_char_oct_ptr^.attribute := attributes [i].end_partial_character;

      = iic$vt_attention_character =
        data_length := data_length + #SIZE (attention_char_oct);
        NEXT attention_char_oct_ptr IN buffer;
        attention_char_oct_ptr^ := attention_char_oct;
        attention_char_oct_ptr^.attribute := attributes [i].attention_character;

      = iic$vt_page_length =
        data_length := data_length + #SIZE (page_length_oct);
        NEXT page_length_oct_ptr IN buffer;
        page_length_oct_ptr^ := page_length_oct;
        page_length_oct_ptr^.attribute := attributes [i].page_length;

      = iic$vt_page_width =
        data_length := data_length + #SIZE (page_width_oct);
        NEXT page_width_oct_ptr IN buffer;
        page_width_oct_ptr^ := page_width_oct;
        page_width_oct_ptr^.attribute := attributes [i].page_width;

      = iic$vt_hold_page =
        data_length := data_length + #SIZE (hold_page_oct);
        NEXT hold_page_oct_ptr IN buffer;
        hold_page_oct_ptr^ := hold_page_oct;
        hold_page_oct_ptr^.attribute := attributes [i].hold_page;

      = iic$vt_hold_page_over =
        data_length := data_length + #SIZE (hold_page_over_oct);
        NEXT hold_page_over_oct_ptr IN buffer;
        hold_page_over_oct_ptr^ := hold_page_over_oct;
        hold_page_over_oct_ptr^.attribute := attributes [i].hold_page_over;

      = iic$vt_fold_line =
        data_length := data_length + #SIZE (fold_line_oct);
        NEXT fold_line_oct_ptr IN buffer;
        fold_line_oct_ptr^ := fold_line_oct;
        fold_line_oct_ptr^.attribute := attributes [i].fold_line;

      = iic$vt_end_output_sequence =
        IF attributes [i].end_output_sequence.size = 1 THEN
          data_length := data_length + #SIZE (end_out_seq_sing_oct);
          NEXT end_out_seq_sing_oct_ptr IN buffer;
          end_out_seq_sing_oct_ptr^ := end_out_seq_sing_oct;
          end_out_seq_sing_oct_ptr^.attribute := attributes [i].end_output_sequence.value;
        ELSE
          data_length := data_length + #SIZE (end_out_seq_mult_oct) + attributes [i].end_output_sequence.size;
          NEXT end_out_seq_mult_oct_ptr IN buffer;
          end_out_seq_mult_oct_ptr^ := end_out_seq_mult_oct;
          NEXT string_attribute: [attributes [i].end_output_sequence.size] IN buffer;
          string_attribute^ := attributes [i].end_output_sequence.value;
          end_out_seq_mult_oct_ptr^.octet_number := attributes [i].end_output_sequence.size;
        IFEND;

      = iic$vt_carriage_return_sequence =
        IF attributes [i].carriage_return_sequence.size = 1 THEN
          data_length := data_length + #SIZE (carr_ret_seq_sing_oct);
          NEXT carr_ret_seq_sing_oct_ptr IN buffer;
          carr_ret_seq_sing_oct_ptr^ := carr_ret_seq_sing_oct;
          carr_ret_seq_sing_oct_ptr^.attribute := attributes [i].carriage_return_sequence.value;
        ELSE
          data_length := data_length + #SIZE (carr_ret_seq_mult_oct) +
                attributes [i].carriage_return_sequence.size;
          NEXT carr_ret_seq_mult_oct_ptr IN buffer;
          carr_ret_seq_mult_oct_ptr^ := carr_ret_seq_mult_oct;
          NEXT string_attribute: [attributes [i].carriage_return_sequence.size] IN buffer;
          string_attribute^ := attributes [i].carriage_return_sequence.value;
          carr_ret_seq_mult_oct_ptr^.octet_number := attributes [i].carriage_return_sequence.size;
        IFEND;

      = iic$vt_line_feed_sequence =
        IF attributes [i].line_feed_sequence.size = 1 THEN
          data_length := data_length + #SIZE (line_feed_seq_sing_oct);
          NEXT line_feed_seq_sing_oct_ptr IN buffer;
          line_feed_seq_sing_oct_ptr^ := line_feed_seq_sing_oct;
          line_feed_seq_sing_oct_ptr^.attribute := attributes [i].line_feed_sequence.value;
        ELSE
          data_length := data_length + #SIZE (line_feed_seq_mult_oct) +
                attributes [i].line_feed_sequence.size;
          NEXT line_feed_seq_mult_oct_ptr IN buffer;
          line_feed_seq_mult_oct_ptr^ := line_feed_seq_mult_oct;
          NEXT string_attribute: [attributes [i].line_feed_sequence.size] IN buffer;
          string_attribute^ := attributes [i].line_feed_sequence.value;
          line_feed_seq_mult_oct_ptr^.octet_number := attributes [i].line_feed_sequence.size;
        IFEND;

      = iic$vt_form_feed_sequence =
        IF attributes [i].form_feed_sequence.size = 1 THEN
          data_length := data_length + #SIZE (form_feed_seq_sing_oct);
          NEXT form_feed_seq_sing_oct_ptr IN buffer;
          form_feed_seq_sing_oct_ptr^ := form_feed_seq_sing_oct;
          form_feed_seq_sing_oct_ptr^.attribute := attributes [i].form_feed_sequence.value;
        ELSE
          data_length := data_length + #SIZE (form_feed_seq_mult_oct) +
                attributes [i].form_feed_sequence.size;
          NEXT form_feed_seq_mult_oct_ptr IN buffer;
          form_feed_seq_mult_oct_ptr^ := form_feed_seq_mult_oct;
          NEXT string_attribute: [attributes [i].form_feed_sequence.size] IN buffer;
          string_attribute^ := attributes [i].form_feed_sequence.value;
          form_feed_seq_mult_oct_ptr^.octet_number := attributes [i].form_feed_sequence.size;
        IFEND;

      = iic$vt_end_page_action =
        data_length := data_length + #SIZE (end_page_action_oct);
        NEXT end_page_action_oct_ptr IN buffer;
        end_page_action_oct_ptr^ := end_page_action_oct;
        end_page_action_oct_ptr^.attribute := attributes [i].end_page_action;

      = iic$vt_carriage_return_delay =
        IF attributes [i].carriage_return_delay <= 255 THEN
          data_length := data_length + #SIZE (carr_ret_delay_sing_oct);
          NEXT carr_ret_delay_sing_oct_ptr IN buffer;
          carr_ret_delay_sing_oct_ptr^ := carr_ret_delay_sing_oct;
          carr_ret_delay_sing_oct_ptr^.attribute := attributes [i].carriage_return_delay;
        ELSE
          data_length := data_length + #SIZE (carr_ret_delay_mult_oct);
          NEXT carr_ret_delay_mult_oct_ptr IN buffer;
          carr_ret_delay_mult_oct_ptr^ := carr_ret_delay_mult_oct;
          carr_ret_delay_mult_oct_ptr^.attribute := attributes [i].carriage_return_delay;
        IFEND;

      = iic$vt_line_feed_delay =
        IF attributes [i].line_feed_delay <= 255 THEN
          data_length := data_length + #SIZE (line_feed_delay_sing_oct);
          NEXT line_feed_delay_sing_oct_ptr IN buffer;
          line_feed_delay_sing_oct_ptr^ := line_feed_delay_sing_oct;
          line_feed_delay_sing_oct_ptr^.attribute := attributes [i].line_feed_delay;
        ELSE
          data_length := data_length + #SIZE (line_feed_delay_mult_oct);
          NEXT line_feed_delay_mult_oct_ptr IN buffer;
          line_feed_delay_mult_oct_ptr^ := line_feed_delay_mult_oct;
          line_feed_delay_mult_oct_ptr^.attribute := attributes [i].line_feed_delay;
        IFEND;

      = iic$vt_form_feed_delay =
        IF attributes [i].form_feed_delay <= 255 THEN
          data_length := data_length + #SIZE (form_feed_delay_sing_oct);
          NEXT form_feed_delay_sing_oct_ptr IN buffer;
          form_feed_delay_sing_oct_ptr^ := form_feed_delay_sing_oct;
          form_feed_delay_sing_oct_ptr^.attribute := attributes [i].form_feed_delay;
        ELSE
          data_length := data_length + #SIZE (form_feed_delay_mult_oct);
          NEXT form_feed_delay_mult_oct_ptr IN buffer;
          form_feed_delay_mult_oct_ptr^ := form_feed_delay_mult_oct;
          form_feed_delay_mult_oct_ptr^.attribute := attributes [i].form_feed_delay;
        IFEND;

      = iic$vt_end_line_positioning =
        data_length := data_length + #SIZE (end_line_position_oct);
        NEXT end_line_position_oct_ptr IN buffer;
        end_line_position_oct_ptr^ := end_line_position_oct;
        end_line_position_oct_ptr^.attribute := attributes [i].end_line_positioning;

      = iic$vt_end_partial_positioning =
        data_length := data_length + #SIZE (end_partial_position_oct);
        NEXT end_partial_position_oct_ptr IN buffer;
        end_partial_position_oct_ptr^ := end_partial_position_oct;
        end_partial_position_oct_ptr^.attribute := attributes [i].end_partial_positioning;

      = iic$vt_character_flow_control =
        data_length := data_length + #SIZE (char_flow_control_oct);
        NEXT char_flow_control_oct_ptr IN buffer;
        char_flow_control_oct_ptr^ := char_flow_control_oct;
        char_flow_control_oct_ptr^.attribute := attributes [i].character_flow_control;

      = iic$vt_function_key_class =
        IF attributes [i].function_key_class.size = 1 THEN
          data_length := data_length + #SIZE (function_key_class_sing_oct);
          NEXT function_key_class_sing_oct_ptr IN buffer;
          function_key_class_sing_oct_ptr^ := function_key_class_sing_oct;
          function_key_class_sing_oct_ptr^.attribute := attributes [i].function_key_class.value;
        ELSE
          data_length := data_length + #SIZE (function_key_class_mult_oct) +
                attributes [i].function_key_class.size;
          NEXT function_key_class_mult_oct_ptr IN buffer;
          function_key_class_mult_oct_ptr^ := function_key_class_mult_oct;
          NEXT string_attribute: [attributes [i].function_key_class.size] IN buffer;
          string_attribute^ := attributes [i].function_key_class.value;
          function_key_class_mult_oct_ptr^.octet_number := attributes [i].function_key_class.size;
        IFEND;

      = iic$vt_terminal_model =
        IF attributes [i].terminal_model.size = 1 THEN
          data_length := data_length + #SIZE (terminal_model_sing_oct);
          NEXT terminal_model_sing_oct_ptr IN buffer;
          terminal_model_sing_oct_ptr^ := terminal_model_sing_oct;
          terminal_model_sing_oct_ptr^.attribute := attributes [i].terminal_model.value;
        ELSE
          data_length := data_length + #SIZE (terminal_model_mult_oct) + attributes [i].terminal_model.size;
          NEXT terminal_model_mult_oct_ptr IN buffer;
          terminal_model_mult_oct_ptr^ := terminal_model_mult_oct;
          NEXT string_attribute: [attributes [i].terminal_model.size] IN buffer;
          string_attribute^ := attributes [i].terminal_model.value;
          terminal_model_mult_oct_ptr^.octet_number := attributes [i].terminal_model.size;
        IFEND;

      = iic$vt_code_set =
        data_length := data_length + #SIZE (code_set_oct);
        NEXT code_set_oct_ptr IN buffer;
        code_set_oct_ptr^ := code_set_oct;
        code_set_oct_ptr^.attribute := attributes [i].code_set;

      = iic$vt_parity =
        data_length := data_length + #SIZE (parity_type_oct);
        NEXT parity_type_oct_ptr IN buffer;
        parity_type_oct_ptr^ := parity_type_oct;
        parity_type_oct_ptr^.attribute := attributes [i].parity;

      = iic$vt_echoplex =
        data_length := data_length + #SIZE (echoplex_oct);
        NEXT echoplex_oct_ptr IN buffer;
        echoplex_oct_ptr^ := echoplex_oct;
        echoplex_oct_ptr^.attribute := attributes [i].echoplex;

      = iic$vt_status_action =
        data_length := data_length + #SIZE (status_action_oct);
        NEXT status_action_oct_ptr IN buffer;
        status_action_oct_ptr^ := status_action_oct;
        status_action_oct_ptr^.attribute := attributes [i].status_action;

      = iic$vt_trans_protocol_mode =
        data_length := data_length + #SIZE (transp_protocol_mode_oct);
        NEXT transp_protocol_mode_oct_ptr IN buffer;
        transp_protocol_mode_oct_ptr^ := transp_protocol_mode_oct;
        transp_protocol_mode_oct_ptr^.attribute := attributes [i].trans_protocol_mode;

      = iic$vt_code_set_name =

          data_length := data_length + #SIZE (code_set_name_oct) + attributes [i].code_set_name.size;
          NEXT code_set_name_oct_ptr IN buffer;
          code_set_name_oct_ptr^ := code_set_name_oct;
          NEXT string_attribute: [attributes [i].code_set_name.size] IN buffer;
          string_attribute^ := attributes [i].code_set_name.value;
          code_set_name_oct_ptr^.octet_number := attributes [i].code_set_name.size + 1;


      = iic$vt_control_code_replacement =
        IF attributes [i].control_code_replacement.
          total_substitution_count <= 63 THEN
          IF attributes [i].control_code_replacement.
            total_substitution_count <> 0 THEN
            data_length := data_length + #SIZE (control_code_rep_mult_oct) +
              2 * attributes [i].control_code_replacement.
              total_substitution_count;
            NEXT control_code_rep_mult_oct_ptr IN buffer;
            control_code_rep_mult_oct_ptr^ := control_code_rep_mult_oct;
            control_code_rep_mult_oct_ptr^.octet_number := 2 *
              attributes [i].control_code_replacement.total_substitution_count;
            NEXT control_code_replacement_value:
              [1..attributes [i].control_code_replacement.
              total_substitution_count] IN buffer;
            FOR j := 1 TO attributes [i].control_code_replacement.
              total_substitution_count DO
                control_code_replacement_value^[j].original_control_code :=
                  attributes[i].control_code_replacement.value[j].
                  original_control_code;
                control_code_replacement_value^[j].substitute_control_code :=
                  attributes[i].control_code_replacement.value[j].
                  substitute_control_code;
            FOREND;
          ELSE
            data_length := data_length + #SIZE (control_code_rep_none_oct);
            NEXT control_code_rep_none_oct_ptr IN buffer;
            control_code_rep_none_oct_ptr^ := control_code_rep_none_oct;
          IFEND;
        ELSE
          data_length := data_length + #SIZE (control_code_rep_ext_oct) +
            2 * attributes [i].control_code_replacement.
            total_substitution_count;
          NEXT control_code_rep_ext_oct_ptr IN buffer;
          control_code_rep_ext_oct_ptr^ := control_code_rep_ext_oct;
            control_code_rep_ext_oct_ptr^.octet_number := 2 * attributes[i].
              control_code_replacement.total_substitution_count;
          NEXT control_code_replacement_value:
            [1..attributes [i].control_code_replacement.
            total_substitution_count] IN buffer;
          FOR j := 1 TO attributes [i].control_code_replacement.
            total_substitution_count DO
              control_code_replacement_value^[j].original_control_code :=
                attributes[i].control_code_replacement.value[j].
                original_control_code;
              control_code_replacement_value^[j].substitute_control_code :=
                attributes[i].control_code_replacement.value[j].
                substitute_control_code;
          FOREND;
        IFEND;

      ELSE
        {}
      CASEND;
    FOREND;


  PROCEND iip$vt_create_attribute_octets;

?? TITLE := '[XDCL] iip$vt_change_attributes', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_change_attributes
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         attributes: iit$vt_attributes;
         wait: ost$wait;
     VAR activity_status: ost$activity_status;
     VAR status: ost$status);

    VAR
      data: array [1 .. 1] of nat$data_fragment,
      local_file_name: amt$local_file_name;

    VAR
      buffer: ^SEQ ( * ),
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      data_length: nat$data_length,
      data_ptr: ^cell,
      send_change_header: [STATIC, READ, oss$job_paged_literal] iit$vt_message_types :=
        iic$vt_change_attributes,
      send_change_header_ptr: ^iit$vt_message_types;


    status.normal := TRUE;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid, ordinal_char, status);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      buffer := connection^.output_buffer;
      data [1].address := buffer;
      data [1].length := #SIZE (send_change_header);
      RESET buffer;
      NEXT send_change_header_ptr IN buffer;
      send_change_header_ptr^ := send_change_header;
      iip$vt_create_attribute_octets (attributes, buffer, data [1].length);
      WHILE connection^.change.head <> NIL DO
        remove_queue_entry (iic$vt_change, vtp_connection_id, status);
      WHILEND;
      nap$se_send_data (file_identifier, data, TRUE {EOM} , FALSE {not qualified data} , wait,
            activity_status, status);
    IFEND;

  PROCEND iip$vt_change_attributes;

?? TITLE := '[XDCL] iip$vt_check_data_available', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_check_data_available
    (    file_identifier: amt$file_identifier;
     VAR activity_complete: boolean;
     VAR status: ost$status);

    VAR
      file_id_is_valid: boolean,
      file_instance: ^bat$task_file_entry,
      st_open_file_dsc_pointer: ^iit$st_open_file_description;

    activity_complete := false;
*copy bai$validate_file_identifier
*copy iii$fetch_st_open_file_desc_ptr
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF st_open_file_dsc_pointer^.vtp_connection_id.connection^.input.head
         <> NIL THEN
      activity_complete := true;
      RETURN;
    ELSEIF jmp$is_xterm_job () THEN

{ Check for message from the xterm task that communicates with the X terminal.

      iip$xt_check_upline (st_open_file_dsc_pointer^.vtp_file_id,
           activity_complete, status);

    ELSE { This is a timesharing job.
      nap$check_data_available (st_open_file_dsc_pointer^.vtp_file_id,
        activity_complete,status);
    IFEND;

  PROCEND iip$vt_check_data_available;
?? TITLE := '[XDCL] iip$vt_close', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_close
    (    file_identifier: amt$file_identifier;
     VAR status: ost$status);


    amp$close (file_identifier, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;


  PROCEND iip$vt_close;
?? TITLE := '[XDCL] iip$vt_flush_input', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_flush_input
    (    vtp_connection_id: iit$vtp_connection_id;
     VAR status: ost$status);

    VAR
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection;

    status.normal := TRUE;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_already_closed, '', status);
      RETURN;
    ELSE

      WHILE connection^.input.head <> NIL DO
        remove_queue_entry (iic$vt_input, vtp_connection_id, status);
      WHILEND;

      WHILE connection^.output.head <> NIL DO
        remove_queue_entry (iic$vt_output, vtp_connection_id, status);
      WHILEND;

    IFEND;

  PROCEND iip$vt_flush_input;

?? TITLE := '[XDCL] iip$vt_get_attr_ch_indications', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_get_attr_ch_indications
    (    vtp_connection_id: iit$vtp_connection_id;
     VAR attributes: iit$vt_attributes;
     VAR number_of_attributes: 0 .. iic$vt_max_number_of_attributes;
     VAR status: ost$status);

    VAR
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      local_file_name: amt$local_file_name,
      message_type: ^iit$vt_message_types,
      query_response: ^SEQ ( * ),
      start_of_octets: ^SEQ ( * ),
      transfer_count: nat$data_length,
      vtp_buffer: ^SEQ ( * );

    status.normal := TRUE;
    connection := vtp_connection_id.connection;

    IF connection = NIL THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      number_of_attributes := 0;
      IF connection^.indications.head <> NIL THEN
        vtp_buffer := connection^.indications.head^.vtp_buffer;
        RESET vtp_buffer;
        transfer_count := connection^.indications.head^.q_header.transfer_length;
        NEXT query_response: [[REP transfer_count OF cell]] IN vtp_buffer;
        RESET query_response;
        NEXT message_type IN query_response;
        IF queue_type_from_message [message_type^] = iic$vt_indications THEN
          iip$vt_externalize_octets (query_response, attributes, number_of_attributes);
        IFEND;
        remove_queue_entry (iic$vt_indications, vtp_connection_id, status);
      IFEND;
    IFEND;

  PROCEND iip$vt_get_attr_ch_indications;
?? TITLE := '[XDCL] iip$vt_get_change_response', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_get_change_response
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         wait: ost$wait;
     VAR error_code: iit$vt_change_error_codes;
     VAR attribute_error_pairs: array [1 .. 2] of iit$vt_attribute;
     VAR response_received: boolean;
     VAR status: ost$status);


    VAR
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      end_of_message: boolean,
      extra_status: ost$status,
      input: iit$vt_input_information,
      local_file_name: amt$local_file_name,
      queue_entry: ^iit$vt_queue_entry,
      transfer_count: nat$data_length,
      timeout: iit$vt_timeout,
      vtp_buffer: ^SEQ ( * );

?? NEWTITLE := '  EXTERNALIZE_CHANGE', EJECT ??

    PROCEDURE externalize_change
      (VAR vtp_buffer: ^SEQ ( * );
       VAR error_code: iit$vt_change_error_codes;
       VAR attribute_error_pairs: iit$vt_attributes;
       VAR status: ost$status);

      VAR
        error: ^iit$vt_change_error_codes,
        message_type: ^iit$vt_message_types,
        number_of_octets: 0 .. iic$vt_max_number_of_attributes;


      NEXT message_type IN vtp_buffer;
      IF message_type = NIL THEN
        RETURN;
      IFEND;
      IF message_type^ = iic$vt_change_attribute_confirm THEN
        status.normal := TRUE;
      ELSE
        IF message_type^ = iic$vt_change_attributes_reject THEN
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_change_attributes_error, '', status);
          NEXT error IN vtp_buffer;
          IF error = NIL THEN
            RETURN;
          IFEND;
          error_code := error^;
          iip$vt_externalize_octets (vtp_buffer, attribute_error_pairs, number_of_octets);
        ELSE
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_incorrect_entry_on_queue, '', status);
          RETURN;
        IFEND;
      IFEND;


    PROCEND externalize_change;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid, ordinal_char, status);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      queue_entry := connection^.change.head;
      response_received := FALSE;
      IF queue_entry <> NIL THEN
        vtp_buffer := queue_entry^.vtp_buffer;
        RESET vtp_buffer;
        externalize_change (vtp_buffer, error_code, attribute_error_pairs, status);
        extra_status.normal := TRUE;
        remove_queue_entry (iic$vt_change, vtp_connection_id, extra_status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF NOT extra_status.normal THEN
          status := extra_status;
          RETURN;
        IFEND;
        response_received := TRUE;
      ELSE
        vtp_buffer := connection^.input_buffer;
        RESET vtp_buffer; {gkc}
        timeout. ON := TRUE;
        timeout.length := 12000;
        timeout.purge := FALSE;
        get_next_special_block (vtp_connection_id, file_identifier, iic$vt_change, vtp_buffer,
              iic$vt_max_transfer_length, wait, timeout, response_received, end_of_message, transfer_count,
              input, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF response_received THEN
          externalize_change (vtp_buffer, error_code, attribute_error_pairs, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND iip$vt_get_change_response;
?? TITLE := '[XDCL] iip$vt_get_query_response', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_get_query_response
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         wait: ost$wait;
     VAR confirmed: boolean;
     VAR attributes: iit$vt_attributes;
     VAR unknown_attribute_number: iit$vt_attribute_kind;
     VAR response_received: boolean;
     VAR status: ost$status);

    VAR
      end_of_message: boolean,
      extra_status: ost$status,
      timeout: iit$vt_timeout,
      queue_entry: ^iit$vt_queue_entry,
      query_response: ^SEQ ( * ),
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      local_file_name: amt$local_file_name,
      transfer_count: nat$data_length,
      vtp_buffer: ^SEQ ( * ),
      input: iit$vt_input_information;

?? NEWTITLE := '  EXTERNALIZE_QUERY', EJECT ??

    PROCEDURE externalize_query
      (VAR query_response: ^SEQ ( * );
       VAR confirmed: boolean;
       VAR attributes: iit$vt_attributes;
       VAR unknown_attribute_number: iit$vt_attribute_kind;
       VAR status: ost$status);

      VAR
        message_type: ^iit$vt_message_types,
        attribute_number: ^iit$vt_attribute_kind,
        number_of_octets: 0 .. iic$vt_max_number_of_attributes;


      NEXT message_type IN query_response;
      IF message_type = NIL THEN
        RETURN;
      IFEND;
      confirmed := message_type^ = iic$vt_query_attributes_confirm;
      IF confirmed THEN
        iip$vt_externalize_octets (query_response, attributes, number_of_octets);
      ELSE
        IF message_type^ = iic$vt_query_attributes_reject THEN
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$unknown_attribute_key, '', status);
          NEXT attribute_number IN query_response;
          IF attribute_number = NIL THEN
            RETURN;
          IFEND;
          unknown_attribute_number := attribute_number^;
          osp$append_status_integer (osc$status_parameter_delimiter, $INTEGER (unknown_attribute_number), 10,
                FALSE, status)
        ELSE
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_incorrect_entry_on_queue, '', status);
        IFEND;
      IFEND;


    PROCEND externalize_query;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    connection := vtp_connection_id.connection;

    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid, ordinal_char, status);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      queue_entry := connection^.status.head;
      confirmed := FALSE;
      response_received := FALSE;
      IF queue_entry <> NIL THEN
        vtp_buffer := queue_entry^.vtp_buffer;
        RESET vtp_buffer;
        transfer_count := queue_entry^.q_header.transfer_length;
        NEXT query_response: [[REP transfer_count OF cell]] IN vtp_buffer;
        IF query_response = NIL THEN
          RETURN;
        IFEND;
        RESET query_response;
        externalize_query (query_response, confirmed, attributes, unknown_attribute_number, status);
        extra_status.normal := TRUE;
        remove_queue_entry (iic$vt_status, vtp_connection_id, extra_status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF NOT extra_status.normal THEN
          status := extra_status;
          RETURN;
        IFEND;
        response_received := TRUE;
      ELSE
        vtp_buffer := connection^.input_buffer;
        RESET vtp_buffer; {gkc}
        timeout. ON := TRUE;
        timeout.length := 12000;
        timeout.purge := FALSE;
        get_next_special_block (vtp_connection_id, file_identifier, iic$vt_status, vtp_buffer,
              iic$vt_max_transfer_length, wait, timeout, response_received, end_of_message, transfer_count,
              input, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF response_received THEN
          NEXT query_response: [[REP transfer_count OF cell]] IN vtp_buffer;
          IF query_response = NIL THEN
            RETURN;
          IFEND;
          RESET query_response;
          externalize_query (query_response, confirmed, attributes, unknown_attribute_number, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND iip$vt_get_query_response;
?? TITLE := '[XDCL] iip$vt_initialize_connection', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_initialize_connection
    (VAR vtp_connection_id: iit$vtp_connection_id;
     VAR status: ost$status);

    VAR
      new_connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection;

    ALLOCATE new_connection IN osv$task_shared_heap^; { job_pageable }
    new_connection^.input.head := NIL;
    new_connection^.input.offset := 0;
    new_connection^.output.head := NIL;
    new_connection^.change.head := NIL;
    new_connection^.status.head := NIL;
    new_connection^.indications.head := NIL;

    ALLOCATE new_connection^.input_buffer: [[REP iic$vt_max_transfer_length OF cell]] IN
          osv$task_shared_heap^; { job_pageable }
    ALLOCATE new_connection^.output_buffer: [[REP iic$vt_max_output_mess_length OF cell]] IN
          osv$task_shared_heap^; { job_pageable }
          vtp_connection_id.connection := new_connection;

  PROCEND iip$vt_initialize_connection;
?? TITLE := '[XDCL] iip$vt_input', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_input
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         buffer_ptr: ^cell;
         buffer_length: nat$data_length;
         timeout: iit$vt_timeout;
     VAR message_received: boolean;
     VAR end_of_message: boolean;
     VAR transfer_count: nat$data_length;
     VAR input_information: iit$vt_input_information;
     VAR status: ost$status);

    VAR
      wait: ost$wait,
      offset: 0 .. iic$vt_max_transfer_length - 1,
      file_id_is_valid: boolean,
      vtp_buffer: ^iit$vt_ibs_buffer_hold,
      local_file_name: amt$local_file_name,
      message_type: ^iit$vt_message_types,
      input: ^iit$vt_input_information,
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      vtp_buffer_data: ^cell,
      queue_entry: ^iit$vt_queue_entry;

    #KEYPOINT (osk$entry, 0, iik$vt_input);

    end_of_message := TRUE;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid,
              ordinal_char (1, char_length), status);
        #KEYPOINT (osk$exit, 0, iik$vt_input);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      queue_entry := connection^.input.head;
      offset := connection^.input.offset;
      IF queue_entry <> NIL THEN
        message_received := TRUE;
        vtp_buffer := queue_entry^.vtp_buffer;
        RESET vtp_buffer;
        NEXT input IN vtp_buffer;
        input_information := input^;
        IF (queue_entry^.q_header.transfer_length - (iic$vt_header_length_input + offset)) >= 0 THEN
          transfer_count := queue_entry^.q_header.transfer_length - (iic$vt_header_length_input + offset);
        ELSE
          transfer_count := 0;
        IFEND;
        vtp_buffer_data := i#ptr (iic$vt_header_length_input + offset, ^vtp_buffer^);
        IF (buffer_length <= 0) OR (buffer_length >= transfer_count) OR (input_information.cancel) THEN
          IF transfer_count > 0 THEN
            IF transfer_count > buffer_length THEN
              transfer_count := buffer_length;
            IFEND;
            IF transfer_count > 0 THEN
              i#move (vtp_buffer_data, buffer_ptr, transfer_count);
            IFEND;
          IFEND;
          remove_queue_entry (iic$vt_input, vtp_connection_id, status);
        ELSE
          transfer_count := buffer_length;
          i#move (vtp_buffer_data, buffer_ptr, transfer_count);
          connection^.input.offset := offset + buffer_length;
          end_of_message := FALSE;
        IFEND;

      ELSE
        wait := osc$wait;
        get_next_special_block (vtp_connection_id, file_identifier, iic$vt_input, buffer_ptr, buffer_length,
              wait, timeout, message_received, end_of_message, transfer_count, input_information, status);
      IFEND;
    IFEND;

    #KEYPOINT (osk$exit, 0, iik$vt_input);

  PROCEND iip$vt_input;
?? TITLE := '[XDCL] iip$vt_open', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_open
    (    lfn: amt$local_file_name;
     VAR file_identifier: amt$file_identifier;
     VAR status: ost$status);

    VAR
      access_selections: [STATIC, READ, oss$job_paged_literal] array [1 .. 1] of amt$access_selection :=
            [[amc$ring_attributes, [3, 3, 3]]];

{ Every task running in an xterm job needs to open a downline and
{ an upline message file.  The task sends output on the downline message file
{ to the xterm task.  The task receives input from the xterm task on
{ the upline message file.

    IF jmp$is_xterm_job () THEN
      IF NOT iiv$xt_xterm_downline.opened THEN
        iip$xt_open_downline_messages (iiv$xt_xterm_downline.file_identifier,
         iiv$xt_xterm_downline.segment_pointer, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        iiv$xt_xterm_downline.opened := TRUE;
      IFEND;

      IF NOT iiv$xt_xterm_upline.opened THEN
        iip$xt_open_upline_messages (iiv$xt_xterm_upline.file_identifier,
         iiv$xt_xterm_upline.segment_pointer, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        iiv$xt_xterm_upline.opened := TRUE;
      IFEND;
    IFEND;

    amp$open (lfn, amc$record, ^access_selections, file_identifier, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND iip$vt_open;

?? TITLE := '[XDCL] iip$vt_output', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_output
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         data: nat$data_fragments;
         output_information: iit$vt_output_information;
         wait: ost$wait;
     VAR activity_status: ost$activity_status;
     VAR status: ost$status);

    VAR

      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      data_hold: ^array [1 .. * ] of nat$data_fragment,
      file_id_is_valid: boolean,
      i: 1 .. nac$max_data_fragment_count,
      local_file_name: amt$local_file_name,
      local_status: ost$status,
      output_information_hold: iit$vt_output_information,
      ready_index: integer,
      wait_complete: boolean,
      wait_list: array [1 .. 2] of ost$i_activity;

    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid,
              ordinal_char (1, char_length), status);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE

      PUSH data_hold: [1 .. UPPERBOUND (data) + 1];
      output_information_hold := output_information;
      output_information_hold.message_type := iic$vt_output_data_message;
      data_hold^ [1].address := ^output_information_hold;
      data_hold^ [1].length := #SIZE (output_information_hold);
      FOR i := 1 TO UPPERBOUND (data) DO
        data_hold^ [i + 1] := data [i];
      FOREND;
      nap$se_send_data (file_identifier, data_hold^, TRUE {eom} , FALSE {not qualified} , wait,
            activity_status, status);
      IF (wait = osc$nowait) AND NOT activity_status.complete THEN
        wait_list [1].activity := osc$i_await_time;
        wait_list [1].milliseconds := iiv$terminal_timeout_limit;
        wait_list [2].activity := nac$i_await_activity_status;
        wait_list [2].activity_status := ^activity_status;
        osp$i_await_activity (wait_list, ready_index, wait_complete, local_status)
      IFEND;
    IFEND;


  PROCEND iip$vt_output;
?? TITLE := '[XDCL] iip$vt_query_attributes', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_query_attributes
    (    vtp_connection_id: iit$vtp_connection_id;
         file_identifier: amt$file_identifier;
         attribute_kinds: iit$vt_attribute_kinds;
         wait: ost$wait;
     VAR activity_status: ost$activity_status;
     VAR status: ost$status);

    VAR
      buffer: ^SEQ ( * ),
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      kinds_ptr: ^iit$vt_attribute_kinds,
      local_file_name: amt$local_file_name,
      query_attributes_header: [STATIC, READ, oss$job_paged_literal] iit$vt_message_types :=
        iic$vt_query_attributes,
      query_attributes_header_ptr: ^iit$vt_message_types,
      data: array [1 .. 1] of nat$data_fragment,
      i: integer,
      attribute_kind_ptr: ^iit$vt_attribute_kind;

    status.normal := TRUE;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      iip$vt_validate_file_identifier (file_identifier, local_file_name, file_id_is_valid);
      IF NOT file_id_is_valid THEN
        STRINGREP (ordinal_char, char_length, file_identifier.ordinal);
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid, ordinal_char, status);
        RETURN;
      IFEND;
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
    ELSE
      data [1].length := #SIZE (query_attributes_header) + #SIZE (attribute_kinds);
      PUSH buffer: [[REP data [1].length OF cell]];
      data [1].address := buffer;
      RESET buffer;
      NEXT query_attributes_header_ptr IN buffer;
      query_attributes_header_ptr^ := query_attributes_header;
      NEXT kinds_ptr: [1 .. UPPERBOUND (attribute_kinds)] IN buffer;
      kinds_ptr^ := attribute_kinds;
      WHILE connection^.status.head <> NIL DO
        remove_queue_entry (iic$vt_status, vtp_connection_id, status);
      WHILEND;
      nap$se_send_data (file_identifier, data, TRUE {EOM} , FALSE {not qualified data} , wait,
            activity_status, status);
    IFEND;

  PROCEND iip$vt_query_attributes;
?? TITLE := '[XDCL] iip$vt_terminate_connection', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$vt_terminate_connection
    (VAR vtp_connection_id: iit$vtp_connection_id;
     VAR status: ost$status);


    IF vtp_connection_id.connection = NIL THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_already_closed, '', status);
      RETURN;
    ELSE

      WHILE vtp_connection_id.connection^.input.head <> NIL DO
        remove_queue_entry (iic$vt_input, vtp_connection_id, status);
      WHILEND;

      WHILE vtp_connection_id.connection^.output.head <> NIL DO
        remove_queue_entry (iic$vt_output, vtp_connection_id, status);
      WHILEND;

      WHILE vtp_connection_id.connection^.change.head <> NIL DO
        remove_queue_entry (iic$vt_change, vtp_connection_id, status);
      WHILEND;

      WHILE vtp_connection_id.connection^.status.head <> NIL DO
        remove_queue_entry (iic$vt_status, vtp_connection_id, status);
      WHILEND;

      WHILE vtp_connection_id.connection^.indications.head <> NIL DO
        remove_queue_entry (iic$vt_indications, vtp_connection_id, status);
      WHILEND;

      IF vtp_connection_id.connection^.input_buffer = NIL THEN
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_input_buffer_not_found, '', status);
        return;
      ELSE
        FREE vtp_connection_id.connection^.input_buffer IN osv$task_shared_heap^; { job_pageable }
      IFEND;


      IF vtp_connection_id.connection^.output_buffer = NIL THEN
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_output_buffer_not_found, '', status);
        return;
      ELSE
        FREE vtp_connection_id.connection^.output_buffer IN osv$task_shared_heap^; { job_pageable }
      IFEND;
      FREE vtp_connection_id.connection IN osv$task_shared_heap^; { job_pageable }

    IFEND;


  PROCEND iip$vt_terminate_connection;
?? TITLE := ' debug_log', EJECT ??

  PROCEDURE debug_log
    (    str: string ( * ));

    VAR
      ignore_status: ost$status;

    ignore_status.normal := TRUE;
    pmp$log_ascii (str, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_program,
          ignore_status);

  PROCEND debug_log;
?? TITLE := ' debug_log', EJECT ??

  PROCEDURE debug_status
    (    status: ost$status);

    VAR
      ignore_status: ost$status,
      length_pointer: ^ost$status_message_line_size,
      line_count_pointer: ^ost$status_message_line_count,
      line_index: ost$status_message_line_count,
      message: ost$status_message,
      message_sequence: ^SEQ ( * ),
      text_pointer: ^string ( * );

    osp$format_message (status, osc$full_message_level, osc$max_status_message_line, message, ignore_status);
    message_sequence := ^message;
    RESET message_sequence;
    NEXT line_count_pointer IN message_sequence;
    FOR line_index := 1 TO line_count_pointer^ DO
      NEXT length_pointer IN message_sequence;
      NEXT text_pointer: [length_pointer^] IN message_sequence;
      debug_log (text_pointer^);
    FOREND;

  PROCEND debug_status;
?? TITLE := '  IIP$VT_EXTERNALIZE_OCTETS', EJECT ??

  PROCEDURE [XDCL] iip$vt_externalize_octets
    (    octets: ^SEQ ( * );
     VAR attributes: iit$vt_attributes;
     VAR number_of_attributes: 0 .. iic$vt_max_number_of_attributes);

  { Purpose: Initialize an iit$vt_attributes array from a sequence of octets.
  {
  { Design:   All octets pertaining to a particular attribute are used
  {           to construct an element in the iit$vt_attributes array.
  {           This array is returned to the caller as well as the number
  {           of elements in the array.  The procedure returns when it
  {           has seen the last octet and created an attribute for it.

    VAR
      octets_hold: ^SEQ ( * ),
      ptr: ^SEQ ( * ),
      j: 0 .. iic$vt_max_number_of_attributes,
      octet_found: boolean,
      attribute: iit$vt_attribute;

      {The following subranges of integer must exactly fill one byte.}

    VAR
      octet_length:  ^packed record
        multiple_attribute_length_octet: boolean,
        fill_0: 0..0EE(16),
        attribute_length_octet_number: 1 .. 2,
      recend,
      octet_number_mult: ^0 .. ifc$total_substitution_count * 2,
      number_of_octets: ^packed record
        multiple_octet: boolean,
        number: 0..127,
      recend,
      number: 0 .. 127;

    VAR
      octet_header: ^iit$vt_octet_header,
      attribute_kind: iit$vt_attribute_kind,
      char_string: ^string ( * ),
      int: ^0 .. 0ffff(16),
      bool: ^boolean;

    VAR
      input_output_mode: ^ift$input_output_mode,
      input_editing_mode: ^ift$input_editing_mode,
      transp_char_mode: ^ift$trans_character_mode,
      transp_protocol_mode: ^ift$trans_protocol_mode,
      transp_timeout_mode: ^ift$trans_timeout_mode,
      transp_len_mode: ^ift$trans_length_mode,
      atten_char_act: ^ift$attention_character_action,
      break_key_action: ^ift$break_key_action,
      input_block_size: ^ift$input_block_size,
      page_length: ^ift$page_length,
      page_width: ^ift$page_width,
      end_page_action: ^ift$end_page_action,
      carr_ret_delay: ^ift$carriage_return_delay,
      line_feed_delay: ^ift$line_feed_delay,
      form_feed_delay: ^ift$form_feed_delay,
      end_line_position: ^ift$end_line_positioning,
      end_partial_position: ^ift$end_partial_positioning,
      code_set: ^ift$code_set,
      code_set_name: ^ift$code_set_name,
      control_code_replacement: ^ift$control_code_replacement,
      control_code_replacement_value: ^array [1 .. *]
        OF ift$control_code_rep_char,
      parity_type: ^ift$parity,
      single_octet_ptr: ^0 .. 0ff(16),  { For NEXTs of multiple-byte types but single-byte values. }
      status_action: ^ift$status_action;


    number_of_attributes := 0;
    octets_hold := octets;

  /parse_responses/
    FOR j := 1 TO UPPERBOUND (attributes) DO
      NEXT octet_header IN octets_hold;
      IF octet_header = NIL THEN
        octet_found := FALSE;
        EXIT /parse_responses/;
      ELSE
        octet_found := TRUE;
      IFEND;
      IF octet_header^.multiple_octet THEN
        NEXT number_of_octets IN octets_hold;
        IF number_of_octets = NIL THEN
          octet_found := FALSE;
          EXIT /parse_responses/;
        IFEND;
        IF number_of_octets^.multiple_octet = FALSE THEN
          number := number_of_octets^.number;
        ELSE
          RESET octets_hold TO number_of_octets;
          NEXT octet_length IN octets_hold;
          NEXT octet_number_mult IN octets_hold;
          number := octet_number_mult^;
        IFEND;
      ELSE
        number := 1;
      IFEND;
      attribute.kind := octet_header^.kind;
      CASE octet_header^.kind OF

      = iic$vt_input_output_mode =
        NEXT input_output_mode IN octets_hold;
        IF input_output_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.input_output_mode := input_output_mode^;

      = iic$vt_input_editing_mode =
        NEXT input_editing_mode IN octets_hold;
        IF input_editing_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.input_editing_mode := input_editing_mode^;

      = iic$vt_trans_character_mode =
        NEXT transp_char_mode IN octets_hold;
        IF transp_char_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.trans_character_mode := transp_char_mode^;

      = iic$vt_trans_forward_character =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.trans_forward_character.value := char_string^;
        IFEND;
        attribute.trans_forward_character.size := number;

      = iic$vt_trans_term_character =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.trans_terminate_character.value := char_string^;
        IFEND;
        attribute.trans_terminate_character.size := number;

      = iic$vt_trans_timeout_mode =
        NEXT transp_timeout_mode IN octets_hold;
        IF transp_timeout_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.trans_timeout_mode := transp_timeout_mode^;

      = iic$vt_trans_length_mode =
        NEXT transp_len_mode IN octets_hold;
        IF transp_len_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.trans_length_mode := transp_len_mode^;

      = iic$vt_trans_message_length =
        IF number > 1 THEN
          NEXT int IN octets_hold;
          IF int = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.trans_message_length := int^;
        ELSEIF number = 1 THEN
          NEXT single_octet_ptr IN octets_hold;
          IF single_octet_ptr = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.trans_message_length := single_octet_ptr^;
        IFEND;

      = iic$vt_partial_char_forwarding =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.partial_char_forwarding := bool^;

      = iic$vt_attention_char_action =
        NEXT atten_char_act IN octets_hold;
        IF atten_char_act = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.attention_character_action := atten_char_act^;

      = iic$vt_break_key_action =
        NEXT break_key_action IN octets_hold;
        IF break_key_action = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.break_key_action := break_key_action^;

      = iic$vt_input_block_size =
        IF number > 1 THEN
          NEXT input_block_size IN octets_hold;
          IF input_block_size = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.input_block_size := input_block_size^;
        ELSEIF number = 1 THEN
          NEXT single_octet_ptr IN octets_hold;
          IF single_octet_ptr = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.input_block_size := single_octet_ptr^;
        IFEND;

      = iic$vt_store_nuls_dels =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.store_nuls_dels := bool^;

      = iic$vt_store_backspace_char =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.store_backspace_character := bool^;

      = iic$vt_network_command_char =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.network_command_character := char_string^ (1);

      = iic$vt_cancel_line_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.cancel_line_character := char_string^ (1);

      = iic$vt_end_line_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.end_line_character := char_string^ (1);

      = iic$vt_begin_line_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.begin_line_character := char_string^ (1);

      = iic$vt_backspace_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.backspace_character := char_string^ (1);

      = iic$vt_end_partial_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.end_partial_character := char_string^ (1);

      = iic$vt_attention_character =
        IF number = 0 THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        NEXT char_string: [number] IN octets_hold;
        IF char_string = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.attention_character := char_string^ (1);

      = iic$vt_page_length =
        NEXT page_length IN octets_hold;
        IF page_length = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.page_length := page_length^;

      = iic$vt_page_width =
        NEXT page_width IN octets_hold;
        IF page_width = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.page_width := page_width^;

      = iic$vt_hold_page =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.hold_page := bool^;

      = iic$vt_hold_page_over =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.hold_page_over := bool^;

      = iic$vt_fold_line =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.fold_line := bool^;

      = iic$vt_end_output_sequence =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.end_output_sequence.value := char_string^;
        IFEND;
        attribute.end_output_sequence.size := number;

      = iic$vt_carriage_return_sequence =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.carriage_return_sequence.value := char_string^;
        IFEND;
        attribute.carriage_return_sequence.size := number;

      = iic$vt_line_feed_sequence =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.line_feed_sequence.value := char_string^;
        IFEND;
        attribute.line_feed_sequence.size := number;

      = iic$vt_form_feed_sequence =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.form_feed_sequence.value := char_string^;
        IFEND;
        attribute.form_feed_sequence.size := number;

      = iic$vt_end_page_action =
        NEXT end_page_action IN octets_hold;
        IF end_page_action = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.end_page_action := end_page_action^;

      = iic$vt_carriage_return_delay =
        IF number > 1 THEN
          NEXT carr_ret_delay IN octets_hold;
          IF carr_ret_delay = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.carriage_return_delay := carr_ret_delay^;
        ELSEIF number = 1 THEN
          NEXT single_octet_ptr IN octets_hold;
          IF single_octet_ptr = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.carriage_return_delay := single_octet_ptr^;
        IFEND;

      = iic$vt_line_feed_delay =
        IF number > 1 THEN
          NEXT line_feed_delay IN octets_hold;
          IF line_feed_delay = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.line_feed_delay := line_feed_delay^;
        ELSEIF number = 1 THEN
          NEXT single_octet_ptr IN octets_hold;
          IF single_octet_ptr = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.line_feed_delay := single_octet_ptr^;
        IFEND;

      = iic$vt_form_feed_delay =
        IF number > 1 THEN
          NEXT form_feed_delay IN octets_hold;
          IF form_feed_delay = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.form_feed_delay := form_feed_delay^;
        ELSEIF number = 1 THEN
          NEXT single_octet_ptr IN octets_hold;
          IF single_octet_ptr = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.form_feed_delay := single_octet_ptr^;
        IFEND;

      = iic$vt_end_line_positioning =
        NEXT end_line_position IN octets_hold;
        IF end_line_position = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.end_line_positioning := end_line_position^;

      = iic$vt_end_partial_positioning =
        NEXT end_partial_position IN octets_hold;
        IF end_partial_position = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.end_partial_positioning := end_partial_position^;

      = iic$vt_character_flow_control =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.character_flow_control := bool^;

      = iic$vt_function_key_class =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.function_key_class.value := char_string^;
        IFEND;
        IF number > 0 THEN
          attribute.function_key_class.size := number;
        ELSE
          attribute.function_key_class.size := 1;
          attribute.function_key_class.value := ' ';
        IFEND;

      = iic$vt_terminal_model =
        IF number > 0 THEN
          NEXT char_string: [number] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.terminal_model.value := char_string^;
        IFEND;
        IF number > 0 THEN
          attribute.terminal_model.size := number;
        ELSE
          attribute.terminal_model.size := 1;
          attribute.terminal_model.value := ' ';
        IFEND;

      = iic$vt_code_set =
        IF number = 1 THEN
          NEXT code_set IN octets_hold;
          IF code_set = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.code_set := code_set^;
        ELSE

          NEXT code_set IN octets_hold;
          NEXT char_string: [number-1] IN octets_hold;
          IF char_string = NIL THEN
            octet_found := FALSE;
            RETURN;
          IFEND;
          attribute.code_set_name.size := number;
          attribute.code_set_name.value := char_string^;
          attribute.kind := iic$vt_code_set_name;
        IFEND;

      = iic$vt_parity =
        NEXT parity_type IN octets_hold;
        IF parity_type = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.parity := parity_type^;

      = iic$vt_echoplex =
        NEXT bool IN octets_hold;
        IF bool = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.echoplex := bool^;

      = iic$vt_status_action =
        NEXT status_action IN octets_hold;
        IF status_action = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.status_action := status_action^;

      = iic$vt_trans_protocol_mode =
        NEXT transp_protocol_mode IN octets_hold;
        IF transp_protocol_mode = NIL THEN
          octet_found := FALSE;
          RETURN;
        IFEND;
        attribute.trans_protocol_mode := transp_protocol_mode^;

      = iic$vt_control_code_replacement =
        attribute.control_code_replacement.total_substitution_count :=
          number DIV 2;
        IF number DIV 2 <> 0 THEN
          NEXT control_code_replacement_value:
            [1..attribute.control_code_replacement.total_substitution_count] IN
              octets_hold;
          attribute.control_code_replacement.value :=
            control_code_replacement_value^;
        IFEND;
      ELSE
        octet_found := FALSE;
      CASEND;

      IF octet_found THEN
        number_of_attributes := number_of_attributes + 1;
        attributes [j] := attribute;
      ELSE
        EXIT /parse_responses/;
      IFEND;
    FOREND /parse_responses/;


  PROCEND iip$vt_externalize_octets;
?? TITLE := 'GET_NEXT_SPECIAL_BLOCK', EJECT ??

  PROCEDURE get_next_special_block
    (    vtp_connection_id: iit$vtp_connection_id;
         input_file_identifier: amt$file_identifier;
         special_block: iit$vt_queue_types;
         buffer_ptr: ^cell;
         buffer_length: nat$data_length;
         wait: ost$wait;
         timeout: iit$vt_timeout;
     VAR message_received: boolean;
     VAR end_of_message: boolean;
     VAR transfer_count: nat$data_length;
     VAR input: iit$vt_input_information;
     VAR status: ost$status);

    VAR

      empty_header: [STATIC, READ, oss$job_paged_literal] iit$vt_input_information :=
        [0, iic$vt_input_data_message, 0, 0, iic$vt_character, FALSE, FALSE, TRUE, FALSE, 'a'],
      file_id_is_valid: boolean,
      file_instance: ^bat$task_file_entry,
      length_to_queue: nat$data_length,
      local_file_name: amt$local_file_name,
      activity_status: [STATIC, oss$task_shared {NAMVE workaround} ] ost$activity_status,
      peer_operation: [STATIC, oss$task_shared {NAMVE workaround} ] nat$se_peer_operation,
      st_open_file_dsc_pointer: ^iit$st_open_file_description,
      message_type: iit$vt_message_types,
      message_type_ptr: ^iit$vt_message_types,
      vtp_buffer: ^SEQ ( * ),
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      timeout_data: SEQ (REP 1 of cell),
      data: [STATIC, oss$task_shared {NAMVE workaround} ] array [1 .. 2] of nat$data_fragment,
      data1: [STATIC, oss$task_shared {NAMVE workaround} ] array [1 .. 1] of nat$data_fragment,
      file_identifier: amt$file_identifier,
      input_header_data: iit$vt_input_information,
      input_header: ^iit$vt_input_information,
      wait_time: integer,
      ibs_buffer: [STATIC, oss$task_shared] iit$vt_ibs_buffer,
      status_save: ost$status,
      text: [STATIC, READ, oss$job_paged_literal] string(35) :=
         ' TERMINAL TIMEOUT IN 30 SECONDS.' CAT $CHAR(7) CAT
         $CHAR(13) CAT $CHAR(10),
      move_ptr: ^cell,
      move_length: 0 .. iic$vt_max_transfer_length,
      timeout_message: string (80),
      str: ost$string,
      user_supplied_name: jmt$user_supplied_name,
      system_supplied_name: jmt$system_supplied_name,
      put_byte_address: ^amt$file_byte_address,
      warning_displayed: boolean;

?? OLDTITLE, EJECT ??

    #KEYPOINT (osk$entry, 0, iik$vt_get_next_special_block);

    status.normal := TRUE;
    message_received := FALSE;
    transfer_count := 0;
    warning_displayed := FALSE;

    REPEAT
      IF timeout. ON THEN
        wait_time := iiv$terminal_timeout_limit_left;
        IF timeout.length <= wait_time THEN
          wait_time := timeout.length;
        IFEND;

        nap$await_data_available (input_file_identifier, wait_time,
          wait_time, status);
        IF timeout.length <= iiv$terminal_timeout_limit_left THEN
          IF NOT status.normal THEN
            IF (status.condition = nae$no_event) OR (status.condition = nae$no_data_available) OR
                  (status.condition = nae$data_transfer_timeout) THEN
              iiv$terminal_timeout_limit_left := iiv$terminal_timeout_limit_left -
                timeout.length;
              status_save := status;
              IF timeout.length <> 0 THEN
                IF timeout.purge THEN
                  nap$se_synchronize (input_file_identifier,
                    nac$se_synchronize_all_data, timeout_data, status);
                  IF NOT status.normal THEN
                    IF status.condition = nae$se_synch_confirm_pending THEN
                      status.normal := TRUE;
                    IFEND;
                    #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                    RETURN;
                  ELSE
                    status := status_save;
                  IFEND;
                IFEND; { of timeout.purge }
              IFEND; { of timeout.length nonzero }
            IFEND; { of timeout-related status }
            #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
            RETURN; { for any abnormal status }
          IFEND; { of abnormal status }

        ELSE { timeout.length > iiv$terminal_timeout_limit left }
          IF NOT status.normal THEN
            IF (status.condition = nae$no_event) OR (status.condition = nae$no_data_available) OR
                  (status.condition = nae$data_transfer_timeout) THEN
              IF NOT warning_displayed THEN
              clp$get_system_file_id (clc$job_output, file_identifier, status);
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;
*copy bai$validate_file_identifier
*copy iii$fetch_st_open_file_desc_ptr
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;

              warning_displayed := TRUE;
              iip$st_put (file_identifier, st_open_file_dsc_pointer,
              amc$put_next_req, ^text, STRLENGTH (text), put_byte_address,
                amc$terminate, status);
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;
              amp$flush (file_identifier, osc$wait, status);
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;
              IFEND; {of NOT warning displayed}
              nap$await_data_available (input_file_identifier, 30000,
                30000, status);

              IF NOT status.normal THEN
                IF (status.condition = nae$no_event) OR (status.condition = nae$no_data_available) OR
                  (status.condition = nae$data_transfer_timeout) THEN
                  status_save := status;

{ Display the time and job name in the terminal timeout message.

                  clp$get_time_string (str, status);
                  timeout_message (1, 1) := ' ';
                  timeout_message (2, str.size) := str.value (1, str.size);
                  timeout_message (str.size + 2, 24) := ' TERMINAL TIMEOUT.  JOB ';
                  pmp$get_job_names (user_supplied_name, system_supplied_name, status);
                  timeout_message (str.size + 26, 19) := system_supplied_name;
                  timeout_message (str.size + 46, 12) :=
                    ' DETACHED.' CAT $char(13) CAT $char (10);
                  iip$st_put (file_identifier, st_open_file_dsc_pointer,
                    amc$put_next_req, #LOC (timeout_message), str.size + 57,
                   put_byte_address, amc$terminate, status);
                  amp$flush (file_identifier, osc$wait, status);
                  file_identifier := input_file_identifier;
*copy bai$validate_file_identifier
                  nap$se_clear_request(file_instance^.local_file_name,status);
                IFEND; { of timeout-related status }
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;
            IFEND;  { of check for timeout status }
          IFEND;  { of NOT status.normal }
        IFEND; { of timeout.length vs iiv$terminal_timeout_limit_left }
      ELSE { NOT timeout.on }

        wait_time := iiv$terminal_timeout_limit;
        nap$await_data_available (input_file_identifier,
          wait_time, wait_time, status);
        IF NOT status.normal THEN
          IF (status.condition = nae$no_event) OR (status.condition = nae$no_data_available) OR
            (status.condition = nae$data_transfer_timeout) THEN
            IF NOT warning_displayed THEN
            clp$get_system_file_id (clc$job_output, file_identifier, status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
*copy bai$validate_file_identifier
*copy iii$fetch_st_open_file_desc_ptr
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;

            warning_displayed := TRUE;
            iip$st_put (file_identifier, st_open_file_dsc_pointer,
              amc$put_next_req, ^text, STRLENGTH (text), put_byte_address,
              amc$terminate, status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
            amp$flush (file_identifier, osc$wait, status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
            IFEND; {warning displayed}
            nap$await_data_available (input_file_identifier, 30000,
              30000, status);
            IF NOT status.normal THEN
              IF (status.condition = nae$no_event) OR (status.condition = nae$no_data_available) OR
                (status.condition = nae$data_transfer_timeout) THEN
                status_save := status;

{ Display the time and job name in the terminal timeout message.

                clp$get_time_string (str, status);
                timeout_message (1, 1) := ' ';
                timeout_message (2, str.size) := str.value (1, str.size);
                timeout_message (str.size + 2, 24) := ' TERMINAL TIMEOUT.  JOB ';
                pmp$get_job_names (user_supplied_name, system_supplied_name, status);
                timeout_message (str.size + 26, 19) := system_supplied_name;
                timeout_message (str.size + 46, 12) :=
                  ' DETACHED.' CAT $char(13) CAT $char (10);
                iip$st_put (file_identifier, st_open_file_dsc_pointer,
                  amc$put_next_req, #LOC (timeout_message), str.size + 57,
                  put_byte_address, amc$terminate, status);
                amp$flush (file_identifier, osc$wait, status);
                file_identifier := input_file_identifier;
*copy bai$validate_file_identifier
                nap$se_clear_request(file_instance^.local_file_name,status);
              IFEND; { of timeout-related status }
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND; { of abnormal status }
          IFEND; { of timeout-related status }
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN; { for any abnormal status }
        IFEND; { of abnormal status}
      IFEND; { of timeout.on }

{ Receive block and return it or queue it.}
      connection := vtp_connection_id.connection;
      IF connection = NIL THEN
        iip$vt_validate_file_identifier (input_file_identifier,
          local_file_name, file_id_is_valid);
        IF NOT file_id_is_valid THEN
          STRINGREP (ordinal_char, char_length, input_file_identifier.ordinal);
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_id_not_valid, ordinal_char,
                status);
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;
        IFEND;
        osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, local_file_name, status);
        #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
        RETURN;
      IFEND;
      IF special_block = iic$vt_input THEN
        connection^.data := ^data;
        connection^.data^ [1].address := ^input;
        connection^.data^ [1].length := iic$vt_header_length_input;
        connection^.data^ [2].address := buffer_ptr;
        connection^.data^ [2].length := buffer_length;
        nap$se_receive_data (input_file_identifier,
          connection^.data^, wait, peer_operation, activity_status,
              status);
        IF (status.normal) AND (activity_status.complete) AND (NOT activity_status.status.normal) THEN
          status := activity_status.status;
        IFEND;
        IF NOT status.normal THEN
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;
        IFEND;
        CASE peer_operation.kind OF

        = nac$se_interrupt =
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_unsupported_event, '', status);
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;

        = nac$se_synchronize =
          IF peer_operation.direction = nac$se_synchronize_receive_data THEN
            transfer_count := 0;
            input := empty_header;
            message_received := TRUE;
          ELSE
            nap$se_synchronize_confirm (input_file_identifier, status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
          IFEND;

        = nac$se_synchronize_confirm =
          ; { add code someday if there is  anything to do }

        = nac$se_send_data =
          iiv$terminal_timeout_limit_left := iiv$terminal_timeout_limit;
          IF NOT peer_operation.end_of_message THEN
            IF queue_type_from_message [input.message_type] = iic$vt_input THEN
              message_received := TRUE;
              transfer_count := peer_operation.data_length - iic$vt_header_length_input;
              end_of_message := false;
              ibs_buffer := connection^.input_buffer;
              reset ibs_buffer;
              move_ptr := ibs_buffer;
              i#move (^input, move_ptr, iic$vt_header_length_input);
              length_to_queue := iic$vt_header_length_input;

              connection^.data := ^data1;
              connection^.data^ [1].address := i#ptr (iic$vt_header_length_input, move_ptr);
              connection^.data^ [1].length := iic$vt_max_transfer_length - iic$vt_header_length_input;
              nap$se_receive_data (input_file_identifier,
               connection^.data^, wait, peer_operation, activity_status,
                    status);
              IF (status.normal) AND (activity_status.complete) AND (NOT activity_status.status.normal) THEN
                status := activity_status.status;
              IFEND;
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;

              IF NOT peer_operation.end_of_message THEN
                osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_no_eom_found, ' ', status);
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;

              CASE peer_operation.kind OF

              = nac$se_interrupt =
                osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_unsupported_event, '', status);
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;

              = nac$se_synchronize =
                IF peer_operation.direction = nac$se_synchronize_receive_data THEN
                  transfer_count := 0;
                  input := empty_header;
                  message_received := TRUE;
                ELSE
                  nap$se_synchronize_confirm (input_file_identifier, status);
                  IF NOT status.normal THEN
                    #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                    RETURN;
                  IFEND;
                IFEND;

              = nac$se_synchronize_confirm =
                ; { add code someday if there is  anything to do }

              = nac$se_send_data =
                length_to_queue := length_to_queue + peer_operation.data_length;
                queue_message (ibs_buffer, vtp_connection_id, input.message_type, length_to_queue, status);
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;

              CASEND; { of peer_operation.kind, outer layer }

            ELSE { not input data }

              ibs_buffer := connection^.input_buffer;
              reset ibs_buffer;
              move_ptr := ibs_buffer;
              i#move (^input, move_ptr, iic$vt_header_length_input);
              move_ptr := i#ptr (iic$vt_header_length_input, move_ptr);
              length_to_queue := iic$vt_header_length_input;
              IF peer_operation.data_length > iic$vt_header_length_input THEN
                move_length := peer_operation.data_length - iic$vt_header_length_input;
                i#move (buffer_ptr, move_ptr, move_length);
                move_ptr := i#ptr (move_length, move_ptr);
                length_to_queue := length_to_queue + move_length;
              IFEND;

              connection^.data := ^data1;
              connection^.data^ [1].address := move_ptr;
              connection^.data^ [1].length := iic$vt_max_transfer_length - length_to_queue;

              nap$se_receive_data (input_file_identifier,
                connection^.data^, wait, peer_operation, activity_status,
                    status);
              IF (status.normal) AND (activity_status.complete) AND (NOT activity_status.status.normal) THEN
                status := activity_status.status;
              IFEND;
              IF NOT status.normal THEN
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;

              IF NOT peer_operation.end_of_message THEN
                osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_no_eom_found, ' ', status);
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;
              IFEND;


              CASE peer_operation.kind OF

              = nac$se_interrupt =
                osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_unsupported_event, '', status);
                #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                RETURN;

              = nac$se_synchronize =
                IF peer_operation.direction = nac$se_synchronize_receive_data THEN
                  transfer_count := 0;
                  input := empty_header;
                  message_received := TRUE;
                ELSE
                  nap$se_synchronize_confirm (input_file_identifier, status);
                  IF NOT status.normal THEN
                  #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
                    RETURN;
                  IFEND;
                IFEND;

              = nac$se_synchronize_confirm =
                ; { add code someday if there is  anything to do }

              = nac$se_send_data =

                length_to_queue := length_to_queue + peer_operation.data_length;
                queue_message (ibs_buffer, vtp_connection_id, input.message_type, length_to_queue, status);


              CASEND; { of peer_operation.kind, outer layer }

            IFEND; { not input data}


          ELSE {eom encountered}
            end_of_message := peer_operation.end_of_message;
            IF queue_type_from_message [input.message_type] = iic$vt_input THEN
              message_received := TRUE;
              transfer_count := peer_operation.data_length - iic$vt_header_length_input;
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            ELSE
              ibs_buffer := connection^.input_buffer;
              reset ibs_buffer;
              move_ptr := ibs_buffer;
              i#move (^input, move_ptr, iic$vt_header_length_input);
              IF peer_operation.data_length > iic$vt_header_length_input THEN
                move_length := peer_operation.data_length - iic$vt_header_length_input;
                move_ptr := i#ptr (iic$vt_header_length_input, move_ptr);
                i#move (buffer_ptr, move_ptr, move_length);
              IFEND;
              queue_message (ibs_buffer, vtp_connection_id, input.message_type, peer_operation.data_length,
                    status);
            IFEND;
          IFEND; {eom encountered }
        ELSE
        CASEND; { of peer_operation.kind, outer layer }

      ELSE {The special block is not of type INPUT.}
        IF buffer_length <> iic$vt_max_transfer_length THEN
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_incorrect_buffer_size, '', status);
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;
        IFEND;
        connection^.data := ^data1;
        connection^.data^ [1].address := buffer_ptr;
        connection^.data^ [1].length := buffer_length;
        nap$se_receive_data (input_file_identifier,
          connection^.data^, wait, peer_operation, activity_status,
              status);
        IF (status.normal) AND (activity_status.complete) AND (NOT activity_status.status.normal) THEN
          status := activity_status.status;
        IFEND;
        IF NOT status.normal THEN
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;
        IFEND;
        CASE peer_operation.kind OF

        = nac$se_interrupt =
          osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_unsupported_event, '', status);
          #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
          RETURN;

        = nac$se_synchronize =
          IF peer_operation.direction = nac$se_synchronize_receive_data THEN
            transfer_count := 0;
            input := empty_header;
            message_received := TRUE;
          ELSE
            nap$se_synchronize_confirm (input_file_identifier, status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
          IFEND;

        = nac$se_synchronize_confirm =
          { add code if there is anything to be done here }

        = nac$se_send_data =
          IF NOT peer_operation.end_of_message THEN
            osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_no_eom_found, ' ', status);
            #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
            RETURN;
          IFEND;
          message_type_ptr := ^message_type;
          i#move (buffer_ptr, message_type_ptr, 1);
          IF queue_type_from_message [message_type_ptr^] = special_block THEN
            message_received := TRUE;
            transfer_count := peer_operation.data_length;
            #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
            RETURN;
          ELSEIF queue_type_from_message [message_type_ptr^] = iic$vt_input THEN
            queue_message (buffer_ptr, vtp_connection_id, message_type_ptr^, peer_operation.data_length,
                  status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
          ELSE
            queue_message (buffer_ptr, vtp_connection_id, message_type_ptr^, peer_operation.data_length,
                  status);
            IF NOT status.normal THEN
              #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);
              RETURN;
            IFEND;
          IFEND;
        ELSE
        CASEND; { of peer_operation.kind }
      IFEND; { of IF/ELSE for special_block  = iic$vt_input }

    UNTIL message_received;

    #KEYPOINT (osk$exit, 0, iik$vt_get_next_special_block);

  PROCEND get_next_special_block;
?? TITLE := 'QUEUE_MESSAGE', EJECT ??

  PROCEDURE queue_message
    (    entry_ptr: ^cell;
         vtp_connection_id: iit$vtp_connection_id;
         message_type: iit$vt_message_types;
     VAR transfer_count: nat$data_length;
     VAR status: ost$status);

    VAR

      queue_type: iit$vt_queue_types,
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      queue_entry: ^iit$vt_queue_entry,
      ptr: ^iit$vt_queue_entry;

?? NEWTITLE := '  FIND_TAIL', EJECT ??

    PROCEDURE [INLINE] find_tail
      (VAR queue_entry_ptr {input/output} : ^iit$vt_queue_entry);

      WHILE queue_entry_ptr^.q_header.next_entry <> NIL DO
        queue_entry_ptr := queue_entry_ptr^.q_header.next_entry;
      WHILEND;
    PROCEND find_tail;
?? OLDTITLE, EJECT ??

    IF NOT syv$job_initialization_complete THEN
      {Must not queue data if job not yet cloned
      status.normal := TRUE;
      RETURN;
    IFEND;

    IF $INTEGER (message_type) >= iic$vt_message_type_max THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_unexpected_message, '', status);
      RETURN;
    IFEND;

    ptr := NIL;
    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, '', status);
    ELSE
      queue_type := queue_type_from_message [message_type];
      ALLOCATE queue_entry IN osv$task_shared_heap^; { job_pageable }
      ALLOCATE queue_entry^.vtp_buffer IN osv$task_shared_heap^; { job_pageable }
      queue_entry^.q_header.transfer_length := transfer_count;
      queue_entry^.q_header.next_entry := NIL;

      i#move (entry_ptr, queue_entry^.vtp_buffer, transfer_count);
      CASE queue_type OF

      = iic$vt_input =
        ptr := connection^.input.head;

      = iic$vt_output =
        ptr := connection^.output.head;

      = iic$vt_change =
        ptr := connection^.change.head;

      = iic$vt_status =
        ptr := connection^.status.head;

      = iic$vt_indications =
        ptr := connection^.indications.head;

      ELSE
      CASEND;
      IF ptr = NIL THEN
        CASE queue_type OF

        = iic$vt_input =
          connection^.input.head := queue_entry;

        = iic$vt_output =
          connection^.output.head := queue_entry;

        = iic$vt_change =
          connection^.change.head := queue_entry;

        = iic$vt_status =
          connection^.status.head := queue_entry;

        = iic$vt_indications =
          connection^.indications.head := queue_entry;
        ELSE
        CASEND;
      ELSE
        find_tail (ptr);
        ptr^.q_header.next_entry := queue_entry;
      IFEND;
    IFEND;

  PROCEND queue_message;

?? TITLE := 'REMOVE_QUEUE_ENTRY', EJECT ??

  PROCEDURE remove_queue_entry
    (    queue_type: iit$vt_queue_types;
         vtp_connection_id: iit$vtp_connection_id;
     VAR status: ost$status);

    VAR
      connection: [STATIC, oss$task_shared {namve workaround} ] ^iit$vt_connection,
      queue_entry: ^iit$vt_queue_entry;

    connection := vtp_connection_id.connection;
    IF connection = NIL THEN
      osp$set_status_abnormal (ifc$interactive_facility_id, ife$vt_file_not_open, '', status);
      RETURN;
    ELSE

      CASE queue_type OF

      = iic$vt_input =
        queue_entry := connection^.input.head;
        connection^.input.head := queue_entry^.q_header.next_entry;

      = iic$vt_output =
        queue_entry := connection^.output.head;
        connection^.output.head := queue_entry^.q_header.next_entry;

      = iic$vt_change =
        queue_entry := connection^.change.head;
        connection^.change.head := queue_entry^.q_header.next_entry;

      = iic$vt_status =
        queue_entry := connection^.status.head;
        connection^.status.head := queue_entry^.q_header.next_entry;

      = iic$vt_indications =
        queue_entry := connection^.indications.head;
        connection^.indications.head := queue_entry^.q_header.next_entry;

      ELSE
      CASEND;
      FREE queue_entry^.vtp_buffer IN osv$task_shared_heap^; { job_pageable }
      FREE queue_entry IN osv$task_shared_heap^; { job_pageable }
    IFEND;
    connection^.input.offset := 0;


  PROCEND remove_queue_entry;

MODEND iim$vtp_interface;
