#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include "mfjterm.h"
#include "misc.h"


char *sb_buf;
char *sb_bufstr[809];
int strno = 0, strptr = 0, sb_up = 0, sb_dn = 0, firstup = 0, lncntr = 0, lines_in_buffer = 0;
WINDOW *sbwin;


void init_scrollback(void)
{
       int i;

       sb_buf = malloc(65536);
       for (i = 0; i < 809; i++)
               sb_bufstr[i] = sb_buf+(81*i);
}


void exit_scrollback(void)
{
       free(sb_buf);
}


static void chk_firstup(void)
{
       int i;

       if (firstup) {
               firstup = FALSE;
               for (i = tnc_y; i > 0 ; i--) {
                       if (++lncntr > lines_in_buffer) break;
                       if (--sb_up < 0) sb_up = 808;
               }
       }
}


static void plot_uppage(int refresh)
{
       char buf[1440], *p;
       int i, j;

       j = sb_up;

       memset(buf, 0x20, 1440);

       p = buf;

       for (i = 1; i <= tnc_y; i++) {
               if (++j > 808) j = 0;
               memcpy(p, sb_bufstr[j], strlen(sb_bufstr[j]));
               p += 80;
       }

       wmove(sbwin, 0, 0);
       waddnstr(sbwin, buf, 1440);
       if (refresh)
               wrefresh(sbwin);
}


static void plot_dnpage(int refresh)
{
       char buf[1440], *p;
       int i, j;

       j = sb_dn;

       memset(buf, 0x20, 1440);

       p = buf + 1360;

       for (i = tnc_y; i > 0; i--) {
               if ((--j) < 0) j = 808;
               memcpy(p, sb_bufstr[j], strlen(sb_bufstr[j]));
               p -= 80;
       }

       wmove(sbwin, 0, 0);
       waddnstr(sbwin, buf, 1440);
       if (refresh)
               wrefresh(sbwin);
}


static void home(void)
{
       chk_firstup();
       if (lncntr <= lines_in_buffer) {
               while (lncntr <= lines_in_buffer) {
                       if (--sb_up < 0) sb_up = 808;
                       if (--sb_dn < 0) sb_dn = 808;
                       lncntr++;
               }
               plot_uppage(1);
       }
}


static void end(void)
{
       if (lncntr > 18){
               while (lncntr > 18) {
                       if (++sb_up > 808) sb_up = 0;
                       if (++sb_dn > 808) sb_dn = 0;
                       lncntr--;
               }
               plot_dnpage(1);
       }
}


static void pgup(int refresh)
{
       int i;

       chk_firstup();
       if (lncntr <= lines_in_buffer) {
               for (i = 1; i < 19; i++) {
                       if (--sb_up < 0) sb_up = 808;
                       if (--sb_dn < 0) sb_dn = 808;
                       if (++lncntr > lines_in_buffer) break;

               }
               plot_uppage(refresh);
       }
}


static void pgdn(int refresh)
{
       int i;

       if (lncntr > 18) {
               for (i = 1; i < 19; i++){
                       if (++sb_up > 808) sb_up = 0;
                       if (++sb_dn > 808) sb_dn = 0;
                       if (--lncntr == 18) break;
               }
               plot_dnpage(refresh);
       }
}


static void lnup(void)
{
       char *s;

       chk_firstup();
       if (lncntr <= lines_in_buffer) {
               wmove(sbwin, 0, 0);
               wscrl(sbwin, -1);
               s = sb_bufstr[sb_up];
               waddstr(sbwin, s);
               wrefresh(sbwin);
               if (--sb_up < 0) sb_up = 808;
               if (--sb_dn < 0) sb_dn = 808;
               lncntr++;
       }
}


static void lndn(void)
{
       char *s;

       if (lncntr > 18) {
               wmove(sbwin, 17, 0);
               wscrl(sbwin, 1);
               s = sb_bufstr[sb_dn];
               waddstr(sbwin, s);
               wrefresh(sbwin);
               if (++sb_up > 808) sb_up = 0;
               if (++sb_dn > 808) sb_dn = 0;
               lncntr--;
       }
}



void scrollback(void)
{
       int k;

       sbwin = newwin(18, 80, 1, 0);
       if (sbwin == NULL)
               return;
       scrollok(sbwin, TRUE);
       curs_set(0);

       attrset(A_REVERSE);
       move(19, 1);
       addstr("Scroll-back Mode");
       attrset(A_NORMAL);

       firstup = TRUE;
       sb_dn = (strno)+1;
       sb_up = strno;
       lncntr = 0;

       pgup(0);
       pgdn(0);
       wrefresh(sbwin);

       while (1) {
               k = getch();

               switch(k){
                       case KEY_HOME :
                               home();
                               break;
                       case KEY_END :
                               end() ;
                               break;
                       case KEY_PPAGE :
                               pgup(1);
                               break;
                       case KEY_NPAGE :
                               pgdn(1);
                               break;
                       case KEY_UP :
                               lnup();
                               break;
                       case KEY_DOWN :
                               lndn();
                               break;
                       case 'q':
                       case 'Q':
                               goto rdy;
               }
       }
rdy:
       delwin(sbwin);
       redrawwin(stdscr);
       attrset(A_REVERSE);
       move(19, 1);
       addstr("                ");
       attrset(A_NORMAL);
       curs_set(1);
       move(tnc_y, tnc_x);
       refresh();
}