?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Operator Facility : VED JL, SL, OM and TM Displays' ??
MODULE ofm$console_displays;

{   PURPOSE:
{     This module contains procedures that drive the operator displays.
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clt$value
*copyc clt$display_control
*copyc dme$tape_errors
*copyc dpt$number_of_window_lines
*copyc iot$no_of_tape_units
*copyc iot$rvl_entry_information
*copyc jmt$system_supplied_name
*copyc ofd$type_definition
*copyc ofe$error_codes
*copyc oft$operator_classes
*copyc oft$operator_message_descriptor
*copyc osc$multiprocessor_constants
*copyc oss$task_private
*copyc oss$task_shared
*copyc oss$job_paged_literal
*copyc ost$cpu_idle_statistics
*copyc ost$status
*copyc ost$string
*copyc pmt$ascii_logs
?? POP ??
*copyc avp$system_displays
*copyc clp$close_display
*copyc clp$new_display_line
*copyc clp$new_display_page
*copyc clp$put_display
*copyc clp$trimmed_string_size
*copyc dpp$get_starting_line
*copyc dpp$put_next_line
*copyc i#current_sequence_position
*copyc ifp$invoke_pause_utility
*copyc iop$get_tape_mount_information
*copyc iop$tape_mount_count
*copyc jmp$get_ijle_p
*copyc jmp$system_job
*copyc lgp$get_critical_log_read_info
*copyc lgp$get_global_log_read_info
*copyc lgp$get_local_log_read_info
*copyc lgp$get_entry_from_critical_log
*copyc lgp$get_entry_from_global_log
*copyc lgp$get_entry_from_local_log
*copyc ofp$get_active_operator_classes
*copyc ofp$build_system_line
*copyc ofp$get_operator_messages
*copyc ofp$open_display
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$establish_condition_handler
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc pmp$binary_to_ascii_fit
*copyc pmp$continue_to_cause
*copyc pmp$get_os_version
*copyc pmp$long_term_wait

?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    one_second = 1000 {milliseconds};

{  Global variables referenced by this module.

*copyc avv$active_sou_capabilities
*copyc jmv$ajl_p
*copyc jmv$ijl_p
*copyc jmv$max_ajl_ordinal_in_use
*copyc jsv$swap_status_id_array
*copyc mmv$gpql
*copyc tmv$display_actual_priority
*copyc mtv$cst0
*copyc osv$task_shared_heap

?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  TYPE
    log_info = record
      log: pmt$ascii_logs,
      log_cycle: lgt$log_cycle,
      address: ^SEQ ( * ),
    recend;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] ofp$critical_window_log_display', EJECT ??

{   The purpose of this procedure is to start up the display of an ascii log.
{ The task that this procedure is running under will periodically update the
{ header part of the display until another task takes over as the driver of
{ the console display.

  VAR
    cwl_info: [oss$task_shared] log_info;

  PROCEDURE [XDCL] ofp$critical_window_log_display
    (    wid: dpt$window_id;
         display_name: ost$name;
         file_name: amt$local_file_name;
         initial_call: boolean;
     VAR status: ost$status);

    display_log (wid, file_name, initial_call, 'Critical Window Log Display',
          {critical_window_message = } TRUE, cwl_info, status);

  PROCEND ofp$critical_window_log_display;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] ofp$job_log_display', EJECT ??

{   The purpose of this procedure is to start up the display of an ascii log.
{ The task that this procedure is running under will periodically update the
{ header part of the display until another task takes over as the driver of
{ the console display.

  VAR
    jl_info: [oss$task_shared] log_info;

  PROCEDURE [XDCL] ofp$job_log_display
    (    wid: dpt$window_id;
         display_name: ost$name;
         file_name: amt$local_file_name;
         initial_call: boolean;
     VAR status: ost$status);


    IF initial_call THEN
      jl_info.log := pmc$job_log;
    IFEND;

    display_log (wid, file_name, initial_call, 'Job Log Display            ',
          {critical_window_message = } FALSE, jl_info, status);

  PROCEND ofp$job_log_display;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] ofp$operator_message_display', EJECT ??

{ PURPOSE:
{   This procedure displays messages which are awaiting action by the operator.

  PROCEDURE [XDCL] ofp$operator_message_display
    (    wid: dpt$window_id;
         display_name: ost$name;
         file_name: amt$local_file_name;
         initial_call: boolean;
     VAR status: ost$status);
?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure provides clean-up processing when a task abort occurs.

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information_p: ^pmt$condition_information;
           save_area_p: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      IF wid = 0 THEN
        clp$close_display (display_control, ignore_status);
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??

    VAR
      active_operator_classes: oft$operator_classes,
      blank_line: string (2),
      display_control: clt$display_control,
      display_line: string (80),
      ignore_status: ost$status,
      index: oft$number_of_displayable_lines,
      length: integer,
      line_index: dpt$number_of_window_lines,
      line_number: integer,
      lines_written: dpt$number_of_window_lines,
      message_array_entries: integer,
      message_array_p: ^ARRAY [1 .. *] OF oft$operator_message_descriptor,
      message_count: integer,
      message_id: string (8),
      message_index: integer,
      no_messages_line: [READ, oss$job_paged_literal] string (60) :=
            '                   *** No operator messages outstanding. ***',
      starting_line: integer,
      title_line: [READ, oss$job_paged_literal] string (24) := 'Operator Message Display';

    status.normal := TRUE;
    blank_line := ' ';

    { If this is the system job and the display is being written to DISPLAY_A or DISPLAY_B, then operator
    { messages are validated for display based upon the capabilities of the job synchronous task rather
    { than the capabilities of the executing task.

    IF jmp$system_job() AND (wid <> 0) THEN
      IF avc$cc_system_displays IN avv$active_sou_capabilities THEN
        active_operator_classes := -$oft$operator_classes [];
      ELSE
        IF avc$cc_system_operator IN avv$active_sou_capabilities THEN
          active_operator_classes := $oft$operator_classes [ofc$system_operator];
        ELSE
          active_operator_classes := $oft$operator_classes [];
        IFEND;
        IF avc$cc_removable_media_operator IN avv$active_sou_capabilities THEN
          active_operator_classes := active_operator_classes +
                $oft$operator_classes [ofc$removable_media_operator];
        IFEND;
      IFEND;
    ELSE
      IF avp$system_displays () THEN
        active_operator_classes := -$oft$operator_classes [];
      ELSE
        ofp$get_active_operator_classes (active_operator_classes);
      IFEND;
    IFEND;

    IF wid = 0 THEN
      osp$establish_block_exit_hndlr (^abort_handler);
    IFEND;
    IF initial_call THEN
      ofp$open_display (file_name, wid, dpc$wc_sharing, dpc$wk_table, title_line, display_control, status);
      IF NOT status.normal THEN
        IF wid = 0 THEN
          osp$disestablish_cond_handler;
        IFEND;
        RETURN;
      IFEND;
    IFEND;

   /display_opened/
    BEGIN
      IF wid = 0 THEN
        clp$put_display (display_control, blank_line, clc$trim, status);
        IF NOT status.normal THEN
          EXIT /display_opened/;
        IFEND;
      ELSE
        dpp$get_starting_line (wid, starting_line, status);
        IF NOT status.normal THEN
          EXIT /display_opened/;
        IFEND;
        lines_written := 0;
      IFEND;

      { Get a copy of the messages that this operator is validated to display.  Loop until all messages
      { are retrieved.  Will probably only take two tries.

      message_array_entries := 0;
      message_count := 2;
      WHILE message_array_entries < message_count DO
        message_array_entries := message_count;
        PUSH message_array_p: [1 .. message_array_entries];
        ofp$get_operator_messages (active_operator_classes, message_array_p^, message_count, status);
        IF NOT status.normal THEN
          EXIT /display_opened/;
        IFEND;
        IF message_count = 0 THEN
          IF wid = 0 THEN
            clp$put_display (display_control, blank_line, clc$trim, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
            clp$put_display (display_control, no_messages_line, clc$trim, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
          ELSE
            dpp$put_next_line (wid, blank_line, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
            dpp$put_next_line (wid, no_messages_line, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
            lines_written := lines_written + 2;
            FOR line_index := (lines_written + 1) TO dpc$number_of_window_lines DO
              dpp$put_next_line (wid, blank_line, status);
              IF NOT status.normal THEN
                EXIT /display_opened/;
              IFEND;
            FOREND;
          IFEND;
          EXIT /display_opened/;
        IFEND;
      WHILEND;

      { Display the messages.  Each line of each message is checked to see if it falls within the range of
      { lines to be displayed (to support display paging).

      line_number := 1;
      FOR message_index := 1 TO message_count DO

        { Output message header line.

        display_line := ' Message #: ';
        STRINGREP (message_id, length, message_array_p^ [message_index].message_id);
        display_line (17 - length, length) := message_id;
        display_line (55, 6) := 'From: ';
        display_line (61, jmc$system_supplied_name_size) :=
              message_array_p^ [message_index].system_supplied_name;
        IF message_array_p^ [message_index].acknowledgement_allowed THEN
          display_line (22, 28) := 'Acknowledgement: REQUIRED'
        ELSE
          display_line (22, 28) := 'Acknowledgement: NOT ALLOWED'
        IFEND;
        IF wid = 0 THEN
          clp$put_display (display_control, display_line, clc$trim, status);
          IF NOT status.normal THEN
            EXIT /display_opened/;
          IFEND;
        ELSE
          IF starting_line <= line_number THEN
            dpp$put_next_line (wid, display_line, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
            lines_written := lines_written + 1;
            IF lines_written >= dpc$number_of_window_lines THEN
              EXIT /display_opened/;
            IFEND;
          IFEND;
        IFEND;
        line_number := line_number + 1;

        { Output message line(s).

        FOR index := 1 TO message_array_p^ [message_index].number_of_message_lines DO
          IF wid = 0 THEN
            clp$put_display (display_control, message_array_p^ [message_index].formatted_message [index],
                  clc$trim, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
          ELSE
            IF starting_line <= line_number THEN
              dpp$put_next_line (wid, message_array_p^ [message_index].formatted_message [index], status);
              IF NOT status.normal THEN
                EXIT /display_opened/;
              IFEND;
              lines_written := lines_written + 1;
              IF lines_written >= dpc$number_of_window_lines THEN
                EXIT /display_opened/;
              IFEND;
            IFEND;
          IFEND;
          line_number := line_number + 1;
        FOREND;

        { Output blank line.

        IF wid = 0 THEN
          clp$put_display (display_control, blank_line, clc$trim, status);
          IF NOT status.normal THEN
            EXIT /display_opened/;
          IFEND;
        ELSE
          IF starting_line <= line_number THEN
            dpp$put_next_line (wid, blank_line, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
            lines_written := lines_written + 1;
            IF lines_written >= dpc$number_of_window_lines THEN
              EXIT /display_opened/;
            IFEND;
          IFEND;
        IFEND;
        line_number := line_number + 1;
      FOREND;

      { Clear the rest of the display window.

      IF wid <> 0 THEN
        IF lines_written < dpc$number_of_window_lines THEN
          FOR line_index := (lines_written + 1) TO dpc$number_of_window_lines DO
            dpp$put_next_line (wid, blank_line, status);
            IF NOT status.normal THEN
              EXIT /display_opened/;
            IFEND;
          FOREND;
        IFEND;
      IFEND;
    END /display_opened/;

    IF wid = 0 THEN
      clp$close_display (display_control, ignore_status);
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND ofp$operator_message_display;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] ofp$system_log_display', EJECT ??

{   The purpose of this procedure is to start up the display of an ascii log.
{ The task that this procedure is running under will periodically update the
{ header part of the display until another task takes over as the driver of
{ the console display.

  VAR
    sl_info: [oss$task_shared] log_info;

  PROCEDURE [XDCL] ofp$system_log_display
    (    wid: dpt$window_id;
         display_name: ost$name;
         file_name: amt$local_file_name;
         initial_call: boolean;
     VAR status: ost$status);

    IF initial_call THEN
      sl_info.log := pmc$system_log;
    IFEND;

    display_log (wid, file_name, initial_call, 'System Log Display         ',
          {critical_window_message = } FALSE, sl_info, status);

  PROCEND ofp$system_log_display;
?? OLDTITLE ??
?? NEWTITLE := 'display_log', EJECT ??

  PROCEDURE display_log
    (    wid: dpt$window_id;
         file_name: amt$local_file_name;
         initial_call: boolean;
         title: string (27);
         critical_window_message: boolean;
     VAR info: log_info;
     VAR status: ost$status);
?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure provides clean-up processing when a task abort occurs.

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information_p: ^pmt$condition_information;
           save_area_p: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      IF wid = 0 THEN
        clp$close_display (display_control, ignore_status);
      IFEND;

    PROCEND abort_handler;
?? OLDTITLE, EJECT ??

{ The following constant defines the maximum number of entries that will be displayed before this procedure
{ gives up control.  This allows the operator to change displays even though the end of the log has not been
{ reached.

    CONST
      maximum_entries_to_display = 30;

    VAR
      display_control: clt$display_control,
      entry_count: integer,
      byte_address: amt$file_byte_address,
      ignore_status: ost$status,
      length: lgt$log_entry_size,
      line: string (255),
      eof: boolean;

    status.normal := TRUE;

    IF wid = 0 THEN
      osp$establish_block_exit_hndlr (^abort_handler);
    IFEND;
    IF initial_call THEN
      ofp$open_display (file_name, wid, dpc$wc_sharing, dpc$wk_log, title, display_control, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF critical_window_message THEN
        lgp$get_critical_log_read_info (30, info.log_cycle,
              info.address, byte_address, status);
      ELSEIF info.log = pmc$system_log THEN
        lgp$get_global_log_read_info (pmc$system_log, 30, info.log_cycle, info.address, byte_address, status);
      ELSE { info.log = pmc$job_log }
        lgp$get_local_log_read_info (pmc$job_log, 30, info.log_cycle, info.address, byte_address, status);
      IFEND;
    IFEND;
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    entry_count := 0;

  /main_loop/
    BEGIN
      REPEAT
        IF critical_window_message THEN
          lgp$get_entry_from_critical_log (info.log_cycle, info.address, length,
                #SEQ (line) ^, status);
        ELSEIF info.log = pmc$system_log THEN
          lgp$get_entry_from_global_log (pmc$system_log, info.log_cycle, info.address, length,
                #SEQ (line) ^, status);
        ELSE { info.log = pmc$job_log }
          lgp$get_entry_from_local_log (pmc$job_log, info.log_cycle, info.address, length,
                #SEQ (line) ^, status);
        IFEND;
        IF status.normal THEN
          IF length > #SIZE(line) THEN
            length := #SIZE(line);
          IFEND;
          IF wid <> 0 THEN
            dpp$put_next_line (wid, line (1, length), status);
          ELSE
            clp$put_display (display_control, line (1, length), clc$trim, status);
          IFEND;
        IFEND;

        entry_count := entry_count + 1;
      UNTIL (NOT status.normal) OR (entry_count > maximum_entries_to_display);
    END /main_loop/;
    IF NOT status.normal THEN
      IF status.condition = lge$end_of_log THEN
        status.normal := TRUE;
      ELSEIF status.condition = lge$log_cycles_do_not_match THEN
        status.normal := TRUE;
        IF critical_window_message THEN
          lgp$get_critical_log_read_info (0, info.log_cycle,
                info.address, byte_address, status);
        ELSEIF info.log = pmc$system_log THEN
          lgp$get_global_log_read_info (pmc$system_log, 0, info.log_cycle,
                info.address, byte_address, status);
        ELSE { info.log = pmc$job_log }
          lgp$get_local_log_read_info (pmc$job_log, 0, info.log_cycle, info.address, byte_address, status);
        IFEND;
        RESET info.address;
      ELSE
        RETURN;
      IFEND;
    IFEND;

    IF wid = 0 THEN
      clp$close_display (display_control, status);
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND display_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] ofp$tape_mount_display', EJECT ??

{ PURPOSE:
{   This procedure displays tape mount requests which are awaiting
{   action by the operator.

  PROCEDURE [XDCL] ofp$tape_mount_display
    (    wid: dpt$window_id;
         display_name: ost$name;
         file_name: amt$local_file_name;
         initial_call: boolean;
     VAR status: ost$status);

?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure provides clean-up processing when a task abort occurs.

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information_p: ^pmt$condition_information;
           save_area_p: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      IF wid = 0 THEN
        clp$close_display (display_control, ignore_status);
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE ??
?? NEWTITLE := '  output_line', EJECT ??
    PROCEDURE output_line
      (VAR status: ost$status);

      IF wid <> 0 THEN
        dpp$put_next_line (wid, display_line, status);
      ELSE
        clp$put_display (display_control, display_line, clc$trim, status);
      IFEND;

      display_line := ' ';
      col := 3;
    PROCEND output_line;
?? OLDTITLE ??
?? NEWTITLE := '  output_requestor_line', EJECT ??
    PROCEDURE output_requestor_line
      (VAR status: ost$status);

      CONST
        account_text = 'Account: ',
        account_text_size = 9,
        comma_text = ', ',
        comma_text_size = 2,
        family_text = 'Family: ',
        family_text_size = 8,
        project_text = 'Project: ',
        project_text_size = 9,
        user_text = 'User: ',
        user_text_size = 6;

      VAR
        size: 1 .. 31,
        name: ost$name;

      status.normal := TRUE;
      display_line := ' ';
      col := 3;

      IF (rvl_info_array_p^ [index].requested_volume_attributes.family <> osc$null_name) OR
            (rvl_info_array_p^ [index].requested_volume_attributes.user <> osc$null_name) OR
            (rvl_info_array_p^ [index].requested_volume_attributes.account <> osc$null_name) OR
            (rvl_info_array_p^ [index].requested_volume_attributes.project <> osc$null_name) THEN

        IF (rvl_info_array_p^ [index].requested_volume_attributes.family <> osc$null_name) THEN
          display_line (col, family_text_size) := family_text;
          col := col + family_text_size;
          name := rvl_info_array_p^ [index].requested_volume_attributes.family;
          size := clp$trimmed_string_size (name);
          display_line (col, size) := name (1, size);
          col := col + size;
        IFEND;

        IF rvl_info_array_p^ [index].requested_volume_attributes.user <> osc$null_name THEN
          IF col > 3 THEN
            display_line (col, comma_text_size) := comma_text;
            col := col + comma_text_size;
          IFEND;
          name := rvl_info_array_p^ [index].requested_volume_attributes.user;
          size := clp$trimmed_string_size (name);
          IF (col + user_text_size + size) > 80 THEN
            output_line (status);
          IFEND;
          IF status.normal THEN
            display_line (col, user_text_size) := user_text;
            col := col + user_text_size;
            display_line (col, size) := name (1, size);
            col := col + size;
          IFEND;
        IFEND;

        IF status.normal AND (rvl_info_array_p^ [index].requested_volume_attributes.account <> osc$null_name)
              THEN
          IF col > 3 THEN
            display_line (col, comma_text_size) := comma_text;
            col := col + comma_text_size;
          IFEND;
          name := rvl_info_array_p^ [index].requested_volume_attributes.account;
          size := clp$trimmed_string_size (name);
          IF (col + account_text_size + size) > 80 THEN
            output_line (status);
          IFEND;
          IF status.normal THEN
            display_line (col, account_text_size) := account_text;
            col := col + account_text_size;
            display_line (col, size) := name (1, size);
            col := col + size;
          IFEND;
        IFEND;

        IF status.normal AND (rvl_info_array_p^ [index].requested_volume_attributes.project <> osc$null_name)
              THEN
          IF col > 3 THEN
            display_line (col, comma_text_size) := comma_text;
            col := col + comma_text_size;
          IFEND;
          name := rvl_info_array_p^ [index].requested_volume_attributes.project;
          size := clp$trimmed_string_size (name);
          IF (col + project_text_size + size) > 80 THEN
            output_line (status);
          IFEND;
          IF status.normal THEN
            display_line (col, project_text_size) := project_text;
            col := col + project_text_size;
            display_line (col, size) := name (1, size);
            col := col + size;
          IFEND;
        IFEND;
        IF status.normal AND (col > 3) THEN
          output_line (status);
        IFEND;
      IFEND;

    PROCEND output_requestor_line;
?? OLDTITLE ??
?? NEWTITLE := '  output_rms_line', EJECT ??

    PROCEDURE output_rms_line
      (VAR status: ost$status);

      CONST
        comma_text = ', ',
        comma_text_size = 2,
        group_text = 'Group: ',
        group_text_size = 7,
        location_text = 'Location: ',
        location_text_size = 10,
        slot_text = 'Slot: ',
        slot_text_size = 6;

      VAR
        size: 1 .. 31,
        name: ost$name;

      display_line := ' ';
      col := 3;
      status.normal := TRUE;

      IF (rvl_info_array_p^ [index].requested_volume_attributes.removable_media_group <> osc$null_name) OR
            (rvl_info_array_p^ [index].requested_volume_attributes.removable_media_location <>
            osc$null_name) OR (rvl_info_array_p^ [index].requested_volume_attributes.slot <> osc$null_name)
            THEN

        IF (rvl_info_array_p^ [index].requested_volume_attributes.removable_media_group <> osc$null_name) THEN
          name := rvl_info_array_p^ [index].requested_volume_attributes.removable_media_group;
          size := clp$trimmed_string_size (name);
          display_line (col, group_text_size) := group_text;
          col := col + group_text_size;
          display_line (col, size) := name (1, size);
          col := col + size;
        IFEND;

        IF rvl_info_array_p^ [index].requested_volume_attributes.removable_media_location <>
              osc$null_name THEN
          IF col > 3 THEN
            display_line (col, comma_text_size) := comma_text;
            col := col + comma_text_size;
          IFEND;
          name := rvl_info_array_p^ [index].requested_volume_attributes.removable_media_location;
          size := clp$trimmed_string_size (name);
          IF (col + location_text_size + size) > 80 THEN
            output_line (status);
          IFEND;
          IF status.normal AND (size > 0) THEN
            display_line (col, location_text_size) := location_text;
            col := col + location_text_size;
            display_line (col, size) := name (1, size);
            col := col + size;
          IFEND;
        IFEND;

        IF status.normal AND (rvl_info_array_p^ [index].requested_volume_attributes.slot <> osc$null_name)
              THEN
          IF col > 3 THEN
            display_line (col, comma_text_size) := comma_text;
            col := col + comma_text_size;
          IFEND;
          name := rvl_info_array_p^ [index].requested_volume_attributes.slot;
          size := clp$trimmed_string_size (name);
          IF (col + slot_text_size + size) > 80 THEN
            output_line (status);
          IFEND;
          IF status.normal THEN
            display_line (col, slot_text_size) := slot_text;
            col := col + slot_text_size;
            display_line (col, size) := name (1, size);
            col := col + size;
          IFEND;
        IFEND;
        IF status.normal AND (col > 3) THEN
          output_line (status);
        IFEND;
      IFEND;

    PROCEND output_rms_line;

?? OLDTITLE ??
?? NEWTITLE := '  tape_mount_display_handler  ', EJECT ??

    PROCEDURE tape_mount_display_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        ignore_status: ost$status;

      CASE condition.selector OF
      = ifc$interactive_condition =
        CASE condition.interactive_condition OF
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        = ifc$terminate_break =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          EXIT ofp$tape_mount_display;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;

    PROCEND tape_mount_display_handler;

?? OLDTITLE, EJECT ??
    VAR
      all_tape_mounts_found: boolean,
      col: 1 .. 80,
      current_element: iot$rvl_entry_information,
      display_control: clt$display_control,
      display_line: string (80),
      ending_index: integer,
      index: integer,
      ignore_status: ost$status,
      loop1_index: iot$no_of_tape_units,
      loop2_index: iot$no_of_tape_units,
      no_tape_mounts_line: [READ, oss$job_paged_literal] string (61) :=
            '                  *** No tape mount requests outstanding. ***',
      rvl_info_array_p: ^array [1 .. * ] of iot$rvl_entry_information,
      starting_index: integer,
      tape_mount_count: integer,
      title_line: [READ, oss$job_paged_literal] string (80) :=
            ' Mount  M Dens <--Operator Action--> A C System_Job_Name     Time  Prev   Next';

    status.normal := TRUE;

    IF wid = 0 THEN
      osp$establish_block_exit_hndlr (^abort_handler);
    IFEND;
    IF initial_call THEN
      ofp$open_display (file_name, wid, dpc$wc_sharing, dpc$wk_table, title_line, display_control, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    REPEAT
      iop$tape_mount_count (tape_mount_count, status);
      IF NOT status.normal THEN
        IF status.condition = dme$unable_to_lock_tape_table THEN
          osp$establish_condition_handler (^tape_mount_display_handler, {handle block exit} FALSE);
          pmp$long_term_wait (one_second, one_second);
          osp$disestablish_cond_handler;
        ELSE
          tape_mount_count := 0;
          status.normal := TRUE;
        IFEND;
      IFEND;
    UNTIL status.normal;

    IF wid <> 0 THEN
      dpp$get_starting_line (wid, starting_index, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF starting_index <> 1 THEN
        IF tape_mount_count <> 0 THEN
          starting_index := starting_index MOD tape_mount_count;
          IF starting_index = 0 THEN
            starting_index := 1;
          IFEND;
        ELSE
          starting_index := 1;
        IFEND;
      IFEND;

      ending_index := starting_index + dpc$number_of_window_lines - 1;
      index := 0;
    ELSE
      display_line := '  ';
      clp$put_display (display_control, display_line, clc$trim, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

{ If there are active tape mount requests, then obtain all Requested VSN List
{ (rvl) entries for the active requests. To ensure we obtain all of the tape
{ mount requests for display, we repeatedly PUSH space on the run time stack
{ and call iop$get_tape_mount_information until all tape mount requests are
{ found. In theory this loop could be repeated and the run time stack could
{ become very large if new tape mount requests continue to occur each and every
{ time that iop$get_tape_mount_information is called without any of the old
{ requests ever being satisfied. But in actual practice this is a highly
{ unlikely scenario.

    IF tape_mount_count <> 0 THEN
      PUSH rvl_info_array_p: [LOWERBOUND (rvl_info_array_p^) .. tape_mount_count];

      REPEAT
        REPEAT
          iop$get_tape_mount_information (rvl_info_array_p, all_tape_mounts_found, status);
          IF NOT status.normal THEN
            IF status.condition = dme$unable_to_lock_tape_table THEN
              osp$establish_condition_handler (^tape_mount_display_handler, {handle block exit} FALSE);
              pmp$long_term_wait (one_second, one_second);
              osp$disestablish_cond_handler;
            ELSE
              RETURN;
            IFEND;
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        IF NOT all_tape_mounts_found THEN
          tape_mount_count := tape_mount_count + 1;
          PUSH rvl_info_array_p: [LOWERBOUND (rvl_info_array_p^) .. tape_mount_count];
        IFEND;
      UNTIL all_tape_mounts_found;

{ Sort tape mount request array elements according to time the tape file was opened.

    /sort_mount_loop1/
      FOR loop1_index := LOWERBOUND (rvl_info_array_p^) TO UPPERBOUND (rvl_info_array_p^) - 1 DO
        IF rvl_info_array_p^ [loop1_index].null_entry THEN
          EXIT /sort_mount_loop1/;
        IFEND;
        index := loop1_index;
        current_element := rvl_info_array_p^ [loop1_index];

      /sort_mount_loop2/
        FOR loop2_index := (loop1_index + 1) TO UPPERBOUND (rvl_info_array_p^) DO
          IF rvl_info_array_p^ [loop2_index].null_entry THEN
            EXIT /sort_mount_loop2/;
          IFEND;
          IF rvl_info_array_p^ [loop2_index].time_of_mount_request <
                current_element.time_of_mount_request THEN
            index := loop2_index;
            current_element := rvl_info_array_p^ [loop2_index];
          IFEND;
        FOREND /sort_mount_loop2/;

        rvl_info_array_p^ [index] := rvl_info_array_p^ [loop1_index];
        rvl_info_array_p^ [loop1_index] := current_element;
      FOREND /sort_mount_loop1/;

      IF wid <> 0 THEN
        IF starting_index > UPPERBOUND (rvl_info_array_p^) THEN
          starting_index := 1;
          ending_index := starting_index + dpc$number_of_window_lines - 1;
        IFEND;
        IF ending_index > UPPERBOUND (rvl_info_array_p^) THEN
          ending_index := UPPERBOUND (rvl_info_array_p^);
        IFEND;
      ELSE
        starting_index := 1;
        ending_index := UPPERBOUND (rvl_info_array_p^);
      IFEND;

    /scan_rvl_info/
      FOR index := starting_index TO ending_index DO
        display_line := '  ';
        IF rvl_info_array_p^ [index].null_entry THEN
          IF wid <> 0 THEN
            dpp$put_next_line (wid, display_line, status);
          ELSE
            clp$put_display (display_control, display_line, clc$trim, status);
          IFEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          EXIT /scan_rvl_info/;
        IFEND;

        display_line (2, 6) := rvl_info_array_p^ [index].current_vsn;
        display_line (42, 19) := rvl_info_array_p^ [index].ssn;
        display_line (62, 5) := rvl_info_array_p^ [index].time_of_mount_request;
        display_line (68, 6) := rvl_info_array_p^ [index].previous_vsn;
        display_line (75, 6) := rvl_info_array_p^ [index].next_vsn;

        IF rvl_info_array_p^ [index].requested_tape_characteristics.write_ring THEN
          display_line (9, 1) := 'W';
        ELSE
          display_line (9, 1) := 'R';
        IFEND;

        CASE rvl_info_array_p^ [index].requested_tape_characteristics.density OF
        = rmc$200 =
          display_line (11, 3) := '200';
        = rmc$556 =
          display_line (11, 3) := '556';
        = rmc$800 =
          display_line (11, 3) := '800';
        = rmc$1600 =
          display_line (11, 4) := '1600';
        = rmc$6250 =
          display_line (11, 4) := '6250';
        = rmc$38000 =
          display_line (11, 5) := '38000';
        ELSE

{ We have encountered an unknown tape density.

          display_line (12, 4) := '****'
        CASEND;
        IF (rvl_info_array_p^ [index].operator_assignment_type = ioc$expecting_manual_assignment) THEN
          display_line (16, 20) := 'ASSIGN_DEVICE needed';
        IFEND;

        CASE rvl_info_array_p^ [index].requested_tape_characteristics.label_type OF
          = amc$labeled =
            display_line (38, 1) := 'L';
          = amc$unlabeled =
            display_line (38, 1) := 'U';
          = amc$non_standard_labeled =
            display_line (38, 1) := 'N';
        ELSE
        CASEND;

        IF (rvl_info_array_p^ [index].requested_tape_characteristics.character_set = amc$ebcdic) THEN
          display_line (40, 1) := 'E';
        ELSE
          display_line (40, 1) := 'A';
        IFEND;

        output_line (status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

{ The following code adds optional fields to one or two additional lines in the display.
{ A blank field is ignored.  A line is omitted if all of its fields are blank.
          output_requestor_line (status);
          IF status.normal THEN
            output_rms_line (status);
          IFEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
      FOREND /scan_rvl_info/;
    IFEND;

    display_line := ' ';
    IF wid = 0 THEN
      IF tape_mount_count = 0 THEN
        clp$put_display (display_control, display_line, clc$trim, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        clp$put_display (display_control, no_tape_mounts_line, clc$trim, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;
    ELSE
      IF index < starting_index + dpc$number_of_window_lines - 1 THEN
        ending_index := starting_index + dpc$number_of_window_lines - 1;
      IFEND;

      IF tape_mount_count = 0 THEN
        dpp$put_next_line (wid, display_line, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        dpp$put_next_line (wid, no_tape_mounts_line, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        index := index + 2;
      IFEND;

      starting_index := index;
      FOR index := starting_index + 1 TO ending_index DO
        dpp$put_next_line (wid, display_line, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      FOREND;
    IFEND;

    IF wid = 0 THEN
      clp$close_display (display_control, status);
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND ofp$tape_mount_display;
?? OLDTITLE ??

 MODEND ofm$console_displays
