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

            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 Building, 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, 1990, 1991, 1992  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 is in part based on The Elm Mail System:
    ***********************************************************************
    *  The Elm Mail System  -  $Revision: 2.13 $   $State: Exp $          *
    *                                                                     *
    * 			Copyright (c) 1986, 1987 Dave Taylor              *
    * 			Copyright (c) 1988, 1989 USENET Community Trust   *
    ***********************************************************************
 

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

/*======================================================================
       screen.c
       Some functions for screen painting
          - Painting and formatting of the key menu at bottom of screen
          - Convert message status bits to string for display
          - Painting and formatting of the titlebar line on top of the screen
          - Updating of the titlebar line for changes in message number...
  ====*/


#include "headers.h"



/*------ 
   Saved key menu drawing state 
  ------*/
static struct km_state {
    struct key_menu *km;
    int              row, column;
    int              blanked;
} km_state;


/*----------------------------------------------------------------------
      Splat an alredy formated key_menu to the screen

 Args:  km      - key_menu structure
        row     - the row on the screen to begin on, negative values
                  are counted from the bottom of the screen up
        column  - column on the screen to begin on

 Just write out the name and the label at the specified column.

 ----*/
void
output_keymenu(km, row, column)
     struct key_menu *km;
     int row, column;
{
    register struct key *k;
    int                  i, c, ufk, real_row, fkey, max_column;
    char                 temp[20];

    fkey          = 0;         /* Avoid ref before set warning */
    max_column    = ps_global->ttyo->screen_cols;

    if(ps_global->ttyo->screen_rows < 4 || max_column <= 0)
      return;

    for(i = 0; i < 12; i++){
        dprint(9, (debugfile, "%d %-7.7s %-10.10s %d\n", i,
                   km->keys[i].name, km->keys[i].label, km->keys[i].column));
    }
    ufk = ps_global->use_fkeys;
    real_row = row > 0 ? row : ps_global->ttyo->screen_rows + row;
    dprint(9, (debugfile, "row: %d, real_row: %d, column: %d\n", row, 
               real_row, column)) ;
    for(i = 0; i < 2; i++) {
        MoveCursor(real_row + i, column);
        CleartoEOLN();
        for(c = 0, k = &km->keys[i]; k < &km->keys[12]; k += 2) {
            if(ufk)
              fkey =  1 + k - &km->keys[0];
            if(k->name == NULL || k->column > max_column)
              continue;
     
            if(k->column < c) {
                /*--- over writing previous entry, a bit weird */
                MoveCursor(row + i, k->column + column);
            } else { 
                Write_to_screen(repeat_char(k->column - c, ' '));
            }

            StartInverse();
            if(ufk) {
                sprintf(temp, "F%d", fkey);
            } else {
                strcpy(temp, k->name);
            }
            if(strlen(temp) + k->column > max_column)
              temp[max_column - k->column] = '\0';
            Write_to_screen(temp);
            EndInverse();
            c = k->column + strlen(temp);

            if(++c < max_column)
              Writechar(' ', 0);

            strcpy(temp, k->label);
            if(c + strlen(temp) >= max_column)
              temp[max(0,max_column - c)] = '\0';
            Write_to_screen(temp);
            
            c = strlen(k->label) + 1 + k->column +
                (ufk ? (fkey > 9 ? 3 : 2) :strlen(k->name));
        }
    }

    /*--- save state for a possible redraw ---*/
    km_state.km         = km;
    km_state.row        = row;
    km_state.column     = column;
    km_state.blanked    = 0;
}


/*----------------------------------------------------------------------
   Blank out the key menu and clear that part of the screen 
  ----*/
void
blank_keymenu(row, column)
     int row, column;
{
    km_state.blanked    = 1;
    km_state.row        = row;
    km_state.column     = column;
    MoveCursor(row, column);
    CleartoEOLN();
    MoveCursor(row+1, column);
    CleartoEOLN();
}
        


/*----------------------------------------------------------------------
    Calculate formatting for key menu at bottom of screen

   Args:  km -- The key_menu structure to format
          width -- the screen width to format it at

 If already formatted for screen width this just returns.

 The formatting results in the column field in the key_menu being filled in.
 The column field is the column to start the label at, the name of the key;
 after that is the label for or command that key will do. This would be simple
 except for a few long key names such as SPACE. All the calculations are to
 make this look nice. The basic idea is to line up the end of the names and 
 beginning of the labels. If the name is too long and shifting it left
 would run into previous label, then shift the whole menu right, or at least
 that entry of things following are short enough to fit back into the
 regular spacing. There's a special case to make 80 column screens look nice.
 This has to be calculated and not fixed so it can cope with screen resize.
   ----*/
void
format_keymenu(km, width)
     struct key_menu *km;
     int width;
{
    short   spacing[6];
    int     i, first, prev_end_top, prev_end_bot, ufk, top_column, bot_column;
    struct key *keytop, *keybot, *prev_keytop, *prev_keybot;

    if(width == km->width)
      return;

    km->width = width;
    ufk = ps_global->use_fkeys;

    /* this spacing here is column numbers for column key name ends in */
    /*       F1 Menu
              ^            */
    spacing[0] = 0;
    for(i = 1; i < 6; i++) 
      spacing[i] = spacing[i-1] + (width == 80 ? (i > 2 ? 14 : 13) : width/6);


    km->keys[0].column = km->keys[6].column = 0;
    if(ufk)
      first = 2;
    else
      first = max(km->keys[0].name != NULL ? strlen(km->keys[0].name) : 0,
                  km->keys[1].name != NULL ? strlen(km->keys[1].name) : 0);

    prev_keytop = &km->keys[0];
    prev_keybot = &km->keys[1];
    for(i = 1 ; i < 6; i++) {
        keytop = &km->keys[i*2];
        keybot = &km->keys[i*2+1];

        if(keytop->name == NULL) {
            top_column = first + spacing[i];
        } else {
            prev_end_top = 
                 prev_keytop->column +
                 (prev_keytop->name == NULL ? 0 : 
                   (ufk ? (i-1 >= 5 ? 3 : 2) : strlen(prev_keytop->name))) +
                 1 + 
                 (prev_keytop->label==NULL ? 0 : strlen(prev_keytop->label)) +
                 1 +
                 (keytop->name == NULL ? 0 : 
                   (ufk ? (i-1 >= 5 ? 3 : 2) : strlen(keytop->name)));
            top_column = max(prev_end_top, first + spacing[i]);
            dprint(9, (debugfile,
                       "prev_col: %d, prev_end:%d, top_column:%d spacing:%d\n",
                       prev_keytop->column, prev_end_top, top_column,
                       spacing[i]));
        }

        if(keybot->name == NULL) {
            bot_column = first + spacing[i];
        } else {
            prev_end_bot = 
                 prev_keybot->column +
                 (prev_keybot->name  == NULL ? 0 :
                  (ufk ? (i-1 >= 4 ? 3 : 2) :strlen(prev_keybot->name))) +
                 1 +
                 (prev_keybot->label==NULL ? 0 : strlen(prev_keybot->label)) +
                 1 +
                 (keybot->name  == NULL ? 0 :
                  (ufk ? (i-1 >= 4 ? 3 : 2) :strlen(keybot->name)));

            bot_column = max(prev_end_bot, first + spacing[i]);
        }
        keytop->column = max(bot_column, top_column) -
                          (keytop->name == NULL ? 0 : 
                            (ufk ? (i-1 >= 5 ? 3 : 2) : strlen(keytop->name)));
        keybot->column = max(bot_column, top_column) -
                          (keybot->name  == NULL ? 0 :
                            (ufk ? (i-1 >= 4 ? 3 : 2) : strlen(keybot->name)));


                            
        prev_keytop = keytop;
        prev_keybot = keybot;
    }
}



/*----------------------------------------------------------------------
    
 */
void
redraw_keymenu()
{
    if(km_state.blanked) {
        blank_keymenu(km_state.row, km_state.column);
    } else {
        format_keymenu(km_state.km, ps_global->ttyo->screen_cols);
        output_keymenu(km_state.km, km_state.row, km_state.column);
    }
}
    
    

/*----------------------------------------------------------------------
       Create little string for displaying message status

  Args: message_cache  -- pointer to MESSAGECACHE 

    Create a string with letters that indicate the status of the message.
  This is a function despite it's current simplicity so we can easily 
  add a few more flags
  ----------------------------------------------------------------------*/
char *
status_string(message_cache)
     MESSAGECACHE *message_cache;
{
     static char string[3];

     string[1] = '\0';

     if(ps_global->nr_mode) {
         string[0] = ' ';
         return(string);
     } 

     string[0] = 'N';

     if(message_cache == NULL || message_cache->seen)
       string[0] = ' ';

/*     if(message_cache->answered)
       string[0] = 'A'; */

     if(message_cache->deleted)
       string[0] = 'D';

     return(string);
}





static struct titlebar_state {
    char *title;
    char *folder_name;
    int   del_state;
    int   total_pages,
          current_page,
          total_lines,
          current_line,
          total_messages,
          current_message;
    TitleBarType style;
    int   cur_mess_col,
          del_column, 
          percent_column,
          page_column;
    enum  {Normal, ReadOnly, Closed} stream_status;
    int   screen_cols;
} as;
    
          

static char *format_titlebar();    

/*----------------------------------------------------------------------
      Sets up style and contents of current titlebar line

    Args: title -- The title that appears in the center of the line
          display_on_screen -- flag whether to display on screen or generate
                                string
          style  -- The format/style of the titlebar line
          current_message -- The current message number
          current_pl -- The current page or line number
          total_pl   -- The total line or page count

  Set the contents of the acnhor line. It's called an acnhor line
because it's always present and titlebars the user. This accesses a
number of global variables, but doesn't change any. There are 4
different styles of the titlebar line. First three parts are put
together and then the three parts are put together adjusting the
spacing to make it look nice. Finally column numbers and lengths of
various fields are saved to make updating parts of it more efficient.

It's OK to call this withy a bogus current message - it is only used
to look up status of current message 
 
Formats only change the right section (part3).
  FolderName:    "<folder>"  xx Messages
  MessageNumber: "<folder>" message x,xxx of x,xxx XXX
  TextPercent:   "<folder>" message x,xxx of x,xxx  xx% XXX
  PageNumber:    "page xx of xx

Several strings and column numbers are saved so later updates to the status 
line for changes in message number or percentage can be done efficiently.
This code is some what complex, and might benefit from some improvements.
 ----*/

char *
set_titlebar(title, display_on_screen, style, current_message, current_pl,
                                                                  total_pl)
     char        *title;
     TitleBarType style;
     int          display_on_screen, current_pl, total_pl;
     long         current_message;
{
    char          *tb;
    MESSAGECACHE *mc;
    extern char   version_buff[];


    dprint(9, (debugfile,
"set_titlebar - style: %d  current_message:%ld  current_pl: %d  total_pl: %d\n",
               style, current_message, current_pl, total_pl));

    as.style = style;
    as.title = title;
    as.stream_status = (ps_global->mail_stream == NULL ||
                                  ps_global->dead_stream) ? Closed :
                       ps_global->mail_stream->readonly ? ReadOnly : Normal;
    as.folder_name = pretty_fn(ps_global->cur_folder);

    if(current_message < 0)
      current_message = 0; /* BUG Don't like this */

    if(style != FolderName && current_message > 0) {
        (void)mail_fetchenvelope(ps_global->mail_stream,
				 (long)current_message);
        mc  = mail_elt(ps_global->mail_stream,
                       (long)ps_global->sort[current_message]);
    } else {
	mc  = (MESSAGECACHE *)NULL;
    }

    
    
    switch(style) {
      case FolderName:
        as.total_messages = ps_global->max_msgno;
	break;

      case MessageNumber:
        as.total_lines = total_pl;
        as.current_line = current_pl;
        as.current_message = current_message;
        as.total_messages = ps_global->max_msgno;
        as.del_state = mc == NULL ? 0 : mc->deleted;
	break;

      case TextPercent:
        as.total_lines = total_pl;
        as.current_line = current_pl;
        as.current_message = current_message;
        as.total_messages = ps_global->max_msgno;
        as.del_state = mc == NULL ? 0 : mc->deleted;
	break; 

      case PageNumber:
        as.total_pages  = total_pl;
        as.current_page = current_pl;
	break;
    }
    tb = format_titlebar();
    if(display_on_screen) {
        StartInverse();
        PutLine0(0, 0, tb);
        EndInverse();
    }
    return(tb);
}


#define NUM_LEN(x) ((x) < 10 ? 1 : (x) < 100 ? 2 : (x) < 1000 ? 3 : 4)
#define CALC_PERCENT(part, tot) ((tot) == 0 ? 0 : (100 * (part))/(tot))

/*----------------------------------------------------------------------
      Redraw or draw the top line, the title bar 

   Returns - Formatted title bar 
 ----*/
static char *
format_titlebar()
{
    static char titlebar_line[MAX_SCREEN_COLS];
    char        version[50], commatemp[20], *what, *ss_string, *whatelse;
    int         sc, ver_len, tit_len, stat_len, pad, percent, maxfn, fn_off,
                nr, fn_len, ss_len, we_len;
    extern char version_buff[];

    sprintf(version, "PINE %s", version_buff);
    sc                = ps_global->ttyo->screen_cols;
    ver_len           = strlen(version);
    tit_len           = strlen(as.title);
    as.del_column     = -1;
    as.cur_mess_col   = -1;
    as.percent_column = -1;
    as.page_column    = -1;
    what              = ps_global->nr_mode ? "Article" : "Message";
    whatelse          = ps_global->nr_mode ? "News"    : "Folder";
    we_len            = strlen(whatelse);
    nr                = ps_global->nr_mode;
    fn_len            = strlen(as.folder_name);
    ss_string         = as.stream_status == Closed   ? "(CLOSED)" :
                        as.stream_status == ReadOnly ? (nr ? "" : 
                                                             "(READONLY)") 
                                                     : "";
    ss_len            = strlen(ss_string);

    
    if(sc < ver_len + 5) {
        /* Only part of the pine version will fit */
        sprintf(titlebar_line, " %*.*s", sc - 1, sc - 1, version);
        return(titlebar_line);
    }

    if(sc < ver_len + tit_len + 3) {
        /* The version and part of the title */
        int space_left = sc - ver_len - 3;
        sprintf(titlebar_line, "  %s %*.*s", version, space_left, space_left,
                as.title);
        return(titlebar_line);
    }

    if(as.style == PageNumber) {
        stat_len = 14; /* strlen("page xxx of xxx") */
    
        if(sc < ver_len + tit_len + stat_len + 6) {
            /* right part still won't quite fit */
            pad = sc - ver_len - tit_len;
            strcpy(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else {
            /* Now it's got to fit */
            pad = sc - ver_len - tit_len - stat_len;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            as.page_column = strlen(titlebar_line) + 5;
            sprintf(titlebar_line + strlen(titlebar_line), "page %d of %d",
                   as.current_page, as.total_pages);
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        }
    } else if(as.style == FolderName) {
        stat_len = 18 + ss_len + we_len;
                     /* 18 = strlen(":  x,xxx Messages"); */
        if(sc < ver_len + tit_len + stat_len + min(10, fn_len) + 8) {
            /* right part still won't quite fit */
            pad = sc - ver_len - tit_len;
            strcpy(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else if(sc < ver_len + tit_len + stat_len + fn_len + 8) {
            /* will fit with truncated folder name  */
            maxfn = min(sc - ver_len - tit_len - stat_len - 9, fn_len);
            fn_off = fn_len - maxfn;
            pad = sc - ver_len - tit_len - stat_len - maxfn;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%*.*s%s  %s %s%s",
                    whatelse, maxfn, maxfn, as.folder_name + fn_off, ss_string,
                    comatose((long)as.total_messages),
                    what, plural(as.total_messages));
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else {
            /* will fit with complete folder name  */
            pad = sc - ver_len - tit_len - stat_len - fn_len;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%s%s  %s %s%s",
                    whatelse, as.folder_name, ss_string,
                    comatose((long)as.total_messages), what,
                    plural(as.total_messages));
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        }
    } else if(as.style == MessageNumber) {
        if(as.total_messages < 1000) 
          stat_len = 18 + 2 * NUM_LEN(as.total_messages);
        else  /* also assume we can usurp 2 padding chars at the end */
          stat_len = 28; /* strlen(":  Message x,xxx of x,xxx DEL"); */
        stat_len += ss_len + we_len;
        percent = CALC_PERCENT(as.current_line, as.total_lines);
        if(sc < ver_len + tit_len + stat_len + min(10, fn_len) + 8) {
            /* right part still won't quite fit */
            pad = sc - ver_len - tit_len;
            strcpy(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else if(sc < ver_len + tit_len + stat_len + fn_len + 8) {
            /* will fit with truncated folder name  */
            maxfn = min(sc - ver_len - tit_len - stat_len - 8, fn_len);
            fn_off = fn_len - maxfn;
            pad = sc - ver_len - tit_len - stat_len - maxfn;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            as.cur_mess_col = strlen(titlebar_line) + maxfn + 11 + ss_len +
              we_len;
            strcpy(commatemp, comatose((long)as.current_message));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%*.*s%s  %s %s of %s %s",
                    whatelse, maxfn, maxfn, as.folder_name + fn_off,
                    ss_string, what, commatemp,
                    comatose((long)as.total_messages),
                    as.del_state ? "DEL" : "   ");
            as.del_column = as.cur_mess_col;
            as.del_column += strlen(comatose((long)as.current_message));
            as.del_column += strlen(comatose((long)as.total_messages));
            as.del_column += 5; /* strlen (" of  ") */
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else {
            /* will fit with completely  */
            pad = sc - ver_len - tit_len - stat_len - fn_len;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            as.cur_mess_col = strlen(titlebar_line) + fn_len+11+ss_len+we_len;
            strcpy(commatemp,comatose((long)as.current_message));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%s%s  %s %s of %s %s",
                    whatelse, as.folder_name, ss_string,  what, commatemp,
                    comatose((long)as.total_messages),
                    as.del_state ? "DEL" : "   ");
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
            as.del_column = as.cur_mess_col;
            as.del_column += strlen(comatose((long)as.current_message));
            as.del_column += strlen(comatose((long)as.total_messages));
            as.del_column += 5; /* strlen (" of  ") */
        }
    } else if(as.style == TextPercent) {
        if(as.total_messages < 1000) 
          stat_len = 23 + 2 * NUM_LEN(as.total_messages);
        else  /* also assume we can usurp 2 padding chars at the end */
          stat_len = 33; /* strlen(":  Message x,xxx of x,xxx xxx% DEL"); */
        stat_len += ss_len + we_len;
        percent = CALC_PERCENT(as.current_line, as.total_lines);
        if(sc < ver_len+tit_len+stat_len+min(10, fn_len) + 8) {
            /* right part still won't quite fit */
            pad = sc - ver_len - tit_len;
            strcpy(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/3,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else if(sc < ver_len + tit_len + stat_len + fn_len + 8) {
            /* will fit with truncated folder name  */
            maxfn = min(sc - ver_len - tit_len - stat_len - 8, fn_len);
            fn_off = fn_len - maxfn;
            pad = sc - ver_len - tit_len - stat_len - maxfn;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            as.cur_mess_col = strlen(titlebar_line) + maxfn + 11+ss_len+we_len;
            strcpy(commatemp, comatose((long)as.current_message));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%*.*s%s  %s %s of %s %3d%% %s",
                    whatelse, maxfn, maxfn, as.folder_name + fn_off, ss_string,
                    what, commatemp, comatose((long)as.total_messages),
                    percent, as.del_state ? "DEL" : "   ");
            as.percent_column = as.cur_mess_col;
            as.percent_column += strlen(comatose((long)as.current_message));
            as.percent_column += strlen(comatose((long)as.total_messages));
            as.percent_column += 5; /* strlen(" of  ") */
            as.del_column      = as.percent_column;
            as.del_column     += 5;
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        } else {
            /* will fit with completely  */
            pad = sc - ver_len - tit_len - stat_len - fn_len;
            strcpy(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, version);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            strcat(titlebar_line, as.title);
            strcat(titlebar_line, repeat_char(pad/4,' '));
            as.cur_mess_col  = strlen(titlebar_line) +fn_len+11+ ss_len+we_len;
            strcpy(commatemp, comatose((long)as.current_message));
            sprintf(titlebar_line + strlen(titlebar_line),
                    "%s:%s%s  %s %s of %s %3d%% %s",
                    whatelse, as.folder_name, ss_string, what, commatemp,
                    comatose((long)as.total_messages), percent,
                    as.del_state ? "DEL" : "   ");
            as.percent_column  = as.cur_mess_col;
            as.percent_column += strlen(comatose((long)as.current_message));
            as.percent_column += strlen(comatose((long)as.total_messages));
            as.percent_column += 5; /* strlen(" of  ") */
            as.del_column      = as.percent_column;
            as.del_column     += 5;
            strcat(titlebar_line, repeat_char(sc - strlen(titlebar_line),' '));
        }
    } 

    return(titlebar_line);
}

void 
redraw_titlebar()
{
    char * tb = format_titlebar();
    StartInverse();
    PutLine0(0, 0, tb);
    EndInverse();
}
     

/*----------------------------------------------------------------------
    Update the titlebar line if the message number changed

   Args: new_message_number -- message number to display

This is a bit messy because the length of the number displayed might 
change which repositions everything after it, so we adjust all the saved 
columns and shorten tail, the string holding the rest of the line.
  ----*/

void
update_titlebar_message(new_message_number)
     int new_message_number;
{
    char  s_new[20], s_old[20];
    int   l_change;         

    if(as.cur_mess_col < 0) {
      return;
    }

    strcpy(s_new, comatose((long)new_message_number));
    strcpy(s_old, comatose((long)as.current_message));
    l_change = strlen(s_new) - strlen(s_old);
    

    StartInverse();
    if(l_change == 0) {
        PutLine0(0, as.cur_mess_col, s_new);
    } else {
        if(as.style == TextPercent) {
            PutLine5(0, as.cur_mess_col, "%s of %s %3d%% %s%s",
                     s_new, comatose((long)as.total_messages),
                     (void *)CALC_PERCENT(as.current_line, as.total_lines),
                     as.del_state ? "DEL" : "   ",
                     repeat_char(max(0, -l_change),' '));
            if(as.del_column >= 0) {
                as.del_column += l_change;
            }
            if(as.percent_column >= 0) {
                as.percent_column += l_change;
            }
        } else {
            PutLine4(0, as.cur_mess_col, "%s of %s %s%s",
                     s_new, comatose((long)as.total_messages),
                     as.del_state ? "DEL" : "   ",
                     repeat_char(max(0, -l_change),' '));
            if(as.del_column >= 0) {
                as.del_column += l_change;
            }
        }
    }
    EndInverse();
    as.current_message = new_message_number;
}



/*---------------------------------------------------------------------- 
    Update the percentage shown in the titlebar line

  Args: new_line_number -- line number to calculate new percentage
   
  ----*/

void
update_titlebar_percent(new_line_number)
     int new_line_number;
{
    int new_percent, old_percent;
    
    if(as.percent_column < 0) {
        return;
    }

    new_percent     = CALC_PERCENT(new_line_number, as.total_lines);
    old_percent     = CALC_PERCENT(as.current_line, as.total_lines);
    as.current_line = new_line_number;


   if(old_percent == new_percent)
     return;

    StartInverse();
    PutLine1(0, as.percent_column, "%3d", (void *)new_percent);
    EndInverse();
}



/*----------------------------------------------------------------------
    Update the page number. Changes here change only the tail length

  Args:  new_page -- new page number to display

  ---*/
void
update_titlebar_page(new_page)
     int new_page;
{
    if(as.style != PageNumber) 
      panic("Update_titlebar_page with wrong style");

    if(new_page == as.current_page)
      return;

    as.current_page = new_page;

    StartInverse();
    if(NUM_LEN(new_page) != NUM_LEN(as.current_page))  {
        PutLine1(0, as.page_column, "%s", int2string(new_page));
    } else {
      /* Blanks at end for when it gets shorter */
        char tmp[30];
        strcpy(tmp, int2string(new_page));
        PutLine2(0,as.page_column,
                 "%s of %s   ",tmp,int2string(as.total_pages));
    }
    EndInverse();
}
        




update_del(del_flag, display)
     int del_flag, display;
{
    if(as.del_column < 0)
      return(0);

    if(as.del_state == del_flag)
      return(0);

    as.del_state = del_flag;

    if(display) {
        StartInverse();
        PutLine0(0, as.del_column, del_flag ? "DEL" : "   ");
        EndInverse();
    }
    return(1);
}
    
  
