*copyc OSD$DEFAULT_PRAGMATS
MODULE iim$st_get_terminal_attributes;
?? TITLE := 'MODULE iim$st_get_terminal_attributes' ??

?? PUSH (LISTEXT := ON) ??
*copyc ifc$interrupt_timesharing_io
*copyc iik$keypoints
*copyc iip$vt_kind_to_if_key
*copyc iip$terminal_keys_to_vt_kinds
*copyc iip$vt_to_terminal_attributes
*copyc IFE$ERROR_CODES
*copyc ift$terminal_attributes
*copyc IIV$CONNECTION_DESC_PTR
*copyc iiv$interactive_terminated
*copyc IIP$CLEAR_LOCK
*copyc IIP$SET_LOCK
*copyc iip$xlate_local_file_to_session
*copyc iip$search_connection_desc
*copyc iip$xt_get_terminal_attributes
*copyc jmp$get_job_attributes
*copyc jmp$is_xterm_task
*copyc jmp$system_job
*copyc nae$application_interfaces
*copyc nae$namve_conditions
*copyc nat$data_fragments
*copyc oss$task_shared
*copyc OST$STATUS
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc OSP$APPEND_STATUS_INTEGER
*copyc OSP$APPEND_STATUS_PARAMETER
*copyc OSP$SET_STATUS_ABNORMAL
*copyc osp$set_status_from_condition
*copyc osp$system_error
*copyc osp$test_sig_lock
*copyc pmp$continue_to_cause
*copyc pmp$find_executing_task_tcb
*copyc iip$vt_open
*copyc iip$vt_close
*copyc iip$vt_query_attributes
*copyc iip$vt_get_query_response
?? POP ??

?? NEWTITLE := 'PROCEDURE iip$st_get_terminal_attributes', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$st_get_terminal_attributes (file_name: amt$local_file_name;
    VAR terminal_attributes: ift$terminal_attributes;
    VAR status: ost$status);

    VAR
      activity_status: [STATIC, oss$task_shared {namve workaround} ] ost$activity_status,
      attempt_count: integer,
      confirmed: boolean,
      connection_desc_ptr: ^iit$connection_description,
      connection_desc_ptr_set: boolean,
      downline_lock_set: boolean,
      exit_in_progress: boolean,
      get_lock_set: boolean,
      i: integer,
      job_attribute_results: ^jmt$job_attribute_results,
      k: integer,
      local_status: ost$status,
      ls: ost$signature_lock_status,
      response_received: boolean,
      session_file: amt$local_file_name,
      set_of_terminal_attribute_keys: iit$terminal_attribute_keys_set,
      tcb_p: ^pmt$task_control_block,
      terminal_name_ptr: ^ift$terminal_name,
      terminal_name_requested: boolean,
      terminal_name_index: integer,
      unknown_attribute_number: iit$vt_attribute_kind,
      vtp_attributes: ^iit$vt_attributes,
      vtp_attribute_kinds: ^iit$vt_attribute_kinds,
      vtp_file_id: amt$file_identifier;

?? NEWTITLE := 'PROCEDURE handle_condition', EJECT ??

    PROCEDURE handle_condition (cond: pmt$condition;
          cd: ^pmt$condition_information;
          sa: ^ost$stack_frame_save_area;
      VAR ch_status: ost$status);

      VAR
        ignore_status: ost$status;

      ch_status.normal := TRUE;

      IF cond.selector = pmc$block_exit_processing THEN
        IF downline_lock_set THEN
        osp$test_sig_lock (iiv$downline_queue_lock, ls);
          IF ls = osc$sls_locked_by_current_task THEN
            RESET connection_desc_ptr^.output_buffer_entry_loc;
            RESET connection_desc_ptr^.output_buffer_exit_loc;
            connection_desc_ptr^.downline_queue_count := 0;
            iip$clear_lock (iiv$downline_queue_lock, local_status);
          IFEND;
        IFEND;
        IF get_lock_set THEN
        osp$test_sig_lock (connection_desc_ptr^.st_get_lock, ls);
          IF ls = osc$sls_locked_by_current_task THEN
          iip$clear_lock (connection_desc_ptr^.st_get_lock, local_status);
          IFEND;
        IFEND;
      ELSEIF cond.selector = pmc$system_conditions THEN
        IF status.normal THEN
          osp$set_status_from_condition ('II', cond, sa,
                status, ignore_status);
        IFEND;
        EXIT  iip$st_get_terminal_attributes;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, ch_status);
        IF exit_in_progress THEN
          EXIT iip$st_get_terminal_attributes;
        IFEND;
      IFEND;
    PROCEND handle_condition;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;

  /st_get_terminal_attributes/
    BEGIN

      connection_desc_ptr_set := false;
      #spoil(connection_desc_ptr_set);
      exit_in_progress := FALSE;
      downline_lock_set := FALSE;
      get_lock_set := FALSE;
      osp$establish_condition_handler (^handle_condition, TRUE);

{ Validate the terminal attribute keys.

      terminal_name_index := 0;
      set_of_terminal_attribute_keys := - $iit$terminal_attribute_keys_set [];
      FOR i := LOWERBOUND (terminal_attributes) TO UPPERBOUND
            (terminal_attributes) DO
        IF NOT (terminal_attributes [i].key IN set_of_terminal_attribute_keys)
              THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$unknown_attribute_key, '', status);
          k := ORD (terminal_attributes [i].key);
          osp$append_status_integer (osc$status_parameter_delimiter, k, 10,
                FALSE, status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
            'IFP$GET_TERMINAL_ATTRIBUTES', status);
          EXIT /st_get_terminal_attributes/;
        IFEND;
        IF terminal_attributes [i].key = ifc$terminal_name THEN
          terminal_name_ptr := terminal_attributes [i].terminal_name;
          terminal_attributes [i].key := ifc$attention_character;
          terminal_name_index := i;
        IFEND;
      FOREND;

      pmp$find_executing_task_tcb (tcb_p);
      IF jmp$is_xterm_task (tcb_p^.task_id) THEN

{ Get default terminal attributes needed by C to start xterm program.

        iip$xt_get_terminal_attributes (file_name, terminal_attributes, status);
        RETURN;
      IFEND;

{ Build a iit$vt_attribute_kinds array for input to a iip$vt_query_attributes call.

      PUSH vtp_attribute_kinds: [1 .. UPPERBOUND (terminal_attributes)];
      PUSH vtp_attributes: [1 .. UPPERBOUND (terminal_attributes)];

      iip$terminal_keys_to_vt_kinds (terminal_attributes, vtp_attribute_kinds^);

      iip$xlate_local_file_to_session (file_name, session_file, status);
      IF NOT status.normal THEN
        EXIT /st_get_terminal_attributes/;
      IFEND;

      iip$search_connection_desc (session_file, connection_desc_ptr);
      IF connection_desc_ptr = NIL THEN
        EXIT /st_get_terminal_attributes/;
      ELSE
        connection_desc_ptr_set := true;
        #spoil(connection_desc_ptr_set);
      IFEND;

      iip$vt_open (connection_desc_ptr^.session_layer_file_name, vtp_file_id, status);
      IF NOT status.normal THEN
        EXIT /st_get_terminal_attributes/;
      IFEND;

      attempt_count := 0;
      REPEAT
        attempt_count := attempt_count + 1;
        iip$set_lock (iiv$downline_queue_lock, osc$wait, status);
        IF NOT status.normal THEN
          EXIT /st_get_terminal_attributes/;
        IFEND;
        downline_lock_set := true;
        #spoil(downline_lock_set);

        iip$vt_query_attributes (connection_desc_ptr^.vtp_connection_id, vtp_file_id, vtp_attribute_kinds^,
              osc$wait, activity_status, status);
        IF NOT status.normal THEN
          iip$clear_lock (iiv$downline_queue_lock, local_status);
          downline_lock_set := false;
          #spoil(downline_lock_set);
          EXIT /st_get_terminal_attributes/;
        IFEND;
        iip$clear_lock (iiv$downline_queue_lock, status);
        IF NOT status.normal THEN
          EXIT /st_get_terminal_attributes/;
        IFEND;
        downline_lock_set := false;
        #spoil(downline_lock_set);

  { Get the query response and return either the queried attribute values or, if the query
  { caused an error, the attribute key causing the error.

        iip$set_lock (connection_desc_ptr^.st_get_lock, osc$wait, status);
        IF NOT status.normal THEN
          EXIT /st_get_terminal_attributes/;
        IFEND;
        get_lock_set := true;
        #spoil(get_lock_set);

        iip$vt_get_query_response (connection_desc_ptr^.vtp_connection_id, vtp_file_id, osc$wait, confirmed,
              vtp_attributes^, unknown_attribute_number, response_received, status);
        { status check will not happen till outside of loop }
        iip$clear_lock (connection_desc_ptr^.st_get_lock, local_status);
        get_lock_set := false;
        #spoil(get_lock_set);
      UNTIL (attempt_count > 9) OR (status.normal) OR
            ((NOT status.normal) AND (status.condition <> nae$no_event)
            AND (status.condition <> nae$no_data_available)
            AND (status.condition <> nae$data_transfer_timeout));
      IF NOT status.normal THEN
        EXIT /st_get_terminal_attributes/;
      IFEND;

      iip$vt_close (vtp_file_id, local_status);
      IF NOT local_status.normal THEN
        IF status.normal THEN
          status := local_status;
        IFEND;
        EXIT /st_get_terminal_attributes/;
      IFEND;

      IF confirmed THEN
        iip$vt_to_terminal_attributes (vtp_attributes^, terminal_attributes);
      IFEND;

      IF terminal_name_index <> 0 THEN
        terminal_attributes [terminal_name_index].key := ifc$terminal_name;
        terminal_attributes [terminal_name_index].terminal_name := terminal_name_ptr;
        terminal_attributes [terminal_name_index].terminal_name^ :=
              connection_desc_ptr^.terminal_name;
      IFEND;

    END /st_get_terminal_attributes/;

    osp$disestablish_cond_handler;

  PROCEND iip$st_get_terminal_attributes;

MODEND iim$st_get_terminal_attributes;
