/*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


    Email address:
    lush@Athena.EE.MsState.EDU
*/
#include "bbs.h"

#define PUTCURS   move(4+locmem->crs_line-locmem->top_line,0);prints(">");
#define RMVCURS   move(4+locmem->crs_line-locmem->top_line,0);prints(" ");

struct keeploc {
    char *key ;
    int top_line ;
    int crs_line ;
    struct keeploc *next ;
} ;

struct keeploc *
getkeep(s,def_topline,def_cursline)
char *s ;
{
    static struct keeploc *keeplist = NULL ;
    struct keeploc *p ;
    void *malloc() ;

    for(p = keeplist; p!= NULL; p = p->next) {
        if(!strcmp(s,p->key))
          return p ;
    }
    p = (struct keeploc *) malloc(sizeof (*p)) ;
    p->key = (char *) malloc(strlen(s)+1) ;
    strcpy(p->key,s) ;
    p->top_line = def_topline ;
    p->crs_line = def_cursline ;
    p->next = keeplist ;
    keeplist = p ;
    return p ;
}

char dirbuf[4096] ;
struct fileheader *files = NULL;

i_read(direct, dotitle, doentry, rcmdlist)
char *direct ;
int (*dotitle)() ;
char *(*doentry)() ;
struct one_key *rcmdlist ;
{
    extern int t_lines ;
    char lbuf[11] ;
    int lbc ;
    struct keeploc *locmem ;
	int screen_len = SCREEN_SIZE - 4 ;
	int num_entries ;
	int ch ;
	int i ;
	int last_line ;
	int mode = DONOTHING ;
    char *calloc() ;

    if(!files)
      files = (struct fileheader *)calloc(screen_len,sizeof(*files)) ;
    strcpy(dirbuf,direct) ;
	move(0,0) ;
	(*dotitle)() ;
	clrtobot() ;
	last_line = get_num_records(dirbuf, sizeof(struct fileheader)) ;
	if(last_line == 0) {
		prints("No Messages on this board\n") ;
		return ;
	}
    locmem = getkeep(dirbuf,
             (last_line-screen_len+1 < 1)?1:last_line-screen_len+1,last_line) ;
	num_entries = get_records(dirbuf, files, sizeof(struct fileheader),
							  locmem->top_line,screen_len) ;
	move(4,0) ;
	for(i=0; i < num_entries ; i++) {
		char *t = (*doentry)(locmem->top_line+i,&files[i]) ;
		if(strlen(t) >= 79) {
			t[78] = '^' ;
			t[79] = '\0' ;
		}
		prints("%s\n",t) ;
	}
	PUTCURS ;
    lbc = 0 ;
	while((ch = igetch()) != EOF) {
		extern int talkrequest ;
		if(talkrequest) {
			talkreply() ;
			mode = FULLUPDATE ;
			goto endofloop ;
		}
        if(isdigit(ch)) {
            if(lbc < 9)
              lbuf[lbc++] = ch ;
            goto endofloop ;
        }
        if(ch != '\n' && ch != '\r')
          lbc = 0 ;
		switch(ch) {
            int val ;

		  case 'q':
		  case 'e':
			mode = DOQUIT ;
			break ;
          case '\n':
          case '\r':
            if(lbc == 0)
              break ;
            lbuf[lbc] = '\0' ;
 			val = atoi(lbuf) ;
            lbc = 0 ;
			if(val > last_line)
			  val = last_line ;
			if(val <= 0)
			  val = 1 ;
			if(val >= locmem->top_line && val < locmem->top_line + screen_len) {
				RMVCURS ;
				locmem->crs_line = val ;
				PUTCURS ;
				continue ;
			}
			locmem->top_line = val - 10 ;
			if(locmem->top_line <= 0)
			  locmem->top_line = 1 ;
			locmem->crs_line = val ;
			mode = PARTUPDATE ;
			goto endofloop ;
		  case 'p':
			if(locmem->crs_line == locmem->top_line) {
				if(locmem->crs_line == 1) {
					bell() ;
					break ;
				}
				locmem->top_line -= screen_len - 2 ;
				if(locmem->top_line <= 0)
				  locmem->top_line = 1 ;
				locmem->crs_line-- ;
				mode = PARTUPDATE ;
				break ;
			}
			RMVCURS ;
			locmem->crs_line-- ;
			PUTCURS ;
			break ;
		  case 0x0c: /* CTRL(L) */
			redoscr() ;
			break ;
		  case 'n':
			if(locmem->crs_line == last_line) {
				bell() ;
				break ;
			}
			if(locmem->crs_line+1 == locmem->top_line+screen_len) {
				locmem->top_line += screen_len - 2 ;
				locmem->crs_line++ ;
				mode = PARTUPDATE ;
				break ;
			}
			RMVCURS ;
			locmem->crs_line++ ;
			PUTCURS ;
			break ;
		  case 'N':
			if(locmem->top_line + screen_len - 1 >= last_line) {
				bell() ;
				break ;
			}
			locmem->top_line += screen_len - 1 ;
			locmem->crs_line = locmem->top_line ;
			mode = PARTUPDATE ;
			break ;
		  case 'P':
			if(locmem->top_line == 1) {
				bell() ;
				break ;
			}
			locmem->top_line -= screen_len - 1 ;
			if(locmem->top_line <= 0)
			  locmem->top_line = 1 ;
			locmem->crs_line = locmem->top_line ;
			mode = PARTUPDATE ;
			break ;
		  case '$':
			if(last_line < locmem->top_line + screen_len) {
				RMVCURS ;
				locmem->crs_line = last_line ;
				PUTCURS ;
				break ;
			}
			locmem->top_line = last_line - screen_len + 1 ;
			if(locmem->top_line <= 0)
			  locmem->top_line = 1 ;
			locmem->crs_line = last_line ;
			mode = PARTUPDATE ;
			break ;
		  default:
			for(i = 0; rcmdlist[i].fptr != NULL; i++) {
				if(rcmdlist[i].key == ch) {
					mode = (*(rcmdlist[i].fptr))(locmem->crs_line,
                              &files[locmem->crs_line - locmem->top_line], dirbuf);
					break ;
				}
			}
			if(rcmdlist[i].fptr == NULL)
			  bell() ;
			break ;
		}

	  endofloop:

		switch(mode) {
          case NEWDIRECT:
		  case FULLUPDATE:
			clear() ;
			move(0,0) ;
			(*dotitle)() ;
			clrtobot() ;
		  case PARTUPDATE:
			last_line = get_num_records(dirbuf, sizeof(struct fileheader)) ;
            if(mode == NEWDIRECT)
              locmem = getkeep(dirbuf,
            (last_line-screen_len < 1)?1:last_line-screen_len+1,last_line) ;

			if(last_line == 0) {
				prints("No Messages\n") ;
				num_entries = 0 ;
			} else 
			  num_entries = get_records(dirbuf, files, sizeof(struct fileheader),
										locmem->top_line,screen_len) ;
			if(locmem->crs_line > last_line)
			  locmem->crs_line = last_line ;
			move(4,0) ;
			for(i=0; i < num_entries ; i++) {
				char *t = (*doentry)(locmem->top_line+i,&files[i]) ;
				if(strlen(t) >= 79) {
					t[78] = '^' ;
					t[79] = '\0' ;
				}
				prints("%s\n",t) ;
			}
			clrtobot() ;
			PUTCURS ;
			break ;
		  default:
			break ;
		}
		if(mode == DOQUIT)
		  break ;
		mode = DONOTHING ;
		if(num_entries == 0)
		  break ;
	}
	clear() ;
}


