
#ifndef plist_h
#define plist_h

#include <conio.h>
#include "mystring.h"
/*  this is a class that creates a list of strings on the screen with one of
strings being a cursor.  the size of the list can be anywhere from 1 to I guess
the max# of size_t.  It uses three simple functions: the constructor passes
in the size of the list, insert adds a string to the list, and printlist
displays the list.  the list never prints out more than maxSize strings at
a time however if there are more than maxSize items, arrows will be placed
to show if there are items above or below the list.  the up and down keys
are used to move the cursor.  printlist returns the string that the
cursor rests on when the enter key is hit.
    the printlist doesn't reprint the list every time the cursor moves,
it only removes one line and inserts another.  this way it draws to the
the screen as fast as possible*/

const int maxSize = 13;   //the maximum # of strings to be printed on the screen

class plist
{
 private:
         string *strList; //strList is the array that holds the strings
         size_t size;     //the CURRENT size of the array, NOT the maximum
                          //size of the array
 public:
        plist(int num);   //the constructor that instantiates the array of size num
        ~plist();         //destroys the array
        void insert(string &item); //inserts a string at the end of the list
        string printList(); //printList is described up there
};

void delNumLine(int num)  //this function clears the screen of num lines
{
 int y = wherey();
 for (int i = y; i > (y - num); i--)
     {
      gotoxy(1, i);
      delline();
     }
}

int getach()    //getch() does not work for the up and down arrows
{               //this function will
 int i = getch();
 if (i == 0)
    return getch();
 else
     return i;
}

void printCursor(string &curs)  //prints out the cursor
{
 clreol();

 char ch[40];
 for(int i=0;i<40;i++)
 	if(i<curs.length())
   	ch[i]=curs.get_at(i);
   else
   	ch[i]=NULL;

 textcolor(WHITE);
 textbackground(BLUE);
 cprintf("%s", ch);
 textcolor(LIGHTGRAY);
 textbackground(BLACK);
}

plist::plist(int num)
{
 strList = new string[num];
 size = 0;
}

plist::~plist()
{
 delete []strList;
}

void plist::insert(string &item)
{
 strList[size] = item;
 size++;
}

string plist::printList()
{
 _setcursortype(_NOCURSOR);           //sets the cursor so that it is invisible
 textcolor(LIGHTGRAY);
 textbackground(BLACK);
 bool movedup = false; //the value that tells me if the list is to be moved up
 bool moveddown = false; //the value that tells me if the list is to be moved down
 size_t ptr = 0;     //this value holds which string is highlighted
 size_t bottom = 0;  //this value holds the string that is printed on the bottom
 size_t top;         //this value holds the string that is printed on the top
 if (size > maxSize) //if size of the array is larger than maxSize
    top = maxSize;   //then top is set to maxSize
 else
     top = size;     //else it is set to size
 size_t startLine = wherey(); //this holds the first position on the screen for the list
 size_t endLine = top + wherey() + 1; //this holds the last position on the screen for the list
 int ch = 0;         //this holds the ascii value of the last character
 //bool escape = false;

 cout << endl;
 for (size_t i = bottom; i < top; i++) //this loop prints out the list once
      if (i == ptr)
         {
          printCursor(strList[ptr]);
          cout << endl;
         }
      else
          cout << strList[i] << endl;
 textcolor(BLUE);
 cprintf("\n\nUse the up and down arrow keys and enter to select.");
 textcolor(LIGHTGRAY);

 while (ch != 13)
 {
  gotoxy(1, startLine);
  if (bottom != 0)
     cout << "   /\\";
  else
      clreol();
  if (moveddown)   //if we moved down then we have to insert the string at the
     {             //beginning and delete the string at the end of the list
      gotoxy(1, startLine + 1);
      insline();
      printCursor(strList[ptr]);
      gotoxy(1, wherey() + 1);
      clreol();
      cout << strList[ptr + 1];
      gotoxy(1, endLine);
      delline();
     }
  if (movedup)     //if we moved up then we have to insert the string at the
     {             //end and delete the string at the beginning of the list
      gotoxy(1, startLine + 1);
      delline();
      gotoxy(1, endLine - 2);
      clreol();
      cout << strList[ptr - 1];
      gotoxy(1, endLine - 1);
      insline();
      printCursor(strList[ptr]);
     }
  if (!(moveddown || movedup)) //if we neither moved up nor down, then all we
     {                        //have to do is move the cursor either up or down
      if (ch == 72)  //move the cursor down
         {
          gotoxy(1, startLine + ptr - bottom + 1);
          printCursor(strList[ptr]);
          gotoxy(1, wherey() + 1);
          clreol();
          cout << strList[ptr + 1];
         }
      if (ch == 80)  //move the cursor up
         {
          gotoxy(1, startLine + ptr - bottom);
          clreol();
          cout << strList[ptr - 1];
          gotoxy(1, wherey() + 1);
          printCursor(strList[ptr]);
         }
     }
  gotoxy(1, endLine);
  if (top != size)
     cout << "   \\/";
  else
      clreol();

  ch = getach();     //get the character

  moveddown = false; //reset moveddown and movedup
  movedup = false;
  if (ch == 72)      //the down character
     {
      if (ptr != 0)  //if ptr is pointing the least value, we don't want
         {           //to do anything
          ptr--;     //if not, decrement the ptr
          if (ptr < bottom) //if the ptr moved below bottom then we decrement
             {              //bottom and top, and moveddown gets set to true
              bottom--;
              top--;
              moveddown = true;
             }
         }
     }
  if (ch == 80)      //the up character
     {
      if (ptr != (size - 1)) //if ptr is pointing the highest value we don't
         {                   //want to do anything
          ptr++;             //if not, increment the ptr
          if (ptr > (top - 1)) //if the ptr moved above top then we increment
             {                 //bottom and top, and movedup gets set to true
              top++;
              bottom++;
              movedup = true;
             }
         }
     }                                 /*
  if (ch == 27)
     {
      escape = true;
      ch = 13;
     }                                 */
 } //while

 delNumLine(top - bottom + 4);
 _setcursortype(_NORMALCURSOR);
 //if (!escape)
    return strList[ptr];
 //else
     //{string esc = "eSC";
     //return esc;}
}

#endif

