/*
screenio.c: screen io procedures for selectnews

Copyright (C) 1993 Eugene Eric Kim
All rights reserved.

LAST REVISION: September 4, 1993
*/

#include <stdio.h>
#include <string.h>
#include "headers.h"

void Credits()
{
  standout();
  move(LINES-1,0);
  clrtoeol();
  addstr("selectnews * Copyright (C) Eugene Kim 1993 * Press 'i' for instructions");
  standend();
  refresh();
}

void Topline()
{
#ifdef NCURSES 
  attron(A_BOLD);
#else
  standout();
#endif
  mvaddstr(0,0,"UNSUBSCRIBED");
  mvaddstr(0,COLS - (COLS / 2),"SUBSCRIBED");
#ifdef NCURSES
  attroff(A_BOLD);
#else
  standend();
#endif
}

void initwin()
{
  initscr();
  noecho();
  cbreak();
#ifdef NCURSES
  keypad(stdscr,TRUE);
#endif
  leftscr = newwin(LINES-2,COLS / 2,1,0);
  rightscr = newwin(LINES-2,COLS - (COLS / 2),1,COLS - (COLS / 2));
  scrollok(leftscr,TRUE);
  scrollok(rightscr,TRUE);
  Topline();
  Credits();
}

void Instructions()
{
  clear();
  standout();
  mvaddstr(3,0,"MOVEMENT");
  mvaddstr(3,40,"SUBSCRIBE/UNSUBSCRIBE");
  mvaddstr(8,40,"MISCELLANEOUS");
  mvaddstr(12,0,"QUIT");
  mvaddstr(16,0,"PRESS ANY KEY TO CONTINUE");
  standend();
  mvaddstr(0,0,"selectnews");
  mvaddstr(0,11,VERSION);
  mvaddstr(1,0,"Copyright (C) 1993 Eugene Eric Kim");
  mvaddstr(4,0,"up             = k");
  mvaddstr(5,0,"down           = j");
  mvaddstr(6,0,"switch windows = <space>, h, l");
  mvaddstr(7,0,"scroll down    = >");
  mvaddstr(8,0,"scroll up      = <");
  mvaddstr(9,0,"beginning      = 0");
  mvaddstr(10,0,"end            = $");
  mvaddstr(4,40,"(un)subscribe item = <return>");
  mvaddstr(5,40,"(un)subscribe all  = g");
  mvaddstr(9,40,"sort buffer = s");
  mvaddstr(10,40,"find item   = f");
  mvaddstr(13,0,"quit w/o saving        = q");
  mvaddstr(14,0,"write .newsrc and quit = w");
  refresh();
}

short Sure(str)
char str[80];
{
  char ch;

  move(LINES-1,0);
  clrtoeol();
  addstr(str);
  refresh();
  do
    ch = getch();
  while ( (ch!='y') && (ch!='Y') && (ch!='n') && (ch!='N') );
  if ( (ch == 'y') || (ch == 'Y') )
    return 1;
  else {
    Credits();
    return 0;
  }
}

void cursor(win,loc,str)
WINDOW *win;
int loc;
char* str;
{
  mvwaddstr(win,loc,0,str);
  wrefresh(win);
}

void delcursor(win,loc)
WINDOW *win;
int loc;
{
  mvwaddstr(win,loc,0,"  ");
  wrefresh(win);
}

void showentry(win,b,line)
WINDOW *win;
int b;
char line[LEN];
{
  char temp[LEN];
  int i = 0;

  while ( (line[i]!=':') && (line[i]!='!') ) {
    temp[i] = line[i];
    i++;
  }
  temp[i] = '\0';
  if (i > COLS/2 - 2) {
    i = COLS/2-2;
    temp[i-4] = ' ';
    temp[i-3] = '-';
    temp[i-2] = '>';
    temp[i-1] = '\0';
  }
  mvwaddstr(win,b,2,temp);
}

void showbuffer(win,buffer,start)
WINDOW *win;
dllist buffer;
int start;
{
  node* w;
  int i = 0;

  w = list_position(buffer,start);
  werase(win);
  while ((w!=0) && (i<LINES-2)) {
    showentry(win,i,(*w).entry);
    w = list_next(w);
    i++;
  }
  wrefresh(win);
}

node* moveup(win,cpos,top,w,cchar)
WINDOW *win;
int *cpos, *top;
node* w;
char* cchar;
{
  if ((*cpos) || (*top))
    w = list_prev(w);
  if ((*cpos)) {
    delcursor(win,*cpos);
    (*cpos)--;
    cursor(win,*cpos,cchar);
  }
  else if ((*top)) { /* (*cpos) = 0 */
    (*top)--;
    delcursor(win,*cpos);
    wmove(win,0,0);
    winsertln(win);
    showentry(win,0,(*w).entry);
    cursor(win,(*cpos),cchar);
    wrefresh(win);
  }
  return w;
}

node* movedown(win,cpos,top,list,w,cchar)
WINDOW *win;
int *cpos,*top;
dllist list;
node* w;
char* cchar;
{
  if (list_next(w) != 0) {
    w = list_next(w);
    if ((*cpos)<LINES-3) {
      delcursor(win,*cpos);
      (*cpos)++;
      cursor(win,*cpos,cchar);
    }
    else { /* bottom of screen */
      (*top)++;
      delcursor(win,*cpos);
      wmove(win,0,0);
      wdeleteln(win);
      showentry(win,*cpos,(*w).entry);
      cursor(win,*cpos,cchar);
      wrefresh(win);
    }
  }
  return w;
}

node* scrollup(win,cpos,top,list,w,cchar)
WINDOW *win;
int *cpos, *top;
dllist list;
node* w;
char* cchar;
{
  int i = LINES - 2;

  if (*top) {
    if ( (*top)-i > 0 )
      (*top) -= i;
    else {
      (*top) = (*cpos) = 0;
    }
    showbuffer(win,list,*top);
  }
  delcursor(win,*cpos);
  w = list_position(list,*top + *cpos);
  cursor(win,*cpos,cchar);
  return w;
}

node* scrolldown(win,cpos,top,list,w,cchar)
WINDOW *win;
int *cpos, *top;
dllist list;
node* w;
char* cchar;
{
  int i = LINES - 2;

  if (list_position(list,*top + *cpos + i) != 0) {
    w = list_position(list,*top + *cpos + i);
    (*top) += (*cpos) + i;
    (*cpos) = 0;
  }
  else
    (*cpos) = list_size(list) - (*top) - 1;
  showbuffer(win,list,*top);
  cursor(win,*cpos,cchar);
  return w;
}

node* homepage(win,cpos,top,list,cchar)
WINDOW *win;
int *cpos, *top;
dllist list;
char* cchar;
{
  (*top) = (*cpos) = 0;
  showbuffer(win,list,*top);
  cursor(win,*cpos,cchar);
  return list_start(list);
}

node* endpage(win,cpos,top,list,cchar)
WINDOW *win;
int *cpos, *top;
dllist list;
char* cchar;
{
  int i = list_size(list);
  int screensize = LINES - 2;

  if (i > screensize) {
    (*top) = i - screensize;
    (*cpos) = screensize - 1;
    showbuffer(win,list,(*top));
    cursor(win,(*cpos),cchar);
  }
  else {
    delcursor(win,(*cpos));
    (*cpos) = i - 1;
    cursor(win,(*cpos),cchar);
  }
  return list_end(list);
}

short indexstr(index,len,src,dest,ch)
int index,len;
char src[80], (*dest)[80];
char ch;
{
  int i = 0, found = 0, j, size;

  (*dest)[0] = '\0';
  size = strlen(src);
  while ( (i<size) && (found!=index) ) {
    if (src[i]==ch) found++;
    if (found!=index) i++;
  }
  if (found!=index)
    return 0;
  else {
    if (size - i >= len) {
      for (j = 0; j<len; j++)
	(*dest)[j] = src[i+j];
      (*dest)[j] = '\0';
      return 1;
    }
    else
      return 0;
  }
}

node* find(win,cpos,top,list,cchar)
WINDOW *win;
int *cpos,*top;
dllist list;
char* cchar;
{
  node* w;
  node* v;
  short found = 0, exist;
  char what[80], search[80], temp[80];
  int i = 0, j;

  move(LINES-1,0);
  standend();
  clrtoeol();
  addstr("Find: ");
  getstr(what);
  if (what[0]!='\0') {
    v = w = list_start(list);
    while ( (w!=0) && (!found) ) {
      j = 1;
      while (exist = indexstr(j,strlen(what),(*w).entry,&search,what[0])) {
	if (!strcmp(search,what)) {
	  found = 1;
	  (*top) = i;
	  (*cpos) = 0;
	  v = w;
	  showbuffer(win,list,(*top));
	  cursor(win,(*cpos),cchar);
	  if (!list_last(w) && Sure("Search again (y/n)? ")) {
	    found = j = 0;
	    w = list_next(w);
	    i++;
	  }
	}
        j++;
      }
      if (!exist)
	w = list_next(w);
      i++;
    }
  }
  Credits();
  showbuffer(win,list,(*top));
  cursor(win,(*cpos),cchar);
  return v;
}

int cmp(entry1,entry2)
char entry1[LEN], entry2[LEN];
{
  int i = 0, j = 0;

  while (alpha[i] != entry1[0]) i++;
  while (alpha[j] != entry2[0]) j++;
  if (i<j)
    return 1;
  else if (i>j)
    return 0;
  else {
    i = 1;
    if (strlen(entry1) < strlen(entry2))
      j = strlen(entry1);
    else
      j = strlen(entry2);
    while ( (entry1[i] == entry2[i]) && (i<=j) ) i++;
    if (entry1[i]<entry2[i])
      return 1;
    else
      return 0;
  }
}

void partition(list,low,high,pivotloc)
dllist* list;
int low,high;
int *pivotloc;
{
  char pivot[LEN];
  int i,lastsmall;
  node* temp;

  list_interchange(list,list_position(*list,low),list_position(*list,(low+high)/2));
  strcpy(pivot,(*list_position(*list,low)).entry);
  lastsmall = low;
  temp = list_position(*list,low+1);
  for (i = low+1; i <= high; i++) {
    if (cmp(temp,pivot)) {
      lastsmall++;
      list_interchange(list,temp,list_position(*list,lastsmall));
    }
    temp = list_next(temp);
  }
  list_interchange(list,list_position(*list,low),list_position(*list,lastsmall));
  (*pivotloc) = lastsmall;
}

void quicksort(list,low,high)
dllist* list;
int low,high;
{
  int pivotloc;

  if (low < high) {
    partition(list,low,high,&pivotloc);
    quicksort(list,low,pivotloc - 1);
    quicksort(list,pivotloc + 1,high);
  }
}

void sort(win,list,top,cpos,cchar)
WINDOW *win;
dllist* list;
int top, cpos;
char* cchar;
{
  char ch;

  move(LINES-1,0);
  clrtoeol();
  addstr("Sorting... this may take a few minutes.");
  refresh();
  quicksort(list,0,list_size(*list) - 1);
  showbuffer(win,*list,top);
  cursor(win,cpos,cchar);
  Credits();
}
