?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Prompting Interfaces: Routines used for prompting' ??
MODULE ram$menu_prompting_interfaces;

{ PURPOSE:
{   This module contains interfaces to prompt for user responses.
{
{ DESIGN:
{   The interfaces utilize message templates and message help modules to provide the text for the
{   prompting.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc rac$max_line
*copyc rac$process_id
*copyc rae$prompt_and_message_cc
*copyc rat$message_parameters
*copyc rat$prompting_options
*copyc rat$value_declaration
*copyc rat$value_returned
*copyc rmc$initv_menu_names
?? POP ??
*copyc amp$get_next
*copyc amp$put_next
*copyc amp$return
*copyc clp$convert_integer_to_rjstring
*copyc clp$convert_integer_to_string
*copyc clp$convert_string_to_integer
*copyc clp$get_set_count
*copyc clp$get_value
*copyc clp$include_command
*copyc clp$scan_parameter_list
*copyc clp$trimmed_string_size
*copyc clp$write_variable
*copyc fsp$close_file
*copyc fsp$open_file
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$find_brief_help_message
*copyc osp$find_full_help_message
*copyc osp$find_help_module
*copyc osp$find_param_assist_prompt
*copyc osp$find_parameter_help_message
*copyc osp$find_parameter_prompt
*copyc osp$format_help_message
*copyc osp$format_message
*copyc osp$get_status_severity
*copyc osp$set_status_abnormal
*copyc pmp$get_unique_name
*copyc clv$non_space
*copyc osv$lower_to_upper
*copyc oss$task_shared

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

  CONST
    rac$max_number_of_selections = 10,
    rac$selection_key_size = 2;

  TYPE
    rat$io_identifiers = record
      input_open: boolean,
      input: amt$file_identifier,
      output_open: boolean,
      output: amt$file_identifier,
    recend,
    rat$menu = record
      module_name: pmt$program_name,
      module_ptr: ^ost$help_module,
      parameters: ^ost$message_parameters,
      title_container: ost$status_message,
      prompt_container: ost$status_message,
      selections: rat$menu_selections,
    recend,
    rat$menu_selection = record
      name: clt$parameter_name,
      container: ost$status_message,
    recend,
    rat$menu_selections = ^array [1 .. * ] of rat$menu_selection,
    rat$number_of_selections = 0 .. rac$max_number_of_selections,
    rat$prompt = record
      module_name: pmt$program_name,
      module_ptr: ^ost$help_module,
      name: clt$parameter_name,
      parameters: ^ost$message_parameters,
      container: ost$status_message,
    recend,
    rat$write_scl_procedure = record
      size: integer,
      value: string (osc$max_string_size),
    recend;

?? TITLE := '[XDCL, #GATE] rap$press_next_command', EJECT ??

*copy rah$press_next_command

  PROCEDURE [XDCL, #GATE] rap$press_next_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ pdt press_next_pdt ()

?? PUSH (LISTEXT := ON) ??

    VAR
      press_next_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [NIL, NIL];

?? POP ??

    VAR
      close_status: ost$status,
      io_identifiers: rat$io_identifiers;

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

{ PURPOSE:
{   The purpose of this request is to close the input and output files on an unexpected abort.
{

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

      VAR
        ignore_status: ost$status;


      IF io_identifiers.input_open THEN
        fsp$close_file (io_identifiers.input, ignore_status);
        io_identifiers.input_open := FALSE;
      IFEND;

      IF io_identifiers.output_open THEN
        fsp$close_file (io_identifiers.output, ignore_status);
        io_identifiers.output_open := FALSE;
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    io_identifiers.input_open := FALSE;
    io_identifiers.output_open := FALSE;

    clp$scan_parameter_list (parameter_list, press_next_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$establish_block_exit_hndlr (^abort_handler);

  /press_next/
    BEGIN

      open_input_output (io_identifiers, status);
      IF NOT status.normal THEN
        EXIT /press_next/;
      IFEND;

      press_next_to_continue (io_identifiers, status);

    END /press_next/;

    close_input_output (io_identifiers, close_status);
    IF status.normal AND (NOT close_status.normal) THEN
      status := close_status;
    IFEND;

    osp$disestablish_cond_handler;

  PROCEND rap$press_next_command;

?? TITLE := '[XDCL, #GATE] rap$prompt_for_value', EJECT ??

{ PURPOSE:
{   The purpose of this interface is to prompt for a value.
{
{ DESIGN:
{

  PROCEDURE [XDCL, #GATE] rap$prompt_for_value
    (    prompt_module: pmt$program_name;
         prompt_name: clt$parameter_name;
         prompt_parameters: rat$message_parameters;
         prompting_options: rat$prompting_options;
         value_declaration: rat$value_declaration;
     VAR value_returned: rat$value_returned;
     VAR status: ost$status);


    VAR
      index: rat$number_of_message_params,
      number_of_parameters: rat$number_of_message_params,
      prompt: rat$prompt;


    status.normal := TRUE;

    prompt.module_name := prompt_module;
    prompt.name := prompt_name;

    IF prompt_parameters = NIL THEN
      prompt.parameters := NIL;
    ELSE
      IF UPPERBOUND (prompt_parameters^) > rac$max_message_parameters THEN
        osp$set_status_abnormal (rac$process_id, rae$max_number_of_exceeded, 'prompt parameters', status);
        RETURN;
      IFEND;
      number_of_parameters := UPPERBOUND (prompt_parameters^);

      PUSH prompt.parameters: [1 .. number_of_parameters];
      FOR index := 1 TO number_of_parameters DO
        PUSH prompt.parameters^ [index]: [clp$trimmed_string_size (prompt_parameters^ [index])];
        prompt.parameters^ [index]^ := prompt_parameters^ [index]
              (1, clp$trimmed_string_size (prompt_parameters^ [index]));
      FOREND;
    IFEND;

{ At some point a test will be added here to determine if line or screen mode prompting should be done.
{ The appropriate interface will then be called.  Currently only line mode is avaiable.

    prompt_for_value_line_mode (value_declaration, prompting_options, prompt, value_returned, status);

  PROCEND rap$prompt_for_value;

?? TITLE := '[XDCL, #GATE] rap$prompt_for_value_command', EJECT ??

*copy rah$prompt_for_value_command

  PROCEDURE [XDCL, #GATE] rap$prompt_for_value_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);


{ pdt prompt_for_value_pdt (
{   prompt_module, pm     : name = $required
{   prompt_name, pn       : name = $required
{   prompt_parameters, pp : list 1..10 of string = $optional
{   prompting_options, po : list of key allow_go, allow_null, allow_quit, clear_screen = $optional
{   value_declaration, vd : list 1..2 of string or key hex, string, list = $required
{   value_returned, vr    : var of string = $requried
{   status                : var of status = $optional
{   )

?? PUSH (LISTEXT := ON) ??

    VAR
      prompt_for_value_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^prompt_for_value_pdt_names, ^prompt_for_value_pdt_params];

    VAR
      prompt_for_value_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 13] of
            clt$parameter_name_descriptor := [['PROMPT_MODULE', 1], ['PM', 1], ['PROMPT_NAME', 2], ['PN', 2],
            ['PROMPT_PARAMETERS', 3], ['PP', 3], ['PROMPTING_OPTIONS', 4], ['PO', 4],
            ['VALUE_DECLARATION', 5], ['VD', 5], ['VALUE_RETURNED', 6], ['VR', 6], ['STATUS', 7]];

    VAR
      prompt_for_value_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 7] of
            clt$parameter_descriptor := [

{ PROMPT_MODULE PM }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, 1, osc$max_name_size]],

{ PROMPT_NAME PN }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, 1, osc$max_name_size]],

{ PROMPT_PARAMETERS PP }
      [[clc$optional], 1, 10, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$string_value, 0, osc$max_string_size]],

{ PROMPTING_OPTIONS PO }
      [[clc$optional], 1, clc$max_value_sets, 1, 1, clc$value_range_not_allowed,
            [^prompt_for_value_pdt_kv4, clc$keyword_value]],

{ VALUE_DECLARATION VD }
      [[clc$required], 1, 2, 1, 1, clc$value_range_not_allowed,
            [^prompt_for_value_pdt_kv5, clc$string_value, 0, osc$max_string_size]],

{ VALUE_RETURNED VR }
      [[clc$optional_with_default, ^prompt_for_value_pdt_dv6], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$string_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

    VAR
      prompt_for_value_pdt_kv4: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 4] of
            ost$name := ['ALLOW_GO', 'ALLOW_NULL', 'ALLOW_QUIT', 'CLEAR_SCREEN'];

    VAR
      prompt_for_value_pdt_kv5: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
            ost$name := ['HEX', 'STRING', 'LIST'];

    VAR
      prompt_for_value_pdt_dv6: [STATIC, READ, cls$pdt_names_and_defaults] string (9) := '$requried';

?? POP ??

    VAR
      index: 0 .. clc$max_value_sets,
      number_of_parameters: 0 .. clc$max_value_sets,
      prompt: rat$prompt,
      prompting_options: rat$prompting_options,
      returned: clt$variable_reference,
      val_returned_1: ost$string,
      val_returned_2: array [1 .. osc$max_string_size + 2] of cell,
      value: clt$value,
      value_declaration: rat$value_declaration,
      value_returned: rat$value_returned;


    status.normal := TRUE;

    clp$scan_parameter_list (parameter_list, prompt_for_value_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('prompt_module', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    prompt.module_name := value.name.value;

    clp$get_value ('prompt_name', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    prompt.name := value.name.value;

    clp$get_set_count ('prompt_parameters', number_of_parameters, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    prompt.parameters := NIL;
    IF number_of_parameters > 0 THEN
      PUSH prompt.parameters: [1 .. number_of_parameters];
      FOR index := 1 TO number_of_parameters DO
        clp$get_value ('prompt_parameters', index, 1, clc$low, value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        PUSH prompt.parameters^ [index]: [value.str.size];
        prompt.parameters^ [index]^ := value.str.value;
      FOREND;
    IFEND;

    get_prompting_options (prompting_options, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    get_value_declaration (value_declaration, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ At some point a test will be added here to determine if line or screen mode prompting should be done.
{ The appropriate interface will then be called.  Currently only line mode is avaiable.

    prompt_for_value_line_mode (value_declaration, prompting_options, prompt, value_returned, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Return the value entered by the user to the caller.

    clp$get_value ('value_returned', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    returned := value.var_ref;

    val_returned_1.size := #SIZE (value_returned);
    val_returned_1.value := value_returned;
    #UNCHECKED_CONVERSION (val_returned_1, val_returned_2);
    returned.value.string_value := ^val_returned_2;
    clp$write_variable (returned.reference.value (1, returned.reference.size), returned.value, status);

  PROCEND rap$prompt_for_value_command;

?? TITLE := '[XDCL, #GATE] rap$prompt_via_menu', EJECT ??

{ PURPOSE:
{   The purpose of this interface is to prompt via a menu.
{
{ DESIGN:
{

  PROCEDURE [XDCL, #GATE] rap$prompt_via_menu
    (    menu_module: pmt$program_name;
         menu_selections: array [ * ] of ost$name;
         menu_parameters: rat$message_parameters;
         prompting_options: rat$prompting_options;
     VAR selection_chosen: ost$name;
     VAR status: ost$status);


    VAR
      index: rat$number_of_message_params,
      menu: rat$menu,
      number_of_parameters: rat$number_of_message_params,
      number_of_selections: rat$number_of_selections;

    status.normal := TRUE;

    menu.module_name := menu_module;

    IF UPPERBOUND (menu_selections) > rac$max_number_of_selections THEN
      osp$set_status_abnormal (rac$process_id, rae$max_number_of_exceeded, 'menu selections', status);
      RETURN;
    IFEND;
    number_of_selections := UPPERBOUND (menu_selections);

    PUSH menu.selections: [1 .. number_of_selections];
    FOR index := 1 TO number_of_selections DO
      menu.selections^ [index].name := menu_selections [index];
    FOREND;

{ The first menu parameter is reserved for the selection keys.  This is put on the parameter list
{ automatically.  Any additional parameters that the caller of this interface has provided are then
{ added.

    number_of_parameters := 0;
    IF menu_parameters <> NIL THEN
      IF UPPERBOUND (menu_parameters^) > rac$max_message_parameters - 1 THEN
        osp$set_status_abnormal (rac$process_id, rae$max_number_of_exceeded, 'menu parameters', status);
        RETURN;
      IFEND;
      number_of_parameters := UPPERBOUND (menu_parameters^);
    IFEND;

    PUSH menu.parameters: [1 .. number_of_parameters + 1];
    PUSH menu.parameters^ [1]: [rac$selection_key_size];
    FOR index := 1 TO number_of_parameters DO
      PUSH menu.parameters^ [index + 1]: [clp$trimmed_string_size (menu_parameters^ [index])];
      menu.parameters^ [index + 1]^ := menu_parameters^ [index]
            (1, clp$trimmed_string_size (menu_parameters^ [index]));
    FOREND;

{ At some point a test will be added here to determine if line or screen mode prompting should be done.
{ The appropriate interface will then be called.  Currently only line mode is avaiable.

    prompt_via_menu_line_mode (prompting_options, menu, selection_chosen, status);

  PROCEND rap$prompt_via_menu;

?? TITLE := '[XDCL, #GATE] rap$prompt_via_menu_command', EJECT ??

*copy rah$prompt_via_menu_command
{
{ DESIGN:
{    A menu is defined as having a title, the selections (or choices), and a
{  prompt.  The title defines the purpose of the menu.  The title can be from
{  a couple word statement to a paragraph of information.  The selections is
{  a list (numbered from 1 to n, where n <= 10).  The prompt demands the user
{  to take action.  The actions available are requesting general help on the
{  menu (entering '?'), requesting help on a specific selection (enter
{  selection number followed by a '?') or selecting one of the choices (enter
{  the selection number).  After the choice is verified the name that
{  corresponds to the selection is returned to the calling interface.
{
{    A menu has all of the formating flexibility that the help messages have.
{  Parameter inputs can be used to create menus that contain data supplied by
{  the user or from another source.
{
{    The function of a message module is to provide help for a user executing
{  commands interactively.  Therefore the kinds of messages found in a
{  message module reflect that purpose.  In setting up menus using message
{  module technology the message kinds are interpreted for menus.
{
{    a.  The menu title is created as the brief help message.
{    b.  The menu help is created as the full help message.
{    c.  The menu selections are created as parameter prompt messages.
{    d.  The menu selection help (optional) is created as a parameter help
{        message.
{    e.  the menu selection confirmation (optional) is created as a
{        parameter assist message.
{    f.  The menu prompt is created as a parameter prompt message and
{        given the special name 'prompt'.
{
{    Because of the menu definition there can only be one menu defined by
{  one help module.
{
{ NOTES:
{   The first menu parameter is reserved for the selection key.  Any additional
{   parameter inputs are added after this.

  PROCEDURE [XDCL, #GATE] rap$prompt_via_menu_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);


{ pdt prompt_via_menu_pdt (
{   menu_module, mm       : name = $required
{   menu_selections, ms   : list 1..10 of name = $required
{   menu_parameters, mp   : list 1..50 of string = $optional
{   prompting_options, po : list of key allow_go, allow_null, allow_quit, clear_screen, confirm_selection ..
{                         = $optional
{   selection_chosen, sc  : var of string = $required
{   status                : var of status = $optional
{   )

?? PUSH (LISTEXT := ON) ??

    VAR
      prompt_via_menu_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^prompt_via_menu_pdt_names, ^prompt_via_menu_pdt_params];

    VAR
      prompt_via_menu_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 11] of
            clt$parameter_name_descriptor := [['MENU_MODULE', 1], ['MM', 1], ['MENU_SELECTIONS', 2],
            ['MS', 2], ['MENU_PARAMETERS', 3], ['MP', 3], ['PROMPTING_OPTIONS', 4], ['PO', 4],
            ['SELECTION_CHOSEN', 5], ['SC', 5], ['STATUS', 6]];

    VAR
      prompt_via_menu_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 6] of
            clt$parameter_descriptor := [

{ MENU_MODULE MM }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, 1, osc$max_name_size]],

{ MENU_SELECTIONS MS }
      [[clc$required], 1, 10, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, 1, osc$max_name_size]],

{ MENU_PARAMETERS MP }
      [[clc$optional], 1, 50, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$string_value, 0, osc$max_string_size]],

{ PROMPTING_OPTIONS PO }
      [[clc$optional], 1, clc$max_value_sets, 1, 1, clc$value_range_not_allowed,
            [^prompt_via_menu_pdt_kv4, clc$keyword_value]],

{ SELECTION_CHOSEN SC }
      [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$string_value]],

{ STATUS }
      [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed,
            [NIL, clc$variable_reference, clc$array_not_allowed, clc$status_value]]];

    VAR
      prompt_via_menu_pdt_kv4: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 5] of
            ost$name := ['ALLOW_GO', 'ALLOW_NULL', 'ALLOW_QUIT', 'CLEAR_SCREEN', 'CONFIRM_SELECTION'];

?? POP ??

    VAR
      index: 0 .. clc$max_value_sets,
      menu: rat$menu,
      number_of_parameters: 0 .. clc$max_value_sets,
      number_of_selections: 0 .. clc$max_value_sets,
      prompting_options: rat$prompting_options,
      selection: clt$variable_reference,
      selection_chosen: ost$name,
      selection_val_1: ost$string,
      selection_val_2: array [1 .. osc$max_string_size + 2] of cell,
      value: clt$value;


    status.normal := TRUE;

    clp$scan_parameter_list (parameter_list, prompt_via_menu_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$get_value ('menu_module', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    menu.module_name := value.name.value;

    clp$get_set_count ('menu_selections', number_of_selections, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH menu.selections: [1 .. number_of_selections];
    FOR index := 1 TO number_of_selections DO
      clp$get_value ('menu_selections', index, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      menu.selections^ [index].name := value.name.value;
    FOREND;

    clp$get_set_count ('menu_parameters', number_of_parameters, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH menu.parameters: [1 .. number_of_parameters + 1];
    PUSH menu.parameters^ [1]: [rac$selection_key_size];
    IF number_of_parameters > 0 THEN
      FOR index := 1 TO number_of_parameters DO
        clp$get_value ('menu_parameters', index, 1, clc$low, value, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
        PUSH menu.parameters^ [index + 1]: [value.str.size];
        menu.parameters^ [index + 1]^ := value.str.value;
      FOREND;
    IFEND;

    get_prompting_options (prompting_options, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ At some point a test will be added here to determine if line or screen mode prompting should be done.
{ The appropriate interface will then be called.  Currently only line mode is avaiable.

    prompt_via_menu_line_mode (prompting_options, menu, selection_chosen, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Return the menu selection value chosen to the caller.

    clp$get_value ('selection_chosen', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    selection := value.var_ref;

    selection_val_1.size := #SIZE (selection_chosen);
    selection_val_1.value := selection_chosen;
    #UNCHECKED_CONVERSION (selection_val_1, selection_val_2);
    selection.value.string_value := ^selection_val_2;
    clp$write_variable (selection.reference.value (1, selection.reference.size), selection.value, status);

  PROCEND rap$prompt_via_menu_command;

?? TITLE := 'close_input_output', EJECT ??

{ PURPOSE:
{   The purpose of this request is to close the input and output files.
{
{ DESIGN:
{

  PROCEDURE close_input_output
    (VAR io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      close_status: ost$status;

    status.normal := TRUE;

    fsp$close_file (io_identifiers.input, status);
    IF status.normal THEN
      io_identifiers.input_open := FALSE;
    IFEND;

    fsp$close_file (io_identifiers.output, close_status);
    IF close_status.normal THEN
      io_identifiers.output_open := FALSE;
    ELSEIF status.normal THEN
      status := close_status;
    IFEND;

  PROCEND close_input_output;

?? TITLE := 'confirm_selection', EJECT ??

{ PURPOSE:
{   The purpose of this request is to prompt for a confirmation of the selection chosen.
{
{ DESIGN:
{

  PROCEDURE confirm_selection
    (    module_ptr: ^ost$help_module;
         selection_name: ost$name;
         selection_key: string ( * <= osc$max_string_size);
         io_identifiers: rat$io_identifiers;
     VAR confirmed: boolean;
     VAR status: ost$status);

    VAR
      ignore_byte_address: amt$file_byte_address,
      ignore_file_position: amt$file_position,
      ignore_result: boolean,
      ignore_status: ost$status,
      line_length: integer,
      line_start: integer,
      message_container: ost$status_message,
      message_template: ^ost$message_template,
      response_line: string (osc$max_string_size),
      transfer_count: amt$transfer_count,
      translated_response: string (osc$max_string_size),
      valid_response: boolean;


    status.normal := TRUE;

    osp$find_param_assist_prompt (module_ptr, selection_name, message_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF message_template <> NIL THEN
      osp$format_help_message (message_template, NIL, rac$max_line, message_container, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      issue_message (message_container, io_identifiers.output, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    valid_response := FALSE;

    REPEAT

      issue_status_message (rae$confirmation_prompt, selection_key, io_identifiers.output, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      response_line := '';
      amp$get_next (io_identifiers.input, ^response_line, #SIZE (response_line), transfer_count,
            ignore_byte_address, ignore_file_position, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF (transfer_count = 0) OR (response_line = '') THEN
        issue_status_message (rae$invalid_response, '', io_identifiers.output, status);
        press_next_to_continue (io_identifiers, ignore_status);
      ELSE
        #SCAN (clv$non_space, response_line, line_start, ignore_result);
        line_length := clp$trimmed_string_size (response_line) - line_start + 1;
        #TRANSLATE (osv$lower_to_upper, response_line (line_start, line_length), translated_response);
        IF (translated_response = 'YES') OR (translated_response = 'Y') THEN
          confirmed := TRUE;
          valid_response := TRUE;
        ELSEIF (translated_response = 'NO') OR (translated_response = 'N') THEN
          confirmed := FALSE;
          valid_response := TRUE;
        ELSE
          issue_status_message (rae$invalid_response, '', io_identifiers.output, status);
          press_next_to_continue (io_identifiers, ignore_status);
        IFEND;
      IFEND;

    UNTIL valid_response;

  PROCEND confirm_selection;

?? TITLE := 'display_menu_help', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display the requested menu help when it exists.
{
{ DESIGN:
{

  PROCEDURE display_menu_help
    (    menu: rat$menu;
         selection_chosen: ost$name;
         io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      help_container: ost$status_message,
      help_template: ^ost$message_template,
      ignore_status: ost$status;


    status.normal := TRUE;

    IF selection_chosen = '' THEN
      osp$find_full_help_message (menu.module_ptr, help_template, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF help_template = NIL THEN
        issue_status_message (rae$no_help_for_menu, '', io_identifiers.output, status);
        press_next_to_continue (io_identifiers, ignore_status);
        RETURN;
      IFEND;

    ELSE
      osp$find_parameter_help_message (menu.module_ptr, selection_chosen, help_template, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF help_template = NIL THEN
        issue_status_message (rae$no_help_for_menu_selection, selection_chosen, io_identifiers.output,
              status);
        press_next_to_continue (io_identifiers, ignore_status);
        RETURN;
      IFEND;
    IFEND;

    osp$format_help_message (help_template, menu.parameters, rac$max_line, help_container, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    issue_message (help_container, io_identifiers.output, status);
    press_next_to_continue (io_identifiers, ignore_status);

  PROCEND display_menu_help;

?? TITLE := 'display_value_help', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display the help for the requested value when it exists.
{
{ DESIGN:
{

  PROCEDURE display_value_help
    (    prompt: rat$prompt;
         io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      help_container: ost$status_message,
      help_template: ^ost$message_template,
      ignore_status: ost$status;


    status.normal := TRUE;

    osp$find_parameter_help_message (prompt.module_ptr, prompt.name, help_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF help_template = NIL THEN
      issue_status_message (rae$no_help_for_value, '', io_identifiers.output, status);
      press_next_to_continue (io_identifiers, ignore_status);
      RETURN;
    IFEND;

    osp$format_help_message (help_template, prompt.parameters, rac$max_line, help_container, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    issue_message (help_container, io_identifiers.output, status);
    press_next_to_continue (io_identifiers, ignore_status);

  PROCEND display_value_help;

?? TITLE := 'get_menu_response', EJECT ??

{ PURPOSE:
{   The purpose of this request is to get the user response for the menu issued.
{
{ DESIGN:
{

  PROCEDURE get_menu_response
    (    menu: rat$menu;
         prompting_options: rat$prompting_options;
         io_identifiers: rat$io_identifiers;
     VAR selection_chosen: ost$name;
     VAR help_requested: boolean;
     VAR status: ost$status);

    VAR
      confirmed: boolean,
      ignore_status: ost$status,
      key_chosen: clt$integer,
      length: integer,
      processed: boolean,
      response: string (osc$max_string_size);


    status.normal := TRUE;
    help_requested := FALSE;
    selection_chosen := '';

    get_response (prompting_options, io_identifiers, response, length, processed, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF processed THEN
      selection_chosen := response (1, length);

    ELSE
      IF response (length) = '?' THEN
        help_requested := TRUE;
        length := length - 1;
      IFEND;

      IF length <> 0 THEN
        clp$convert_string_to_integer (response (1, length), key_chosen, status);
        IF status.normal AND (key_chosen.value > 0) AND (key_chosen.value <= UPPERBOUND (menu.selections^))
              THEN
          selection_chosen := menu.selections^ [key_chosen.value].name;
          IF (rac$confirm_selection IN prompting_options) AND (NOT help_requested) THEN
            confirm_selection (menu.module_ptr, selection_chosen, response (1, length), io_identifiers,
                  confirmed, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
            IF NOT confirmed THEN
              selection_chosen := '+INVALID_RESPONSE';
            IFEND;
          IFEND;
        ELSE
          help_requested := FALSE;
          selection_chosen := '+INVALID_RESPONSE';
          issue_status_message (rae$not_valid_selection, response (1, length), io_identifiers.output, status);
          press_next_to_continue (io_identifiers, ignore_status);
          RETURN;
        IFEND;
      IFEND;
    IFEND;

  PROCEND get_menu_response;

?? TITLE := 'get_prompting_options', EJECT ??

{ PURPOSE:
{   The purpose of this request is to get the prompting options from the parameter list.
{
{ DESIGN:
{   The SCL parameter for prompting options is a list of keys.  These are optional.


  PROCEDURE get_prompting_options
    (VAR prompting_options: rat$prompting_options;
     VAR status: ost$status);

    VAR
      index: 0 .. clc$max_value_sets,
      number_in_option_set: 0 .. clc$max_value_sets,
      option: ost$name,
      value: clt$value;


    status.normal := TRUE;

    prompting_options := $rat$prompting_options [];

    clp$get_set_count ('prompting_options', number_in_option_set, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR index := 1 TO number_in_option_set DO
      clp$get_value ('prompting_options', index, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      option := value.name.value;

      IF option = 'ALLOW_GO' THEN
        prompting_options := prompting_options + $rat$prompting_options [rac$allow_go];
      ELSEIF option = 'ALLOW_NULL' THEN
        prompting_options := prompting_options + $rat$prompting_options [rac$allow_null];
      ELSEIF option = 'ALLOW_QUIT' THEN
        prompting_options := prompting_options + $rat$prompting_options [rac$allow_quit];
      ELSEIF option = 'CLEAR_SCREEN' THEN
        prompting_options := prompting_options + $rat$prompting_options [rac$clear_screen];
      ELSEIF option = 'CONFIRM_SELECTION' THEN { only with prompt_via_menu }
        prompting_options := prompting_options + $rat$prompting_options [rac$confirm_selection];
      IFEND;

    FOREND;

  PROCEND get_prompting_options;

?? TITLE := 'get_response', EJECT ??

{ PURPOSE:
{   The purpose of this request is to get the user response.
{
{ DESIGN:
{

  PROCEDURE get_response
    (    prompting_options: rat$prompting_options;
         io_identifiers: rat$io_identifiers;
     VAR response: string (osc$max_string_size);
     VAR length: integer;
     VAR processed: boolean;
     VAR status: ost$status);

    VAR
      ignore_byte_address: amt$file_byte_address,
      ignore_file_position: amt$file_position,
      ignore_result: boolean,
      ignore_status: ost$status,
      line_length: integer,
      line_start: integer,
      response_line: string (osc$max_string_size),
      transfer_count: amt$transfer_count,
      translated_response: string (osc$max_string_size);


    status.normal := TRUE;
    processed := TRUE;
    response_line := '';

    amp$get_next (io_identifiers.input, ^response_line, #SIZE (response_line), transfer_count,
          ignore_byte_address, ignore_file_position, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (transfer_count = 0) OR (response_line = '') THEN
      IF rac$allow_null IN prompting_options THEN
        response := '+NULL';
      ELSE
        response := '+INVALID_RESPONSE';
        issue_status_message (rae$invalid_response, '', io_identifiers.output, status);
        press_next_to_continue (io_identifiers, ignore_status);
      IFEND;

    ELSE

      #SCAN (clv$non_space, response_line, line_start, ignore_result);
      line_length := clp$trimmed_string_size (response_line) - line_start + 1;

      #TRANSLATE (osv$lower_to_upper, response_line (line_start, line_length), translated_response);
      IF (rac$allow_go IN prompting_options) AND ((translated_response = 'GO') OR (translated_response = 'G'))
            THEN
        response := '+GO';
      ELSEIF (rac$allow_quit IN prompting_options) AND ((translated_response = 'QUIT') OR
            (translated_response = 'QUI') OR (translated_response = 'Q')) THEN
        response := '+QUIT';
      ELSE
        response := response_line (line_start, line_length);
        processed := FALSE;
      IFEND;
    IFEND;

    length := clp$trimmed_string_size (response);

  PROCEND get_response;

?? TITLE := 'get_value_declaration', EJECT ??

{ PURPOSE:
{   The purpose of this request is to get the value declaration from the parameter list.
{
{ DESIGN:
{   The SCL parameter for value declaration is a list of string or key.  The value declaration is made
{   up of two parts.  The first part is the value specification which must be a string.  This is required.
{   The second part is a processing key.  This is optional.

  PROCEDURE get_value_declaration
    (VAR value_declaration: rat$value_declaration;
     VAR status: ost$status);

    VAR
      declaration_set_count: 0 .. clc$max_value_sets,
      value: clt$value;


    status.normal := TRUE;

    clp$get_value ('value_declaration', 1, 1, clc$low, value, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF value.kind <> clc$string_value THEN
      osp$set_status_abnormal (rac$process_id, rae$bad_value_specification, '', status);
      RETURN;
    IFEND;

    value_declaration.specification := value.str.value;
    value_declaration.key := rac$undeclared;

    clp$get_set_count ('value_declaration', declaration_set_count, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF declaration_set_count = 2 THEN
      clp$get_value ('value_declaration', 2, 1, clc$low, value, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF value.kind <> clc$name_value THEN
        osp$set_status_abnormal (rac$process_id, rae$bad_value_key, '', status);
        RETURN;
      IFEND;

      IF value.name.value = 'HEX' THEN
        value_declaration.key := rac$hex;
      ELSEIF value.name.value = 'LIST' THEN
        value_declaration.key := rac$list;
      ELSEIF value.name.value = 'STRING' THEN
        value_declaration.key := rac$string;
      IFEND;
    IFEND;

  PROCEND get_value_declaration;

?? TITLE := 'get_value_response', EJECT ??

{ PURPOSE:
{   The purpose of this request is to get the user response to the prompt issued.
{
{ DESIGN:
{

  PROCEDURE get_value_response
    (    value_declaration: rat$value_declaration;
         validation_procedure: ost$name;
         prompting_options: rat$prompting_options;
         io_identifiers: rat$io_identifiers;
     VAR value_returned: rat$value_returned;
     VAR help_requested: boolean;
     VAR status: ost$status);

    VAR
      command: string (osc$max_string_size),
      ignore_status: ost$status,
      length: integer,
      processed: boolean,
      response: string (osc$max_string_size),
      size: integer,
      validation_status: ost$status,
      value_length: integer,
      value_string: string (osc$max_string_size);


    status.normal := TRUE;
    help_requested := FALSE;
    value_returned := '';

    get_response (prompting_options, io_identifiers, response, length, processed, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF processed THEN
      value_returned := response (1, length);

    ELSEIF response = '?' THEN
      help_requested := TRUE;

    ELSE
      CASE value_declaration.key OF
      = rac$hex =
        STRINGREP (value_string, value_length, '0', response (1, length), '(16)');
      = rac$list =
        STRINGREP (value_string, value_length, '(', response (1, length), ')');
      = rac$string =
        STRINGREP (value_string, value_length, '''', response (1, length), '''');
      ELSE
        STRINGREP (value_string, value_length, response (1, length));
      CASEND;

      STRINGREP (command, size, validation_procedure, ' value=', value_string (1, value_length));
      clp$include_command (command (1, size), TRUE, validation_status);
      IF NOT validation_status.normal THEN
        value_returned := '+INVALID_RESPONSE';
        issue_status_message (rae$bad_value, response (1, length), io_identifiers.output, status);
        press_next_to_continue (io_identifiers, ignore_status);
        RETURN;
      IFEND;

      value_returned := response (1, length);

    IFEND;

  PROCEND get_value_response;

?? TITLE := 'initialize_menu_prompt', EJECT ??

{ PURPOSE:
{   The purpose of this request is to initialize the menu containers for displaying the menu prompt.
{
{ DESIGN:
{

  PROCEDURE initialize_menu_prompt
    (VAR menu: rat$menu;
     VAR status: ost$status);

    VAR
      i: rat$number_of_selections,
      ignore_identifier: ost$status_identifier,
      ignore_natural_language: ost$natural_language,
      ignore_online_manual_name: ost$online_manual_name,
      menu_prompt: ost$status,
      prompt_name: [STATIC] ost$name := 'PROMPT                         ',
      prompt_template: ^ost$message_template,
      selection_key: ^string ( * ),
      selection_template: ^ost$message_template,
      title_template: ^ost$message_template;


    status.normal := TRUE;

    osp$find_help_module (menu.module_name, menu.module_ptr, ignore_online_manual_name,
          ignore_natural_language, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$find_brief_help_message (menu.module_ptr, title_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF title_template = NIL THEN
      osp$set_status_abnormal (rac$process_id, rae$menu_definition_error, menu.module_name, status);
      RETURN;
    IFEND;

    osp$format_help_message (title_template, menu.parameters, rac$max_line, menu.title_container, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH selection_key: [rac$selection_key_size];

    FOR i := 1 TO UPPERBOUND (menu.selections^) DO

      clp$convert_integer_to_rjstring (i, 10, FALSE, ' ', selection_key^, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      menu.parameters^ [1]^ := selection_key^;

      osp$find_parameter_prompt (menu.module_ptr, menu.selections^ [i].name, selection_template, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF selection_template = NIL THEN
        osp$set_status_abnormal (rac$process_id, rae$menu_definition_error, menu.module_name, status);
        RETURN;
      IFEND;

      osp$format_help_message (selection_template, menu.parameters, rac$max_line,
            menu.selections^ [i].container, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

    FOREND;

{ Initialize the menu's prompt section.

    osp$find_parameter_prompt (menu.module_ptr, prompt_name, prompt_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF prompt_template = NIL THEN
      osp$set_status_abnormal (rac$process_id, rae$menu_definition_error, menu.module_name, status);
      RETURN;
    IFEND;

    osp$format_help_message (prompt_template, menu.parameters, rac$max_line, menu.prompt_container, status);

  PROCEND initialize_menu_prompt;

?? TITLE := 'initialize_validation_procedure', EJECT ??

{ PURPOSE:
{   The purpose of this request is to set up the SCL procedure that validates the value input.
{
{ DESIGN:
{

  PROCEDURE initialize_validation_procedure
    (    value_declaration: rat$value_declaration;
     VAR validation_procedure: ost$name;
     VAR status: ost$status);

    CONST
      number_of_procedure_lines = 4;

    VAR
      specification_size: integer,
      ignore_byte_address: amt$file_byte_address,
      procedure_lines: array [1 .. number_of_procedure_lines] of rat$write_scl_procedure,
      procedure_fid: amt$file_identifier,
      i: 1 .. number_of_procedure_lines + 1,
      write_attachment: array [1 .. 2] of fst$attachment_option;


    specification_size := clp$trimmed_string_size (value_declaration.specification);

    STRINGREP (procedure_lines [1].value, procedure_lines [1].size, ' PROC validate_value (');
    STRINGREP (procedure_lines [2].value, procedure_lines [2].size, '   value : ',
          value_declaration.specification (1, specification_size));
    STRINGREP (procedure_lines [3].value, procedure_lines [3].size, '   )');
    STRINGREP (procedure_lines [4].value, procedure_lines [4].size, ' PROCEND validate_value');

    write_attachment [1].selector := fsc$access_and_share_modes;
    write_attachment [1].access_modes.selector := fsc$specific_access_modes;
    write_attachment [1].access_modes.value := $fst$file_access_options
          [fsc$read, fsc$shorten, fsc$modify, fsc$append];
    write_attachment [1].share_modes.selector := fsc$determine_from_access_modes;
    write_attachment [2].selector := fsc$create_file;
    write_attachment [2].create_file := TRUE;

    pmp$get_unique_name (validation_procedure, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    fsp$open_file (validation_procedure, amc$record, ^write_attachment, NIL, NIL, NIL, NIL, procedure_fid,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR i := 1 TO number_of_procedure_lines DO
      amp$put_next (procedure_fid, ^procedure_lines [i].value, procedure_lines [i].size, ignore_byte_address,
            status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    FOREND;

    fsp$close_file (procedure_fid, status);

  PROCEND initialize_validation_procedure;

?? TITLE := 'initialize_value_prompt', EJECT ??

{ PURPOSE:
{   The purpose of this request is to initialize the prompt container for displaying the prompt.
{
{ DESIGN:
{

  PROCEDURE initialize_value_prompt
    (VAR prompt: rat$prompt;
     VAR status: ost$status);

    VAR
      ignore_natural_language: ost$natural_language,
      ignore_online_manual_name: ost$online_manual_name,
      prompt_template: ^ost$message_template;


    status.normal := TRUE;

    osp$find_help_module (prompt.module_name, prompt.module_ptr, ignore_online_manual_name,
          ignore_natural_language, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF prompt.module_ptr = NIL THEN
      osp$set_status_abnormal (rac$process_id, rae$module_access_error, prompt.module_name, status);
      RETURN;
    IFEND;

    osp$find_parameter_prompt (prompt.module_ptr, prompt.name, prompt_template, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF prompt_template = NIL THEN
      osp$set_status_abnormal (rac$process_id, rae$message_not_found, prompt.name, status);
      RETURN;
    IFEND;

    osp$format_help_message (prompt_template, prompt.parameters, rac$max_line, prompt.container, status);

  PROCEND initialize_value_prompt;

?? TITLE := 'issue_menu_prompt', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display the menu to output.
{
{ DESIGN:
{

  PROCEDURE issue_menu_prompt
    (    menu: rat$menu;
         prompting_options: rat$prompting_options;
         io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      clear_screen: [STATIC, READ, oss$job_paged_literal] string (2) := '1 ',
      i: rat$number_of_selections,
      ignore_byte_address: amt$file_byte_address;


    status.normal := TRUE;

    IF rac$clear_screen IN prompting_options THEN
      amp$put_next (io_identifiers.output, ^clear_screen, #SIZE (clear_screen), ignore_byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    issue_message (menu.title_container, io_identifiers.output, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    FOR i := 1 TO UPPERBOUND (menu.selections^) DO
      issue_message (menu.selections^ [i].container, io_identifiers.output, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    FOREND;

    issue_message (menu.prompt_container, io_identifiers.output, status);

  PROCEND issue_menu_prompt;

?? TITLE := 'issue_message', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display a message from a message container to output.
{
{ DESIGN:
{

  PROCEDURE issue_message
    (    message_container: ost$status_message;
         output_id: amt$file_identifier;
     VAR status: ost$status);

    VAR
      ignore_byte_address: amt$file_byte_address,
      message_container_ptr: ^ost$status_message,
      message_line: ^ost$status_message_line,
      message_line_count: ^ost$status_message_line_count,
      message_line_index: 1 .. osc$max_status_message_lines,
      message_line_size: ^ost$status_message_line_size;


    status.normal := TRUE;

    message_container_ptr := ^message_container;
    RESET message_container_ptr;
    NEXT message_line_count IN message_container_ptr;

    FOR message_line_index := 1 TO message_line_count^ DO
      NEXT message_line_size IN message_container_ptr;
      NEXT message_line: [message_line_size^] IN message_container_ptr;

      amp$put_next (output_id, message_line, message_line_size^, ignore_byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    FOREND;

  PROCEND issue_message;

?? TITLE := 'issue_status_message', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display an informative message from a status condition to output.
{
{ DESIGN:
{   The status condition is expected to be at the informative level.  When an informative condition is
{   formated as a brief message, two dashes and a space are appended to the front of the message.  This
{   interface strips the two dashes and two spaces off of the first line in the message container, pads
{   it with blanks to the right, and then puts out the message.

  PROCEDURE issue_status_message
    (    message_condition: ost$status_condition_code;
         message_text: string ( * <= osc$max_string_size);
         output_id: amt$file_identifier;
     VAR status: ost$status);

    VAR
      ignore_identifier: ost$status_identifier,
      message_container: ost$status_message,
      message_container_ptr: ^ost$status_message,
      message_line: ^ost$status_message_line,
      message_line_count: ^ost$status_message_line_count,
      message_line_size: ^ost$status_message_line_size,
      message_severity: ost$status_severity,
      message_status: ost$status,
      temp_line: ^ost$status_message_line;


    status.normal := TRUE;

    osp$get_status_severity (message_condition, message_severity, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF message_severity <> osc$informative_status THEN
      osp$set_status_abnormal (rac$process_id, rae$message_not_informative, '', status);
      RETURN;
    IFEND;

    osp$set_status_abnormal (ignore_identifier, message_condition, message_text, message_status);

    osp$format_message (message_status, osc$brief_message_level, rac$max_line, message_container, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    message_container_ptr := ^message_container;
    RESET message_container_ptr;
    NEXT message_line_count IN message_container_ptr;
    NEXT message_line_size IN message_container_ptr;
    NEXT message_line: [message_line_size^] IN message_container_ptr;
    PUSH temp_line: [message_line_size^];

    temp_line^ (1, * ) := message_line^ (5, message_line_size^ -4);
    message_line^ (1, message_line_size^) := temp_line^ (1, message_line_size^);

    issue_message (message_container, output_id, status);

  PROCEND issue_status_message;

?? TITLE := 'issue_value_prompt', EJECT ??

{ PURPOSE:
{   The purpose of this request is to display the prompt to output.
{
{ DESIGN:
{

  PROCEDURE issue_value_prompt
    (    prompt: rat$prompt;
         prompting_options: rat$prompting_options;
         io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      clear_screen: [STATIC, READ, oss$job_paged_literal] string (2) := '1 ',
      ignore_byte_address: amt$file_byte_address;


    status.normal := TRUE;

    IF rac$clear_screen IN prompting_options THEN
      amp$put_next (io_identifiers.output, ^clear_screen, #SIZE (clear_screen), ignore_byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    issue_message (prompt.container, io_identifiers.output, status);

  PROCEND issue_value_prompt;

?? TITLE := 'open_input_output', EJECT ??

{ PURPOSE:
{   The purpose of this request is to open the $input and $output files.
{
{ DESIGN:
{

  PROCEDURE open_input_output
    (VAR io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      read_only_attachment: array [1 .. 2] of fst$attachment_option,
      write_attachment: array [1 .. 3] of fst$attachment_option;


    status.normal := TRUE;

    read_only_attachment [1].selector := fsc$access_and_share_modes;
    read_only_attachment [1].access_modes.selector := fsc$specific_access_modes;
    read_only_attachment [1].access_modes.value := $fst$file_access_options [fsc$read];
    read_only_attachment [1].share_modes.selector := fsc$determine_from_access_modes;
    read_only_attachment [2].selector := fsc$create_file;
    read_only_attachment [2].create_file := FALSE;

    fsp$open_file ('$INPUT', amc$record, ^read_only_attachment, NIL, NIL, NIL, NIL, io_identifiers.input,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    io_identifiers.input_open := TRUE;

    write_attachment [1].selector := fsc$access_and_share_modes;
    write_attachment [1].access_modes.selector := fsc$specific_access_modes;
    write_attachment [1].access_modes.value := $fst$file_access_options
          [fsc$append, fsc$shorten];
    write_attachment [1].share_modes.selector := fsc$determine_from_access_modes;
    write_attachment [2].selector := fsc$access_and_share_modes;
    write_attachment [2].access_modes.selector := fsc$specific_access_modes;
    write_attachment [2].access_modes.value := $fst$file_access_options
          [fsc$append];
    write_attachment [2].share_modes.selector := fsc$determine_from_access_modes;
    write_attachment [3].selector := fsc$create_file;
    write_attachment [3].create_file := FALSE;

    fsp$open_file ('$OUTPUT', amc$record, ^write_attachment, NIL, NIL, NIL, NIL, io_identifiers.output,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    io_identifiers.output_open := TRUE;

  PROCEND open_input_output;

?? TITLE := 'press_next_to_continue', EJECT ??

{ PURPOSE:
{   The purpose of this request is to allow the user to acknowledge previously issued statements before
{   continuing.  Pressing a carriage return causes the processing to continue.
{
{ DESIGN:
{

  PROCEDURE press_next_to_continue
    (    io_identifiers: rat$io_identifiers;
     VAR status: ost$status);

    VAR
      ignore_byte_address: amt$file_byte_address,
      ignore_file_position: amt$file_position,
      ignore_transfer_count: amt$transfer_count,
      ignore_response: string (osc$max_string_size);


    status.normal := TRUE;

    issue_status_message (rae$press_next, '', io_identifiers.output, status);

    amp$get_next (io_identifiers.input, ^ignore_response, #SIZE (ignore_response), ignore_transfer_count,
          ignore_byte_address, ignore_file_position, status);

  PROCEND press_next_to_continue;

?? TITLE := 'prompt_for_value_line_mode', EJECT ??

{ PURPOSE:
{   The purpose of this request is to prompt for a value response in line mode.
{
{ DESIGN:
{

  PROCEDURE prompt_for_value_line_mode
    (    value_declaration: rat$value_declaration;
         prompting_options: rat$prompting_options;
     VAR prompt: rat$prompt;
     VAR value_returned: rat$value_returned;
     VAR status: ost$status);

    VAR
      close_status: ost$status,
      help_requested: boolean,
      ignore_status: ost$status,
      io_identifiers: rat$io_identifiers,
      valid_value: boolean,
      validation_procedure: ost$name;

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

{ PURPOSE:
{   The purpose of this request is to close the input and output files on an unexpected abort.
{

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

      VAR
        ignore_status: ost$status;


      IF io_identifiers.input_open THEN
        fsp$close_file (io_identifiers.input, ignore_status);
        io_identifiers.input_open := FALSE;
      IFEND;

      IF io_identifiers.output_open THEN
        fsp$close_file (io_identifiers.output, ignore_status);
        io_identifiers.output_open := FALSE;
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    valid_value := FALSE;
    io_identifiers.input_open := FALSE;
    io_identifiers.output_open := FALSE;

    osp$establish_block_exit_hndlr (^abort_handler);

  /get_value/
    BEGIN

      open_input_output (io_identifiers, status);
      IF NOT status.normal THEN
        EXIT /get_value/;
      IFEND;

      initialize_value_prompt (prompt, status);
      IF NOT status.normal THEN
        EXIT /get_value/;
      IFEND;

      initialize_validation_procedure (value_declaration, validation_procedure, status);
      IF NOT status.normal THEN
        EXIT /get_value/;
      IFEND;

      REPEAT

        issue_value_prompt (prompt, prompting_options, io_identifiers, status);
        IF NOT status.normal THEN
          EXIT /get_value/;
        IFEND;

        get_value_response (value_declaration, validation_procedure, prompting_options, io_identifiers,
              value_returned, help_requested, status);
        IF NOT status.normal THEN
          EXIT /get_value/;
        IFEND;

        IF help_requested THEN
          display_value_help (prompt, io_identifiers, status);
          IF NOT status.normal THEN
            EXIT /get_value/;
          IFEND;
        ELSEIF value_returned <> '+INVALID_RESPONSE' THEN
          valid_value := TRUE;
        IFEND;

      UNTIL valid_value;

      amp$return (validation_procedure, ignore_status);

    END /get_value/;

    close_input_output (io_identifiers, close_status);
    IF status.normal AND (NOT close_status.normal) THEN
      status := close_status;
    IFEND;

    osp$disestablish_cond_handler;

  PROCEND prompt_for_value_line_mode;

?? TITLE := 'prompt_via_menu_line_mode', EJECT ??

{ PURPOSE:
{   The purpose of this request is to provide prompting via a menu display in line mode.
{
{ DESIGN:
{

  PROCEDURE prompt_via_menu_line_mode
    (    prompting_options: rat$prompting_options;
     VAR menu: rat$menu;
     VAR selection_chosen: ost$name;
     VAR status: ost$status);

    VAR
      help_requested: boolean,
      input_open: boolean,
      io_identifiers: rat$io_identifiers,
      close_status: ost$status,
      output_open: boolean,
      valid_selection: boolean;

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

{ PURPOSE:
{   The purpose of this request is to close the input and output files on an unexpected abort.
{

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

      VAR
        ignore_status: ost$status;

      IF io_identifiers.input_open THEN
        fsp$close_file (io_identifiers.input, ignore_status);
        io_identifiers.input_open := FALSE;
      IFEND;

      IF io_identifiers.output_open THEN
        fsp$close_file (io_identifiers.output, ignore_status);
        io_identifiers.output_open := FALSE;
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;
    valid_selection := FALSE;
    io_identifiers.input_open := FALSE;
    io_identifiers.output_open := FALSE;

    osp$establish_block_exit_hndlr (^abort_handler);

  /get_selection/
    BEGIN

      open_input_output (io_identifiers, status);
      IF NOT status.normal THEN
        EXIT /get_selection/;
      IFEND;

      initialize_menu_prompt (menu, status);
      IF NOT status.normal THEN
        EXIT /get_selection/;
      IFEND;

      REPEAT

        issue_menu_prompt (menu, prompting_options, io_identifiers, status);
        IF NOT status.normal THEN
          EXIT /get_selection/;
        IFEND;

        get_menu_response (menu, prompting_options, io_identifiers, selection_chosen, help_requested, status);
        IF NOT status.normal THEN
          EXIT /get_selection/;
        IFEND;

        IF help_requested THEN
          display_menu_help (menu, selection_chosen, io_identifiers, status);
          IF NOT status.normal THEN
            EXIT /get_selection/;
          IFEND;

        ELSEIF selection_chosen <> '+INVALID_RESPONSE' THEN
          valid_selection := TRUE;
        IFEND;

      UNTIL valid_selection;

    END /get_selection/;

    close_input_output (io_identifiers, close_status);
    IF status.normal AND (NOT close_status.normal) THEN
      status := close_status;
    IFEND;

    osp$disestablish_cond_handler;

  PROCEND prompt_via_menu_line_mode;

MODEND ram$menu_prompting_interfaces;
