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

?? PUSH (LISTEXT := ON) ??
*copyc ifc$interrupt_timesharing_io
*copyc iik$keypoints
*copyc iip$vt_open
*copyc iip$vt_close
*copyc iip$vt_get_change_response
*copyc iip$vt_to_terminal_attributes
*copyc iip$terminal_to_vt_attributes
*copyc IFE$ERROR_CODES
*copyc iip$vt_change_attributes
*copyc iit$vt_change_error_codes
*copyc iiv$connection_desc_ptr
*copyc iip$clear_lock
*copyc iip$set_lock
*copyc iip$search_connection_desc
*copyc iip$xlate_local_file_to_session
*copyc IIT$CONNECTION_DESCRIPTION
*copyc IIV$INTERACTIVE_TERMINATED
*copyc iiv$int_task_open_file_count
*copyc jmp$is_xterm_task
*copyc jmp$system_job
*copyc nae$application_interfaces
*copyc nae$namve_conditions
*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$system_error
*copyc osp$test_sig_lock
*copyc oss$task_shared
*copyc pmp$continue_to_cause
*copyc pmp$find_executing_task_tcb
?? POP ??

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

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

    VAR
      activity_status: [STATIC, oss$task_shared {namve workaround }] ost$activity_status,
      attempt_count: integer,
      attribute_error_pairs: array [1 .. 2] of iit$vt_attribute,
      confirmed: boolean,
      connection_desc_ptr: ^iit$connection_description,
      connection_desc_ptr_set: boolean,
      downline_lock_set: boolean,
      error_code: iit$vt_change_error_codes,
      exit_in_progress: boolean,
      get_lock_already_set: boolean,
      i: integer,
      index: integer,
      j: integer,
      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,
      vtp_attributes: ^iit$vt_attributes,
      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);

      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 NOT get_lock_already_set THEN
        IF connection_desc_ptr_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;
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, ch_status);
        IF exit_in_progress THEN
          EXIT iip$st_chng_terminal_attributes;
        IFEND;
      IFEND;
    PROCEND handle_condition;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;

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

    { Validate the terminal attribute keys.

      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$CHANGE_TERMINAL_ATTRIBUTES', status);
          EXIT /st_change_terminal_attributes/;
        IFEND;
      FOREND;

      IF NOT status.normal THEN
        EXIT /st_change_terminal_attributes/;
      IFEND;

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

{ Do not allow xterm task to change terminal attributes.

        RETURN;
      IFEND;

  {   Build a iit$vt_attributes record for input to the iip$vt_change_attributes call.

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

      iip$terminal_to_vt_attributes (terminal_attributes, vtp_attributes^);

      iip$xlate_local_file_to_session (terminal_file_name, session_file, status);
      IF NOT status.normal THEN
        EXIT /st_change_terminal_attributes/;
      IFEND;
      iip$search_connection_desc (session_file, connection_desc_ptr);
      IF connection_desc_ptr = NIL THEN
        EXIT /st_change_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_change_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_change_terminal_attributes/;
        IFEND;
        downline_lock_set := true;
        #spoil(downline_lock_set);
        iip$vt_change_attributes (connection_desc_ptr^.vtp_connection_id, vtp_file_id, vtp_attributes^,
              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_change_terminal_attributes/;
        IFEND;
        iip$clear_lock (iiv$downline_queue_lock, status);
        IF NOT status.normal THEN
          EXIT /st_change_terminal_attributes/;
        IFEND;
        downline_lock_set := false;
        #spoil(downline_lock_set);

        osp$test_sig_lock (connection_desc_ptr^.st_get_lock, ls);
        IF ls <> osc$sls_not_locked THEN
          get_lock_already_set := TRUE;
          #spoil(get_lock_already_set);
        ELSE
          get_lock_already_set := FALSE;
          #spoil(get_lock_already_set);
          iip$set_lock (connection_desc_ptr^.st_get_lock, osc$wait, status);
          IF NOT status.normal THEN
            EXIT /st_change_terminal_attributes/;
          IFEND;
        IFEND;
        IF (ls = osc$sls_locked_by_current_task) OR (NOT get_lock_already_set) THEN
          iip$vt_get_change_response (connection_desc_ptr^.vtp_connection_id, vtp_file_id, osc$wait,
               {confirmed} error_code, attribute_error_pairs, response_received, status);
          { status check will not happen till outside of loop }
        IFEND;
        IF NOT get_lock_already_set THEN
          iip$clear_lock (connection_desc_ptr^.st_get_lock, local_status);
        IFEND;
      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_change_terminal_attributes/;
      IFEND;

      iip$vt_close (vtp_file_id, status);
      IF NOT status.normal THEN
        EXIT /st_change_terminal_attributes/;
      IFEND;

      confirmed := TRUE;

      IF confirmed THEN

  {     Update the PW, PL and/or TM  attributes in the connection table if they changed.

        iip$set_lock (connection_desc_ptr^.terminal_attributes_lock, osc$wait, status);
        FOR i := 1 TO UPPERBOUND (terminal_attributes) DO
          CASE terminal_attributes [i].key OF
          = ifc$page_length =
            connection_desc_ptr^.page_length := terminal_attributes [i].page_length;
          = ifc$page_width =
            connection_desc_ptr^.page_width := terminal_attributes [i].page_width;
          = ifc$terminal_model =
            connection_desc_ptr^.terminal_model := terminal_attributes [i].terminal_model;
          ELSE
          CASEND;
        FOREND;
      IFEND;
      iip$clear_lock (connection_desc_ptr^.terminal_attributes_lock, status);

    END /st_change_terminal_attributes/;

    osp$disestablish_cond_handler;

  PROCEND iip$st_chng_terminal_attributes;
MODEND iim$st_chng_terminal_attributes;
