/*
 *========================================================================
 * $Id: screen.c 244 2004-09-30 17:59:32Z rgb $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */

#include "wulfstat.h"

/* 
 *==================================================================
 * Curses/screen routines.
 *==================================================================
 */

/*
 * This routine sets up and starts the curses screen(s).
 */
void start_screen()
{

 int i;
 int pos;

 initscr();	/* Initialize screen for manipulation */
 keypad(stdscr, TRUE);	/* enable keyboard mapping */
 cbreak();      /* character at a time */
 noecho();	/* with no character echo */
 nonl();	/* Don't do NL to NL/CR on output */


 /*
  * Now we need to define a bunch of windows, one for each functional
  * display.  Scrollable windows require two windows, one for the "window"
  * (including the pretty border) and the "pad" that fits inside which
  * displays actual content text.  Pads can be bigger than their viewport
  * windows and can be slid up and down, left and right, within the "virtual"
  * window of their viewport.  Not as intuitive as it could be, but I
  * think we've figured it out.  Now to put it all to work.
  */

#define HEADER_LINES 1
#define MENU_LINES 6
#define FOOTER_LINES 3
#define DEBUG_LINES 3

/* there are 3 borders shared, hence the minus 3 below */
#define FIXED_LINES (HEADER_LINES + MENU_LINES + FOOTER_LINES + DEBUG_LINES - 3)
 /*
  * header for host display
  */
 pos = 0;
 display.lines_headerwin = HEADER_LINES;
 headerwin = newwin(display.lines_headerwin,COLS,pos,0);
 keypad(headerwin, TRUE);	/* enable keyboard mapping */
 wrefresh(headerwin);
 pos += HEADER_LINES;

 /*
  * host display
  */
 display.lines_displaywin = LINES - FIXED_LINES;
 display.cols_displaywin = COLS;
 /* Allow for border at top and bottom. */
 displaywin = newwin(display.lines_displaywin ,COLS,pos,0);
 wborder(displaywin,(char)NULL,(char)NULL,(char)NULL,(char)NULL,
      (char)NULL,(char)NULL,(char)NULL,(char)NULL);
 wrefresh(displaywin);
 pos += display.lines_displaywin - 1;

 /*
  * menu display
  */
 menuwin = newwin(MENU_LINES,COLS, pos , 0);
 keypad(menuwin, TRUE);	/* enable keyboard mapping */
 wborder(menuwin,(char)NULL,(char)NULL,(char)NULL,(char)NULL,
      ACS_LTEE,ACS_RTEE,(char)NULL,(char)NULL );
 wrefresh(menuwin);
 pos += MENU_LINES - 1;

 /*
  * footer display
  */
 footerwin = newwin(FOOTER_LINES,COLS, pos  ,0);
 keypad(footerwin, TRUE);	/* enable keyboard mapping */
 wborder(footerwin,(char)NULL,(char)NULL,(char)NULL,(char)NULL,
      ACS_LTEE,ACS_RTEE,(char)NULL,(char)NULL );
 mvwprintw(footerwin,1,1,"             wulfstat %s     Copyright 2004 Robert G. Brown",WULFWARE_VERSION);
 wrefresh(footerwin);
 pos += FOOTER_LINES - 1;

 /*
  * debug display.  Let's try making the debugpad into a window.
  */
 debugwin = newwin(DEBUG_LINES,COLS , pos,0);
 wborder(debugwin,(char)NULL,(char)NULL,(char)NULL,(char)NULL,
      ACS_LTEE,ACS_RTEE,(char)NULL,(char)NULL );
 mvwprintw(debugwin,DEBUG_LINES,33,"Debug/Messages");
 wrefresh(debugwin);
 debugpad = newwin(DEBUG_LINES - 2,COLS-2, pos + 1,1);
 keypad(debugpad, TRUE);	/* enable keyboard mapping */
 scrollok(debugpad, TRUE);      /* Enable a scrolloff at bottom */
 wprintw(debugpad,"mem* entries adjusted for cache/buffers\n");
 wrefresh(debugpad);
 pos += DEBUG_LINES;

 if(display.lines_displaywin < 1){
   mvwprintw(debugwin,1,1,"Warning: display has less than %d rows.", FIXED_LINES);
   mvwprintw(debugwin,2,1,"wulfstat may not display properly...");
   wrefresh(debugwin);
   sleep(5);
 }
}

/*
 * This routine sets up and starts the curses screen(s).
 */
void start_displaypad()
{

 /* this is the top line of the display in screen coords */
 display.line_displaypad = display.lines_headerwin + 1;
 /* leave room for displaywin border */
 display.lines_displaypad = display.lines_displaywin - 1;
 /* start displaypad at top (line 0) */
 display.topline_displaypad = 0;
 /* plenty of room for up to ten lines per host */
 display.bottomline_displaypad = numhosts*10;
 /* The corner of the displayed region is initially the topline */
 display.showline_displaypad = display.topline_displaypad;
 /* Create the pad */
 displaypad = newpad(display.bottomline_displaypad,COLS-2);
 /*
 mvwprintw(displaypad,0,0,"Hi there!  numhosts = %d",numhosts);
 mvwprintw(displaypad,15,0,"Hi there!  numhosts = %d",numhosts);
 mvwprintw(displaypad,16,0,"Hi there!  numhosts = %d",numhosts);
 mvwprintw(displaypad,17,0,"Hi there!  numhosts = %d",numhosts);
 */
 keypad(displaywin, TRUE);	/* enable keyboard mapping */
 /* upper left corners of pad diplayed in sliding window. */
 prefresh(displaypad,display.showline_displaypad,0,display.line_displaypad,1,display.lines_displaypad,COLS-2);

}

/*
 * This routine stops the curses screen if necessary to permit i/o to
 * a normal tty without curses control.  Otherwise it does nothing.
 */
void stop_screen()
{

 endwin();

}

void scroll_displaypad(int scroll_lines)
{

 /*
  * This scrolls displaypad up (+) or down (-) scroll_lines lines or
  * fewer.  We have to make sure that the result stays on the pad, so
  * all this routine does is some bounds checking and then displays the
  * new window onto the pad.
  */

 int new_showline = display.showline_displaypad + scroll_lines;
 int max_showline = display.bottomline_displaypad - display.lines_displaypad + 3;
 if((verbose == D_ALL) || (verbose == D_SCREEN)){
   wprintw(debugpad,"Scrolling %d lines, new = %d max = %d\n",
      scroll_lines,new_showline,max_showline);
 }
 if(new_showline < 0) {
   if((verbose == D_ALL) || (verbose == D_SCREEN)){
     wprintw(debugpad,"too small\n");
   }
   display.showline_displaypad = 0;
 } else if(new_showline > max_showline){
   if((verbose == D_ALL) || (verbose == D_SCREEN)){
     wprintw(debugpad,"too big\n");
   }
   display.showline_displaypad = max_showline;
 } else {
   if((verbose == D_ALL) || (verbose == D_SCREEN)){
     wprintw(debugpad,"just right\n");
   }
   display.showline_displaypad = new_showline;
 }

 if((verbose == D_ALL) || (verbose == D_SCREEN)){
   wprintw(debugpad,"top = %d bottom = %d lines = %d new = %d \n",
     display.showline_displaypad,
     display.bottomline_displaypad,
     display.lines_displaypad,
     new_showline);
   wrefresh(debugpad);
 }

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

}
