#if !defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: status.c,v 4.29 1994/10/03 22:43:31 mikes Exp $";
#endif
/*----------------------------------------------------------------------

            T H E    P I N E    M A I L   S Y S T E M

   Laurence Lundblade and Mike Seibel
   Networks and Distributed Computing
   Computing and Communications
   University of Washington
   Administration Builiding, AG-44
   Seattle, Washington, 98195, USA
   Internet: lgl@CAC.Washington.EDU
             mikes@CAC.Washington.EDU

   Please address all bugs and comments to "pine-bugs@cac.washington.edu"

   Copyright 1989-1994  University of Washington

    Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee to the University of
   Washington is hereby granted, provided that the above copyright notice
   appears in all copies and that both the above copyright notice and this
   permission notice appear in supporting documentation, and that the name
   of the University of Washington not be used in advertising or publicity
   pertaining to distribution of the software without specific, written
   prior permission.  This software is made available "as is", and
   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
   Pine and Pico are trademarks of the University of Washington.
   No commercial use of these trademarks may be made without prior
   written permission of the University of Washington.

   Pine is in part based on The Elm Mail System:
    ***********************************************************************
    *  The Elm Mail System  -  Revision: 2.13                             *
    *                                                                     *
    * 			Copyright (c) 1986, 1987 Dave Taylor              *
    * 			Copyright (c) 1988, 1989 USENET Community Trust   *
    ***********************************************************************
 

  ----------------------------------------------------------------------*/

/*======================================================================
     status.c
     Functions that manage the status line (third from the bottom)
       - put messages on the queue to be displayed
       - display messages on the queue with timers 
       - check queue to figure out next timeout
       - prompt for yes/no type of questions
  ====*/

#include "headers.h"

#ifdef ANSI
int  output_message(char *);
void radio_help(int, int, HelpType);
void draw_radio_prompt(int, int, char *);

#else
int  output_message();
void radio_help();
void draw_radio_prompt();
#endif



/*----------------------------------------------------------------------
     Manage the second line from the bottom where status and error messages
re displayed. A small queue is set up and messages are put on the queue
by calling on of the q_status_message routines. Even though this is a queue
most of the time message will go right on through. The messages are 
displayed just before the read for the next command, or when a read time
out. Read timeouts occur every minute or so for new mail checking and every
few seconds when the are still messages on the queue. Hopefully this scheme 
will not let messages fly past the usr can't see.
  ----------------------------------------------------------------------*/
struct message{
    char text[MAX_SCREEN_COLS+1];
    int  min_display_time, max_display_time;
};

#define QUEUE_LENGTH 6


static struct message  message_queue[QUEUE_LENGTH];
static struct message  currently_displayed;
static int             message_is_displayed = 0,
                       queue_length = 0,
                       needs_clearing = 0; /* Flag set by want_to()
                                              and optionally_enter() */
static time_t          displayed_time;


/*----------------------------------------------------------------------
        Put a message for the status line on the queue

  Args: time    -- the min time in seconds to display the message
        message -- message string

  Result: queues message on queue represented by static variables

    This puts a single message on the queue to be shown.
  ----------*/
void
q_status_message(modal, min_time, max_time, message)
     char *message;
     int   min_time,max_time, modal;
{
    strncpy(message_queue[queue_length].text, message, MAX_SCREEN_COLS);
    (message_queue[queue_length].text)[MAX_SCREEN_COLS] = '\0';

    /* save the display time length */
    message_queue[queue_length].min_display_time = min_time;
    message_queue[queue_length].max_display_time = max_time;


    /* Bump up the queue length if it's not full. (If there's more than
         6 messages we just over write last message */
    if(queue_length < QUEUE_LENGTH - 1 )
      queue_length++;
    dprint(9, (debugfile, "q_status_message, Count %d, \"%s\"\n",
	       queue_length, message))
}


/*----------------------------------------------------------------------
        Put a message with 1 printf argument on queue for status line
 
    Args: min_t -- minimum time to display message for
          max_t -- minimum time to display message for
          s -- printf style control string
          a -- argument for printf
 
   Result: message queued
  ----*/

/*VARARGS1*/
void
q_status_message1(modal, min_t, max_t, s, a)
     int   min_t, max_t, modal;
     char *s;
     void *a;
{
    sprintf(tmp_20k_buf,s,a);
    q_status_message(modal, min_t, max_t, tmp_20k_buf);
}



/*----------------------------------------------------------------------
        Put a message with 2 printf argument on queue for status line

    Args: min_t  -- minimum time to display message for
          max_t  -- maximum time to display message for
          s  -- printf style control string
          a1 -- argument for printf
          a2 -- argument for printf

  Result: message queued
  ---*/

/*VARARGS1*/
void
q_status_message2(modal, min_t, max_t, s, a1, a2)
     int   modal;
     int   min_t, max_t;
     char *s;
     void *a1, *a2;
{
    sprintf(tmp_20k_buf,s, a1, a2);
    q_status_message(modal, min_t, max_t, tmp_20k_buf);
}



/*----------------------------------------------------------------------
        Put a message with 3 printf argument on queue for status line

    Args: min_t  -- minimum time to display message for
          max_t  -- maximum time to display message for
          s  -- printf style control string
          a1 -- argument for printf
          a2 -- argument for printf
          a3 -- argument for printf

  Result: message queued
  ---*/

/*VARARGS1*/
void
q_status_message3(modal, min_t, max_t, s, a1, a2, a3)
     int   min_t, max_t, modal;
     char *s;
     void *a1, *a2, *a3;
{
    sprintf(tmp_20k_buf,s, a1, a2, a3);
    q_status_message(modal, min_t, max_t, tmp_20k_buf);
}



/*----------------------------------------------------------------------
        Put a message with 4 printf argument on queue for status line


    Args: min_t  -- minimum time to display message for
          max_t  -- maximum time to display message for
          s  -- printf style control string
          a1 -- argument for printf
          a2 -- argument for printf
          a3 -- argument for printf
          a4 -- argument for printf

  Result: message queued
  ----------------------------------------------------------------------*/
/*VARARGS1*/
void
q_status_message4(modal, min_t, max_t, s, a1, a2, a3, a4)
     int   min_t, max_t, modal;
     char *s;
     void *a1, *a2, *a3, *a4;
{
	sprintf(tmp_20k_buf,s, a1, a2, a3, a4);
	q_status_message(modal, min_t, max_t, tmp_20k_buf);
}


/*----------------------------------------------------------------------
        Put a message with 7 printf argument on queue for status line


    Args: min_t  -- minimum time to display message for
          max_t  -- maximum time to display message for
          s  -- printf style control string
          a1 -- argument for printf
          a2 -- argument for printf
          a3 -- argument for printf
          a4 -- argument for printf
          a5 -- argument for printf
          a6 -- argument for printf
          a7 -- argument for printf


  Result: message queued
  ----------------------------------------------------------------------*/
/*VARARGS1*/
void
q_status_message7(modal, min_t, max_t, s, a1, a2, a3, a4, a5, a6, a7)
     int   modal;
     int   min_t, max_t;
     char *s;
     void *a1, *a2, *a3, *a4, *a5, *a6, *a7;
{
	sprintf(tmp_20k_buf, s, a1, a2, a3, a4, a5, a6, a7);
	q_status_message(modal, min_t, max_t, tmp_20k_buf);
}


/*----------------------------------------------------------------------
     Mark the status line as dirty so it gets cleared next chance
 ----*/
void
mark_status_dirty()
{
    needs_clearing++;
}


     
/*----------------------------------------------------------------------
     Pause a suitable amount of time if a message is on the display

     Note: This flags the message line as having nothing displayed.
           The idea is that it's a function called by routines that want
	   the message line for a prompt or something, and that they're
	   going to obliterate the message anyway.
 ----*/
void
pause_for_current_message()
{
    if(message_is_displayed){
	int w = (int)(displayed_time - time(0))
					+ currently_displayed.min_display_time;
	if(w > 0)
	  sleep(w);

	message_is_displayed = 0;
    }
}


     
/*----------------------------------------------------------------------
        Find out how many messages are queued for display

  Args:   dtime -- will get set to minimum display time for current message

  Result: number of messages in the queue.

  ---------*/
int
messages_queued(dtime)
    long *dtime;
{
    if(dtime && message_is_displayed)
      *dtime = (long)max(currently_displayed.min_display_time, 1);

    return((ps_global->in_init_seq || queue_length < 1) ? 0 : queue_length);
}



/*----------------------------------------------------------------------
       Update status line, clearing or displaying a message

   Arg: command -- The command that is about to be executed

  Result: status line cleared or
             next message queued is displayed or
             current message is redisplayed.
	     if next message displayed, it's min display time
	     is returned else if message already displayed, it's
	     time remaining on the display is returned, else 0.

   This is called when ready to display the next message, usually just
before reading the next command from the user. We pass in the nature
of the command because it affects what we do here. If the command just
executed by the user is a redraw screen, we don't want to reset or go to 
next message because it might not have been seen.  Also if the  command
is just a noop, which are usually executed when checking for new mail 
and happen every few minutes, we don't clear the message. If it was
really a command and there's nothing more to show, then we clear, because 
know the user has seen the message. In this case the user might be typing 
commands very quickly and miss a message, so there is a time stamp and
time check that each message has been on the screen for a few seconds. 
If it hasn't we just return and let if be taken care of next time.

At slow terminal output speeds all of this can be for not, the amount
of time it takes to paint the screen when the whole screen is being painted
is greater than the second or two delay so the time stamps set here have
nothing to do with when the user actually sees the message.
----------------------------------------------------------------------*/
int
display_message(command)
     int command;
{
    int    rv = 0;

    if(ps_global == NULL  || ps_global->ttyo == NULL ||
       ps_global->ttyo->screen_rows <= 1 || ps_global->in_init_seq)
      return(0);

    if(message_is_displayed) {
	/* message is showing */
	if(command == ctrl('L')) {
	    output_message(currently_displayed.text);
	}
	else {
	    time_t now;
	    int    diff;
	    /* must be displayed for at least 2 seconds */
	    now  = time(0);
	    diff = (int)(displayed_time - now)
			+ ((command == NO_OP_COMMAND || command == NO_OP_IDLE)
			    ? currently_displayed.max_display_time
			    : currently_displayed.min_display_time);
            dprint(9, (debugfile,
		       "STATUS: diff:%d, displayed: %ld, now: %ld\n",
		       diff, displayed_time, now));
            if(diff > 0)
              return(diff);

	    if(queue_length <= 0) {
    	        if(command != NO_OP_COMMAND && command != NO_OP_IDLE) {
    		    /* Clear the message line */
                    dprint(9, (debugfile, "Clearing status line\n"));
		    MoveCursor(ps_global->ttyo->screen_rows - 3, 0);
		    CleartoEOLN();
		    queue_length         = 0;
		    message_is_displayed = 0;
		}
	    }
	}
    }
    else if(queue_length <= 0) {
	if(command == ctrl('L') || needs_clearing) {
	    MoveCursor(ps_global->ttyo->screen_rows - 3, 0);
	    CleartoEOLN();
	}
    }

    if(queue_length > 0){		/* Dequeue message and display next */
	do {
	    currently_displayed = message_queue[0];
	    d_q_status_message();
	    output_message(currently_displayed.text);
	    message_is_displayed = 1;
	    displayed_time       = time(0);
	} while(queue_length > 0
		&& !(rv = (int)currently_displayed.min_display_time));
    }

    needs_clearing = 0;			/* always cleared or overwritten */
    dprint(9, (debugfile,
               "STATUS cmd:%d, disp:%d, length:%d, max:%d, min%d",
	       command, message_is_displayed, queue_length,
	       currently_displayed.max_display_time,
	       currently_displayed.min_display_time));
    fflush(stdout);
    return(rv);
}


/*----------------------------------------------------------------------
     Display all the messages on the queue as quickly as possible
  ----*/
void
flush_status_messages()
{
    pause_for_current_message();

    while(ps_global->ttyo->screen_rows > 1 && queue_length > 0) {
        currently_displayed = message_queue[0];
        d_q_status_message();
        output_message(currently_displayed.text);
	displayed_time = time(0);
        if (currently_displayed.min_display_time > 0)
          sleep(currently_displayed.min_display_time);
        else
          sleep(1);
    }

    message_is_displayed = 1;
}


/*----------------------------------------------------------------------
      Remove a message from the message queue.
  ----*/
void
d_q_status_message()
{
    int i;
    
    for(i = 0; i < queue_length; i++) {
        message_queue[i] = message_queue[i + 1];
    }
    queue_length--;
}



/*----------------------------------------------------------------------
    Actually output the message to the screen

  Args: message -- The message to output
 
 ----*/
int 
output_message(message)
     char        *message;
{
    int  col, row, max_length;
    char obuff[MAX_SCREEN_COLS + 5];

    dprint(9, (debugfile, "output_message(%s)\n", message));
    row = ps_global->ttyo->screen_rows -
                     (ps_global->ttyo->screen_rows < 4 ? 0 : 3);

    MoveCursor(row, 0);
    CleartoEOLN();
    StartInverse();

    /*Put [] around message and truncate to screen width */
    max_length = ps_global->ttyo != NULL ? ps_global->ttyo->screen_cols : 80;
    strcpy(obuff, "[");
    strncat(obuff, message, MAX_SCREEN_COLS);
    obuff[max_length -1] = '\0';
    strcat(obuff, "]");

    col = Centerline(row, obuff);
    EndInverse();
    fflush(stdout);
    return(col);
}


/*
 * want_to's array passed to radio_buttions...
 */
static ESCKEY_S yorn[] = {
    {'y', 'y', "Y", "Yes"},
    {'n', 'n', "N", "No"},
    {-1, 0, NULL, NULL}
};


/*----------------------------------------------------------------------
     Ask a yes/no question in the status line

   Args: question     -- string to prompt user with
         dflt         -- The default answer to the question (should probably
			 be y or n)
         on_ctrl_C    -- Answer returned on ^C
	 help         -- Two line help text
	 display_help -- If true, display help without being asked

 Result: Messes up the status line,
         returns y, n, dflt, or dflt_C
  ---*/
int
want_to(question, dflt, on_ctrl_C, help, display_help, flush)
     char      *question;
     HelpType   help;
     int    dflt, on_ctrl_C, display_help, flush;
{
    char     *q2;
    int	      rv;

    /*----
       One problem with adding the (y/n) here is that shrinking the 
       screen while in radio_buttons() will cause it to get chopped
       off. It would be better to truncate the question passed in
       hear and leave the full "(y/n) [x] : " on.
      ----*/
    q2 = fs_get(strlen(question) + 6);
    sprintf(q2, "%.*s? ", ps_global->ttyo->screen_cols - 6, question);
    rv = radio_buttons(q2, ps_global->ttyo->screen_rows > 4 ? -3 : -1, 0,
                       yorn, dflt, on_ctrl_C, flush, help, 0);
    fs_give((void **)&q2);

    return(rv);
}


int
one_try_want_to(question, dflt, on_ctrl_C, help, display_help, flush)
char      *question;
HelpType   help;
int    dflt, on_ctrl_C, display_help, flush;
{
    char     *q2;
    int	      rv;

    q2 = fs_get(strlen(question) + 6);
    sprintf(q2, "%.*s? ", ps_global->ttyo->screen_cols - 6, question);
    rv = radio_buttons(q2, ps_global->ttyo->screen_rows > 4 ? -3 : -1, 0,
                       yorn, dflt, on_ctrl_C, flush, help, 1);
    fs_give((void **)&q2);

    return(rv);
}



/*----------------------------------------------------------------------
    Prompt user for a choice among alternatives

Args --  prompt:    The prompt for the question/selection
         line:      The line to prompt on, if negative then relative to bottom
         column:    Column number to prompt on
         esc_list:  ESC_KEY_S list of keys
         deefault:  The selection when the <CR> is pressed (should probably
		      be one of the chars in esc_list)
         on_ctrl_C: The selection when ^C is pressed
	 flush:     Discard any pending input chars.
         help_text: Text to be displayed on bottom two lines
	 one_try:   Only give one chance to answer.  Returns on_ctrl_C value
		      if not answered acceptably on first try.

Result -- Returns the letter pressed. Will be one of the characters in the
          esc_list argument or one of the two deefaults.

This will pause for any new status message to be seen and then prompt the user.
The prompt will be truncated to fit on the screen. Redraw and resize are
handled along with ^Z suspension. Typing ^G will toggle the help text on and
off. Character types that are not buttons will result in a beep (unless one_try
is set).
  ----*/
int
radio_buttons(prompt, line, column, esc_list, deefault, on_ctrl_C, flush,
		help_text, one_try)
char	 *prompt;
int       line;
int       column;
ESCKEY_S *esc_list;
int       deefault;
int       on_ctrl_C;
int       flush;
HelpType  help_text;
int       one_try;
{
    register int     ch, real_line;
    char            *q, *ds = NULL;
    int              cursor_moved, max_label, i, start, fkey_table[12];
    struct key	     rb_keys[12];
    struct key_menu  rb_keymenu;
    bitmap_t	     bitmap;

    pause_for_current_message();	/* give user time to see status */
    mark_status_dirty();		/* clear message next display call */
    real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line;
    MoveCursor(real_line, column);
    CleartoEOLN();

    /*---- Find longest label ----*/
    max_label = 0;
    for(i = 0; esc_list && esc_list[i].ch != -1 && i < 12; i++){
      if(esc_list[i].ch == -2) /* -2 means to skip this key and leave blank */
	continue;
      max_label = max(max_label, strlen(esc_list[i].name));
    }

    q = cpystr(prompt); /* So we can truncate string below if need be */
    if(strlen(q) + max_label > ps_global->ttyo->screen_cols) 
        q[ps_global->ttyo->screen_cols - max_label] = '\0';

    /*---- Init structs for keymenu ----*/
    for(i = 0; i < 12; i++)
      memset((void *)&rb_keys[i], 0, sizeof(struct key));

    memset((void *)&rb_keymenu, 0, sizeof(struct key_menu));
    rb_keymenu.how_many = 1;
    rb_keymenu.keys     = rb_keys;

    /*---- Setup key menu ----*/
    start = 0;
    clrbitmap(bitmap);
    memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(int));
    if(help_text != NO_HELP){		/* if shown, always at position 0 */
	rb_keymenu.keys[0].name  = "^G";
	rb_keymenu.keys[0].label = "Help";
	setbitn(0, bitmap);
	fkey_table[0] = ctrl('G');
	start++;
    }

    if(on_ctrl_C){			/* if shown, always at position 1 */
	rb_keymenu.keys[1].name  = "^C";
	rb_keymenu.keys[1].label = "Cancel";
	setbitn(1, bitmap);
	fkey_table[1] = ctrl('C');
	start++;
    }

    start = (start) ? 2 : 0;
    /*---- Show the usual possible keys ----*/
    for(i=start; esc_list && esc_list[i-start].ch != -1 && i < 12; i++){
	if(esc_list[i-start].ch != -2)
	    setbitn(i, bitmap);
	fkey_table[i] = esc_list[i-start].ch;
	rb_keymenu.keys[i].name  = esc_list[i-start].name;
	if(esc_list[i-start].rval == deefault){
	    ds = (char *)fs_get((strlen(esc_list[i-start].label) + 3)
				* sizeof(char));
	    sprintf(ds, "[%s]", esc_list[i-start].label);
	    rb_keymenu.keys[i].label = ds;
	}
	else
	  rb_keymenu.keys[i].label = esc_list[i-start].label;
    }

    for(; i < 12; i++)
      rb_keymenu.keys[i].name = NULL;

    ps_global->mangled_footer = 1;

    draw_radio_prompt(real_line, column, q);

    do {
        fflush(stdout);
        fflush(stdin);

	/*---- Paint the keymenu ----*/
	EndInverse();
	draw_keymenu(&rb_keymenu, bitmap, ps_global->ttyo->screen_cols,
		     -2, 0, FirstMenu, 0);
	StartInverse();
	MoveCursor(real_line, column + strlen(q));

	if(flush)
	  flush_input();

	/* Timeout 5 min to keep imap mail stream alive */
        ch = read_char(600);
        dprint(2, (debugfile,
                   "Want_to read: %s (%d)\n", pretty_command(ch), ch));
        ch = isupper(ch) ? tolower(ch) : ch;

	if(F_ON(F_USE_FK,ps_global)
	   && ((isalpha(ch) && !strchr("YyNn", ch)) /* y & n : special case */
	       || ((ch >= PF1 && ch <= PF12)
		   && (ch = fkey_table[ch - PF1]) == NO_OP_COMMAND))){
	    /*
	     * The funky test above does two things.  First, it maps
	     * esc_list character commands to function keys, *and* prevents
	     * character commands from input while in function key mode.
	     * NOTE: this breaks if we ever need more than the first
	     * twelve function keys...
	     */
	    if(one_try){
		ch = on_ctrl_C;
	        goto out_of_loop;
	    }
	    Writechar('\007', 0);
	    continue;
	}

        switch(ch) {

          default:
	    for(i = 0; esc_list && esc_list[i].ch != -1; i++)
	      if(ch == esc_list[i].ch){
		  Write_to_screen(esc_list[i].label);
		  ch = esc_list[i].rval;
		  goto out_of_loop;
	      }

	    if(one_try){
		ch = on_ctrl_C;
	        goto out_of_loop;
	    }
	    Writechar('\007', 0);
	    break;

          case ctrl('M'):
          case ctrl('J'):
            ch = deefault;
            goto out_of_loop;

          case ctrl('C'):
	    if(on_ctrl_C || one_try){
		ch = on_ctrl_C;
		goto out_of_loop;
	    }

	    Writechar('\007', 0);
	    break;


          case '?':
          case ctrl('G'):
            if(help_text == NO_HELP)
              break;

	    MoveCursor(real_line + 1, column);
	    CleartoEOLN();
	    MoveCursor(real_line + 2, column);
	    CleartoEOLN();
	    radio_help(real_line, column, help_text);
	    sleep(5);

            MoveCursor(real_line, column + strlen(q));
            break;
            

          case NO_OP_COMMAND:
          case NO_OP_IDLE:
            new_mail(&cursor_moved, 0, 2); /* Keep mail stream alive */
            if(!cursor_moved) /* In case checkpoint happened */
              break;
            /* Else fall into redraw */


          case KEY_RESIZE:
          case ctrl('L'):
            real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line;
            EndInverse();
            ClearScreen();
            redraw_titlebar();
            if(ps_global->redrawer != NULL)
              (*ps_global->redrawer)();
            redraw_keymenu();
            draw_radio_prompt(real_line, column, q);
            break;

            
          case ctrl('Z'):
            if(!have_job_control() || F_OFF(F_CAN_SUSPEND,ps_global)) {
                Writechar('\007', 0);
            } else {
                EndInverse();
                do_suspend(ps_global);
                clear_cursor_pos();
                draw_radio_prompt(real_line, column, q);
            }
            break;

        } /* switch */
    } while(1);

  out_of_loop:
    fs_give((void *)&q);
    if(ds)
      fs_give((void *)&ds);

    EndInverse();
    fflush(stdout);
    return(ch);
}


/*----------------------------------------------------------------------

  ----*/
void
radio_help(line, column, help)
     int line, column;
     HelpType help;
{
    char **text;

#ifdef	DOS
    text = get_help_text(help, NULL);
#else
    text = help;
#endif
    if(text == NULL)
      return;
    
    EndInverse();
    MoveCursor(line + 1, column);
    CleartoEOLN();
    if(text[0])
      PutLine0(line + 1, column, text[0]);

    MoveCursor(line + 2, column);
    CleartoEOLN();
    if(text[1])
      PutLine0(line + 2, column, text[1]);

    StartInverse();
#ifdef	DOS
    free_help_text(text);
#endif
    fflush(stdout);
}


/*----------------------------------------------------------------------
   Paint the screen with the radio buttons prompt
  ----*/
void
draw_radio_prompt(l, c, q)
     int       l, c;
     char     *q;
{
    int x;

    StartInverse();
    PutLine0(l, c, q);
    x = c + strlen(q);
    MoveCursor(l, x);
    while(x++ < ps_global->ttyo->screen_cols)
      Writechar(' ', 0);
    MoveCursor(l, c + strlen(q));
    fflush(stdout);
}
