/*
 *========================================================================
 * $Id: display_values.c 239 2004-09-21 23:05:01Z rgb $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */

#include "wulfstat.h"

/*
 * This routine switches between all the different kinds of displays
 * we recognize and walks the linked list of hosts, displaying its
 * (relevant) contents.
 */
void display_values(List *hostlist)
{

 char displaytype[64];

 /* 
  * If verbose is on, we don't do a "real" display at all, regardless
  * of how it is set.
  */
 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_values().  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 switch(display.type) {
   case DISPLAY_BASIC:
     display_basic(hostlist);
     display_messages();
     break;
   case DISPLAY_NET:
     display_net(hostlist);
     display_messages();
     break;
   case DISPLAY_TIMES:
     display_times(hostlist);
     display_messages();
     break;
   case DISPLAY_PIDS:
     display_pids(hostlist);
     /* xml_display_pids(); */
     display_messages();
     break;
   case DISPLAY_PIDS_CMDLINE:
     display_pids_cmdline(hostlist);
     /* xml_display_pids(); */
     display_messages();
     break;
   case DISPLAY_MEMORY:
     display_memory(hostlist);
     display_messages();
     break;
   case DISPLAY_LOAD:
   default:
     display_load(hostlist);
     display_messages();
     break;
 }

}

/*
 *========================================================================
 * display_messages()
 *
 * This routine manages the messages at the bottom of the screen.  We
 * should probably allow this to be dynamically surpressed so it goes
 * from five lines to just 1-2, where a key toggles messages on and off.
 *========================================================================
 */
void display_messages()
{

 mvwprintw(menuwin,1,1,"Monitoring %d hosts every %d seconds, display count = %-6d ",numhosts,update_delay,cycle_cnt);
 mvwprintw(menuwin,2,1,"    Menu: | scroll: up/down arrows   page: Page Up/Page Down");
 mvwprintw(menuwin,3,1,"    Menu: | q(uit) -/+(change update delay)");
 switch(display.type) {
   case DISPLAY_NET:
     mvwprintw(menuwin,1,58,"%+18s ","display: net");
     break;
   case DISPLAY_TIMES:
     mvwprintw(menuwin,1,58,"%+18s ","display: time");
     break;
   case DISPLAY_MEMORY:
     mvwprintw(menuwin,1,58,"%+18s ","display: memory");
     break;
   case DISPLAY_PIDS:
     mvwprintw(menuwin,1,58,"%+18s ","display: pids ");
     break;
   case DISPLAY_PIDS_CMDLINE:
     mvwprintw(menuwin,1,58,"%+18s ","display: cmdline ");
     break;
   case DISPLAY_BASIC:
     mvwprintw(menuwin,1,58,"%+18s ","display: basic ");
     break;
   default:
   case DISPLAY_LOAD:
     mvwprintw(menuwin,1,58,"%+18s","display: load");
     break;
 }
 mvwprintw(menuwin,4,1," Display: | c(mdline) l(oad) m(emory) n(et) t(imes) p(ids) b(asic)");
 wrefresh(menuwin);
  

}


/*
 *========================================================================
 * display_load()
 *
 * This is a new, improved host/load display.  It works with features
 * in ncurses that permit a scrollable virtual viewport to be created,
 * which eliminates the relatively ugly two column display and makes the
 * display itself much prettier/gui-like.
 *
 * As before, this display will be the template for other displays.
 *========================================================================
 */
void display_load(List *hostlist)
{

 /* Loop indices */
 int i,j,k;

 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 ListElement *element;

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_load.  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 mvwprintw(headerwin,0,1,"%-10.10s|%4s|%7s|%7s|%7s|",
      "  name",
      "stat",
      " Load 1",
      " Load 5",
      "Load 15"
   );
 wclrtoeol(headerwin);
 wrefresh(headerwin);

 /*
  * Loop over all hosts and pop them on the display pad
  */
 element = hostlist->head;
 werase(displaypad);
 display.bottomline_displayed = 0;  /* count the lines */
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     mvwprintw(displaypad,i,0,"%-10.10s|%4s|%6.2f |%6.2f |%6.2f |",
       hostptr->hostname,
       " up ",
       hostptr->val.load1,
       hostptr->val.load5,
       hostptr->val.load15);
   } else {
     mvwprintw(displaypad,i,0,"%-10.10s|%4s|%4s   |%4s   |%4s   |",
       hostptr->hostname,
       "down",
       "  -",
       "  -",
       "  -");
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}


void display_basic(List *hostlist)
{

 /* Loop indices */
 int i,j,k;
 unsigned int mem_used,mem_free;
 char scaleout[4][32];

 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 ListElement *element;

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_basic.  Use -v %d to focus.\n",D_DISPLAY_VALUES);
   fprintf(OUTFP,"D_DISPLAY_VALUES: Displaying %d hosts.\n",numhosts);
 }
 mvwprintw(headerwin,0,1,"%-10.10s|%2s|%11s|%7s|%7s|%7s|%7s|%4s|%4s|%7s",
      "  name",
      "st",
      "Load 1,5,15",
      "rx byts",
      "tx byts",
      " si/so ",
      " pi/po ",
      "ctxt",
      "intr",
      "run/blk"
   );
 wclrtoeol(headerwin);
 wrefresh(headerwin);

 /*
  * Loop over all hosts and pop them on the display pad
  */
 element = hostlist->head;
 werase(displaypad);
 display.bottomline_displayed = 0;  /* count the lines */
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
     fprintf(OUTFP,"D_DISPLAY_VALUES: Displaying row for host %s, connected = %d\n",hostptr->hostname,hostptr->connected);
   }
   if(hostptr->connected == 2) {
     mvwprintw(displaypad,i,0,"%-10.10s|%2s|%3.1f,%3.1f,%3.1f|%6.0f |%6.0f |%3.0f/%-3.0f|%3.0f/%-3.0f|%4.0f|%4.0f|%3d/%d",
       hostptr->hostname,
       "up",
       hostptr->val.load1,
       hostptr->val.load5,
       hostptr->val.load15,
       hostptr->val.interface[-1].rx_bytes_rate,
       hostptr->val.interface[-1].tx_bytes_rate,
       hostptr->val.swap_in_rate,
       hostptr->val.swap_out_rate,
       hostptr->val.page_in_rate,
       hostptr->val.page_out_rate,
       hostptr->val.ctxt_rate,
       hostptr->val.intr_rate,
       hostptr->val.procs_running,
       hostptr->val.procs_blocked
     );
   } else {
     mvwprintw(displaypad,i,0,"%-10.10s|%2s|%7s    |%4s   |%4s   |%5s  |%5s  |%3s |%3s |%7s",
       hostptr->hostname,
       "dn",
       "  -",
       "  -",
       "  -",
       "  -",
       "  -",
       "  -",
       "  -",
       "  -",
       "  -",
       "-/-"
       );
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}


/*
 *========================================================================
 * display_memory()
 *
 * This routine displays memory statistics (from meminfo) and related
 * values for each host.
 *========================================================================
 */
void display_memory(List *hostlist)
{

 /* Loop indices */
 int i,j,k;

 /* 
  * A buffer to aid in truncating names.  One extra space for terminating
  * null.  The second one is to hold output from scale_k().
  */
 char namebuf[10];
 char row_out[10][10];
 /* scratch space for positioning and counters both */
 int row = 0,col = 0;
 /* controls the hosts loop so we can page */
 int imin_col,imax_col;

 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 ListElement *element;

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_memory().  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 mvwprintw(headerwin,0,0,"%-9s|%5s|%7s|%7s|%7s|%5s|%7s|%7s|%5s|%5s|%5s|",
    "   name",
    "m-tot",
    "m-used",
    "m-free",
    "m-free*",
    "s-tot",
    "s-used",
    "s-free",
    "m-shr",
    "m-buf",
    "m-cch"
 );
 wclrtoeol(headerwin);
 wrefresh(headerwin);


 /*
  * Loop over all hosts and pop them on the display pad
  */
 element = hostlist->head;
 display.bottomline_displayed = 0;  /* count the lines */
 werase(displaypad);
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     sprintf(row_out[0],"%5.5s",scale_k(hostptr->val.mem_total,5,0));
     sprintf(row_out[1],"%7.7s",scale_k(hostptr->val.mem_used,7,0));
     sprintf(row_out[2],"%7.7s",scale_k(hostptr->val.mem_free,7,0));
     sprintf(row_out[3],"%7.7s",scale_k(hostptr->val.mem_free + hostptr->val.mem_buffers + hostptr->val.mem_cached,7,0));
     sprintf(row_out[4],"%5.5s",scale_k(hostptr->val.swap_total,5,0));
     sprintf(row_out[5],"%7.7s",scale_k(hostptr->val.swap_used,7,0));
     sprintf(row_out[6],"%7.7s",scale_k(hostptr->val.swap_free,7,0));
     sprintf(row_out[7],"%5.5s",scale_k(hostptr->val.mem_shared,5,0));
     sprintf(row_out[8],"%5.5s",scale_k(hostptr->val.mem_buffers,5,0));
     sprintf(row_out[9],"%5.5s",scale_k(hostptr->val.mem_cached,5,0));
     mvwprintw(displaypad,i,0,"%-8.8s|%5.5s|%7.7s|%7.7s|%7.7s|%5.5s|%7.7s|%7.7s|%5.5s|%5.5s|%5.5s",
       hostptr->hostname,
       row_out[0],
       row_out[1],
       row_out[2],
       row_out[3],
       row_out[4],
       row_out[5],
       row_out[6],
       row_out[7],
       row_out[8],
       row_out[9]
     );

   } else {
     mvwprintw(displaypad,i,0,"%-8.8s| Not connected...",
         hostptr->hostname);
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}


/*
 *========================================================================
 * display_pids()
 *
 * This defines the task/user interface and display.  The interface part
 * of this is a bit more complex than the passive displays as one has to
 * be able to add tasknames or usernames to a list to be monitored.  We'll
 * probably need to put an e(dit) command to kick one into an interface
 * where one can add or remove usernames and tasknames (and which displays
 * the ones already there).
 *
 * Of course, we START with pretty much nothing at all.
 *========================================================================
 */
void display_pids(List *hostlist)
{

 /* Loop indices */
 int i,j,k;
 /* 
  * A buffer to aid in truncating names.  One extra space for terminating
  * null.  The second one is to hold output from scale_k().
  */
 char namebuf[10];
 char row_out[10][10];
 /* scratch space for positioning and counters both */
 int row = 0,col = 0;
 /* controls the hosts loop so we can page */
 int imin_col,imax_col;
 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 Pid *pidptr;
 ListElement *element,*pidelement;
 
 

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_user().  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 mvwprintw(headerwin,0,1,"%-9s|%5s|%4s|%8s|%7s|%7s|%8s|%-s",
      "  name",
      "PID ",
      "Nice",
      "User  ",
      "Vsize",
      "RSS  ",
      "Time",
      "  Command"
   );
 wclrtoeol(headerwin);
 wrefresh(headerwin);

 /*
  * Loop over all hosts and pop them on the pad
  */
 element = hostlist->head;
 werase(displaypad);
 display.bottomline_displayed = 0;  /* count the lines */
 j = 0;
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     /*
      * This display is going to be fundamentally different from
      * the others in that one cannot predict how many (if any)
      * tasks that match the specified criteria will be running
      * on any host in the list.  These numbers can also jump
      * up or down without warning as tasks are started or die or
      * or stopped.  To manage this sort of free form data presentation
      * we will collect the pid data in a linked list of structs
      * indexed per host.  That is, hostptr->var.runlist will be
      * a linked list of tasks that match the specified task criteria
      * Filling it will be tricky, but is handled elsewhere.  Here
      * we simply walk the list for each host and displace a line
      * for each entry found.
      sprintf(row_out[0],"%5.5s",scale_k(hostptr->val.mem_total,5,0));
      */

     if(hostptr->pidlist->size == 0){
       mvwprintw(displaypad,j,0,"%-9.9s|%5s| %2s |%8s|%7s|%7s|%8s|%-s",
           hostptr->hostname,
           "  -",
           "-",
           "  -",
           "  -",
           "  -",
           "  -",
           "Idle/No Matching Task"
       );
       j++;
     } else {
       pidelement = hostptr->pidlist->head;
       while(pidelement != NULL){
         pidptr = pidelement->data;
         /*
          * Never display xmlsysd itself.  I know, one "should", but
	  * we won't.
          */
         if(strncmp(pidptr->taskname,"xmlsysd",7) == 0) {
	   if(hostptr->pidlist->size == 1) {
             mvwprintw(displaypad,j,0,"%-9.9s|%5s| %2s |%8s|%7s|%7s|%8s|%-s",
               hostptr->hostname,
               "  -",
               "-",
               "  -",
               "  -",
               "  -",
               "  -",
               "Idle/No Matching Task"
             );
             j++;
	   }
	 } else {
           mvwprintw(displaypad,j,0,"%-9.9s|%5d| %2d |%8s|%7s|%7s|%8s|%-s",
               hostptr->hostname,
               pidptr->pid,
               pidptr->nice,
               pidptr->user,
               pidptr->vsize,
               pidptr->rss,
               pidptr->time,
               pidptr->taskname
           );
           j++;
         }
         pidelement = pidelement->next;
       }
     }
   } else {
     mvwprintw(displaypad,j,0,"%-9.9s|%5s| %2s |%8s|%7s|%7s|%8s|%-s",
         hostptr->hostname,
         "  -",
         "-",
         "  -",
         "  -",
         "  -",
         "  -",
         "Not connected..."
       );
     j++;
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}

/*
 *========================================================================
 * display_pids_cmdline()
 *
 * This defines the task/user interface and display.  It is "like"
 * display_pids(), but shows the whole command line of each running
 * command.  This is very useful if you are tracking a set of distributed
 * jobs.
 *========================================================================
 */
void display_pids_cmdline(List *hostlist)
{

 /* Loop indices */
 int i,j,k;
 /* 
  * A buffer to aid in truncating names.  One extra space for terminating
  * null.  The second one is to hold output from scale_k().
  */
 char namebuf[10];
 char row_out[10][10];
 /* scratch space for positioning and counters both */
 int row = 0,col = 0,colsleft;
 /* controls the hosts loop so we can page */
 int imin_col,imax_col;
 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 Pid *pidptr;
 ListElement *element,*pidelement;
 
 

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_user().  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 mvwprintw(headerwin,0,1,"%-9s|%6s|%6s|%6s|%6s|%-s",
      "  name",
      "User ",
      "Vsize",
      "RSS  ",
      "Time",
      "Cmdline"
   );
 wclrtoeol(headerwin);
 wrefresh(headerwin);

 /*
  * Loop over all hosts and pop them on the pad
  */
 element = hostlist->head;
 werase(displaypad);
 display.bottomline_displayed = 0;  /* count the lines */
 j = 0;
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     /*
      * This display is going to be fundamentally different from
      * the others in that one cannot predict how many (if any)
      * tasks that match the specified criteria will be running
      * on any host in the list.  These numbers can also jump
      * up or down without warning as tasks are started or die or
      * or stopped.  To manage this sort of free form data presentation
      * we will collect the pid data in a linked list of structs
      * indexed per host.  That is, hostptr->var.runlist will be
      * a linked list of tasks that match the specified task criteria
      * Filling it will be tricky, but is handled elsewhere.  Here
      * we simply walk the list for each host and displace a line
      * for each entry found.
      sprintf(row_out[0],"%5.5s",scale_k(hostptr->val.mem_total,5,0));
      */

     if(hostptr->pidlist->size == 0){
       mvwprintw(displaypad,j,0,"%-9.9s|%6s|%6s|%6s|%6s|%-s",
           hostptr->hostname,
           "  -",
           "  -",
           "  -",
           "  -",
           "Idle/No Matching Task"
       );
       j++;
     } else {
       pidelement = hostptr->pidlist->head;
       while(pidelement != NULL){
         pidptr = pidelement->data;
         /*
          * Never display xmlsysd itself.  I know, one "should", but
	  * we won't.
          */
         if(strncmp(pidptr->taskname,"xmlsysd",7) == 0) {
	   if(hostptr->pidlist->size == 1) {
             mvwprintw(displaypad,j,0,"%-9.9s|%6s|%6s|%6s|%6s|%-s",
               hostptr->hostname,
               "  -",
               "  -",
               "  -",
               "  -",
               "Idle/No Matching Task"
             );
             j++;
	   }
	 } else {
	   if(strlen(pidptr->cmdline) == 0){
             mvwprintw(displaypad,j,0,"%-9.9s|%6s|%6s|%6s|%6s|%-s (cmdline N/A)",
               hostptr->hostname,
               pidptr->user,
               pidptr->vsize,
               pidptr->rss,
               pidptr->time,
               pidptr->taskname
             );
	   } else {
             colsleft = display.cols_displaywin - 38;
	     if(strlen(pidptr->cmdline) > colsleft && colsleft < K){
	       pidptr->cmdline[colsleft] = (char)NULL;
	     }
             mvwprintw(displaypad,j,0,"%-9.9s|%6s|%6s|%6s|%6s|%-s",
               hostptr->hostname,
               pidptr->user,
               pidptr->vsize,
               pidptr->rss,
               pidptr->time,
               pidptr->cmdline
             );
	   }
           j++;
         }
         pidelement = pidelement->next;
       }
     }
   } else {
     mvwprintw(displaypad,j,0,"%-9.9s|%6s|%6s|%6s|%6s|%-s",
         hostptr->hostname,
         "  -",
         "  -",
         "  -",
         "  -",
         "Not connected..."
       );
     j++;
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}

/*
 *========================================================================
 * display_net()
 *
 * This routine displays hostname and status and key network interface
 * rates for all eth interfaces found on the host.  For the moment we'll
 * skip the loopback interface.  We'll just have to see if 40 or 80 char
 * columns work better for this.  We may ALSO present data on e.g.
 * number of sockets open and so forth.
 *========================================================================
 */
void display_net(List *hostlist)
{

 /* Loop indices */
 int i,j,k;

 /* scratch space for positioning and counters both */
 int row = 0,col = 0;
 /* controls the hosts loop so we can page */
 int imin_col,imax_col;
 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 ListElement *element;

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting display_net().  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 sprintf(display_msg,"");

 mvwprintw(headerwin,0,0,"%-9.9s|%-15s|%4s|%6s|%6s|%6s|%6s|%6s|%6s|%6s",
    "   name",
    "      ip",
    "dev#",
    "rx_bts",
    "rx_pks",
    "rx_ers",
    "tx_bts",
    "tx_pks",
    "tx_ers",
    "tcp_sk"
 );

 wclrtoeol(headerwin);
 wrefresh(headerwin);

 k = 0;
 element = hostlist->head;
 werase(displaypad);
 display.bottomline_displayed = 0;  /* count the lines */
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     for(j = 0;j < hostptr->val.num_interfaces;j++){
      /* For the moment, only eth displays... */
      if( strncmp("eth",hostptr->val.interface[j].devtype,3) == 0 )
        mvwprintw(displaypad,k++,0,"%-8.8s|%15s|%3s%1s|%6.0f|%6.0f|%6.0f|%6.0f|%6.0f|%6.0f|  %2ld  ",
         hostptr->hostname,
         hostptr->val.interface[j].ip,
         hostptr->val.interface[j].devtype,
         hostptr->val.interface[j].devid,
         hostptr->val.interface[j].rx_bytes_rate,
         hostptr->val.interface[j].rx_packets_rate,
         hostptr->val.interface[j].rx_errs_rate,
         hostptr->val.interface[j].tx_bytes_rate,
         hostptr->val.interface[j].tx_packets_rate,
         hostptr->val.interface[j].tx_errs_rate,
         hostptr->val.tcp_inuse);
     }
   } else {
        mvwprintw(displaypad,k++,0,"%-8.8s|%15s|%s",
         hostptr->hostname,
         hostptr->hostip,
         "Not connected");
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }
 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}

/*
 *========================================================================
 * display_times()
 *
 * This routine displays time, uptime, and some static system stats.
 * Most of this is slowly varying and will only be useful for a glance.
 *========================================================================
 */
void display_times(List *hostlist)
{

 /* Loop indices */
 int i,j,k;
 /* 
  * Display controls, both local and semi-global.
  * minimum number of lines needed to run an xterm display with ONE host
  */
 int minlines;
 /* scratch space for positioning and counters both */
 int row = 0,col = 0;
 /* controls the hosts loop so we can page */
 int imin_col,imax_col;
 /* 
  * We need these to define EACH host as we walk the list of hosts for 
  * display.
  */
 Host *hostptr;
 ListElement *element;

 if((verbose == D_ALL) || (verbose == D_DISPLAY_VALUES)){
   fprintf(OUTFP,"D_DISPLAY_VALUES: Starting D_DISPLAY_VALUES.  Use -v %d to focus.\n",D_DISPLAY_VALUES);
 }

 mvwprintw(headerwin,0,0,"%-8s|   %15.15s    |%3s|%4s|%4s|%7s    |    %7s     |%5s",
      "   name",
      "CPU Model Name",
      "Crs",
      "ClkM",
      "CchK",
      "Time",
      "Uptime",
      "Duty%"
   );
 wclrtoeol(headerwin);
 wrefresh(headerwin);

 element = hostlist->head;
 display.bottomline_displayed = 0;  /* count the lines */
 werase(displaypad);
 for(i=0;i<numhosts;i++){
   if(element == NULL) break;	/* For whatever reason, out of hosts */
   hostptr = element->data;
   if(hostptr->connected) {
     mvwprintw(displaypad,i,0,"%-7.7s|%-22.22s|%2d |%4.f|%4d|%11s|%16s|%3.f",
       hostptr->hostname,
       hostptr->val.cpuinfo_model_name,
       hostptr->val.cpuinfo_cores,
       hostptr->val.cpuinfo_clock,
       hostptr->val.cpuinfo_cachesize,
       hostptr->val.time,
       hostptr->val.uptime,
       hostptr->val.duty_cycle
       );
   } else {
     mvwprintw(displaypad,i,0,"%-7.7s|%22.22s|%2s |%4s|%4s|%11s|%16s|%3s",
       hostptr->hostname,
       "",
       "",
       "",
       "",
       "",
       "down      ",
       "");
   }
   display.bottomline_displayed++;  /* count the lines */
   element = element->next;
 }

 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}

/*
 *========================================================================
 * display_config()
 *
 * This routine manages the interactive interface, where users can
 * manage things like the wulfhost list, the users whose tasks are to
 * be monitored, the tasklist to be monitored, and as the interface
 * evolves, probably things like alarms.
 *========================================================================
 */
void display_config(List *hostlist)
{

}


