//       ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
//       º                      NPSGUI.LIB                         Ç¿
//       º                      GUICLS.CPP                         º³
//       º         Copyright 1993, Nearly Perfect Software.        º³
//       º                 All rights reserved                     º³
//       º                                                         º³
//       º       This file is included in NPSGUI as a set of       º³
//       º      middle-level classes for use by the library        º³
//       º      user. It is intended as a programming example      º³
//       º      and is included as source code. It may be          º³
//       º      modified as needed and used in any application     º³
//       º      that uses NPSGUI, as long as this comment          º³
//       º      block is included.                                 º³
//       º                                                         º³
//       º               þ Written by Brad Broerman                º³
//       º               þ Last Modified: 02/14/95                 º³
//       º               þ Revision 2.5                            º³
//       ÈÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ³
//         ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
#include "npsgui.h"
#include "guicls.h"
#include <iostream.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <alloc.h>
#include <time.h>
#include <dos.h>

extern gmouse mouse; // The global mouse handler...

// These functions find a character 'fnd' in "str" starting at begin, and returns the
// offset of that character (starting at 0). If the character is not found, an error
// is indicated as follows:
int find_char (char *str, char fnd, int begin); // Returns strlen() if not found.
int find_char2 (char *str, char fnd, int begin);// Returns -1 if not found.

//    This function is used to return a sub-part of a string, just like the BASIC
//  function of the same name. The pointer must br free'd after use.
char *mids(char *strr, int beg, int len);

radiopanel::radiopanel(int x, int y, int w, int h, int d, char *Hdr, char *list,int k=1)
 : panel (x,y,w,h,d,7,OUT,k)
 {
  int pos = 0,
      cpos = 0,
      i,
      slen;

  TextClr = WHITE;
  BtnSel = 0;
  slen = strlen(Hdr);
  Header = (char *)calloc(slen+2,1);
  if (Header == NULL)
   {
    closegraph();
    cerr << "Memory Allocation error making rbutton." << endl;
    exit(-1);
   }
  strncpy(Header,Hdr,slen);
  NumItems = 0;
  while (cpos != -1)
	{
	 cpos = find_char2(list,',',pos);
	 pos = cpos + 1;
	 ++ NumItems;
	}
  i = pos = cpos = 0;
  while (cpos != -1)
	{
	 cpos = find_char2(list,',',pos);
	 Items[i++] = mids(list,pos,((cpos == -1) ? strlen(list) : cpos)-pos);
	 pos = cpos + 1;
	}
  for (i = 0; i < NumItems; ++i)
	if ((Buttons[i] = new rbutton(0,0,textheight("Aj")/2+2,BLACK,0)) == NULL)
	 {
	  closegraph();
	  cerr << "Memory Allocation error making rbutton." << endl;
	  exit(-1);
	 }
 }

radiopanel::~radiopanel()
 {
  for (int i=0; i < NumItems; ++i)
	{
	 delete Items[i];
	 delete Buttons[i];
	}
  delete Header;
 }

void radiopanel::setbtnclr(int c)
 {
  int i;

  for (i=0; i < NumItems; ++i);
	Buttons[i]->chgclr(c);
 }

void radiopanel::settextclr(int c)
 {
  TextClr = c;
 }

void radiopanel::show()
 {
  int Xo,i;
  int orig_color;
  struct fillsettingstype orig_settings;
  struct linesettingstype orig_line;
  struct textsettingstype textinfo;

  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  gettextsettings(&textinfo);
  setlinestyle(0,1,0);
  if ((Height-2*Depth) < (NumItems+1) * (textheight("A")+3))
	Height =  (NumItems+1) * (textheight("A")+7) + 2*Depth+2;
  if ((Width -2*Depth) < textwidth (Header))
	Width = textwidth(Header) + 2*Depth+2;
  for (i=0; i < NumItems; ++i)
	if ((Width - 2*Depth) < textheight("A") + 16 + textwidth(Items[i]))
	 Width = textheight("A") + 18 + textwidth(Items[i]) + 2*Depth;

  panel::show();
  mouse.hide();
  setcolor(TextClr);
  settextjustify(CENTER_TEXT,TOP_TEXT);
  outtextxy((X+Width/2),(Xo=Y+Height/2-(NumItems*(textheight("A")+7)+textheight("A"))/2),Header);
  for (i=0; i <NumItems; ++i)
	{
	 Xo += 7+textheight("Aj");
	 Buttons[i]->moveto(X+Depth+10,Xo+textheight("A")/2);
	 Buttons[i]->show();
	 settextjustify(LEFT_TEXT,TOP_TEXT);
	 setcolor(TextClr);
	 outtextxy((X+Depth+16+textheight("A")),Xo,Items[i]);
	}
  mouse.show();
  settextjustify(textinfo.horiz,textinfo.vert);
  setcolor(orig_color);
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
 }

void radiopanel::hide()
 {
  int i;

  for (i=0; i<NumItems; ++i)
   Buttons[i]->hide();
  panel::hide();
 }

int radiopanel::btnhit()
 {
  int i;

  for (i=0; i < NumItems; ++i)
   if (Buttons[i]->hit())
    break;
  if (i == NumItems)
   return 0;
  return (i+1);
 }

void radiopanel::selectbtn(int no)
 {
  if ((no > 0) && (no <= NumItems))
   {
    if (BtnSel > 0)
     Buttons[BtnSel-1]->show();
    Buttons[no-1]->select();
    BtnSel = no;
   }
 }

int radiopanel::checkforevent()
 {
  int c;
  int cb;

  if (!isShown)
   return 0;
  cb = BtnSel;
  while(1)
   {
    if (btnhit() && mouse.getbutton(LEFT_BTN) && btnhit())
     {
      selectbtn(btnhit());
       return 1;
     }
    if (keyhit())
     {
      c = getkey();
      if (c > 255)
       {
	c= c & 0xf;
	if (c == 80) // Down Arrow
	 selectbtn(cb = (cb+1 > 7) ? 7 : cb+1);
	else if (c == 72) // Up Arrow
	 selectbtn(cb =(cb-1 > 1) ? cb-1 : 1);
       }
      else if (c == 13) // The Enter Key
       return 1;
      else if (c == 27) // The Escape Key
       break;
     }
   }
  return 0;
 }

int radiopanel::btnselected()
 {
  return (BtnSel);
 }

void radiopanel::btnclear()
 {
  Buttons[BtnSel-1]->show();
  BtnSel = 0;
 }

void textplane::ANSI_Decode(char c) // Decodes ANSI escape sequences.
 {
  int attrib,
      i,
      Indx;

  if (REscSeq) // If we are recording a sequence,
   {
    if (isalpha(c)) // and we encounter an alpha,
     {    // no more than 40 in STR[].
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = c; // Store it,
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = 0x00; // terminate the string,
      --SIndex;
      REscSeq = 0;  // And terminate recording.
     }
    else      // Otherwise,
     {
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = c; // Store it, and return. Keep recording!
      return;
     }
   }
  else // Otherwise, if we aren't recording a sequence,
   {
    if (c == 27) // Check for escape sequence.
     {
      REscSeq = 1; // Indicate that we are reading a sequence.
      SIndex = 0;  // Start at the beginning of the buffer.
      for (i=0; i<20; ++i) // Clear the buffer.
       STR[i] = 0;
      STR[0] = 27; // Set the beginning of the string to the ESC chaaracter.
      return;      // and return.
     }
    else // If we aren't beginning a new one,
     {
      STR[0] = c;    // Place the character in STR,
      STR[1] = 0x00; // and terminate it.
     }
   }

  // Now, when we reach this point, we are ready to translate the string STR.

  int orig_color;                         // Store original screen settings,
  struct fillsettingstype orig_settings;  // So we can fet them back later.
  struct linesettingstype orig_line;
  struct textsettingstype textinfo;

  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  gettextsettings(&textinfo);
  setlinestyle(0,1,0);
  if ((STR[0] == 27) && (STR[1] == '[')) // Check for an escape sequence in STR.
   {
    switch (STR[SIndex])  // get the character that tells what the code is for.
     {
      case 's': SavY = CsrY;
		SavX = CsrX;
		break;
      case 'u': CsrX = SavX;
		CsrY = SavY;
		break;
      case 'K': mouse.hide();
		CsrX = X+textwidth("A")/2-1;
		setcolor(BkgClr);
		setfillstyle(SOLID_FILL,BkgClr);
		bar(X,CsrY-textheight("A")/2,X+Width-1,CsrY+textheight("A")/2-1);
		for (Indx =0; Indx < (Width/textwidth("A"));++Indx)
		 {
		  *(TxtBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
		  *((char *)(AtrBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))) = 0x00;
		 }
		mouse.show();
		break;
      case 'A': if (atoi(STR+2) >0)
		 CsrY = CsrY - (textheight("A"))*atoi(STR+2);
		else
		 CsrY = CsrY - textheight("A");
		if (CsrY < Y+textheight("A")/2)
		 CsrY = Y+textheight("A")/2;
		break;
      case 'B': if (atoi(STR+2) > 0)
		 CsrY = CsrY + (textheight("A"))*atoi(STR+2);
		else
		 CsrY = CsrY + textheight("A");
		while (CsrY > (Y+Height-textheight("A")/2))
		 CsrY -= textheight("A");
		break;
      case 'C': if (atoi(STR+2) > 0)
		 CsrX = CsrX + textwidth("A")*atoi(STR+2);
		else
		 CsrX = CsrX + textwidth("A");
		while (CsrX > (X+Width - textwidth("A")/2))
		 CsrX -= textwidth("A");
		break;
      case 'D': if (atoi(STR+2) > 0)
		 CsrX = CsrX - textwidth("A")*atoi(STR+2);
		else
		 CsrX = CsrX - textwidth("A");
		if (CsrX < X + textwidth("A")/2-1)
		 CsrX = X + textwidth("A")/2-1;
		break;
      case 'J': if (atoi(STR+2) == 2)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,Y,X+Width-1,Y+Height-1);
		  CsrX = X+textwidth("A")/2-1;
		  CsrY = Y+textheight("A")/2;
		  for (Indx = 0; Indx < (Width/textwidth("A"))* (Height/textheight("A")) ; ++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx) = (char)0x00;
		    (AtrBuf+CurScrn+Indx)->Bkg = BkgClr;
		   }
		  mouse.show();
		 }
		break;
      case 'H':
      case 'f': CsrY = (textheight("A")) * (((atoi(STR+2)-1) > 0) ? (atoi(STR+2)-1) : 0) +Y+textheight("A")/2;
		CsrX = textwidth("A") * ( (atoi((STR+find_char(STR,';',0)+1))>0)?(atoi((STR+find_char(STR,';',0)+1))-1):0)+X+textwidth("A")/2-1;
		while (CsrX > (X+Width - textwidth("A")/2))
		 CsrX -= textwidth("A");
		while (CsrY > (Y+Height-textheight("A")/2))
		 CsrY -= textheight("A");
		break;
      case 'm': i=-1;
		do
		 {
		  attrib = atoi(STR+3+i);
		  if (attrib == 0) Bold = 0;
		  if (attrib == 1) Bold = 1;
		  if ((attrib > 29) && (attrib < 38))
		   switch (attrib-30)
		    {
		     case 0:TxtClr =  BLACK+8*Bold; break;
		     case 1:TxtClr =  RED+8*Bold; break;
		     case 2:TxtClr =  GREEN+8*Bold; break;
		     case 3:TxtClr =  BROWN+8*Bold; break;
		     case 4:TxtClr =  BLUE+8*Bold; break;
		     case 5:TxtClr =  MAGENTA+8*Bold; break;
		     case 6:TxtClr =  CYAN+8*Bold; break;
		     case 7:TxtClr =  LIGHTGRAY+8*Bold; break;
		    }
		  if ((attrib > 39) && (attrib < 48))
		   switch (attrib-40)
		    {
		     case 0:BkgClr =  BLACK; break;
		     case 1:BkgClr =  RED; break;
		     case 2:BkgClr =  GREEN; break;
		     case 3:BkgClr =  BROWN; break;
		     case 4:BkgClr =  BLUE; break;
		     case 5:BkgClr =  MAGENTA; break;
		     case 6:BkgClr =  CYAN; break;
		     case 7:BkgClr =  LIGHTGRAY; break;
		    }
		  i = find_char(STR+2,';',i+1);
		 }
		while (i < strlen(STR)-2);
     }
   }
  else
   Print_Char(STR[0]);
  move_csr();
  settextjustify(textinfo.horiz,textinfo.vert); //   Reset various screen parameters
  setcolor(orig_color);                         // that we may have changed here.
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
 }

void textplane::VT100_Decode(char c)
 {
  int attrib,
      i,
      Indx;

  if (REscSeq) // If we are recording a sequence,
   {
    if (isalpha(c)) // and we encounter an alpha,
     {
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = c; // Store it,
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = 0x00; // terminate the string,
      --SIndex;
      REscSeq = 0;  // And terminate recording.
     }
    else      // Otherwise,
     {
      STR[(SIndex = (SIndex<39) ? SIndex+1 : 39)] = c; // Store it, and return. Keep recording!
      return;
     }
   }
  else // Otherwise, if we aren't recording a sequence,
   {
    if (c == 27) // Check for escape sequence.
     {
      REscSeq = 1; // Indicate that we are reading a sequence.
      SIndex = 0;  // Start at the beginning of the buffer.
      memset(STR,0,20);// Clear the buffer.
      STR[0] = 27; // Set the beginning of the string to the ESC chaaracter.
      return;      // and return.
     }
    else // If we aren't beginning a new one,
     {
      STR[0] = c;    // Place the character in STR,
      STR[1] = 0x00; // and terminate it.
     }
   }

  // Now, when we reach this point, we are ready to translate the string STR.

  if ((STR[0] == 27) && (STR[1] == '[')) // Check for an escape sequence in STR.
   {
    switch(STR[SIndex])
     {
      case 'A': if (atoi(STR+2) >0)
		 CsrY = CsrY - (textheight("A"))*atoi(STR+2);
		else
		 CsrY = CsrY - textheight("A");
		if (CsrY < Y+textheight("A")/2)
		 CsrY = Y+textheight("A")/2;
		break;
      case 'B': if (atoi(STR+2) > 0)
		 CsrY = CsrY + (textheight("A"))*atoi(STR+2);
		else
		 CsrY = CsrY + textheight("A");
		while (CsrY > (Y+Height-textheight("A")/2))
		 CsrY -= textheight("A");
		break;
      case 'C': if (atoi(STR+2) > 0)
		 CsrX = CsrX + textwidth("A")*atoi(STR+2);
		else
		 CsrX = CsrX + textwidth("A");
		while (CsrX > (X+Width - textwidth("A")/2))
		 CsrX -= textwidth("A");
		break;
      case 'D': if (atoi(STR+2) > 0)
		 CsrX = CsrX - textwidth("A")*atoi(STR+2);
		else
		 CsrX = CsrX - textwidth("A");
		if (CsrX < X + textwidth("A")/2-1)
		 CsrX = X + textwidth("A")/2-1;
		break;
      case 'H':
      case 'f': CsrY = (textheight("A")) * (((atoi(STR+2)-1) > 0) ? (atoi(STR+2)-1) : 0) +Y+textheight("A")/2;
		CsrX = textwidth("A") * ( (atoi((STR+find_char(STR,';',0)+1))>0)?(atoi((STR+find_char(STR,';',0)+1))-1):0)+X+textwidth("A")/2-1;
		while (CsrX > (X+Width - textwidth("A")/2))
		 CsrX -= textwidth("A");
		while (CsrY > (Y+Height-textheight("A")/2))
		 CsrY -= textheight("A");
		break;
      case 'J': if (atoi(STR+2) == 2)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,Y,X+Width-1,Y+Height-1);
		  CsrX = X+textwidth("A")/2-1;
		  CsrY = Y+textheight("A")/2;
		  for (Indx = 0; Indx < (Width/textwidth("A"))* (Height/textheight("A")) ; ++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx) = (char)0x00;
		    (AtrBuf+CurScrn+Indx)->Bkg = BkgClr;
		   }
		  mouse.show();
		 }
		else if (atoi(STR+2) == 1)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,Y,X+Width-1,CsrY+textheight("A")/2-1);
		  for (Indx = 0; Indx < (Width/textwidth("A"))* (((CsrY-Y)+textheight("A")/2)/textheight("A")) ; ++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx) = (char)0x00;
		    (AtrBuf+CurScrn+Indx)->Bkg = BkgClr;
		   }
		  mouse.show();
		 }
		else //if (atoi(STR+2) == 0)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,CsrY-textheight("A")/2,X+Width-1,Y+Height-1);
		  for (Indx = ((Width/textwidth("A"))* (((CsrY-Y)-textheight("A")/2)/textheight("A"))) ; Indx < ((Width/textwidth("A"))* (Height/textheight("A"))) ; ++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx) = (char)0x00;
		    (AtrBuf+CurScrn+Indx)->Bkg = BkgClr;
		   }
		  mouse.show();
		 }
		break;
      case 'K': if (atoi(STR+2) == 2)
		 {
		  mouse.hide();
		  CsrX = X+textwidth("A")/2-1;
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,CsrY-textheight("A")/2,X+Width-1,CsrY+textheight("A")/2-1);
		  for (Indx =0; Indx < (Width/textwidth("A"));++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
		    *((char *)(AtrBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))) = 0x00;
		   }
		  mouse.show();
		 }
		else if (atoi(STR+2) == 1)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X,CsrY-textheight("A")/2,X+CsrX+textwidth("A")/2,CsrY+textheight("A")/2-1);
		  for (Indx =0; Indx <= ((CsrX-X)/textwidth("A")) ;++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
		    *((char *)(AtrBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))) = 0x00;
		   }
		  mouse.show();
		 }
		else //if (atoi(STR+2) == 0)
		 {
		  mouse.hide();
		  setcolor(BkgClr);
		  setfillstyle(SOLID_FILL,BkgClr);
		  bar(X+CsrX+textwidth("A")/2+1,CsrY-textheight("A")/2,X+Width-1,CsrY+textheight("A")/2-1);
		  for (Indx =((CsrX-X)/textwidth("A")) ; Indx < (Width/textwidth("A"));++Indx)
		   {
		    *(TxtBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
		    *((char *)(AtrBuf+CurScrn+Indx+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))) = 0x00;
		   }
		  mouse.show();
		 }
		break;
      case 'm': attrib = atoi(STR+2);
		if (attrib == 0)
		 {
		  Bold = 0;
		  TxtClr = LIGHTGRAY;
		  BkgClr = BLACK;
		 }
		else if (attrib == 1)
		 {
		  Bold = 1;
		  if (TxtClr == LIGHTGRAY)
		   TxtClr = WHITE;
		 }
		else if (attrib == 7)
		 {
		  TxtClr = BLACK;
		  BkgClr = LIGHTGRAY+8*Bold;
		 }
		break;
     }
   }
  else if ((STR[0] == 27) && (isalpha(STR[1])))
   {

   }
  else
   Print_Char(STR[0]);
  move_csr();
 }

void textplane::Print_Char(char c)  // Displays the character on the screen.
 {
  char S[2];
  int Indx, i;

  S[0] = c;
  S[1] = 0x00;
  int orig_color;                         // Store original screen settings,
  struct fillsettingstype orig_settings;  // So we can fet them back later.
  struct linesettingstype orig_line;
  struct textsettingstype textinfo;
  unsigned long istr;
  
  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  gettextsettings(&textinfo);
  setlinestyle(0,1,0);
  switch ((int) S[0])  // If it isn't a control sequence, translate and print it.
   {

    case 10: CsrY += textheight("Aj");
	     break;
    case 13: CsrX = X+textwidth("A")/2-1;
	     break;
    case 9:  CsrX += 5*textwidth("A")-1;
	     break;
    case 8:  if (CsrX >X+textwidth("A")/2+1)
	      {
	       mouse.hide();
	       CsrX -= textwidth("A");
	       setcolor(BkgClr);
	       setfillstyle(SOLID_FILL,BkgClr);
	       bar (CsrX-textwidth("A")/2+1,CsrY-textheight("A")/2,
		    CsrX+textwidth("A")/2,CsrY+textheight("A")/2-1);
	       *(TxtBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
	       (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Fgd = TxtClr;
	       (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Bkg = BkgClr;
	       mouse.show();
	      }
	     break;
    case 127:mouse.hide();
	     setcolor(BkgClr);
	     setfillstyle(SOLID_FILL,BkgClr);
	     bar (CsrX-textwidth("A")/2+1,CsrY-textheight("A")/2,
		  CsrX+textwidth("A")/2,CsrY+textheight("A")/2-1);
	     *(TxtBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = 0x00;
	     (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Fgd = TxtClr;
	     (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Bkg = BkgClr;
	     mouse.show();
	     break;
    default: setcolor(BkgClr);
	     setfillstyle(SOLID_FILL,BkgClr);
	     mouse.hide();
	     bar (CsrX-textwidth("A")/2+1,CsrY-textheight("A")/2,
		  CsrX+textwidth("A")/2,CsrY+textheight("A")/2-1);
	     setcolor(TxtClr);
	     settextjustify(CENTER_TEXT,CENTER_TEXT);
	     outtextxy(CsrX,CsrY,S);
	     *(TxtBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A"))) = S[0];
	     (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Fgd = TxtClr;
	     (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Bkg = BkgClr;
	     mouse.show();
	     CsrX += textwidth("A");
	     break;
   }
  if (CsrX >= X+Width-textwidth("A")/2)
   {
    CsrX = X+textwidth("A")/2-1;
    CsrY += textheight("Aj");
   }
  if (CsrY > Y+Height- textheight("Aj")/2)
   {
    mouse.hide();
    setcolor(DefBkgClr);
    setfillstyle(SOLID_FILL,DefBkgClr);
    CurScrn += ((Width/textwidth("A"))*((Height/textheight("A"))/2));
    if (CurScrn >= SBBSize-((Width/textwidth("A"))*((Height/textheight("A"))/2))-(SBBSize%((Width/textwidth("A"))*((Height/textheight("A"))/2))))
     {
      for (istr = 0; istr < SBBSize-(Width/textwidth("A"))*((Height/textheight("A"))/2); ++ istr)
       {
	*(TxtBuf+istr) = *(TxtBuf+(Width/textwidth("A"))*((Height/textheight("A"))/2)+istr);
	*((char far *)AtrBuf+istr) = *((char far *)AtrBuf+(Width/textwidth("A"))*((Height/textheight("A"))/2)+istr);
       }
      for (istr = 0; istr < ((Width/textwidth("A"))*((Height/textheight("A"))/2)); ++istr)
       {
	*((char far *)AtrBuf+SBBSize-(Width/textwidth("A"))*((Height/textheight("A"))/2)+istr) = 0x00;
	*(TxtBuf+SBBSize-(Width/textwidth("A"))*((Height/textheight("A"))/2)+istr) = 0x00;
       }
      CurScrn -= ((Width/textwidth("A"))*((Height/textheight("A"))/2));
     }
    drawscrn((TxtBuf+CurScrn),(AtrBuf+CurScrn),(Height/textheight("A")));
    CsrY = Y+((Height/textheight("A"))/2+((Height/textheight("A"))%2 == 1))*textheight("A")+textheight("A")/2;
    mouse.show();
   }
  move_csr();
  settextjustify(textinfo.horiz,textinfo.vert); //   Reset various screen parameters
  setcolor(orig_color);                         // that we may have changed here.
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
 }

textplane::textplane(int x, int y, int w, int h, int tc, int bc)
 : gbase(x,y,w,h,0)
 {
  OldX = SavX = CsrX = x+textwidth("A")/2-1;
  OldY = SavY = CsrY = y+textheight("A")/2;
  DefBkgClr = BkgClr = bc;
  TxtClr = tc;
  TermEm = 3;
  Echo = Bold = 0;
  STR[0]=0x00;
  SIndex = REscSeq = 0;
  Buffer = NULL;
  SBBSize = (Width/textwidth("A"))*(Height/textheight("A"));
  CurScrn = 0;
  ShowCsr = 0;
  CsrShwn = 0;
  TxtBuf = (char far *)farcalloc(SBBSize,1);
  AtrBuf = (attr far *)farcalloc(SBBSize,1);
  move_csr();
  if ((!TxtBuf) || (!AtrBuf))
   {
    closegraph();
    cerr << "Memory allocatin error in scrollback buffer in textplane."<<endl;
    if (TxtBuf)
     free(TxtBuf);
    else
     free (AtrBuf);
    exit(1);
   }
 }

textplane::~textplane()
 {
  if (Buffer)
   farfree(Buffer);
  if (TxtBuf)
   farfree(TxtBuf);
  if (AtrBuf)
   farfree(AtrBuf);
 }
int textplane::setbuffsize(unsigned size)
 {
  char *NewTxtBuf;
  attr *NewAtrBuf;

  if (size < (Width/textwidth("A"))*(Height/textheight("A")))
   size =(Width/textwidth("A"))*(Height/textheight("A"));
  if (size % (Width/textwidth("A"))*(Height/textheight("A")))
   size -= (size%(Width/textwidth("A"))*(Height/textheight("A")));
  NewTxtBuf = (char far *)farcalloc(size,1);
  NewAtrBuf = (attr far *)farcalloc(size,1);
  if ((!NewTxtBuf) || (!NewAtrBuf))
   {
    if (NewTxtBuf)
     farfree (NewTxtBuf);
    if (NewAtrBuf)
     farfree (NewAtrBuf);
    return 0;
   }
  _fmemcpy(NewTxtBuf,TxtBuf,((size > SBBSize) ? SBBSize : size));
  _fmemcpy(NewAtrBuf,AtrBuf,((size > SBBSize) ? SBBSize : size));
  farfree(TxtBuf);
  farfree(AtrBuf);
  TxtBuf = NewTxtBuf;
  AtrBuf = NewAtrBuf;
  SBBSize = size;
  return 1;
 }

void textplane::show()
 {
  mouse.hide();
  if (Buffer)
   {
    putimage(X,Y,Buffer,COPY_PUT);
    farfree(Buffer);
    Buffer = NULL;
   }
  else
   {
    int orig_color;                         // Store original screen settings,
    struct fillsettingstype orig_settings;  // So we can fet them back later.
    struct linesettingstype orig_line;

    orig_color=getcolor();
    getfillsettings(&orig_settings);
    getlinesettings(&orig_line);
    setlinestyle(0,1,0);
    setcolor(BkgClr);
    setfillstyle(SOLID_FILL,BkgClr);
    bar(X,Y,X+Width-1,Y+Height-1);
    setcolor(orig_color);                         // that we may have changed here.
    setfillstyle(orig_settings.pattern, orig_settings.color);
    setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
   }
  STR[0] = 0x00;
  SIndex = REscSeq = 0;
  isShown = 1;
  move_csr();
  mouse.show();
 }

void textplane::drawscrn(char far *Buffer,attr far *AtrBuf,int lines)
 {
  int  i,
       j,
       Cx,
       Cy;
  char C[2] = {0x00,0x00};

  mouse.hide();
  for (i = 0; i < lines; ++i)
   for (j=0; j<(Width/textwidth("A")); ++j)
     {
      setcolor((AtrBuf+i*(Width/textwidth("A"))+j)->Bkg);
      setfillstyle(SOLID_FILL,(AtrBuf+i*(Width/textwidth("A"))+j)->Bkg);
      bar (j*textwidth("A")+X-1,i*textheight("A")+Y,
	   (j+1)*textwidth("A")+X-1,(i+1)*textheight("A")+Y-1);
      setcolor((AtrBuf+i*(Width/textwidth("A"))+j)->Fgd);
      settextjustify(CENTER_TEXT,CENTER_TEXT);
      Cx = j*textwidth("A")+X+textwidth("A")/2-1;
      Cy = i*textheight("A")+Y+textheight("A")/2;
      *C  = *(Buffer+i*(Width/textwidth("A"))+j);
      if (*C != (char)0x00)
       outtextxy(Cx,Cy,C);
     }
  mouse.show();
 }

void textplane::hide()
 {
  long int imgsize;

  if (Buffer)
   delete Buffer;
  imgsize = imagesize(X,Y,X+Width-1, Y+Height-1);
  Buffer = (char *)farmalloc(imgsize);
  if (!Buffer)
   {
    closegraph();
    cerr << "Error allocating memory in textplane::hide."<<endl;
    exit(1);
   }
  int orig_color;                         // Store original screen settings,
  struct fillsettingstype orig_settings;  // So we can fet them back later.
  struct linesettingstype orig_line;

  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  setlinestyle(0,1,0);
  mouse.hide();
  getimage (X,Y,X+Width-1,Y+Height+1,Buffer);
  isShown = 0;
  setcolor(DefBkgClr);
  setfillstyle(SOLID_FILL,DefBkgClr);
  bar (X,Y,X=Width-1,Y+Height-1);
  STR[0] = 0x00;
  SIndex = REscSeq = 0;
  setcolor(orig_color);                         // that we may have changed here.
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
  mouse.show();
 }

void textplane::settxtclr(int c)            // Set the text color.
 {
  TxtClr = c;
 }

void textplane::setbkgclr(int c)            // Set the background color.
 {
  DefBkgClr = BkgClr = c;
 }

void textplane::gotoxy(int x, int y)        // Move the cursor to x,y (in pixels).
 {
  CsrY = (textheight("A") * y)+Y+textheight("A")/2;
  CsrX = (textwidth("A") * x)+X+textwidth("A")/2-1;
  while (CsrX > (X+Width - textwidth("A")/2))
   CsrX -= textwidth("A");
  while (CsrY > (Y+Height-textheight("A")/2))
   CsrY -= textheight("A");
  move_csr();
 }

void textplane::move_csr(void)
 {
  char FgChar,
       C[3]={0x00,0x00,0x00};
  int  FgClr,
       BkClr;

  mouse.hide();
  if (CsrShwn)
   {
    FgChar = *(TxtBuf+CurScrn+(OldX-X)/textwidth("A")+(OldY-Y)/textheight("A")*(Width/textwidth("A")));
    FgClr =   (AtrBuf+CurScrn+(OldX-X)/textwidth("A")+(OldY-Y)/textheight("A")*(Width/textwidth("A")))->Fgd;
    BkClr =   (AtrBuf+CurScrn+(OldX-X)/textwidth("A")+(OldY-Y)/textheight("A")*(Width/textwidth("A")))->Bkg;
    setcolor(BkClr);
    setfillstyle(SOLID_FILL,BkClr);
    bar (OldX-textwidth("A")/2+1,OldY-textheight("A")/2,
	 OldX+textwidth("A")/2,OldY+textheight("A")/2-1);
    setcolor(FgClr);
    settextjustify(CENTER_TEXT,CENTER_TEXT);
    C[0] = FgChar;
    outtextxy(OldX,OldY,C);
    CsrShwn = 0;
   }
  if (ShowCsr)
   {
    FgChar = *(TxtBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")));
    FgClr =   (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Fgd;
    BkClr =   (AtrBuf+CurScrn+(CsrX-X)/textwidth("A")+(CsrY-Y)/textheight("A")*(Width/textwidth("A")))->Bkg;
    BkClr = (BkClr >= 7) ? BLACK : WHITE;
    FgClr = (BkClr == WHITE) ? BLACK : WHITE;
    setcolor(BkClr);
    setfillstyle(SOLID_FILL,BkClr);
    bar (CsrX-textwidth("A")/2+1,CsrY-textheight("A")/2,
	 CsrX+textwidth("A")/2,CsrY+textheight("A")/2-1);
    setcolor(FgClr);
    settextjustify(CENTER_TEXT,CENTER_TEXT);
    C[0] = FgChar;
    outtextxy(CsrX,CsrY,C);
    CsrShwn = 1;
    OldX = CsrX;
    OldY = CsrY;
   }
  mouse.show();
 }

void textplane::setcsr(int F)
 {
  ShowCsr = (F != 0);
 }

void textplane::settermem(int t)            // Sets the terminal emulation. (ANSI, VT100, ASCII)
 {
  switch (t)
   {
    case 1: TermEm = 1; break;  // Ansi Emulation.
    case 2: TermEm = 2; break;  // VT100 Emulation.
    case 3:
    default: TermEm = 3; break; // Straight ASCII.
   }
  TxtClr = LIGHTGRAY;
  BkgClr = BLACK;
  STR[0] = 0x00;
  SIndex = REscSeq = 0;
 }

void textplane::clearwin(void)              // Clears the textplane to the background color.
 {
  int Indx;
  int orig_color;                         // Store original screen settings,
  struct fillsettingstype orig_settings;  // So we can fet them back later.
  struct linesettingstype orig_line;

  mouse.hide();
  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  setlinestyle(0,1,0);
  setcolor (BkgClr);
  setfillstyle(SOLID_FILL,BkgClr);
  bar (X,Y,X+Width-1,Y+Height-1);
  setcolor(orig_color);                         // that we may have changed here.
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
  for (Indx = 0; Indx < (Width/textwidth("A"))* (Height/textheight("A")) ; ++Indx)
   {
    *(TxtBuf+Indx) = (char) 0x00;
    *((char *)(AtrBuf+Indx)) = (char) 0x00;
   }
  mouse.show();
 }

char textplane::peek()
 {
  char c;

  c = getkey();
  putbk(c);
  return ((char)(c & 0xff));
 }

textplane &textplane::operator << (char &c)
 {
  switch (TermEm)
   {
    case 1: ANSI_Decode(c); break;
    case 2: VT100_Decode(c); break;
    case 3: Print_Char(c); break;
   }
  return *this;
 }

textplane &textplane::operator << (char *c)
 {
  for (int i=0; i < strlen(c); ++i)
   operator <<( (char) *(c+i) );
  return *this;
 }

textplane &textplane::operator << (int &I)
 {
  char Strn[10];

  itoa(I,Strn,10);
  operator <<(Strn);
  return *this;
 }

textplane &textplane::operator << (long &L)
 {
  char Strn[15];

  ltoa(L,Strn,10);
  operator <<(Strn);
  return *this;
 }

textplane &textplane::operator << (double &D)
 {
  char Strn[10];

  gcvt(D,7,Strn);
  operator <<(Strn);
  return *this;
 }

textplane &textplane::operator >> (char &c)
 {
  if (keyhit())
   {
    c = (char)(getkey() & 0xff);
    if (Echo)
     operator <<(c);
   }
  return *this;
 }

textplane &textplane::operator >> (char *C)
 {
  char inchar;
  int index = 0;

  while (isspace(peek()))
   operator >> (inchar);       // Skip leading whitespace.
  while (!(isspace(peek())))
   {
    operator >> (inchar);      // Get characters until whitespace.
    *(C+index++) = inchar;
   }
  *(C+index) = 0x00;           // Null terminate end of string.
  return *this;
 }

textplane &textplane::operator >> (int &I)
 {
  char inchar, C[9];
  int index=0;

  while (isspace(peek()))      // Skip leading whitespace.
   operator >> (inchar);
  if ((peek() == '+') || (peek() == '-')) // Get sign character.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  while ((isdigit(peek())) && (index < 8))// Get characters until no more digits.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  *(C+index) = 0x00;           // Null terminate end of string.
  I =atoi(C);                  // Convert it to an int.
  return *this;
 }

textplane &textplane::operator >> (long &L)
 {
  char inchar, C[16];
  int index=0;

  while (isspace(peek()))      // Skip leading whitespace.
   operator >> (inchar);
  if ((peek() == '+') || (peek() == '-'))  // Get sign character.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  while ((isdigit(peek())) && (index <15)) // Get characters until no more digits.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  *(C+index) = 0x00;           // Null terminate end of string.
  L =atol(C);                  // Convert it to a long.
  return *this;
 }

textplane &textplane::operator >> (double &D)
 {
  char inchar, C[30], *endptr;
  int index=0;

  while (isspace(peek()))      // Skip leading whitespace.
   operator >> (inchar);
  if ((peek() == '+') || (peek() == '-'))  // Get sign character.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  while (((isdigit(peek())) || (peek() == '.') || (peek() == 'e') ||
	 (peek() == 'E') || (peek() == '+') || (peek() == '-')) && (index <29)) // Get characters until no more digits.
   {
    operator >> (inchar);
    *(C+index++) = inchar;
   }
  *(C+index) = 0x00;           // Null terminate end of string.
  D =strtol(C, &endptr, 10);  // Convert it to a double.
  return *this;
 }

char *textplane::gettxt(void)               // returns a copy of the screen text buffer.
 {
  return (TxtBuf);
 }

char *textplane::getatr(void)
 {
  return ((char *)AtrBuf);
 }

unsigned textplane::getscrnptr(void)
 {
  return CurScrn;
 }

unsigned textplane::getbufsize(void)
 {
  return SBBSize;
 }

selectbar::selectbar(int x, int y, int w, char *Lst, int bw, int h, int c, int bc, int k)
 : instrn (x,y,w,h,1,c,k)
 {
  char Dn[3] = {23,0,0};
  int Error = 0,
      slen;

  pulled_down = 0;
  itm_selected = 0;
  BW = bw;
  Hi_Clr = LIGHTRED;
  slen = strlen(Lst);
  List = (char *)calloc(1,slen+1);
  if (List != NULL)
   {
	 strncpy(List,Lst,slen);
	 num_itms = 1;
	 for (int i=0;*(List+i) != 0x00; ++i)
	  if (*(List+i) == ',')
		++num_itms;
	}
  else
	Error = 1;
  DnBtn = new button(x+w+4,y+1,bw,h-2,1,bc,1,TEXT,Dn,k);
  if (!DnBtn)
	Error = 1;
  PlDn = new panel(x,y+h+2,w,num_itms*(textheight("Aj")+2)+2,1,IN,c,1);
  if (!PlDn)
	Error = 1;
  if (Error)
	{
	 if (List)
	  free(List);
	 if (DnBtn)
	  delete DnBtn;
	 if (PlDn)
	  delete PlDn;
	 closegraph();
	 cerr << "Memory allocation error in selectbar::selectbar()" << endl;
	 exit(-1);
	}
 }

selectbar::~selectbar(void)
  {
	if (PlDn)
	 delete PlDn;
	if (DnBtn)
	 delete DnBtn;
	if (List)
	 free (List);
  }

void selectbar::show(void)
 {
  instrn::show();
  DnBtn->show();
  if (pulled_down)
	PlDn->hide();
  pulled_down = 0;
 }

/*void selectbar::newlist(char *Lst)
 {
  if (List)
	free(List);
  List = (char *)calloc(1,strlen(Lst)+1);
  if (List != NULL)
	{
	 strcpy(List,Lst);
	 num_itms = 1;
	 for (int i=0;*(List+i) != 0x00; ++i)
	  if (*(List+i) == ',')
		++num_itms;
	}
  else
	Error = 1;
  if (PlDn)
	delete PlDn;
  PlDn = new panel(x,y+h+2,w,num_itms*(textheight("Aj")+2)+2,1,IN,c,1);
  if (!PlDn)
	Error = 1;
  if (Error)
	{
	 if (List)
	  free(List);
	 if (PlDn)
	  delete PlDn;
	 closegraph();
	 cerr << "Memory allocation error in selectbar::newlist()" << endl;
	 exit(-1);
	}
 }*/

void selectbar::hide(void)
 {
  instrn::hide();
  DnBtn->hide();
  if (pulled_down)
	PlDn->hide();
  pulled_down = 0;
 }

char *selectbar::inptstrn()
 {
  return instrn::getinput();
 }

char *selectbar::getinput()
 {
  char *Temp,
       *Temp2;
  int Key,
      Itm;

  while(1)
	{
	 Temp = instrn::getinput();
	 if ((lastkey() == 0x50) || btnhit())
	  {
	   push();
	   while(mouse.btnpressed() && btnhit())
	    ;
	   rels();
	   pulldown();
	   if (lastkey() == 0x50)
	    selitem(1);
	   while(1)
	    {
	if ((!btnhit()) && DnBtn->is_selected())
	 rels();
	if (mouse.getbutton(LEFT_BTN))
	 {
	  while (mouse.getbutton(LEFT_BTN))
	   {
	    if (btnhit() && (!DnBtn->is_selected()))
	     push();
	    if ((!btnhit()) && DnBtn->is_selected())
	     rels();
	    if (itmhit())
	     {
	      if (itmhit() != itmselected())
	       {
		clritem();
		selitem(itmhit());
	       }
	     }
	    if (!pnlhit() && !btnhit() && pulled_down)
	     {
	      rels();
	      pushup();
	      break;
	     }
	   }
	  if (itmhit())
	   {
	    Temp2 = getitem();
	    preset(Temp2);
	    free(Temp2);
	    instrn::show();
	    pushup();
	    break;
	   }
	  else if (btnhit())
	   rels();
	  else
	   {
	    pushup();
	    break;
	   }
	 }
	if (keyhit())
	 {
	  Key = getkey();
	  if (Key == 336) // Down Arrow
		{
		 Itm = itmselected();
		 clritem();
		 Itm = (Itm < num_itms) ? Itm+1 : num_itms;
		 selitem(Itm);
		}
	  if (Key == 328) // Up Arrow
		{
		 Itm = itmselected();
		 clritem();
		 Itm = (Itm > 1) ? Itm-1 : 1;
		 selitem(Itm);
		}
	  if (Key == 13)
		{
		 Temp2 = getitem();
		 preset(Temp2);
		 free(Temp2);
		 instrn::show();
		 pushup();
		 break;
	   }
	  if (Key == 27)
	   {
	    pushup();
	    break;
	   }
	 }
       }
     }
    else
     break;
   }
  return Temp;
 }

void selectbar::pulldown(void)
 {
  int i,
      l,
      h;
  char *Tmp;

  mouse.hide();
  PlDn->show();
  setcolor(TxtColor);
  settextjustify(LEFT_TEXT,CENTER_TEXT);
  itm_selected = 0;
  h = Y+Height+3+textheight("Aj")/2;
  for (i=0, l=0; *(List+i) != 0x00;)
   {
    i = find_char(List,',',l);
    outtextxy(X+4,h,(Tmp = mids(List,l,i-l)));
    free(Tmp);
    l=i+1;
	 h += textheight("Aj")+2;
   }
  pulled_down = 1;
  mouse.show();
 }

void selectbar::pushup(void)
 {
  if (pulled_down)
   PlDn->hide();
  pulled_down = 0;
 }

void selectbar::push(void)
 {
  DnBtn->select();
 }

void selectbar::rels(void)
 {
  DnBtn->show();
 }

void selectbar::selitem (int itm)
 {
  int h;
  char *Tmp;

  if (!((itm > 0) && (itm <= num_itms)))
   return;
  mouse.hide();
  itm_selected = itm;
  h = Y+Height+2+(textheight("Aj")+2)*(itm-1);
  setcolor(Hi_Clr);
  setfillstyle(SOLID_FILL,Hi_Clr);
  bar(X+3,h,X+Width-4,h+textheight("Aj")+1);
  setcolor(TxtColor);
  settextjustify(LEFT_TEXT,CENTER_TEXT);
  outtextxy(X+4,h+textheight("Aj")/2+1,(Tmp = getitem()));
  free(Tmp);
  mouse.show();
 }

void selectbar::clritem (void)
 {
  pulldown();
 }

int selectbar::itmselected(void)
 {
  return itm_selected;
 }

char *selectbar::getitem(void)
 {
  int Cnt = 0,
      i = 0,
      l = 0;

  for (i=0,l=0; *(List+i) != 0x00;l=i+1)
   {
    i = find_char(List,',',l);
    if (++Cnt == itm_selected)
     break;
   }
  if (l < i)
   return (mids(List,l,i-l));
  return NULL;
 }

int  selectbar::itmhit(void)
 {
  int itm = 0;

  if (pulled_down)
   if (PlDn->hit())
    itm = ((mouse.getmY()-(Y+Height)-2) / (textheight("Aj")+2))+1;
  if ((itm <0) || (itm > num_itms))
   return 0;
  return itm;
 }

int  selectbar::btnhit(void)
 {
  return DnBtn->hit();
 }

int  selectbar::pnlhit(void)
 {
  return PlDn->hit();
 }

void selectbar::setbtnclr(int c)
 {
  DnBtn->setextclr(c);
 }

void selectbar::setbkgclr(int c)
 {
  instrn::setbkgclr(c);
  PlDn->setbkgclr(c);
 }

void selectbar::sethiclr(int c)
 {
  Hi_Clr = c;
 }

void selectbar::moveto (int x, int y)
 {
  instrn::moveto(x,y);
  PlDn->moveto(x,y+Height);
  DnBtn->moveto(x+Width+2,y+1);
 }

void selectbar::resize(int w, int h)
 {
  instrn::resize(w,h);
  PlDn->moveto(X,Y+Height+2);
  PlDn->resize(w,num_itms*(textheight("Aj")+2));
  DnBtn->moveto(X+Width+4,Y+1);
  DnBtn->resize(BW,h);
 }

int find_char (char *str, char fnd, int begin)
 {
  int i;

  for (i= begin; *(str+i) != '\0' ;++i)
   {
    if ( *(str+i) == fnd )
     break;
   }
  if (!(*(str+i) == '\0'))
   return i;
  else
   return strlen(str);
 }

int find_char2 (char *str, char fnd, int begin)
 {
  int i;

  for (i= begin; *(str+i) != '\0' ;++i)
   {
    if ( *(str+i) == fnd )
     break;
   }
  if (!(*(str+i) == '\0'))
   return i;
  else
   return -1;
 }

char *mids(char *Str, int beg, int cnt)
 {
  int i;
  char *target;

  target =(char *)malloc(cnt+1);
  if (target != NULL)
   {
    for (i=0; i< cnt; ++i)
     *(target+i) = *(Str+i+beg);
    *(target+i) = '\0';
   }
  else
   {
    closegraph();
    cerr << "Memory allocation error in:  char *mids(char *, int, int)."<<endl;
    exit (-1);
	}
  return target;
 }

wndow::wndow(int x,int y,int w,int h,int d,int bw,char *caption, int k)
		 : bevel(x,y,w,h,d,bw,7,k)
 {
  int caplen;

  Caption = NULL;
  cl_button = NULL;
  cap_panl = NULL;
  Client_Clr = 7;
  Txt_Clr = 15;
  cl_button = new button(x+d+1,y+d+1,9,9,d,7,1,TEXT,"",0);
  if (!cl_button)
	{
	 closegraph();
	 cerr << "Memory allocation error in window::window" << endl;
	 exit(-1);
	}
  cap_panl = new panel(x+3*d+11,y+d,w-4*d-11,11,d,OUT,7,0);
  if (!cap_panl)
	{
	 delete cl_button;
	 closegraph();
	 cerr << "Memory allocation error in window::window" << endl;
	 exit(-1);
	}
  caplen = strlen(caption)+2;
  Caption = (char *)farcalloc(caplen,1);
  if (!Caption)
	{
	 delete cl_button;
	 delete cap_panl;
	 closegraph();
	 cerr << "Memory allocation error in wndow::wndow" << endl;
	 exit(-1);
	}
  strncpy(Caption,caption,caplen);
 }

 wndow::~wndow()
 {
	delete cl_button;
	delete cap_panl;
	farfree(Caption);
 }

void wndow::show(void)
 {
  char temp[80];
  int size,
		i,
		orig_color;
  struct textsettingstype textinfo;
  struct fillsettingstype orig_settings;
  struct linesettingstype orig_line;


  if (isShown)
	return;
  mouse.hide();
  bevel::show();
  cl_button->show();
  cap_panl->show();
  orig_color=getcolor();
  getfillsettings(&orig_settings);
  getlinesettings(&orig_line);
  gettextsettings(&textinfo);
  setlinestyle(0,1,1);
  setcolor(Client_Clr);
  setfillstyle(SOLID_FILL,Client_Clr);
  bar(X+2*Depth+BWidth,Y+6*Depth+2*BWidth+10,X+Width-2*Depth-BWidth-1,Y+Height-2*Depth-BWidth-1);
  setcolor((Color+8 > 15) ? 15 : Color+8);
  for (i=0; i< Depth; ++i)
	line(X+Depth+BWidth+(Depth-1-i),Y+4*Depth+BWidth+11+i,X+Width-Depth-BWidth-(Depth-1-i)-1,Y+4*Depth+BWidth+11+i);
  setcolor(Color);
  for (i=0; i< BWidth; ++i)
	line(X+Depth+BWidth,Y+5*Depth+BWidth+11+i,X+Width-Depth-BWidth,Y+5*Depth+BWidth+11+i);
  setcolor((Color >8) ? Color-8 : DARKGRAY);
  for (i=0; i< Depth; ++i)
	line(X+Depth+BWidth+i,Y+5*Depth+2*BWidth+11+i,X+Width-Depth-BWidth-i-1,Y+5*Depth+2*BWidth+11+i);
  memset(temp,0,80);
  settextjustify(CENTER_TEXT,CENTER_TEXT);
  setcolor(Txt_Clr);
  strncpy(temp,Caption,79);
  outtextxy(X+3*Depth+BWidth+13+(Width-8*Depth-2*BWidth-10)/2,Y+3*Depth+BWidth+6,temp);
  settextjustify(textinfo.horiz,textinfo.vert);
  setcolor(orig_color);
  setfillstyle(orig_settings.pattern, orig_settings.color);
  setlinestyle(orig_line.linestyle, orig_line.upattern, orig_line.thickness);
  mouse.show();
  return;
 }

void wndow::moveto(int x, int y)
 {
  int reshow = 0;

  if(isShown)
	{
	 hide();
	 reshow = 1;
	}
  bevel::moveto(x,y);
  cl_button->moveto(x+Depth+1,y+Depth+1);
  cap_panl->moveto(x+3*Depth+10,y+Depth);
  if (reshow)
	show();
 }

void wndow::resize(int w, int h)
 {
  int reshow = 0;

  if(isShown)
	{
	 hide();
	 reshow = 1;
	}
  bevel::resize(w,h);
  cl_button->moveto(X+3*Depth+BWidth+1,Y+3*Depth+BWidth+1);
  cap_panl->moveto(X+5*Depth+BWidth+10,Y+3*Depth+BWidth);
  cap_panl->resize(w-4*Depth-10,10);
  if (reshow)
	show();
 }

void wndow::setbkgclr(int c)
 {
  int reshow = 0;

  if(isShown)
	{
	 hide();
	 reshow = 1;
	}
  bevel::setbkgclr(c);
  if (reshow)
	show();
 }

void wndow::setcliclr(int c)
 {
  int orig_color;
  struct textsettingstype textinfo;
  struct fillsettingstype orig_settings;
  struct linesettingstype orig_line;

  Client_Clr = c;
  if(isShown)
   {
    orig_color=getcolor();
    getfillsettings(&orig_settings);
    setcolor(Client_Clr);
    setfillstyle(SOLID_FILL,Client_Clr);
	 bar(X+2*Depth+BWidth,Y+6*Depth+2*BWidth+10,X+Width-2*Depth-BWidth,Y+Height-2*Depth-BWidth);
    setcolor(orig_color);
    setfillstyle(orig_settings.pattern, orig_settings.color);
   }
 }

void wndow::setcapclr(int c)
 {
  char temp[80];
  int size,
		orig_color;
  struct textsettingstype textinfo;

  cap_panl->setbkgclr(c);
  if(isShown)
	{
	 orig_color=getcolor();
	 gettextsettings(&textinfo);
	 cap_panl->show();
	 memset(temp,0,80);
	 settextjustify(CENTER_TEXT,CENTER_TEXT);
	 setcolor(Txt_Clr);
	 strncpy(temp,Caption,79);
	 outtextxy(X+3*Depth+BWidth+13+(Width-8*Depth-2*BWidth-10)/2,Y+3*Depth+BWidth+6,temp);
	 settextjustify(textinfo.horiz,textinfo.vert);
	 setcolor(orig_color);
	}
 }

void wndow::settxtclr(int c)
 {
  char temp[200];
  int size,
		orig_color;
  struct textsettingstype textinfo;

  Txt_Clr = c;
  if(isShown)
	{
	 orig_color=getcolor();
	 gettextsettings(&textinfo);
	 cap_panl->show();
	 memset(temp,0,200);
	 settextjustify(CENTER_TEXT,CENTER_TEXT);
	 setcolor(Txt_Clr);
	 strncpy(temp,Caption,199);
	 outtextxy(X+3*Depth+BWidth+13+(Width-8*Depth-2*BWidth-10)/2,Y+3*Depth+BWidth+6,temp);
	 settextjustify(textinfo.horiz,textinfo.vert);
	 setcolor(orig_color);
	}
 }

int wndow::clbtnhit(void)
 {
  return (cl_button->hit());
 }

int wndow::capbarhit(void)
 {
  return(cap_panl->hit());
 }

void wndow::clbtnprs(void)
 {
  cl_button->select();
 }

void wndow::clbtnrls(void)
 {
  cl_button->show();
 }

int wndow::clbtnpressed(void)
 {
  return(cl_button->is_selected());
 }