?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Operator Facility : Asynchronous system task procedures' ??
MODULE ofm$async_task_interfaces;

{ PURPOSE:
{   This module contains procedures to execute the display task in an asynchronous task.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc oss$task_shared
*copyc ofd$type_definition
*copyc dme$tape_errors
*copyc ofe$condition_codes
*copyc ofe$error_codes
*copyc clt$parameter_list
*copyc fst$file_reference
*copyc oft$display_procedure
*copyc oft$operator_alarm
*copyc oft$operator_classes
*copyc oft$refreshing_displays
*copyc oft$screen_status
?? POP ??
*copyc avp$removable_media_admin
*copyc avp$removable_media_operator
*copyc avp$system_displays
*copyc avp$system_operator
*copyc clp$convert_str_to_path_handle
*copyc cmp$ved_display_configuration
*copyc cmp$ved_display_pp
*copyc dfp$file_server_display
*copyc dmp$display_mass_storage
*copyc dmp$tape_reservations_display
*copyc dmp$tape_status_display
*copyc dpp$change_window
*copyc dpp$open_window
*copyc dpp$set_180_operator_action
*copyc dpp$set_title
*copyc iop$log_usage_statistics
*copyc iop$tape_mounts_pending
*copyc jmp$purge_expired_file
*copyc jmp$purge_expired_queue_file
*copyc jmp$purge_printed_file
*copyc jmp$purge_processed_queue_file
*copyc jmp$system_job
*copyc ofp$critical_window_log_display
*copyc ofp$display
*copyc ofp$display_resource_table
*copyc ofp$dynamic_aging_stat_disp
*copyc ofp$dynamic_aging_stat_tot_disp
*copyc ofp$general_statistics_display
*copyc ofp$get_active_operator_classes
*copyc ofp$get_first_operator_menu_r1
*copyc ofp$get_operator_messages
*copyc ofp$io_summary_display
*copyc ofp$job_log_display
*copyc ofp$mass_storage_space_display
*copyc ofp$mass_storage_usage_display
*copyc ofp$mem_manager_stat_total_disp
*copyc ofp$memory_manager_stat_display
*copyc ofp$memory_ring_request_trace
*copyc ofp$operator_message_display
*copyc ofp$pico_statistics
*copyc ofp$queue_files_display
*copyc ofp$shared_aging_stat_inc_disp
*copyc ofp$shared_aging_stat_tot_disp
*copyc ofp$special_statistics_display
*copyc ofp$swap_state_stat_inc_disp
*copyc ofp$swap_state_stat_total_disp
*copyc ofp$swap_trace_stat_inc_disp
*copyc ofp$swap_trace_stat_total_disp
*copyc ofp$system_header_display
*copyc ofp$system_log_display
*copyc ofp$tape_mount_display
*copyc ofp$verify_display_name
*copyc osp$change_date_time
*copyc osp$clear_signature_lock
*copyc osp$emit_os_statistics
*copyc osp$establish_condition_handler
*copyc osp$initialize_signature_lock
*copyc osp$set_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$update_wait_frc
*copyc pmp$continue_to_cause
*copyc pmp$log
*copyc pmp$wait
*copyc qfp$ready_deferred_file
*copyc qfp$ready_deferred_job
*copyc qfp$ready_deferred_queue_file
?? EJECT ??
*copyc avv$validated_sou_capabilities
*copyc clv$standard_files
*copyc dpv$display_delay
*copyc dpv$system_core_display
*copyc iov$time_to_log_usage_stats
*copyc jmv$purge_expired_qfile_time
*copyc jmv$purge_processed_qfile_time
*copyc jmv$ready_deferred_qfile_time
*copyc jmv$time_to_purge_expired_file
*copyc jmv$time_to_purge_printed_file
*copyc jmv$time_to_ready_deferred_file
*copyc jmv$time_to_ready_deferred_job
*copyc osv$os_defaults
*copyc osv$time_to_emit_statistics
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    half_second = 500 {milliseconds},
    one_second = 1000 {milliseconds};

  VAR
    ofv$screen_status: [XDCL, oss$task_shared] oft$screen_status :=
          [REP 3 of [[0], 0, ofc$da_process_display,' ', ofc$du_no_one, NIL, FALSE, 0]],

    v$displays: [XDCL, #GATE, READ, oss$job_paged_literal] ARRAY [0 .. 31] OF RECORD
      long_name: string (31),
      short_name: string (4),
      procedure_p: oft$display_procedure,
    RECEND := [
{     } [' user defined ',                    ' ud ',  ^ofp$display],
{     } ['CRITICAL_WINDOW_LOG',               'CWL',   ^ofp$critical_window_log_display],
{     } ['JOB_LOG',                           'JL ',   ^ofp$job_log_display],
{     } ['GENERAL_STATISTICS',                'GS ',   ^ofp$general_statistics_display],
{     } ['SPECIAL_STATISTICS',                'SS ',   ^ofp$special_statistics_display],
{     } ['IO_SUMMARY',                        'IS ',   ^ofp$io_summary_display],
{     } ['SYSTEM_LOG',                        'SL ',   ^ofp$system_log_display],
{     } ['MASS_STORAGE',                      'MS ',   ^dmp$display_mass_storage],
{     } ['TAPE_STATUS',                       'TS',    ^dmp$tape_status_display],
{     } ['TAPE_RESERVATIONS',                 'TR',    ^dmp$tape_reservations_display],
{     } ['PP_ASSIGNMENT',                     'PA',    ^cmp$ved_display_pp],
{     } ['DEVICE_STATUS',                     'DS',    ^cmp$ved_display_configuration],
{     } ['FILE_SERVER',                       'FS',    ^dfp$file_server_display],
{     } ['OPERATOR_MESSAGE',                  'OM',    ^ofp$operator_message_display],
{     } ['TAPE_MOUNT',                        'TM',    ^ofp$tape_mount_display],
{     } ['IOU_RESOURCE_TABLE',                'IRT',   ^ofp$display_resource_table],
{     } ['MASS_STORAGE_SPACE',                'MSS',   ^ofp$mass_storage_space_display],
{     } ['MASS_STORAGE_USAGE',                'MSU',   ^ofp$mass_storage_usage_display],
{     } ['MEMORY_MANAGER_STATISTICS',         'MMS',   ^ofp$memory_manager_stat_display],
{     } ['MEMORY_MANAGER_STATISTICS_TOTAL',   'MMST',  ^ofp$mem_manager_stat_total_disp],
{     } ['MEMORY_RING_REQUEST_TRACE',         'MRRT',  ^ofp$memory_ring_request_trace],
{     } ['SHARED_AGING_STATISTICS',           'SAS',   ^ofp$shared_aging_stat_inc_disp],
{     } ['SHARED_AGING_STATISTICS_TOTAL',     'SAST',  ^ofp$shared_aging_stat_tot_disp],
{     } ['SWAP_TRACE_STATISTICS_TOTAL',       'STST',  ^ofp$swap_trace_stat_total_disp],
{     } ['SWAP_TRACE_STATISTICS',             'STS',   ^ofp$swap_trace_stat_inc_disp],
{     } ['SWAP_STATE_STATISTICS_TOTAL',       'SSST',  ^ofp$swap_state_stat_total_disp],
{     } ['SWAP_STATE_STATISTICS',             'SSS',   ^ofp$swap_state_stat_inc_disp],
{     } ['DYNAMIC_AGING_STATISTICS_TOTAL',    'DAST',  ^ofp$dynamic_aging_stat_tot_disp],
{     } ['DYNAMIC_AGING_STATISTICS',          'DAS',   ^ofp$dynamic_aging_stat_disp],
{     } ['QUEUE_FILES             ',          'QF',    ^ofp$queue_files_display],
{     } ['PICO_STATISTICS',                   'PICO',  ^ofp$pico_statistics],
{     } ['NULL',                              'NULL',  NIL]],

    v$screen_name: [STATIC, READ, oss$job_paged_literal] ARRAY [oft$screen_files] OF ost$name :=
          ['DISPLAY_A', 'DISPLAY_B', 'OUTPUT'];

 VAR
    ofv$enable_user_displays: [XREF] boolean;

?? OLDTITLE ??
?? NEWTITLE := 'ofp$get_active_operator_alarms', EJECT ??

{ PURPOSE:
{   This procedure returns a set indicating the operator conditions currently requiring attention.

  PROCEDURE [XDCL, #GATE] ofp$get_active_operator_alarms
    (VAR active_operator_alarms: oft$operator_alarms);

    VAR
      active_operator_classes: oft$operator_classes,
      menu_descriptor: oft$operator_menu_descriptor,
      message_array: array [1 .. 1] of oft$operator_message_descriptor,
      message_count: integer,
      messages_active: boolean,
      mounts_pending: boolean,
      status: ost$status;

    active_operator_alarms := $oft$operator_alarms [];
    IF avp$system_displays () THEN
      active_operator_classes := -$oft$operator_classes [];
    ELSE
      ofp$get_active_operator_classes (active_operator_classes);
      IF active_operator_classes = $oft$operator_classes [] THEN
        RETURN;
      IFEND;
    IFEND;

    IF (ofc$removable_media_operator IN active_operator_classes) THEN
      REPEAT
        iop$tape_mounts_pending (mounts_pending, status);
        IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
          pmp$wait (one_second, one_second);
        IFEND;
      UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
      IF status.normal AND mounts_pending THEN
        active_operator_alarms := active_operator_alarms + $oft$operator_alarms [ofc$tape_mounts];
      IFEND;
    IFEND;

    ofp$get_first_operator_menu_r1 (active_operator_classes, menu_descriptor, status);
    IF status.normal THEN
      active_operator_alarms := active_operator_alarms + $oft$operator_alarms [ofc$menu_requests];
    IFEND;

    ofp$get_operator_messages (active_operator_classes, message_array, message_count, status);
    IF message_count <> 0 THEN
      active_operator_alarms := active_operator_alarms + $oft$operator_alarms [ofc$operator_messages];
    IFEND;
  PROCEND ofp$get_active_operator_alarms;
?? OLDTITLE ??
?? NEWTITLE := 'ofp$execute_display_task', EJECT ??

{ PURPOSE:
{   This procedure executes the requested procedure.  If a display file
{   is not requested as the output file the requested procedure is executed.
{   if a display file is requested as the output file then the display file
{   is set up so that during the system console task's main loop the
{   procedure will be executed.

  PROCEDURE [XDCL, #GATE] ofp$execute_display_task
    (    file_reference: fst$file_reference;
         xdisplay_name: ost$name;
     VAR status: ost$status);

    VAR
      di: integer,
      display_name: ost$name,
      ignore_file_reference: fst$evaluated_file_reference,
      new_screen_file: oft$screen_files,
      old_screen_file: oft$screen_files,
      operator_class_name: string (osc$max_string_size),
      operator_class_name_length: integer,
      path_handle_name: fst$path_handle_name,
      removable_media_admin_name: [READ, oss$job_paged_literal] string (30) :=
            'REMOVABLE_MEDIA_ADMINISTRATION',
      removable_media_operator_name: [READ, oss$job_paged_literal] string (25) := 'REMOVABLE_MEDIA_OPERATION',
      screen_file: oft$screen_files,
      screen_file_name: ost$name,
      system_displays_name: [READ, oss$job_paged_literal] string (19) := 'SYSTEM_DISPLAYS or ',
      system_operator_name: [READ, oss$job_paged_literal] string (16) := 'SYSTEM_OPERATION';

    status.normal := TRUE;
    di := 0;

    { Search the user defined display name list. If not found check for a hard-coded display name.
    { Error if name not found in either list.

    ofp$verify_display_name (xdisplay_name, display_name, status);
    IF NOT status.normal THEN
      ofp$search_for_display_name (xdisplay_name, di);
      IF di = 0 THEN
        RETURN;
      IFEND;
      display_name := v$displays [di].long_name;
    IFEND;

  /execute_task/
    BEGIN

      { The caller is validated for use of the requested display according to the
      { following set of rules:
      {
      { 1. The NULL, JOB_LOG, CRITICAL_WINDOW_LOG and SYSTEM_LOG display options are available only to
      {    the system console.
      { 2. The OPERATOR_MESSAGE display is available to callers with SYSTEM_OPERATION
      {    and/or REMOVABLE_MEDIA_OPERATION capability.
      { 3. The TAPE_RESERVATIONS display is available to callers with
      {    REMOVABLE_MEDIA_OPERATION capability.
      { 4. The TAPE_MOUNT and TAPE_STATUS displays are available to callers with
      {    REMOVABLE_MEDIA_ADMINISTRATION and/or REMOVABLE_MEDIA_OPERATION capability.
      { 5. All additional displays (those not covered in items 1 thru 4) require
      {    SYSTEM_OPERATION capability.
      { 6. If the caller has SYSTEM_DISPLAYS capability, then the rules specified
      {    in items 2 thru 5 do not apply, and those displays are available.

    /validate_for_display/
      BEGIN
        IF v$displays [di].procedure_p = NIL THEN
          IF NOT jmp$system_job () THEN
            osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_display_for_user, 'NULL', status);
            EXIT /execute_task/;
          IFEND;

          EXIT /validate_for_display/;
        IFEND;

        IF v$displays [di].procedure_p = ^ofp$job_log_display THEN
          IF NOT jmp$system_job () THEN
            osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_display_for_user, 'JOB_LOG',
                  status);
            EXIT /execute_task/;
          IFEND;
          EXIT /validate_for_display/;
        IFEND;

        IF v$displays [di].procedure_p = ^ofp$system_log_display THEN
          IF NOT jmp$system_job () THEN
            osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_display_for_user, 'SYSTEM_LOG',
                  status);
            EXIT /execute_task/;
          IFEND;
          EXIT /validate_for_display/;
        IFEND;

        IF v$displays [di].procedure_p = ^ofp$critical_window_log_display THEN
          IF NOT jmp$system_job () THEN
            osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_display_for_user,
                  'CRITICAL_WINDOW_LOG', status);
            EXIT /execute_task/;
          IFEND;
          EXIT /validate_for_display/;
        IFEND;

        IF NOT avp$system_displays () AND NOT ofv$enable_user_displays THEN
          operator_class_name := system_displays_name;
          operator_class_name_length := #SIZE(system_displays_name);
          IF v$displays [di].procedure_p = ^ofp$operator_message_display THEN
            IF NOT (avp$removable_media_operator () OR avp$system_operator ()) THEN
              operator_class_name (operator_class_name_length + 1, #SIZE (removable_media_operator_name)) :=
                    removable_media_operator_name;
              operator_class_name_length := operator_class_name_length + #SIZE(removable_media_operator_name);
              operator_class_name (operator_class_name_length + 1, 4) := ' or ';
              operator_class_name_length := operator_class_name_length + 4;
              operator_class_name (operator_class_name_length + 1, #SIZE (system_operator_name)) :=
                    system_operator_name;
              operator_class_name_length := operator_class_name_length + #SIZE(system_operator_name);
            ELSE
              EXIT /validate_for_display/;
            IFEND;

          ELSEIF v$displays [di].procedure_p = ^dmp$tape_reservations_display THEN
            IF avp$removable_media_operator () THEN
              EXIT /validate_for_display/;
            ELSE
              operator_class_name (operator_class_name_length + 1, #SIZE (removable_media_operator_name)) :=
                    removable_media_operator_name;
              operator_class_name_length := operator_class_name_length + #SIZE(removable_media_operator_name);
            IFEND;

          ELSEIF (v$displays [di].procedure_p = ^ofp$tape_mount_display) OR
                (v$displays [di].procedure_p = ^dmp$tape_status_display) THEN
            IF avp$removable_media_admin () OR avp$removable_media_operator () THEN
              EXIT /validate_for_display/;
            ELSE
              operator_class_name (operator_class_name_length + 1, #SIZE (removable_media_admin_name)) :=
                    removable_media_admin_name;
              operator_class_name_length := operator_class_name_length + #SIZE(removable_media_admin_name);
              operator_class_name (operator_class_name_length + 1, 4) := ' or ';
              operator_class_name_length := operator_class_name_length + 4;
              operator_class_name (operator_class_name_length + 1, #SIZE (removable_media_operator_name)) :=
                    removable_media_operator_name;
              operator_class_name_length := operator_class_name_length + #SIZE(removable_media_operator_name);
            IFEND;

          ELSE

            IF avp$system_operator () THEN
              EXIT /validate_for_display/;
            ELSE
              operator_class_name (operator_class_name_length + 1,
                    #SIZE (system_operator_name)) := system_operator_name;
              operator_class_name_length := operator_class_name_length + #SIZE (system_operator_name);
            IFEND;
          IFEND;

          osp$set_status_abnormal (ofc$operator_facility_id, ofe$sou_not_active,
                operator_class_name (1, operator_class_name_length), status);
          EXIT /execute_task/;
        IFEND;

      END /validate_for_display/;

      { Determine whether one of the screen files already has the requested display.
      { The main screen file will be used as the default.

      old_screen_file := ofc$sf_main_or_other;

    /search_for_old/
      FOR screen_file := ofc$sf_display_a TO ofc$sf_display_b DO
        osp$set_signature_lock (ofv$screen_status [screen_file].file_lock, osc$wait, status);
        IF ofv$screen_status [screen_file].display_name = display_name THEN
          old_screen_file := screen_file;
          osp$clear_signature_lock (ofv$screen_status [screen_file].file_lock, status);
          EXIT /search_for_old/;
        IFEND;
        osp$clear_signature_lock (ofv$screen_status [screen_file].file_lock, status);
      FOREND /search_for_old/;

      { Determine which screen file is being requested for the new display.

      clp$convert_str_to_path_handle (file_reference, FALSE, TRUE, TRUE, path_handle_name,
            ignore_file_reference, status);
      IF NOT status.normal THEN
        EXIT /execute_task/;
      IFEND;

      IF path_handle_name = clv$standard_files [clc$sf_display_a_file].path_handle_name THEN
        new_screen_file := ofc$sf_display_a;
      ELSEIF path_handle_name = clv$standard_files [clc$sf_display_b_file].path_handle_name THEN
        new_screen_file := ofc$sf_display_b;
      ELSE
        new_screen_file := ofc$sf_main_or_other;
      IFEND;

      { If the display procedure is NIL then terminate the window.

      IF v$displays [di].procedure_p = NIL THEN
        osp$set_signature_lock (ofv$screen_status [new_screen_file].file_lock, osc$wait, status);
        ofv$screen_status [new_screen_file].display_action := ofc$da_terminate_window;
        osp$clear_signature_lock (ofv$screen_status [new_screen_file].file_lock, status);
        EXIT /execute_task/;
      IFEND;

      IF old_screen_file <> new_screen_file THEN

        { Terminate the old display.

        osp$set_signature_lock (ofv$screen_status [old_screen_file].file_lock, osc$wait, status);
        ofv$screen_status [old_screen_file].display_action := ofc$da_terminate_window;
        osp$clear_signature_lock (ofv$screen_status [old_screen_file].file_lock, status);
      ELSEIF new_screen_file <> ofc$sf_main_or_other THEN

        { Same display requested, no need to rerequest the display it will be updated
        { during the operator display task.

        EXIT /execute_task/;
      IFEND;

      { If the file requested is the main screen or some other file then call the procedure.

      IF new_screen_file = ofc$sf_main_or_other THEN
        v$displays [di].procedure_p^ (0, display_name, path_handle_name, TRUE, status);
        EXIT /execute_task/;
      IFEND;

      { Wait for previous display to finish processing on the desired screen file.
      { Set the screen status so the screen file will be processed with the new display
      { in the system display manager task.

      WHILE TRUE DO
        osp$set_signature_lock (ofv$screen_status [new_screen_file].file_lock, osc$wait, status);
        IF ofv$screen_status [new_screen_file].display_user = ofc$du_no_one THEN
          ofv$screen_status [new_screen_file].display_procedure_p := v$displays [di].procedure_p;
          ofv$screen_status [new_screen_file].display_name := display_name;
          ofv$screen_status [new_screen_file].display_action := ofc$da_process_display;
          ofv$screen_status [new_screen_file].initial_call := TRUE;
          ofv$screen_status [new_screen_file].display_user := ofc$du_ve_display_user;
          osp$clear_signature_lock (ofv$screen_status [new_screen_file].file_lock, status);
          EXIT /execute_task/;
        ELSEIF ofv$screen_status [new_screen_file].display_user = ofc$du_file_user THEN
          osp$clear_signature_lock (ofv$screen_status [new_screen_file].file_lock, status);
          osp$set_status_abnormal ('OF', 1, 'display is busy', status);
          EXIT /execute_task/;
        ELSE
          ofv$screen_status [new_screen_file].display_action := ofc$da_new_display_requested;
          osp$clear_signature_lock (ofv$screen_status [new_screen_file].file_lock, status);
          pmp$wait (half_second, half_second);
        IFEND;
      WHILEND;

    END /execute_task/;

  PROCEND ofp$execute_display_task;
?? OLDTITLE ??
?? NEWTITLE := 'ofp$search_for_display_name', EJECT ??

{ PURPOSE:
{   Search standard display list for display name. If not found (di=0), assume its a user defined display.
{ NOTE:
{   The procedure is used by OFM$DESIGNER_SCREENS to check for duplicate display names

  PROCEDURE [XDCL, INLINE] ofp$search_for_display_name
    (     display_name: ost$name;
      VAR di: integer);

    di := UPPERBOUND (v$displays);

    WHILE (di > 0 ) AND (v$displays [di].long_name <> display_name)
        AND (v$displays [di].short_name <> display_name) DO
      di := di - 1;
    WHILEND;

 PROCEND ofp$search_for_display_name;
?? OLDTITLE ??
?? NEWTITLE := 'ofp$system_display_manager', EJECT ??

{ PURPOSE:
{   This procedure runs as an asynchronous task in the system job and creates the system console output.

  PROCEDURE [XDCL, #GATE] ofp$system_display_manager
    (    parameters: clt$parameter_list;
     VAR status: ost$status);

    VAR
      action_set: [STATIC, oss$task_private] boolean := FALSE,
      current_time: integer,
      delay_time: integer,
      screen_file: oft$screen_files,
      screen_file_index: oft$screen_files, {  Copy of 'screen_file'.
      screen_status_set_up: [STATIC, oss$task_shared] boolean := FALSE,
      unused_os_defaults: ost$operating_system_default;
?? NEWTITLE := 'clear_screen_file_lock', EJECT ??

{ PURPOSE:
{   This procedures is a condition handler established to clear the screen file lock if the system
{   display manager aborts.  The lock must be clear for the system display manager task to restart.
{
{ NOTE:
{   The variable 'screen_file_index' must be in memory for this condition handler to work.  Users
{   should use #SPOIL to ensure this.

    PROCEDURE clear_screen_file_lock
      (    condition: pmt$condition;
           cond_desc: ^pmt$condition_information;
           save: ^ost$stack_frame_save_area;
       VAR status: ost$status);

      VAR
        local_status: ost$status, {  Use local status, handler status has special meaning to condition.
        lock_status: ost$signature_lock_status;

      IF condition.selector = pmc$block_exit_processing THEN

        { This task is terminating, clear screen file lock if set.

        osp$initialize_signature_lock (ofv$screen_status [screen_file_index].file_lock,local_status);

      ELSE {  Ignore all other conditions.
        pmp$continue_to_cause (pmc$execute_standard_procedure, local_status);
      IFEND;

    PROCEND clear_screen_file_lock;
?? OLDTITLE ??
?? NEWTITLE := 'manage_alarm_fields', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to manage the fields on the main console
{   which alert the operator to conditions requiring operator action
{ NOTE:
{   If any alarm conditions exist to which the main console operator may respond,
{   then initiate the flashing attention field in the main window header. If the
{   attention field is currently flashing, but no alarm conditons exist, then
{   clear the field. The variable dpv$180_operator_action is managed similarly to
{   the attention field to ensure that an operator on a dual state system is
{   aware of any NOS/VE conditions requiring operator action.

    PROCEDURE manage_alarm_fields;

      VAR
        alarm_conditions_exist: boolean,
        capabilities: oft$operator_classes,
        capable: boolean,
        main_window_title:  string (80),
        menu_descriptor: oft$operator_menu_descriptor,
        message_array: array [1 .. 1] of oft$operator_message_descriptor,
        message_count: integer,
        mounts_pending: boolean;

      alarm_conditions_exist := FALSE;
      capabilities := $oft$operator_classes [];

     /check_for_alarm_conditions/
      BEGIN
        IF avc$cc_removable_media_operator IN avv$validated_sou_capabilities THEN
          REPEAT
            iop$tape_mounts_pending (mounts_pending, status);
            IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
              pmp$wait (one_second, one_second);
            IFEND;
          UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IF status.normal THEN
            IF mounts_pending THEN
              alarm_conditions_exist := TRUE;
              EXIT /check_for_alarm_conditions/;
            ELSE
              capabilities := $oft$operator_classes [ofc$removable_media_operator];
            IFEND;
          IFEND;
        IFEND;

        IF avc$cc_system_operator IN avv$validated_sou_capabilities THEN
          capabilities := capabilities + $oft$operator_classes [ofc$system_operator];
        IFEND;

        IF capabilities <> $oft$operator_classes [] THEN
          ofp$get_first_operator_menu_r1 (capabilities, menu_descriptor, status);
          IF status.normal THEN
            alarm_conditions_exist := TRUE;
            EXIT /check_for_alarm_conditions/;
          IFEND;

          ofp$get_operator_messages (capabilities, message_array, message_count, status);
          IF message_count <> 0 THEN
            alarm_conditions_exist := TRUE;
          IFEND;
        IFEND;
      END /check_for_alarm_conditions/;

      IF alarm_conditions_exist THEN
        IF NOT action_set THEN
          action_set := TRUE;
          main_window_title :=
                '                              Main Operator Window                       ACTION ';
          main_window_title (1, 1) := $CHAR (14);
          dpp$set_title (dpv$system_core_display, main_window_title, status);
          dpp$set_180_operator_action (TRUE);
        IFEND;
      ELSE
        IF action_set THEN
          action_set := FALSE;
          main_window_title :=
                '                              Main Operator Window                              ';
          dpp$set_title (dpv$system_core_display, main_window_title, status);
          dpp$set_180_operator_action (FALSE);
        IFEND;
      IFEND;

    PROCEND manage_alarm_fields;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;

    { Setup the screen status data.  Date and time must be updated once per deadstart to assure accuracy.
    { It is done at this point because it can handle the delay for top of minute once it enters the master
    { task loop.

    IF NOT screen_status_set_up THEN
      osp$change_date_time (FALSE, unused_os_defaults, status);
      screen_status_set_up := TRUE;
      FOR screen_file := ofc$sf_display_a TO ofc$sf_main_or_other DO
        IF screen_file = ofc$sf_main_or_other THEN
          ofv$screen_status [screen_file].window_id := dpv$system_core_display;
        ELSE
          dpp$open_window (dpc$wc_invisible, dpc$wk_table, v$screen_name [screen_file],
                ofv$screen_status [screen_file].window_id, status);
        IFEND;
        ofv$screen_status [screen_file].display_action := ofc$da_process_display;
        ofv$screen_status [screen_file].display_name := ' ';
        ofv$screen_status [screen_file].display_user := ofc$du_no_one;
        ofv$screen_status [screen_file].display_procedure_p := NIL;
        ofv$screen_status [screen_file].initial_call := FALSE;
        ofv$screen_status [screen_file].open_file_count := 0;
        osp$initialize_signature_lock (ofv$screen_status [screen_file].file_lock, status);
      FOREND;
    ELSE
      pmp$log (' Operator Display Task Restarted', status);

      osp$initialize_signature_lock (ofv$screen_status [screen_file].file_lock, status);

    IFEND;

    {  The following loop is the main processing loop for updating the operating displays.  It loops for the
    {  life of the operator display task.  Establish a condition handler to clear screen file lock if this
    {  task is aborted with screen file lock set.

    osp$establish_condition_handler (^clear_screen_file_lock, TRUE);

  /master_task_loop/
    WHILE TRUE DO

      { Display the display header and adjust time if necessary.

      ofp$system_header_display;

      manage_alarm_fields;

      { Refresh displays for each screen.

    /process_screen_file/
      FOR screen_file := ofc$sf_display_a TO ofc$sf_display_b DO
        screen_file_index := screen_file;
        #SPOIL (screen_file_index); {  Ensure that variable is in memory for use by the condition handler.

        osp$set_signature_lock (ofv$screen_status [screen_file].file_lock, osc$nowait, status);
        IF NOT status.normal THEN
          CYCLE /process_screen_file/;
        IFEND;

        IF ofv$screen_status [screen_file].display_action = ofc$da_process_display THEN

          { Process the display procedure if one exists.

          IF ofv$screen_status [screen_file].display_procedure_p = NIL THEN
            osp$clear_signature_lock (ofv$screen_status [screen_file].file_lock, status);
            CYCLE /process_screen_file/;
          IFEND;
          ofv$screen_status [screen_file].display_procedure_p^
                (ofv$screen_status [screen_file].window_id, ofv$screen_status [screen_file].display_name,
                v$screen_name [screen_file], ofv$screen_status [screen_file].initial_call, status);
          ofv$screen_status [screen_file].initial_call := FALSE;
          IF NOT status.normal THEN
            ofv$screen_status [screen_file].display_action := ofc$da_terminate_window;
          IFEND;
        ELSEIF ofv$screen_status [screen_file].display_user <> ofc$du_file_user THEN

          { The screen file is not terminated if the file user is still using the display.

          IF ofv$screen_status [screen_file].display_action = ofc$da_terminate_window THEN
            dpp$change_window (ofv$screen_status [screen_file].window_id, dpc$wc_invisible, dpc$wk_table,
                  status);
          IFEND;
          ofv$screen_status [screen_file].display_action := ofc$da_process_display;
          ofv$screen_status [screen_file].display_name := ' ';
          ofv$screen_status [screen_file].display_user := ofc$du_no_one;
          ofv$screen_status [screen_file].display_procedure_p := NIL;
        IFEND;
        osp$clear_signature_lock (ofv$screen_status [screen_file].file_lock, status);

      FOREND /process_screen_file/;

      current_time := #FREE_RUNNING_CLOCK (0);

      { Determine whether or not it is time to emit statistics.

      IF current_time >= osv$time_to_emit_statistics THEN
        osp$emit_os_statistics;
      IFEND;

      { Determine whether or not it is time to log usage statistics.

      IF current_time >= iov$time_to_log_usage_stats THEN
        iop$log_usage_statistics;
      IFEND;

      { Determine whether or not a deferred job has become a candidate for initiation.

      IF current_time >= jmv$time_to_ready_deferred_job THEN
        qfp$ready_deferred_job;
      IFEND;

      { Determine if a deferred print file has become available.

      IF current_time >= jmv$time_to_ready_deferred_file THEN
        qfp$ready_deferred_file;
      IFEND;

      { Determine if a deferred queue file has become available.

      IF current_time >= jmv$ready_deferred_qfile_time THEN
        qfp$ready_deferred_queue_file;
      IFEND;

      { Determine if an expired print file (latest print time) is in the queue.

      IF current_time >= jmv$time_to_purge_expired_file THEN
        jmp$purge_expired_file;
      IFEND;

      { Determine if a printed file needs to be purged (purge delay).

      IF current_time >= jmv$time_to_purge_printed_file THEN
        jmp$purge_printed_file;
      IFEND;

      { Determine if an expired queue file (latest run time) is in the queue.

      IF current_time >= jmv$purge_expired_qfile_time THEN
        jmp$purge_expired_queue_file;
      IFEND;

      { Determine if a processed queue file needs to be purged (purge delay).

      IF current_time >= jmv$purge_processed_qfile_time THEN
        jmp$purge_processed_queue_file;
      IFEND;

      { Wait for the next period to update the display.  If the hardware date/time needs to be updated at the
      { top of minute then adjust the delay time to assure that this task will wake up in time.  If the
      { current time is greater then the maximum wait time then adjust the maximum wait time by multiples of
      { one minute to be greater then current time.  If the current time is less then the minimum wait time
      { then adjust the delay time if necessary else the current time is between the minimum wait time and
      { the maximum wait time so no delay is necessary and the hardware date/time should be updated.

      IF osv$os_defaults.time_data.wait_to_change THEN
        current_time := #FREE_RUNNING_CLOCK (0);
        IF current_time >= osv$os_defaults.time_data.wait_frc.max THEN
          osp$update_wait_frc (current_time);
        IFEND;
        IF current_time < osv$os_defaults.time_data.wait_frc.min THEN
          delay_time := (osv$os_defaults.time_data.wait_frc.min - current_time) DIV 1000;
          IF delay_time < dpv$display_delay THEN
            pmp$wait (delay_time, delay_time);
          ELSE
            pmp$wait (dpv$display_delay, dpv$display_delay);
          IFEND;
        ELSE

          { Current time is between the minimum wait time and the maximum wait time so no delay should
          { be performed.

        IFEND;
      ELSE
        pmp$wait (dpv$display_delay, dpv$display_delay);
      IFEND;

    WHILEND /master_task_loop/;

  PROCEND ofp$system_display_manager;
?? OLDTITLE ??
MODEND ofm$async_task_interfaces;
