MODULE ofm$mass_storage_space_display;
?? RIGHT := 110 ??

{         Capacity (MB)              Queue  Trans  - Disk Errors -
{VSN      Total   Avail   Status     Count  Count   Rec  Int Unrec  Parity FF  Nr
{xxxxxx    5000    5000   space low    xxx    xxx  xxxx xxxx  xxxx      On
{xxxxxx    5000    5000   space low    xxx    xxx  xxxx xxxx  xxxx      No
{xxxxxx  xxxxxx  xxxxxx   normal       xxx    xxx  xxxx xxxx  xxxx     Off FF  23
{xxxxxx  xxxxxx  xxxxxx   normal       xxx    xxx  xxxx xxxx  xxxx Restore     17

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc oss$task_shared
*copyc dmt$active_volume_table_index
*copyc ost$halfword
*copyc ost$status
?? POP ??
*copyc clp$close_display
*copyc clp$put_display
*copyc cmp$get_element_entry_via_lun
*copyc cmp$get_logical_unit_state
*copyc dmp$get_allocation_info
*copyc dmp$get_out_of_space_sets
*copyc dmp$get_physical_attributes
*copyc dpp$clear_window
*copyc dpp$put_next_line
*copyc ofp$build_system_line
*copyc ofp$get_next_avt_index
*copyc ofp$open_display
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc pmp$binary_to_ascii_fit
*copyc cmv$logical_unit_table
*copyc dmv$active_volume_table
*copyc iov$disk_unit_usage_p
*copyc ofv$mass_storage_display_infos
*copyc osv$task_shared_heap

  VAR
    dmv$q_devices_added: [XREF] integer;

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

  CONST
    c$title_seperator_line =
          '--------------------------------------------------------------------------------';

  CONST
    c$init_offline_drive_number = 0ff(16),
    c$no_drives_offline = 0fe(16);

  TYPE
    t$total_attributes = record
      space_1: integer, {availabe or DAT
      space_2: integer, {capacity or MAT
      status_counts: array [t$volume_status] of integer,
      transfer_count: integer,
      queue_count: integer,
      recovered_errors: integer,
      intermediate_errors: integer,
      unrecovered_errors: integer,
      parity_protection_counts: array [t$parity_protection] of integer,
      force_format_count: integer,
      restoring_drive_count: integer,
    recend;

  TYPE
    t$volume_attributes = record
      vsn: rmt$recorded_vsn,
      space_1: integer, {availabe or DAT
      space_2: integer, {capacity or MAT
      status: t$volume_status,
      transfer_count: integer,
      queue_count: 0 .. 0ffff(16),
      parity_protection: t$parity_protection,
      off_line_drive_number: 0 .. 0ff(16),
      force_format: boolean,
      restoring_drive: boolean,
      recovered_errors: integer,
      intermediate_errors: integer,
      unrecovered_errors: integer,
    recend;


  TYPE
    t$parity_protection = (c$pp_no_protection, c$pp_disabled, c$pp_enabled);

  TYPE
    t$volume_status_set = set of t$volume_status,
    t$volume_status = (c$vs_normal, c$vs_disabled, c$vs_down, c$vs_off, c$vs_allocation_not_allowed,
          c$vs_not_available, c$vs_logging_damaged, c$vs_no_space, c$vs_no_files, c$vs_space_low);

  VAR
    v$titles: [READ, oss$job_paged_literal] array [boolean] of array [boolean] of array [1 .. 2] of
          string (80) := [
{ MBYTES         } [
{   CAPACITY&AVAIL } [
{     LINE 1         } '         Capacity (MB)              Queue  Trans  - Disk Errors -',
{     LINE 2         } 'VSN      Total   Avail   Status     Count  Count   Rec  Int Unrec  Parity FF  Nr'],
{   MAT&DAT        } [
{     LINE 1         } '         Capacity (MB)              Queue  Trans  - Disk Errors -',
{     LINE 2         } 'VSN        MAT     DAT   Status     Count  Count   Rec  Int Unrec  Parity FF  Nr']],
{ DAUS           } [
{   CAPACITY&AVAIL } [
{     LINE 1         } '         Capacity (DAUs)            Queue  Trans  - Disk Errors -',
{     LINE 2         } 'VSN      Total   Avail   Status     Count  Count   Rec  Int Unrec  Parity FF  Nr'],
{   MAT&DAT        } [
{     LINE 1         } '         Capacity (DAUs)            Queue  Trans  - Disk Errors -',
{     LINE 2         } 'VSN        MAT     DAT   Status     Count  Count   Rec  Int Unrec  Parity FF  Nr']]];

?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #GATE] OFP$MASS_STORAGE_SPACE_DISPLAY', EJECT ??

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

    VAR
      v$title: [READ, oss$job_paged_literal] string (18) := 'Mass Storage Space',
      v$volume_state_labels: [READ, oss$job_paged_literal] array [t$volume_status] of string (49) := [
{ c$vs_normal                 } 'normal',
{ c$vs_disabled               } 'disabled',
{ c$vs_down                   } 'down    ',
{ c$vs_off                    } 'off     ',
{ c$vs_allocation_not_allowed } 'no alloc',
{ c$vs_not_available          } 'volume is not available',
{ c$vs_logging_damaged        } 'volume is not available - logging process damaged',
{ c$vs_no_space               } 'no space',
{ c$vs_no_files               } 'no files',
{ c$vs_space_low              } 'space low'];

    VAR
      previous_data_for_display: [STATIC, oss$task_shared] boolean := FALSE,
      system_line_info: [STATIC, oss$task_shared] ^oft$system_line_info := NIL;

    VAR
      avt_index: dmt$active_volume_table_index,
      class: dmt$class_member,
      class_index: integer,
      classes: dmt$class,
      control: oft$msdi_volume_access_control,
      display_control: clt$display_control,
      eot: boolean,
      index: integer,
      name_length: integer,
      out_of_space_sets_p: ^dmt$out_of_space_sets,
      set_count: integer,
      set_name: stt$set_name,
      str: string (80),
      string_length: integer,
      total_attributes: t$total_attributes,
      volume_attributes: t$volume_attributes,
      volume_status: t$volume_status,
      volume_status_line_output: boolean;

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

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

      VAR
        ignore_status: ost$status;

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

    PROCEND p$abort_handler;
?? OLDTITLE ??
?? NEWTITLE := 'p$format_total_attributes', EJECT ??

    PROCEDURE p$format_total_attributes
      (    total_attributes: t$total_attributes;
       VAR str: string (80));

      CONST
        c$mega_bytes = 1024 * 1024;

      str := 'Total';
      IF ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity = ofc$msdi_dau THEN
        pmp$binary_to_ascii_fit (total_attributes.space_2, 10, 7, 7, str (8, 7));
        pmp$binary_to_ascii_fit (total_attributes.space_1, 10, 7, 7, str (16, 7));
      ELSE
        pmp$binary_to_ascii_fit (total_attributes.space_2 DIV c$mega_bytes, 10, 7, 7, str (8, 7));
        pmp$binary_to_ascii_fit (total_attributes.space_1 DIV c$mega_bytes, 10, 7, 7, str (16, 7));
      IFEND;
      pmp$binary_to_ascii_fit (total_attributes.queue_count, 10, 5, 5, str (37, 5));
      pmp$binary_to_ascii_fit (total_attributes.transfer_count, 10, 6, 6, str (43, 6));
      pmp$binary_to_ascii_fit (total_attributes.recovered_errors, 10, 5, 5, str (50, 5));
      pmp$binary_to_ascii_fit (total_attributes.intermediate_errors, 10, 4, 4, str (56, 4));
      pmp$binary_to_ascii_fit (total_attributes.unrecovered_errors, 10, 5, 5, str (61, 5));

      IF (total_attributes.parity_protection_counts [c$pp_disabled] <> 0)
{   } OR (total_attributes.restoring_drive_count <> 0) THEN
        pmp$binary_to_ascii_fit (total_attributes.parity_protection_counts [c$pp_disabled],
              10, 3, 3, str (67, 3));
        str (70) := '/';
        pmp$binary_to_ascii_fit (total_attributes.restoring_drive_count, 10, 3, 3, str (71, 3));
      IFEND;

      IF total_attributes.force_format_count <> 0 THEN
        pmp$binary_to_ascii_fit (total_attributes.force_format_count, 10, 3, 3, str (74, 3));
      IFEND;

    PROCEND p$format_total_attributes;
?? OLDTITLE ??
?? NEWTITLE := 'p$format_volume_attributes', EJECT ??

    PROCEDURE p$format_volume_attributes
      (    volume_attributes: t$volume_attributes;
       VAR str: string (80));

      CONST
        c$mega_bytes = 1024 * 1024;

      str := volume_attributes.vsn;
      CASE volume_attributes.status OF
      = c$vs_not_available =
        str (9, 23) := 'Volume is not available';
        RETURN; {----->
      = c$vs_logging_damaged =
        str (9, 49) := 'Volume is not available - logging process damaged';
        RETURN; {----->
      ELSE
        str (26, 9) := v$volume_state_labels [volume_attributes.status];
      CASEND;

      IF ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity = ofc$msdi_dau THEN
        pmp$binary_to_ascii_fit (volume_attributes.space_2, 10, 7, 7, str (8, 7));
        pmp$binary_to_ascii_fit (volume_attributes.space_1, 10, 7, 7, str (16, 7));
      ELSE
        pmp$binary_to_ascii_fit (volume_attributes.space_2 DIV c$mega_bytes, 10, 7, 7, str (8, 7));
        pmp$binary_to_ascii_fit (volume_attributes.space_1 DIV c$mega_bytes, 10, 7, 7, str (16, 7));
      IFEND;
      pmp$binary_to_ascii_fit (volume_attributes.queue_count, 10, 5, 5, str (37, 5));
      pmp$binary_to_ascii_fit (volume_attributes.transfer_count, 10, 6, 6, str (43, 6));
      pmp$binary_to_ascii_fit (volume_attributes.recovered_errors, 10, 5, 5, str (50, 5));
      pmp$binary_to_ascii_fit (volume_attributes.intermediate_errors, 10, 4, 4, str (56, 4));
      pmp$binary_to_ascii_fit (volume_attributes.unrecovered_errors, 10, 5, 5, str (61, 5));

      CASE volume_attributes.parity_protection OF
      = c$pp_disabled =
        IF volume_attributes.restoring_drive THEN
          str (67, 7) := 'Restore';
        ELSE
          str (67, 7) := '    Off';
        IFEND;
      = c$pp_enabled =
        str (67, 7) := '     On';
      ELSE
        str (67, 7) := '';
      CASEND;

      IF volume_attributes.force_format THEN
        str (74, 3) := ' FF';
      ELSE
        str (74, 3) := '   ';
      IFEND;

      IF (volume_attributes.off_line_drive_number = c$init_offline_drive_number)
{   } OR (volume_attributes.off_line_drive_number = c$no_drives_offline) THEN
        str (78, 3) := '   ';
      ELSE
        pmp$binary_to_ascii_fit (volume_attributes.off_line_drive_number, 16, 3, 3, str (78, 3));
      IFEND;

    PROCEND p$format_volume_attributes;
?? OLDTITLE ??
?? NEWTITLE := 'p$get_volume_attributes', EJECT ??

    PROCEDURE p$get_volume_attributes
      (    avt_index: dmt$active_volume_table_index;
       VAR volume_attributes: t$volume_attributes;
       VAR total_attributes: t$total_attributes);

      VAR
        allocation_info: dmt$allocation_info,
        element_state: cmt$element_state,
        logical_unit_p: ^cmt$logical_unit,
        lun: iot$logical_unit,
        status: ost$status,
        unit_interface_entry_p: ^iot$unit_interface_table;

?? NEWTITLE := '[unsafe] f$calculate_device_capacity', EJECT ??

      FUNCTION [UNSAFE] f$calculate_device_capacity
        (    lun: iot$logical_unit): integer;

        VAR
          attributes_p: ^dmt$physical_device_attributes,
          capacity: integer,
          entry_p: ^cmt$peripheral_element_entry,
          status: ost$status;

        capacity := 0;
        cmp$get_element_entry_via_lun (lun, entry_p);
        IF entry_p <> NIL THEN
          PUSH attributes_p: [1 .. 3];
          attributes_p^ [1].keyword := dmc$bytes_per_mau;
          attributes_p^ [2].keyword := dmc$cylinders_per_device;
          attributes_p^ [3].keyword := dmc$maus_per_cylinder;

          dmp$get_physical_attributes (entry_p^.product_id, attributes_p, status);
          IF status.normal THEN
            capacity := attributes_p^ [1].bytes_per_mau * attributes_p^ [2].cylinders_per_device *
                  attributes_p^ [3].maus_per_cylinder;
          IFEND;
        IFEND;

        f$calculate_device_capacity := capacity;

      FUNCEND f$calculate_device_capacity;
?? OLDTITLE ??
?? EJECT ??

      volume_attributes.vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;
      IF NOT dmv$active_volume_table.table_p^ [avt_index].mass_storage.volume_unavailable THEN
        dmp$get_allocation_info (volume_attributes.vsn, avt_index, allocation_info, status);
        IF NOT status.normal THEN
          volume_attributes.status := c$vs_not_available;
          RETURN; {----->
        IFEND;

        lun := dmv$active_volume_table.table_p^ [avt_index].logical_unit_number;

        IF allocation_info.no_space THEN
          volume_attributes.status := c$vs_no_space;
        ELSEIF allocation_info.no_file_entries THEN
          volume_attributes.status := c$vs_no_files;
        ELSEIF allocation_info.space_low THEN
          volume_attributes.status := c$vs_space_low;
        ELSEIF NOT allocation_info.allocation_allowed THEN
          volume_attributes.status := c$vs_allocation_not_allowed;
        ELSE
          volume_attributes.status := c$vs_normal;
        IFEND;

{May be, we alway see ON here, as the AVT sais the volume is available. But I have seen strange
{things in that area!
        IF volume_attributes.status IN $t$volume_status_set
              [c$vs_normal, c$vs_no_space, c$vs_no_files, c$vs_space_low] THEN
          cmp$get_logical_unit_state (lun, cmv$logical_unit_table, element_state);
          CASE element_state OF
          = cmc$off =
            volume_attributes.status := c$vs_off;
          = cmc$down =
            volume_attributes.status := c$vs_down;
          ELSE
            ;
          CASEND;
        IFEND;

        volume_attributes.transfer_count := allocation_info.device_log_count;
        IF ofv$mass_storage_display_infos [ofc$ved_mss].space_selection = ofc$msdi_capacity_available THEN
          volume_attributes.space_1 := allocation_info.available_mat_space +
                allocation_info.available_dat_space;
          volume_attributes.space_2 := f$calculate_device_capacity (lun);

          IF ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity = ofc$msdi_dau THEN
            volume_attributes.space_2 := volume_attributes.space_2 DIV allocation_info.bytes_per_dau;
          ELSE
            volume_attributes.space_1 := volume_attributes.space_1 * allocation_info.bytes_per_dau;
          IFEND;
        ELSEIF ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity = ofc$msdi_dau THEN
          volume_attributes.space_1 := allocation_info.available_dat_space;
          volume_attributes.space_2 := allocation_info.available_mat_space;
        ELSE
          volume_attributes.space_1 := allocation_info.available_dat_space * allocation_info.bytes_per_dau;
          volume_attributes.space_2 := allocation_info.available_mat_space * allocation_info.bytes_per_dau;
        IFEND;

        logical_unit_p := ^cmv$logical_unit_table^ [lun];
        unit_interface_entry_p := logical_unit_p^.unit_interface_table;
        IF (logical_unit_p^.configured) AND (unit_interface_entry_p <> NIL) THEN
          volume_attributes.queue_count := unit_interface_entry_p^.queue_count;
          IF (unit_interface_entry_p^.unit_type <> ioc$dt_ms5833_1p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms5838_1p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms47444_1p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms5837_1p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms5833_3p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms5838_3p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms47444_3p) AND
                (unit_interface_entry_p^.unit_type <> ioc$dt_ms5837_3p) THEN
            volume_attributes.parity_protection := c$pp_no_protection;
          ELSEIF unit_interface_entry_p^.unit_status.parity_protection_enabled THEN
            volume_attributes.parity_protection := c$pp_enabled;
          ELSE
            volume_attributes.parity_protection := c$pp_disabled;
          IFEND;
          volume_attributes.force_format := unit_interface_entry_p^.unit_status.force_format;
          volume_attributes.restoring_drive := unit_interface_entry_p^.unit_status.restoring_drive;
          volume_attributes.off_line_drive_number := unit_interface_entry_p^.unit_status.
                off_line_drive_number;

          IF (unit_interface_entry_p^.unit_status.disabled) AND
                (volume_attributes.status IN $t$volume_status_set
                [c$vs_normal, c$vs_no_space, c$vs_no_files, c$vs_space_low]) THEN
            volume_attributes.status := c$vs_disabled;
          IFEND;
        ELSE
          volume_attributes.queue_count := 0;
          volume_attributes.parity_protection := c$pp_no_protection;
          volume_attributes.force_format := FALSE;
          volume_attributes.restoring_drive := FALSE;
          volume_attributes.off_line_drive_number := 0ff(16);
        IFEND;

        IF (iov$disk_unit_usage_p <> NIL) AND (iov$disk_unit_usage_p^ [lun] <> NIL) THEN
          volume_attributes.recovered_errors := iov$disk_unit_usage_p^ [lun]^.recovered_errors;
          volume_attributes.intermediate_errors := iov$disk_unit_usage_p^ [lun]^.intermediate_errors;
          volume_attributes.unrecovered_errors := iov$disk_unit_usage_p^ [lun]^.unrecovered_errors;
        ELSE
          volume_attributes.recovered_errors := 0;
          volume_attributes.intermediate_errors := 0;
          volume_attributes.unrecovered_errors := 0;
        IFEND;

        total_attributes.space_1 := total_attributes.space_1 + volume_attributes.space_1;
        total_attributes.space_2 := total_attributes.space_2 + volume_attributes.space_2;
        total_attributes.transfer_count := total_attributes.transfer_count + volume_attributes.transfer_count;
        total_attributes.queue_count := total_attributes.queue_count + volume_attributes.queue_count;
        total_attributes.recovered_errors := total_attributes.recovered_errors +
              volume_attributes.recovered_errors;
        total_attributes.intermediate_errors := total_attributes.intermediate_errors +
              volume_attributes.intermediate_errors;
        total_attributes.unrecovered_errors := total_attributes.unrecovered_errors +
              volume_attributes.unrecovered_errors;
        total_attributes.parity_protection_counts [volume_attributes.parity_protection] :=
              total_attributes.parity_protection_counts [volume_attributes.parity_protection] + 1;

        IF volume_attributes.force_format THEN
          total_attributes.force_format_count := total_attributes.force_format_count + 1;
        IFEND;

        IF volume_attributes.restoring_drive THEN
          total_attributes.restoring_drive_count := total_attributes.restoring_drive_count + 1;
        IFEND;

      ELSEIF dmv$active_volume_table.table_p^ [avt_index].mass_storage.logging_process_damaged THEN
        volume_attributes.status := c$vs_logging_damaged;
      ELSE {Volume not available
        volume_attributes.status := c$vs_not_available;
      IFEND;

      total_attributes.status_counts [volume_attributes.status] :=
            total_attributes.status_counts [volume_attributes.status] + 1;

    PROCEND p$get_volume_attributes;
?? OLDTITLE ??
?? NEWTITLE := '[inline] p$put_line', EJECT ??

    PROCEDURE [INLINE] p$put_line
      (    str: string ( * <= 80));

      VAR
        status: ost$status;

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

    PROCEND p$put_line;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;
    IF wid = 0 THEN
      osp$establish_block_exit_hndlr (^p$abort_handler);
    IFEND;
    IF initial_call THEN
      ofp$open_display (file_name, wid, dpc$wc_sharing, dpc$wk_table, v$title, display_control, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

{ Establish base values for the display if they do not already exist.

    IF NOT previous_data_for_display THEN
      ALLOCATE system_line_info IN osv$task_shared_heap^;
      system_line_info^.initialized := FALSE;
      previous_data_for_display := TRUE;
    IFEND;

    ofp$build_system_line (system_line_info^, str);
    IF wid <> 0 THEN
      dpp$clear_window (wid, status);
    IFEND;

    p$put_line (str);
    p$put_line ('');
    p$put_line (v$titles [ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity =
          ofc$msdi_dau] [ofv$mass_storage_display_infos [ofc$ved_mss].space_selection = ofc$msdi_mat_dat]
          [1]);
    p$put_line (v$titles [ofv$mass_storage_display_infos [ofc$ved_mss].space_quantity =
          ofc$msdi_dau] [ofv$mass_storage_display_infos [ofc$ved_mss].space_selection = ofc$msdi_mat_dat]
          [2]);
    p$put_line (c$title_seperator_line);

    total_attributes.space_1 := 0;
    total_attributes.space_2 := 0;
    total_attributes.transfer_count := 0;
    total_attributes.queue_count := 0;
    total_attributes.recovered_errors := 0;
    total_attributes.intermediate_errors := 0;
    total_attributes.unrecovered_errors := 0;
    total_attributes.parity_protection_counts [c$pp_no_protection] := 0;
    total_attributes.parity_protection_counts [c$pp_disabled] := 0;
    total_attributes.parity_protection_counts [c$pp_enabled] := 0;
    total_attributes.force_format_count := 0;
    total_attributes.restoring_drive_count := 0;
    FOR volume_status := LOWERVALUE (volume_status) TO UPPERVALUE (volume_status) DO
      total_attributes.status_counts [volume_status] := 0;
    FOREND;

    IF ofc$msdi_classes_out_of_space IN ofv$mass_storage_display_infos [ofc$ved_mss].display_options.
          values THEN
      PUSH out_of_space_sets_p: [1 .. UPPERBOUND (dmv$active_volume_table.table_p^) + 1];
      dmp$get_out_of_space_sets (out_of_space_sets_p^, set_count);

      FOR index := 1 TO set_count DO
        set_name := out_of_space_sets_p^ [index].set_name;
        classes := out_of_space_sets_p^ [index].classes;
        IF (classes <> $dmt$class []) THEN
          IF (set_name = osc$null_name) THEN
            STRINGREP (str, string_length, ' Classes out of space:');
          ELSE
            name_length := STRLENGTH (set_name);
            WHILE (name_length > 0) AND (set_name (name_length) = ' ') DO
              name_length := name_length - 1;
            WHILEND;
            STRINGREP (str, string_length, ' ', set_name (1, name_length), ' classes out of space:');
          IFEND;
          class_index := string_length + 1;

          FOR class := LOWERVALUE (dmt$class_member) TO UPPERVALUE (dmt$class_member) DO
            IF class IN classes THEN
              IF (class_index >= STRLENGTH (str)) THEN
                p$put_line (str (1, class_index - 1));
                str (1, string_length) := ' ';
                class_index := string_length + 1;
              IFEND;
              str (class_index, 1) := ' ';
              str (class_index + 1, 1) := $CHAR ($INTEGER (class));
              class_index := class_index + 2;
            IFEND;
          FOREND;

          p$put_line (str (1, class_index - 1));
        IFEND;
      FOREND;
    IFEND;

    IF ofc$msdi_crit_class_added_count IN ofv$mass_storage_display_infos [ofc$ved_mss].display_options.
          values THEN
      IF dmv$q_devices_added <> 0 THEN
        STRINGREP (str, string_length, ' Class Q devices automatically added: ', dmv$q_devices_added);
        p$put_line (str (1, string_length));
      IFEND;
    IFEND;

    control.last_used_index := 0;
    control.sort_option_p := ^ofv$mass_storage_display_infos [ofc$ved_mss].sort_option;
    IF (control.sort_option_p^.key = ofc$msdi_user_defined)
{ } AND (control.sort_option_p^.display_omitted_units) THEN
      PUSH control.avt_entries_displayed_p: [LOWERBOUND (dmv$active_volume_table.table_p^
            ) .. UPPERBOUND (dmv$active_volume_table.table_p^)];
      FOR avt_index := LOWERBOUND (control.avt_entries_displayed_p^)
            TO UPPERBOUND (control.avt_entries_displayed_p^) DO
        control.avt_entries_displayed_p^ [avt_index] := FALSE;
      FOREND;
    ELSE
      control.avt_entries_displayed_p := NIL;
    IFEND;

    REPEAT
      ofp$get_next_avt_index (control, avt_index, eot);
      IF NOT eot THEN
        p$get_volume_attributes (avt_index, volume_attributes, total_attributes);
        p$format_volume_attributes (volume_attributes, str);
        p$put_line (str);
      IFEND;
    UNTIL eot;

    IF ofc$msdi_total IN ofv$mass_storage_display_infos [ofc$ved_mss].display_options.values THEN
      p$put_line (c$title_seperator_line);
      p$format_total_attributes (total_attributes, str);
      p$put_line (str);
    IFEND;

    IF ofc$msdi_volume_status_summary IN ofv$mass_storage_display_infos [ofc$ved_mss].display_options.
          values THEN
      {Output Volume Status Summary if not all Volumes Normal
      volume_status_line_output := FALSE;
      FOR volume_status := SUCC (c$vs_normal) TO UPPERVALUE (volume_status) DO
        IF total_attributes.status_counts [volume_status] <> 0 THEN
          IF NOT volume_status_line_output THEN
            volume_status_line_output := TRUE;
            p$put_line ('');
          IFEND;
          str := 'Volume Status Counts: ';
          pmp$binary_to_ascii_fit (total_attributes.status_counts [volume_status], 10, 5, 5, str (23, 5));
          str (29) := '-';
          str (31, 49) := v$volume_state_labels [volume_status];
          p$put_line (str);
        IFEND;
      FOREND;
    IFEND;

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

  PROCEND ofp$mass_storage_space_display;
?? OLDTITLE ??
MODEND ofm$mass_storage_space_display;
