#include<stdio.h> 
#include<stdlib.h>
#include<string.h>
/* 




                 VV                   VV    EEEEEEEEEEEEEE   
                  VV                 VV     EE  
                   VV               VV      EE
                    VV             VV       EE
                     VV           VV        EE
                      VV         VV         EEEEEEEEEEEEEE
                       VV       VV          EE
                        VV     VV           EE
                         VV   VV            EE
                          VV VV             EE
                           VVV              EE
                            V               EEEEEEEEEEEEEE
                                                       
 
 
 
 
                       MODULE  : optcmd.c
 
                       VERSION : v3.5
 
                       REVISED : 12 Jul 2005
 
                       AUTHOR  : Michael A. Campbell
 
 
 
 
 
 


                          FUNCTIONAL DESCRIPTION
                          ----------------------
 
               This module contains the options commands for VE.  These
 
               allow the user to change various operating parameters 
 
               of the editor, such as tabs, autoindent, etc.








*/

/* .page */

/************************************************
 * INCLUDE FILES, LOCAL DEFINITIONS, STRUCTURES *
 ************************************************/

#include <curses.h>

#include "../def/common.def"
#include "../def/termif.def"
#include "../def/kbdif.def"

#define WRAP_TEXT_OPTION      1
#define AUTO_INDENT_OPTION    2

#include "../str/vestruct.str"

struct screen_colors {
    short fg_color;
    short bg_color;
    BOOL  colors_applied;
};

#include "../inc/vedbase.inc"
#include "../inc/termif.inc"


#include "../ext/termif.ext"
#include "../ext/kbdif.ext"
#include "../ext/veutils.ext"
#include "../ext/stacks.ext"
#include "../ext/wordcmd.ext"


/********************
 * STATIC VARIABLES *
 ********************/

char *text_wrapping_msg [] = {
    "Text wrapping ON",
    "Text wrapping OFF",
    "Couldn't wrap text",
    "Line not wrappable, "
};

char *right_justify_msg [] = {
    "Right Justify ON",
    "Right Justify OFF"
};

char *on_off_msg [] = {
    "OFF",
    "ON"
};

char ve_opt_fn [] = "/.ve.opt";

/* .page */

/*********************
 * LOCAL PROCEDURES  *
 *********************/

BOOL margin_check ( prev_left_margin, prev_right_margin )

/*****************************************************************************
 *                                                                           *
 *   This procedure checks that the right margin is greater than the         *
 *   left margin, and will modify them if not.                               *
 *                                                                           *
 *****************************************************************************/

int prev_left_margin;
int prev_right_margin;

 begin
    register int ret_val = TRUE;

    if ( ( options.right_margin <= options.left_margin ) ||
         ( options.right_margin > columns              )    ) begin

       options.left_margin  = prev_left_margin;
       options.right_margin = prev_right_margin;
       ret_val              = FALSE;

    end

    return ( ret_val );

end /* margin_check */

/* .page */

short get_new_color ( curr_color_value, color_prompt, px, py, status )

/*****************************************************************************
 *                                                                           *
 * This function prompts the user for a new color selection, including the   *
 * current value as part of the prompt, and then reads in a new color name.  *
 * It then verifies the color name and translates it to a color_value. If    *
 * this is successful, it returns the new color value. Else, it returns the  *
 * currrent color value.                                                     *
 *                                                                           *
 *****************************************************************************/

short curr_color_value;       /* Color value to be replaced                  */
char color_prompt [];         /* Prompt string for the new color             */
int px, py;                   /* Where to position cursor if divider msg     */
int *status;                  /* Result of this function                     */

begin
   register int x, len;       /* X co-ordinate for prompts, length of input  */
   short new_color_value;     /* Color_value for new color selection         */
   char curr_color_name [20]; /* Buffer to place the new color name into     */
   char new_color_name [82];  /* The new color's name                        */

   *status = E_OK;

   get_color_name ( curr_color_value, curr_color_name );

   write_status_line ( color_prompt );
   x = strlen(color_prompt);

   len = prompt_read_str ( x, 0, curr_color_name, x, 0, new_color_name, 78 - x );

   /* If the user simply presses ENTER, re-use the current color,    */
   /* else use the new color they have entered.                      */

   if ( len == 0 ) then
      strcpy ( new_color_name, curr_color_name );

   new_color_value = get_color_value ( new_color_name );

   if ( new_color_value == -2 ) begin

      /* Invalid color entered - tell the user and try again         */

      *status = E_INVALID_SELECTION;
      write_divider_msg ( "Unrecognized color - must be on palette", px, py );

      new_color_value = curr_color_value;
   end

   return ( new_color_value );

end /* get_new_color */

/* .page */

void display_color_names ( set_name, fg_color, bg_color, cx, cy )

/****************************************************************************
 * This function displays the provided colors on the divider line and then  *
 * places the cursor at the indicated cx, cy co-ordinates.                  *
 ****************************************************************************/

char  *set_name; /* The color set - "working" or "displayed"                */
short fg_color;  /* The foreground color value                              */
short bg_color;  /* The background color value                              */
int   cx, cy;    /* Co-ordinates to leave the cursor at                     */

begin
   char fg_color_name [20];
   char bg_color_name [20];
   char color_msg [82];

   get_color_name ( fg_color, fg_color_name );
   get_color_name ( bg_color, bg_color_name );

   sprintf ( color_msg, "%s%s %s %s, %s %s", 
             "> ", set_name, "foreground color is", fg_color_name,
                       "background color is", bg_color_name   );

   write_divider_msg ( color_msg, cx, cy );

end /* display_color_name */

/* .page */

void tab_options_subcommand ()

/*****************************************************************************
 *                                                                           *
 * This function implements the Tab subcommand of the Options menu. This     *
 * subcommand allows users to change the tabstop in use, and whether tabs    *
 * are translated to spaces when files are read, and whether tabs are used   *
 * to compress spaces when files are written.                                *
 *                                                                           *
 *****************************************************************************/

begin
   char selection;
   char tab_option_menu [] = "Input  Output  Tabstop : ";

   /* Present a menu of available TAB options, and the current state    */
   /* of those options                                                  */

   push_status_line ( tab_option_menu );

   do
   begin
      sprintf ( temp.text, "%s %s, %s %s, %s %d",
                "> Input xlate",  on_off_msg[options.input_tab_translation ],
                  "Output xlate", on_off_msg[options.output_tab_translation],
                  "Tabstop =",   options.tab_stop );

      write_divider_msg ( temp.text, strlen(tab_option_menu), 0 );

      /* Until the user enters ENTER, continue in the TAB options menu */

      selection = toupper(read_char());

      /* Expand input tabs to spaces ?                                 */

      if (selection == 'I') 
          options.input_tab_translation = !options.input_tab_translation;

      /* Compact spaces to tabs on output ?                            */

      else if (selection == 'O') 
         options.output_tab_translation = !options.output_tab_translation;

      /* Set a new tab stop width                                      */

      else if (selection == 'T') 
      begin
          prompt_read_str ( 0, 0, "Tabstop: ", -1, -1, temp.text, 10 );
          sscanf (temp.text, "%d", &options.tab_stop);
      end

       /* Invalid option                                                */

      else if ( selection != ENTER )
         writechar ( BEL );

      write_status_line ( tos(&status_stack) );

   end
   while ( selection != ENTER );

   clear_divider_msg ();
   pop_status_line ();

end /* tab_options_subcommand */

/* .page */

void binary_options_subcommand ( option_name, option_flag )

/****************************************************************************
 * This subcommand implements the AutoIndent selection of the Options menu. *
 * It allows users to select auto indent On or Off.                         *
 ****************************************************************************/

char option_name [];
int  *option_flag;

begin
   char option_menu  [82];
   char option_state [82];
   register int  name_len;
   register char selection;

   name_len = strlen ( option_name );

   strcpy ( option_menu, option_name              );
   strcat ( option_menu, " ? (Enable/Disable) : " );

   strcpy ( option_state, option_name );
   strcat ( option_state, " Oxx"      );

   do
   begin
      /* Write out the menu and the current status of auto indent */

      write_status_line ( option_menu );

      if ( *option_flag )
      begin
         option_state[name_len + 2] = 'N';
         option_state[name_len + 3] = ' ';
      end
      else begin
         option_state[name_len + 2] = 'F';
         option_state[name_len + 3] = 'F';
      end

      write_divider_msg ( option_state, strlen(option_menu), 0 );

      /* Read the users selection */

      selection = toupper(read_char());

      if ( selection != ENTER )
         *option_flag = (selection == 'E') ? TRUE : FALSE;

   end
   while ( selection != ENTER );

   clear_divider_msg ();

end /* binary_options_subcommand */

/* .page */

void text_wrapping_options_subcommand ()

/****************************************************************************
 * This subcommand implements the AutoIndent selection of the Options menu. *
 * It allows users to select auto indent On or Off.                         *
 ****************************************************************************/

begin
   register char selection;          /* Users command key                   */
   register BOOL show_status = TRUE; /* Show status or error message        */
   int left_margin, right_margin;    /* Current left and right margins      */
   int selection_w, selection_j;     /* Wrap and Justify msg indices (0/1)  */
   BOOL margin_ok;                   /* Are new margins OK?                 */
   int lines_wrapped;                /* Lines that got wrapped              */
   int x, len;                       /* Prompting temp vars                 */
   char wrap_msg [82];
   char wrap_options_menu [] = "Enable  Disable  Left  Right  Justify : ";

   push_status_line ( wrap_options_menu );

   do
   begin
      /* Present a menu of available text wrapping options, and the current */
      /* status of those options. Until ENTER, continue with text wrapping  */
      /* option menu                                                        */

      left_margin  = options.left_margin;
      right_margin = options.right_margin;

      if ( show_status )
      begin
         selection_w = (options.wrap_text     ? 0 : 1);
         selection_j = (options.right_justify ? 0 : 1);

         sprintf (wrap_msg, "%s, %s, %s %d, %s %d",
                  text_wrapping_msg[selection_w], right_justify_msg[selection_j],
                  "Left margin:", options.left_margin, "Right margin:", options.right_margin );

         write_divider_msg ( wrap_msg, strlen(wrap_options_menu), 0 );
   
      end

      show_status = TRUE;

      selection = toupper(read_char());

      if (selection == 'E') 
      begin
         /* If text wrapping is selected, deselect auto indent   */
         /* and force VE into insert mode                        */

         options.wrap_text   = TRUE;
         options.auto_indent = FALSE;
         ve_mode             = last_ve_mode = M_INSERT;
            
         wrap_line ( TRUE );
      end

      else if (selection == 'D')             /* Disable wrapping      */
      begin
          options.wrap_text = FALSE;
      end

      else if (selection == 'R') begin       /* Set the right margin  */

         write_status_line ( "Right Margin: " );
         x = 14;  /* strlen( "Right Margin: " ) */

         sprintf ( wrap_msg, "%d", options.right_margin );
         len = prompt_read_str ( x, 0, wrap_msg, x, 0, temp.text, 10 );

          if ( len != 0 ) begin
             sscanf (temp.text, "%d", &options.right_margin);
             margin_ok = margin_check (left_margin, right_margin);

             if ( !margin_ok )
             begin
                write_divider_msg ( "Invalid right margin",
                                    strlen(wrap_options_menu), 0 );
                show_status = FALSE;
             end

          end
      end

      else if (selection == 'L') begin       /* Set the left margin    */

         write_status_line ( "Left Margin: " );
         x = 13;  /* strlen( "Left Margin: " ) */

         sprintf ( wrap_msg, "%d", options.left_margin );
         len = prompt_read_str ( x, 0, wrap_msg, x, 0, temp.text, 10 );

         if ( len != 0 ) begin
            sscanf (temp.text, "%d", &options.left_margin);
            margin_ok = margin_check (left_margin, right_margin);

            if ( !margin_ok )
            begin
               write_divider_msg ( "Invalid left margin",
                                   strlen(wrap_options_menu), 0 );
               show_status = FALSE;
            end

         end

         if ( options.wrap_text ) begin
              ve_mode = last_ve_mode = M_INSERT;
              wrap_line ( TRUE );
         end

      end /* selection == 'L' */

      else if (selection == 'J')
         options.right_justify = !options.right_justify;

      else if (selection != ENTER)
         writechar ( BEL );

      write_status_line ( tos(&status_stack) );

   end
   while ( selection != ENTER );

   clear_divider_msg ();
   pop_status_line ();

end /* text_wrapping_options_subcommand */

/* .page */

void color_options_subcommand ()

/*****************************************************************************
 *                                                                           *
 * This function implements the Colors subcommand of the Options menu.       *
 * This subcommand allows users to change the foreground and background      *
 * colors used by the VE editor. These colors are set into the options block *
 * and can be saved out and subsequently auto loaded by the Options, Save    *
 * selection, thus changing the default colors that VE uses when loaded by   *
 * a given user.                                                             *
 *                                                                           *
 *****************************************************************************/

begin
   register char selection;   /* User's menu selection                       */
   int status;                /* Result of a get_new_color call              */

   char color_msg [82];       /* Message construction buffer                 */

   BOOL show_status = TRUE;             /* Show status or error/info message */
   struct screen_colors working_colors; /* Working colors, not yet set       */

   char color_options_menu [] = "Palette  Working  Foreground  Background  Apply  Query : ";
   char fg_color_prompt []    = "Enter new foreground (text) color: ";
   char bg_color_prompt []    = "Enter new background color: ";

   working_colors.fg_color = options.fg_color;
   working_colors.bg_color = options.bg_color;

   push_status_line ( color_options_menu );

   /* Until ENTER, continue to operate within the Colors submenu      */

   do
   begin
       if ( show_status )
       begin
          display_color_names ( "Displayed", options.fg_color, options.bg_color, 
                                 strlen(color_options_menu), 0 );
          show_status = FALSE;
       end


       selection = toupper(read_char());

       if (selection == 'P') begin

          /* Palette command entered - present the available colors         */

          strcpy ( color_msg, "> " );
          strcat ( color_msg, get_color_palette() );
          write_divider_msg ( color_msg, strlen(color_options_menu), 0 );

       end /* selection == 'P' */


       else if ( selection == 'W' ) begin

          /* Working command - report on the working colors        */

          display_color_names ( "Working", working_colors.fg_color, working_colors.bg_color, 
                                 strlen(color_options_menu), 0 );

       end /* selection == 'W' */


       else if ( selection == 'F' ) begin

          /* Foreground command - set the working Foreground color          */
          /* Prompt for the new color name, including the current value as  */
          /* part of the prompt, and then attempt to get the associated     */
          /* color value. If successful, put it into the working colors.    */

          working_colors.fg_color = get_new_color ( working_colors.fg_color,
                                    fg_color_prompt, strlen(color_options_menu), 0, &status );
          if ( status == E_OK )
             display_color_names ( "Working", working_colors.fg_color, working_colors.bg_color, 
                                    strlen(color_options_menu), 0 );
       end /* selection == 'F' */


       else if ( selection == 'B' ) begin

          /* Background command - set the working Background color          */
          /* Prompt for the new color name, including the current value as  */
          /* part of the prompt, and then attempt to get the associated     */
          /* color value. If successful, put it into the working colors.    */

          working_colors.bg_color = get_new_color ( working_colors.bg_color,
                                    bg_color_prompt, strlen(color_options_menu), 0, &status );
          if ( status == E_OK )
             display_color_names ( "Working", working_colors.fg_color, working_colors.bg_color, 
                                    strlen(color_options_menu), 0 );

       end /* selection == 'B' */


       else if ( selection == 'A' ) begin

          /* Apply command - apply the the working colors to the display.  */

          if ( (working_colors.fg_color != working_colors.bg_color ) || 
               (working_colors.fg_color == DEFAULT_FG_COLOR && 
                working_colors.bg_color == DEFAULT_BG_COLOR        ) ) begin

             options.fg_color = working_colors.fg_color;
             options.bg_color = working_colors.bg_color;

             ti_set_screen_colors ();

             show_status = TRUE;
          end


          else
             write_divider_msg ( "> Foreground and Background colors must be different",
                                 strlen(color_options_menu), 0 );
       end /* selection == 'A' */


       else begin
          show_status = TRUE;

          if ( selection != 'Q' && selection != ENTER )
             writechar ( BEL );
       end

       /* Restore Colors menu */

       write_status_line ( tos(&status_stack) );

   end
   while ( selection != ENTER );

   clear_divider_msg ();
   pop_status_line ();

end /* color_options_subcommand */

/* .page */

void set_match_char ( prompt, match_char )

/*****************************************************************************
 *                                                                           *
 * This function prompts the user for a Start-of-line or End-of-line match   *
 * character, and updates the supplied character with the result. If the     *
 * user enters a blank ENTER, the existing value is re-used.                 *
 *                                                                           *
 *****************************************************************************/

char prompt [];              /* The prompt to issue                          */
char *match_char;            /* The char to update                           */

begin
   register int x, len;      /* x coordinate for message, length of response */
   char     curr_val [ 4];   /* Buffer for building current value prompts    */
   char     new_val  [22];   /* Buffer for user's new requested val          */

   write_status_line ( prompt );
   x = strlen(prompt);

   curr_val[0] = *match_char;
   curr_val[1] = '\0';

   len = prompt_read_str ( x, 0, curr_val, x, 0, new_val, 10 );
   if ( len == 0 ) then
      new_val[0] = *match_char;

   *match_char = new_val[0];

end /* set_match_char */

/* .page */

void match_options_subcommand ()

/*****************************************************************************
 *                                                                           *
 * This function implements the Match subcommand of the Options menu. This   *
 * subcommand allows users to change the characters that can be used in the  *
 * Find and Replace commands to match either the Start-of-Line or the        *
 * End-of-Line. The user's selections are loaded into the options block, and *
 * may be saved out with the Options, Save command and henceforth auto       *
 * loaded by VE at start up, thus "permanently" changing the match chars for *
 * that user.                                                                *
 *                                                                           *
 *****************************************************************************/

begin
   register char selection;   /* User's menu selection                       */
   int x, len;                /* For prompt_read_str                         */
   char curr_val [4];         /* Buffer for building current value prompts   */
   char new_val [82];         /* Buffer for user's new requested val         */
   int status;                /* Result of a get_new_color call              */

   char sol_prompt [] = "Enter char to match start-of-line: ";
   char eol_prompt [] = "Enter char to match end-of-line: ";

   char match_options_menu [] = "Start-of-line  End-of-line  Query : ";

   push_status_line ( match_options_menu );

   do
   begin
      /* Until ENTER, continue to operate within the Match submenu          */

      sprintf ( new_val, "%s %c %s %c %s",
                "> Find/Replace uses",        options.sol_match_char, 
                "to match Start-ofline, and", options.eol_match_char,
                "to match End-of-line"                                   );

      write_divider_msg ( new_val, strlen(match_options_menu), 0 );

      selection = toupper(read_char());

      if (selection == 'S') begin

         /* Start-of-line command entered - prompt for, save character that */
         /* will match Start-of-Line in Find/Replace                        */

         set_match_char ( sol_prompt, &options.sol_match_char );

      end /* selection is 'S' */

      else if ( selection == 'E' ) begin

         /* End-of-line command entered - prompt for, save character that   */
         /* will match End-of-Line in Find/Replace                          */

         set_match_char ( eol_prompt, &options.eol_match_char );

      end

      /* Invalid selection - just beep at them */

      else if ( selection != 'Q' && selection != ENTER )
         writechar ( BEL );

      /* Restore Match menu */

      write_status_line ( tos(&status_stack) );

   end
   while ( selection != ENTER );

   clear_divider_msg ();
   pop_status_line ();

end /* match_options_subcommand */

/* .page */

void file_format_options_subcommand ()

/*****************************************************************************
 *                                                                           *
 * This function implements the File Format subcommand of the Options menu.  *
 * This subcommand allows users to change the file format in which files are *
 * written between "linux" and "dos". The Linux choice uses only a LF char   *
 * for the end-of-line indicator. The DOS choice uses CR, LF.                *
 *                                                                           *
 *****************************************************************************/

begin
   register char selection;
   char msg_buf [82];

   char file_format_prompt [] = "Select text file format - Unix or DOS/Win : ";

   selection = toupper(curr_file.file_format);

   do
   begin
      write_status_line ( file_format_prompt );

      strcpy ( msg_buf, "> Text file format is " );

      if ( selection == 'D' ) begin
          curr_file.file_format = 'd';
          strcat ( msg_buf, "DOS/Win" );
      end

      else begin
          curr_file.file_format = 'u';
          strcat ( msg_buf, "Unix" );
      end

      write_divider_msg ( msg_buf, strlen(file_format_prompt), 0 );

      selection = toupper(read_char ());

   end
   while ( selection != ENTER );

   clear_divider_msg ();

end /* file_format_options_subcommand */

/* .page */

/*********************
 * PUBLIC PROCEDURES *
 *********************/

int save_ve_opt_file ()

/*****************************************************************************
 *                                                                           *
 * Write the VE options block to the file "~/.ve.opt".                       *
 *                                                                           *
 *****************************************************************************/

begin
   char *user_home;          /* pathname of user's home directory            */
   char options_fn [256];    /* name of VE options file in home directory    */
   FILE *options_conn;       /* connection handle for options file           */

   int result = E_OPEN_ERROR;

   user_home = getenv ( "HOME" );

   if ( user_home != NULL ) begin

      strcpy ( options_fn, user_home );
      strcat ( options_fn, ve_opt_fn );

      options_conn = fopen ( options_fn, "wb" );  /* open for write, binary    */

      if ( options_conn != NULL ) begin

         result = E_OK;

         fwrite ( &options, sizeof(options), 1, options_conn );
         fclose ( options_conn );

      end
   end

   return ( result );
   
end /* save_ve_opt_file */

/* .page */

int load_ve_opt_file ()

/*****************************************************************************
 *                                                                           *
 * Load the options block from the file "~/.ve.opt". Perform a set of the    *
 * selected colors.                                                          *
 *                                                                           *
 *****************************************************************************/

begin
   char *user_home;          /* pathname of user's home directory            */
   char options_fn [256];    /* name of VE options file in home directory    */
   FILE *options_conn;       /* connection handle for options file           */

   int result = E_OPEN_ERROR;

   user_home = getenv ( "HOME" );

   if ( user_home != NULL ) begin

      strcpy ( options_fn, user_home );
      strcat ( options_fn, ve_opt_fn );

      options_conn = fopen ( options_fn, "rb" );  /* open for read, binary  */

      if ( options_conn != NULL ) begin

         result = E_OK;

         fread ( &options, sizeof(options), 1, options_conn );
         fclose ( options_conn );

      end
   end

   return ( result );

end

/* .page */

void option_cmd ()

/*****************************************************************************
 *                                                                           *
 *   Manipulate the VE option set.                                           *
 *                                                                           *
 *****************************************************************************/

begin
    register char selection;     /* Selection of command                     */
    register char selection_w;   /* Selection for text wrapping              */
    register char selection_j;   /* Selection for right justification        */
    char convert_buf [20];       /* For converting numbers                   */
    char msg_buf [82];           /* For constructing output messages         */
    int len, x;                  /* Length of user input                     */
    int lines_wrapped;           /* how many lines were wrapped              */
    int status;                  /* Status of an operation                   */

    char options_menu [] = "Tabs  Indent  Wrap  Colors  Match  Fileformat  Rodent  Save : ";

    /* Present a menu of available options and read in a selection           */

    update_curr_line ();

    push_status_line ( options_menu );

    /* Continue to process options until user enters ESC or ENTER to exit    */

    do
    begin
       selection = toupper(read_char());

       /* Handle a selection of TAB                                          */

       if (selection == 'T')
          tab_options_subcommand ();

       /* Handle a selection of Auto Indent */

       else if (selection == 'I')
          binary_options_subcommand ( "Auto Indent", &options.auto_indent );
   
       /* Handle a selection of On-the-Fly Text Wrapping                      */
       /* ("Power Typing" in the Qunix original)                              */
   
       else if (selection == 'W')
          text_wrapping_options_subcommand ();

       /* Selection is Colors - set the foreground and background colors used */
       /* by VE                                                               */

       else if ( selection == 'C' )
          color_options_subcommand ();

       /* Selection is Match - set the characters used to match the start and */
       /* end of line                                                         */

       else if ( selection == 'M' )
          match_options_subcommand ();

       /* Selection is Format - select either linux or DOS/Win file           */
       /* format for new lines: either LF, or CR,LF                           */

       else if ( selection == 'F' )
          file_format_options_subcommand ();

       /* Selection is "Rodent" (mouse) - sorry, 'M' is used already!         */

       else if (selection == 'R')
       begin
          binary_options_subcommand ( "Mouse Support", &options.mouse_enabled );

          if ( options.mouse_enabled )
             mousemask ( ALL_MOUSE_EVENTS, NULL );
          else
             mousemask ( 0,                NULL );
       end
   
       /* Save current ve options to ~/.ve.opt */

       else if ( selection == 'S' ) begin

          status = save_ve_opt_file ();

          if ( status == E_OK ) then
             write_divider_msg ( "> Options saved to ~/.ve.opt - loaded by VE at next start",
                                 strlen(options_menu), 0 );
          else
             write_divider_msg ( "> Could not save options to ~/.ve.opt",
                                 strlen(options_menu), 0 );

       end /* selection == 'S' */

       /* Load current ve options from ~/.ve.opt                              */
       /* This is a hidden command - ve options are auto loaded by main.c     */
/*
       else if ( selection == 'L' ) begin

          status = load_ve_opt_file ();

          if ( status == E_OK ) then
             write_divider_msg ( "Options loaded from ~/.ve.opt",
                                 strlen(options_menu), 0 );
          else
             write_divider_msg ( "Could not load options from ~/.ve.opt",
                                 strlen(options_menu), 0 );

       end
*/

       /* Entered an invalid choice from the master menu */

       else if ( selection != ENTER )
           writechar ( BEL );

       /* Re-present the menu and read the next user selection */

       write_status_line ( tos(&status_stack) );

    end
    while ( selection != ENTER );

    clear_divider_msg ();
    pop_status_line (); /* Restore previous menu, if any */

end /* option_cmd */

