/*				console.c			      */
/*Contains routines that interact with the console.device (generally) */

#include "globals.h"

void WriteConsole(Buffer,Length)   /*Write a string to the console*/
char *Buffer;
int Length;
{
   consoleWriteMsg->io_Command=CMD_WRITE;
   consoleWriteMsg->io_Data=(char *)Buffer;
   consoleWriteMsg->io_Length=Length;
   DoIO(consoleWriteMsg);
}

void JumpToTop() /*Jump to top of outline*/
{
   FirstScrnItem=CurrentItem=(struct LineItem *)FirstItem;
   PrintItemList(CurrentItem,1);
   PlotCursor(MinX(CurrentItem),1);
}

void JumpToBottom() /*Jump to bottom of outline*/
{
   struct LineItem *Item;
   int c;

   CurrentItem=(struct LineItem *)LastItem;
   for(c=0,Item=(struct LineItem *)LastItem;Item!=FirstItem &&
	 c < SCRNHEIGHT-1;Item=(struct LineItem *)Item->PrevItem,c++);
   FirstScrnItem=(struct LineItem *)Item;
   PrintItemList(FirstScrnItem,1);
   PlotCursor(MinX(CurrentItem),DispRows);
}

void PrintItem(Item)   /*Print an item at the current Y location*/
struct LineItem *Item;
{
   char ConsoleBuffer[256];
   SHORT maxlen;

   ConsoleBuffer[0]=CSI;
   ConsoleBuffer[1]=0x4b;
   ConsoleBuffer[2]=NULL;

   GetOutlineChars(Item,ConsoleBuffer);
   strcat(ConsoleBuffer,"  ");
   strcat(ConsoleBuffer,Item->Text);
   maxlen=strlen(Item->Text)-MaxLen(Item->Level);

   WriteConsole(ConsoleBuffer,-1);
}

void PlotCursor(x,y)      /*Plot the console cursor on the screen*/
int x,y;
{
   char Buffer[10];
   int len=1;

   Buffer[0]=CSI;
   len+=stci_d(&Buffer[1],y);
   Buffer[len]=0x3b;
   len+=stci_d(&Buffer[len+1],x);
   Buffer[len+1]=0x48;
   Buffer[len+2]=NULL;
   WriteConsole(Buffer,-1);
   CurX=x;
   CurY=y;
}

void CursorRight(Qualifier) /*Move the cursor one to the right*/
USHORT Qualifier;
{
   UBYTE TempX;
   int min;

   min=MinX(CurrentItem);
   if(ErrorInTitle)
      TitleErrorCancel();
   if(InvsMode < NOINV)
      CancelInvs();
   if(CurX >= MaxX(CurrentItem)) /*If at the end of the line*/
   {			/*move to the start of the next one*/
      TempX=CurX;
      CurX=1;
      if(!CursorDown())
	 CurX=TempX;
   }
   else
      if(Qualifier & 3) /*Handle SHIFT-cursor-right*/
	 PlotCursor(CurX+FindNextWord(&CurrentItem->Text[CurX-min]),
	       CurY);
      else
	 if(Qualifier & 8) /*Handle CTRL-cursor-right*/
	    PlotCursor(MaxX(CurrentItem),CurY); /*(end of line)*/
	 else
	    PlotCursor(CurX+1,CurY);
}

void CursorLeft(Qualifier) /*Move the cursor one to the left*/
USHORT Qualifier;
{
   UBYTE TempX;

   if(ErrorInTitle)
      TitleErrorCancel();
   if(InvsMode < NOINV)
      CancelInvs();
   if(CurX <= MinX(CurrentItem)) /*If at the beginning of the line*/
   {		     /*move to the end of the previous one*/
      TempX=CurX;
      CurX=100;
      if(!CursorUp())
	 CurX=TempX;
   }
   else
      if(Qualifier & 3) /*Handle SHIFT-cursor-left*/
	 PlotCursor(MinX(CurrentItem)+FindPrevWord(
	       CurrentItem->Text,CurX-MinX(CurrentItem)),CurY);
      else
	 if(Qualifier & 8) /*Handle CTRL-cursor-left*/
	    PlotCursor(MinX(CurrentItem),CurY);
	 else
	    PlotCursor(CurX-1,CurY);
}

FindNextWord(string)
char *string;
{
   int end;
   for(end=0;string[end] != ' ' && string[end] != NULL;end++);
   if(end==strlen(string))
      return(end);

   for(end++;string[end] ==' ' && string[end] != NULL;end++);
   return(end);
}

FindPrevWord(string,start)
char *string;
int start;
{
   int end;

   end=start;
   if(string[end]!=' ' && end > 0 && string[end-1]==' ')
      end--;

   for(;string[end-1] != ' ' && end > 0;end--);

   while(end > 0 && string[end]== ' ')
      for(end--;string[end-1] != ' ' && end > 0;end--);
   return(end);
}

void InsertChar(Text,Character,Pos)   /*Insert a char into an item*/
char *Text,Character;
int Pos;
{
   int c;

   for(c=strlen(Text);c>=Pos;c--)
      Text[c+1]=Text[c];
   Text[Pos]=Character;
}

void DeleteChar(Text,Pos)    /*Delete a char in an item*/
char *Text;
int Pos;
{
   int lim;

   for(lim=strlen(Text);Pos<lim;Pos++)
      Text[Pos]=Text[Pos+1];
}

WholeScreenDown() /*Scrolls down by an entire screen*/
{
   struct LineItem *item;
   UBYTE c,X,Y;

   item=(struct LineItem *)ScrnBtm;
   if(item->NextItem == NULL)   /*No lines after screen bottom?*/
      {  /*Move to last line*/
      CurrentItem=(struct LineItem *)LastItem;
      PlotCursor(MinX(CurrentItem),DispRows);
      return(FALSE);
      }
   /*Get the first screen item*/
   item=FirstScrnItem=(struct LineItem *)item->NextItem;
   for(c=1;(c < CurY) && (item->NextItem != NULL);c++)
      item=(struct LineItem *)item->NextItem; /*Get item at old Y*/

   CurrentItem=(struct LineItem *)item;  /*It is now the CurrentItem*/
   Y=c;     /*In case CurY is no longer possible (23 lines down)*/
   /*If CurX's old position is no longer possible*/
   /*move the cursor to the nearest possible position*/
   if(CurX < MinX(CurrentItem))
      X=MinX(CurrentItem);
   else
      if(CurX > MaxX(CurrentItem))
	 X=MaxX(CurrentItem);
      else
	 X=CurX;

   for(c=1;(c < SCRNHEIGHT-CurY) && (item->NextItem != NULL);c++)
      item=(struct LineItem *)item->NextItem; /*Find screen bottom*/
   ScrnBtm=(struct LineItem *)item;  /*Got it!*/
   DispRows=c; /*Get the number of lines*/
   PrintItemList(FirstScrnItem,1); /*Refresh the display*/
   PlotCursor(X,Y);
   return(TRUE);     /*Done!*/
}

WholeScreenUp() /*Move up one screenfull of lines*/
{
   struct LineItem *item;
   UBYTE c,X,Y;

   Y=CurY;
   item=(struct LineItem *)FirstScrnItem;
   if(item->PrevItem == NULL) /*At the top?*/
      {  /*Move cursor to first line*/
      CurrentItem=(struct LineItem *)FirstItem;
      PlotCursor(MinX(CurrentItem),1);
      return(FALSE);
      }
   for(c=0;(c<SCRNHEIGHT) & (item->PrevItem != NULL);c++)
      item=(struct LineItem *)item->PrevItem;
   FirstScrnItem=(struct LineItem *)item;
   for(c=1;(c<CurY) && (item->NextItem != NULL);c++) /*Get new CurrentItem*/
      item=(struct LineItem *)item->NextItem;
   CurrentItem=(struct LineItem *)item;

   if(CurX < MinX(CurrentItem))  /*If CurX is no longer possible*/
      X=MinX(CurrentItem);    /*get closest possible X*/
   else
      if(CurX > MaxX(CurrentItem))
	 X=MaxX(CurrentItem);
      else
	 X=CurX;
   for(;(c<SCRNHEIGHT) & (item->NextItem != NULL);c++)
      item=(struct LineItem *)item->NextItem; /*Get ScrnBtm*/
   ScrnBtm=(struct LineItem *)item;
   DispRows=c;	  /*Number of lines*/
   PrintItemList(FirstScrnItem,1); /*Refresh display*/
   PlotCursor(X,Y);
   return(TRUE); /*Done!*/
}

HandleTAB(Qualifier) /*The TAB key was pressed...*/
USHORT Qualifier;
{
   UBYTE TempY;
   CheckModified();
   if(InvsMode < NOINV)  /*Block highlighted*/
      if(Qualifier & 3) /*If SHIFT-TAB, pull out*/
	 if(InvsMode==BLOCK_DOWN)
	    PullOutBlock(StartIItem,EndIItem,InvY,TRUE);
	 else
	    PullOutBlock(EndIItem,StartIItem,EndIY,TRUE);
      else  /*otherwise, push in*/
	 if(InvsMode==BLOCK_DOWN)
	    PushInBlock(StartIItem,EndIItem,InvY,TRUE);
	 else
	    PushInBlock(EndIItem,StartIItem,EndIY,TRUE);
   else
   {
      if(CancelInvs())
	 return(FALSE);
      TempY=CurY;
      PlotCursor(1,TempY);
      if(Qualifier & 3)    /*TAB out (shift pressed)*/
	 PullOut(CurrentItem);
      else
	 PushIn(CurrentItem); /*TAB in*/
      PlotCursor(MinX(CurrentItem),TempY);
   }
}

/*~~~End of console.c*/
