?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Operator Facility : Operator Menu Management' ??
MODULE ofm$operator_action_menu;

{ PURPOSE:
{   This module contains the procedures involved in displaying an operator
{   action menu and obtaining an operator choice from the menu.
{
{ DESIGN:
{   The procedures in this module call the system core procedures which
{   directly manipulate the list of operator action menus.
{
{ NOTES:
{   Because the output variables for the procedures in this module are
{   passed from the user's execution ring, and because the return values
{   must be determined at ring 1, local variables are defined within
{   these procedures and passed to the ring 1 routines. The values
{   returned from ring 1 are then stored in the output variable parameters.
{   In the case of status variables, the values returned from ring 1 are
{   stored via the osp$copy_local_status_to_status procedure as per the
{   NOS/VE coding standards.
{
{   The format of a menu should conform to the following guidelines:
{
{     Line   1 : < Description of the condition. >
{     Line   2 :
{     Line   3 :    You have the following choices:
{     Line   4 :
{     Line   5 :      1 - < Action to be taken if '1' is chosen. >
{     Line   6 :      2 - < Action to be taken if '2' is chosen. >
{       .      :                 .
{       .      :                 .
{       .      :                 .
{     Line n+4 :      n - < Action to be taken if 'n' is chosen. >

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ofd$type_definition
*copyc ofe$error_codes
*copyc oft$menu_selections
*copyc oft$operator_menu_descriptor
*copyc ost$parameter_help_names
*copyc ost$status
*copyc ost$string
?? POP ??
*copyc avp$system_displays
*copyc clp$convert_integer_to_rjstring
*copyc ifp$invoke_pause_utility
*copyc ofp$add_operator_menu
*copyc ofp$clear_operator_message
*copyc ofp$delete_operator_menu
*copyc ofp$display_status_message
*copyc ofp$format_operator_message
*copyc ofp$get_active_operator_classes
*copyc ofp$get_first_operator_menu_r1
*copyc ofp$get_menu_choice
*copyc ofp$get_menu_help_text_r1
*copyc ofp$get_next_operator_menu_r1
*copyc ofp$store_menu_choice_r1
*copyc ofp$store_menu_help_text
*copyc osp$clear_wait_message
*copyc osp$copy_local_status_to_status
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$find_brief_help_message
*copyc osp$find_help_module
*copyc osp$find_parameter_prompt
*copyc osp$format_help_message
*copyc osp$get_current_display_message
*copyc osp$get_full_help_message
*copyc osp$get_parameter_help_message
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc osp$system_error
*copyc pmp$continue_to_cause
*copyc pmp$log_ascii
*copyc pmp$long_term_wait
?? TITLE := 'ofp$format_operator_menu', EJECT ??
*copy ofh$format_operator_menu

  PROCEDURE [XDCL, #GATE] ofp$format_operator_menu
    (    seed_name: pmt$program_name;
         parameter_names: ^ost$parameter_help_names;
         message_parameters: ^ost$message_parameters;
         number_of_choices: oft$number_of_choices;
         operator_class: oft$operator_class;
     VAR choice: oft$number_of_choices;
     VAR response_string: ost$string;
     VAR status: ost$status);

?? NEWTITLE := 'menu_condition_handler', EJECT ??

{ PURPOSE:
{   This condition handler is intended to clean up the menu which
{   may have been posted by this task in the event that a block
{   exit occurs and to repost the menu if a job recovery takes
{   place since, in that case, the menu list will have been destroyed.

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

   VAR
     ignore_status: ost$status,
     wait_message_displayed: boolean;

      CASE condition.selector OF

      = ifc$interactive_condition =

        CASE condition.interactive_condition OF
        = ifc$terminate_break =
          osp$set_status_from_condition (ofc$operator_facility_id, condition, save_area, status,
                ignore_status);
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          EXIT ofp$format_operator_menu;
        = ifc$pause_break =
          /process_pause_operator_menu/
          BEGIN
            osp$get_full_help_message (seed_name, message_parameters, operator_menu_line_width,
                  help_message, status);
            IF NOT status.normal THEN
              EXIT /process_pause_operator_menu/;
            IFEND;
            ofp$format_operator_message (help_message, 1, formatted_message, help_message_line_count);
            ofp$store_menu_help_text (menu_id, formatted_message, help_message_line_count, local_status);
            IF NOT local_status.normal THEN
              osp$copy_local_status_to_status (local_status, status);
              EXIT /process_pause_operator_menu/;
            IFEND;

            FOR i:= 1 to help_message_line_count DO
              pmp$log_ascii (formatted_message [i], $pmt$ascii_logset [pmc$system_log],
                   pmc$msg_origin_program, ignore_status);
            FOREND;
            choice_made := FALSE;
          END /process_pause_operator_menu/;
          ifp$invoke_pause_utility (ignore_status);
        = ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;

      = pmc$block_exit_processing =

        ofp$delete_operator_menu (menu_id, condition_status);
        wait_message_displayed := TRUE;
        osp$clear_wait_message (original_message, wait_message_displayed);

      = pmc$user_defined_condition =

        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          ofp$format_operator_menu (seed_name, parameter_names, message_parameters, number_of_choices,
                operator_class, choice, response_string, status);
          EXIT ofp$format_operator_menu;
        IFEND;
      ELSE
      CASEND;
    PROCEND menu_condition_handler;
?? OLDTITLE, EJECT ??

    CONST
      five_minutes = 300000,
      operator_menu_line_width = 80,
      thirty_seconds = 30000;

    VAR
      choice_made: boolean,
      formatted_message: oft$formatted_operator_message,
      help_message: ost$status_message,
      help_message_line_count: oft$number_of_displayable_lines,
      i: oft$number_of_displayable_lines,
      ignore_status: ost$status,
      invalid_class_string: string (16),
      local_choice: oft$number_of_choices,
      local_response_string: ost$string,
      local_status: ost$status,
      log_string: string (80),
      menu_id: oft$menu_id,
      menu_selections: oft$menu_selections,
      number_of_displayable_lines: oft$number_of_displayable_lines,
      operator_response: ost$string,
      original_message: oft$display_message,
      string_size: integer,
      wait_message_displayed: boolean;

    status.normal := TRUE;

    IF NOT ((operator_class = ofc$removable_media_operator) OR (operator_class = ofc$system_operator)) THEN
      STRINGREP (invalid_class_string, string_size, ofc$max_valid_operator_class);
      osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_operator_class,
            invalid_class_string (1, string_size) , status);
      RETURN;
    IFEND;

    ofp$get_operator_menu (seed_name, parameter_names, message_parameters, operator_menu_line_width,
          menu_selections, number_of_displayable_lines, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF number_of_displayable_lines > 0 THEN
      osp$get_current_display_message (original_message);
      #SPOIL (original_message);

      FOR i:= 1 to number_of_displayable_lines DO
        pmp$log_ascii (menu_selections [i], $pmt$ascii_logset [pmc$system_log], pmc$msg_origin_program,
           ignore_status);
      FOREND;

    /process_operator_menu/
      BEGIN
        osp$establish_condition_handler (^menu_condition_handler, TRUE);

        ofp$display_status_message ('Waiting For Operator Action', local_status);
        ofp$add_operator_menu (^menu_selections, number_of_displayable_lines, number_of_choices,
              operator_class, menu_id, local_status);
        IF NOT local_status.normal THEN
          osp$copy_local_status_to_status (local_status, status);
          EXIT /process_operator_menu/;
        IFEND;

        REPEAT
          pmp$long_term_wait (five_minutes, thirty_seconds);
          ofp$get_menu_choice (menu_id, choice_made, local_choice, local_response_string, local_status);
          IF NOT local_status.normal THEN
            osp$system_error ('Posted operator action menu missing from menu list.', NIL);
          IFEND;

          IF choice_made AND (local_response_string.value (1, 1) = '?') THEN
            IF local_choice < ofc$max_menu_lines THEN
              STRINGREP (log_string, string_size, ' Operator Response: ', local_choice, ' ',
                local_response_string.value (1, local_response_string.size));
              pmp$log_ascii (log_string (1, string_size), $pmt$ascii_logset [pmc$system_log],
                pmc$msg_origin_program, ignore_status);
              IF parameter_names <> NIL THEN
                osp$get_parameter_help_message (seed_name, parameter_names^ [local_choice],
                      message_parameters, operator_menu_line_width, help_message, status);
                IF NOT status.normal THEN
                  EXIT /process_operator_menu/;
                IFEND;
              IFEND;
            ELSE { full help was requested }
              STRINGREP (log_string, string_size, ' Operator Response: ', ' ',
                local_response_string.value (1, local_response_string.size));
              pmp$log_ascii (log_string (1, string_size), $pmt$ascii_logset [pmc$system_log],
                pmc$msg_origin_program, ignore_status);
              osp$get_full_help_message (seed_name, message_parameters, operator_menu_line_width,
                    help_message, status);
              IF NOT status.normal THEN
                EXIT /process_operator_menu/;
              IFEND;
            IFEND;

            ofp$format_operator_message (help_message, 1, formatted_message, help_message_line_count);
            ofp$store_menu_help_text (menu_id, formatted_message, help_message_line_count, local_status);
            IF NOT local_status.normal THEN
              osp$copy_local_status_to_status (local_status, status);
              EXIT /process_operator_menu/;
            IFEND;

            FOR i:= 1 to help_message_line_count DO
              pmp$log_ascii (formatted_message [i], $pmt$ascii_logset [pmc$system_log],
                 pmc$msg_origin_program, ignore_status);
            FOREND;
            choice_made := FALSE;
          IFEND;

        UNTIL choice_made;

        choice := local_choice;
        response_string := local_response_string;
        STRINGREP (log_string, string_size, ' Operator Response: ', local_choice, ' ',
          local_response_string.value (1, local_response_string.size));
        pmp$log_ascii (log_string (1, string_size), $pmt$ascii_logset [pmc$system_log],
          pmc$msg_origin_program, ignore_status);
      END /process_operator_menu/;

      osp$disestablish_cond_handler;
      wait_message_displayed := TRUE;
      osp$clear_wait_message (original_message, wait_message_displayed);
    IFEND;

  PROCEND ofp$format_operator_menu;
?? TITLE := 'ofp$get_first_operator_menu', EJECT ??

*copyc ofh$get_first_operator_menu

  PROCEDURE [XDCL, #GATE] ofp$get_first_operator_menu
    (VAR menu_descriptor: oft$operator_menu_descriptor;
     VAR status: ost$status);

    VAR
      active_operator_classes: oft$operator_classes,
      local_menu_descriptor: oft$operator_menu_descriptor,
      local_status: ost$status;

    status.normal := TRUE;
    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
        osp$set_status_abnormal (ofc$operator_facility_id, ofe$no_menus_available, ' ', status);
        RETURN;
      IFEND;
    IFEND;

    ofp$get_first_operator_menu_r1 (active_operator_classes, local_menu_descriptor, local_status);
    IF local_status.normal THEN
      menu_descriptor := local_menu_descriptor;
    IFEND;

    osp$copy_local_status_to_status (local_status, status);

  PROCEND ofp$get_first_operator_menu;
?? TITLE := 'ofp$get_menu_help_text', EJECT ??

*copyc ofh$get_menu_help_text

  PROCEDURE [XDCL, #GATE] ofp$get_menu_help_text
    (    menu_id: oft$menu_id;
         global_task_id: ost$global_task_id;
         help_text_p: {input, output} ^oft$menu_selections;
     VAR help_text_found: boolean;
     VAR help_text_line_count: oft$number_of_displayable_lines;
     VAR status: ost$status);

    VAR
      local_help_text_p: ^oft$menu_selections,
      local_status: ost$status;

    status.normal := TRUE;

    PUSH local_help_text_p;

    ofp$get_menu_help_text_r1 (menu_id, global_task_id, local_help_text_p, help_text_found,
          help_text_line_count, local_status);
    IF local_status.normal THEN
      IF help_text_found AND (help_text_p <> NIL) THEN
        help_text_p^ := local_help_text_p^;
      IFEND;
    ELSE
      osp$copy_local_status_to_status (local_status, status);
    IFEND;

  PROCEND ofp$get_menu_help_text;
?? TITLE := 'ofp$get_next_operator_menu', EJECT ??

*copyc ofh$get_next_operator_menu

  PROCEDURE [XDCL, #GATE] ofp$get_next_operator_menu
    (    current_menu_id: oft$menu_id;
     VAR menu_descriptor: oft$operator_menu_descriptor;
     VAR status: ost$status);

    VAR
      active_operator_classes: oft$operator_classes,
      local_menu_descriptor: oft$operator_menu_descriptor,
      local_status: ost$status;

    status.normal := TRUE;
    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
        osp$set_status_abnormal (ofc$operator_facility_id, ofe$no_menus_available, ' ', status);
        RETURN;
      IFEND;
    IFEND;

    ofp$get_next_operator_menu_r1 (current_menu_id, active_operator_classes, local_menu_descriptor,
          local_status);
    IF local_status.normal THEN
      menu_descriptor := local_menu_descriptor;
    IFEND;

    osp$copy_local_status_to_status (local_status, status);

  PROCEND ofp$get_next_operator_menu;
?? TITLE := 'ofp$get_operator_menu', EJECT ??
*copy ofh$get_operator_menu

  PROCEDURE ofp$get_operator_menu
    (    seed_name: pmt$program_name;
         choice_names: ^ost$parameter_help_names;
         message_parameters: ^ost$message_parameters;
         max_message_line: ost$max_status_message_line;
     VAR operator_message: oft$formatted_operator_message;
     VAR line_count: oft$number_of_displayable_lines;
     VAR status: ost$status);

    CONST
      choice_number_size = 2;

    VAR
      choice: oft$number_of_choices,
      help_module: ^ost$help_module,
      message: ost$status_message,
      message_template: ^ost$message_template,
      natural_language: ost$natural_language,
      online_manual_name: ost$online_manual_name,
      starting_line: oft$number_of_displayable_lines,
      substitute_choice_numbers: boolean;

    osp$find_help_module (seed_name, help_module, online_manual_name, natural_language, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$find_brief_help_message (help_module, message_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF message_template = NIL THEN
      osp$set_status_abnormal ('OF', ofe$menu_definition_error, seed_name, status);
      RETURN;
    IFEND;

    osp$format_help_message (message_template, message_parameters, max_message_line, message, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    ofp$format_operator_message (message, 1, operator_message, line_count);

    IF message_parameters^ [1] = NIL THEN
      PUSH message_parameters^ [1]: [choice_number_size];
      substitute_choice_numbers := TRUE;
    ELSE
      substitute_choice_numbers := FALSE;
    IFEND;

    FOR choice := 1 TO UPPERBOUND (choice_names^) DO
      IF substitute_choice_numbers THEN
        clp$convert_integer_to_rjstring (choice, 10, FALSE, ' ', message_parameters^ [1]^, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

      osp$find_parameter_prompt (help_module, choice_names^ [choice], message_template, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF message_template = NIL THEN
        osp$set_status_abnormal ('OF', ofe$menu_definition_error, seed_name, status);
        RETURN;
      IFEND;

      osp$format_help_message (message_template, message_parameters, max_message_line, message, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      starting_line := line_count + 1;
      ofp$format_operator_message (message, starting_line, operator_message, line_count);

    FOREND;

  PROCEND ofp$get_operator_menu;
?? TITLE := 'ofp$store_menu_choice', EJECT ??

*copyc ofh$store_menu_choice

  PROCEDURE [XDCL, #GATE] ofp$store_menu_choice
    (    menu_id: oft$menu_id;
         choice: oft$number_of_choices;
         response_string: ost$string;
     VAR status: ost$status);

    VAR
      active_operator_classes: oft$operator_classes,
      local_status: ost$status;

    status.normal := TRUE;
    ofp$get_active_operator_classes (active_operator_classes);
    IF active_operator_classes = $oft$operator_classes [] THEN
      osp$set_status_abnormal (ofc$operator_facility_id, ofe$invalid_menu_id, ' ', status);
      RETURN;
    IFEND;

    ofp$store_menu_choice_r1 (menu_id, active_operator_classes, choice, response_string, local_status);
    osp$copy_local_status_to_status (local_status, status);

  PROCEND ofp$store_menu_choice;
MODEND ofm$operator_action_menu;
