/*Clipboard I/O routines*/
#include "Globals.h"

#define WCLIP_FIRST_WRITE  0
#define WCLIP_CONT_WRITE   1
#define WCLIP_LAST_WRITE   2

void SetupClipboard()  /*Setup the clipboard device*/
{
   if(OpenDevice("clipboard.device",0L,&ClipboardIO,0L)!=0)
   {
      Leave(0,"Can't open clipboard!");
      CloseWindow(Window);
      CloseScreen(Screen);
      exit(200);
   }

      /*Establish the clipboard communication port*/
   clipboardMsgPort.mp_Node.ln_Type=NT_MSGPORT;
   clipboardMsgPort.mp_Flags=0;
   clipboardMsgPort.mp_SigBit=AllocSignal(-1);
   clipboardMsgPort.mp_SigTask=(struct Task *)FindTask((char *)NULL);
   AddPort(&clipboardMsgPort);
   ClipboardIO.io_Message.mn_ReplyPort=(struct MsgPort *)&clipboardMsgPort;
}

void WriteInvsTextToClip(StartLoc,Chars,String)
int StartLoc,Chars;	/*Write a highlighted text block to clipboard*/
char *String;
{
   char WorkString[80];

   strcpy(WorkString,"");
   strcpy(WorkString,&String[StartLoc]);
   WorkString[Chars]=NULL;
   WriteStringClip(WorkString);
}

void WriteStringClip(string) /*Write a single string to the Clipboard*/
char *string;
{
   int len;

   /*Write the data, in IFF (Formatted TeXT) form*/
   WriteClip(&ClipboardIO,"FORM",4,WCLIP_FIRST_WRITE);
   len=strlen(string)+12;
   WriteClip(&ClipboardIO,&len,4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,"FTXT",4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,"CHRS",4,WCLIP_CONT_WRITE);
   len=strlen(string);
   WriteClip(&ClipboardIO,&len,4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,string,len,WCLIP_LAST_WRITE);
}

void WriteClip(ioreq,buf,bufsiz,whichone)   /*Writes a clip to the clipboard*/
register struct IOClipReq *ioreq;
char *buf;
int bufsiz;
int whichone;
{
   if(whichone==WCLIP_FIRST_WRITE)  /*First time*/
   {
      ioreq->io_Offset=0;
      ioreq->io_ClipID=0;
   }
   ioreq->io_Command=CMD_WRITE;
   ioreq->io_Data=buf;
   ioreq->io_Length=bufsiz;
   DoIO(ioreq);
   if(whichone==WCLIP_LAST_WRITE)  /*Last time, tell clipboard to make the*/
      { 			   /*data available to the system*/
      ioreq->io_Command=CMD_UPDATE;
      DoIO(ioreq);
      }
}

void ShutDownClipboard()
{
   RemPort(&clipboardMsgPort);
   CloseDevice(&ClipboardIO);
}

void ReadItemString(Start,Len,string)
int Start,Len;	  /*Read a string from the clipboard and put it into*/
char *string;	  /*the specified string*/
{
   char WorkString[160];
   char TmpString[160];
   register int c;

   strcpy(TmpString,"");
   strcpy(WorkString,"");

   ReadString(WorkString,159);
   strcpy(TmpString,string);
   TmpString[Start]=NULL;
   strcat(TmpString,WorkString);
   strncat(TmpString,&string[Start],159-strlen(TmpString));

   TmpString[159]=NULL;  /*Trundicate the inputted string*/

   for(c=0;c<159 && TmpString[c]!=NULL;c++)
      if(TmpString[c]==0x0a)
	 TmpString[c]=NULL;
   strcpy(string,TmpString);
}

ReadString(string,len) /*Read a string from the Clipboard*/
char *string;
int len;
{
   char WorkingString[180];
   int length;

   strcpy(WorkingString,"");

   length=ReadClip(&ClipboardIO,WorkingString,179);
   if(!strncmp("FTXT",WorkingString,4))
      return(FALSE);
   strcpy(string,&WorkingString[20]);
   string[20+len]=NULL;
   return(TRUE);

}

ReadClip(ioreq,buf,bufsiz)
register struct IOClipReq *ioreq;
char *buf;     /*Read data from the Clipboard*/
int bufsiz;
{
   int length;

   ioreq->io_Command=CMD_READ;
   ioreq->io_Data=buf;
   ioreq->io_Length=bufsiz-1;
   ioreq->io_Offset=0;
   ioreq->io_ClipID=0;

   DoIO(ioreq);

   length=ioreq->io_Actual;
   *(buf+length)='\0';

   if(ioreq->io_Actual <(bufsiz-1))
      {
      ioreq->io_Command=CMD_READ;
      ioreq->io_Length=1;
      ioreq->io_Data=NULL;
      DoIO(ioreq);
      }
   return(length);
}

SnagBlock(Source,Last)  /*Copy block of lines into clip area*/
struct LineItem *Source,*Last;
{
   struct LineItem *Dest;
   struct LineItem *item;
   char buffer[90];
   ULONG blocklen=0;
   ULONG len;

      /*This keeps a continuation from being CUT all by itself...*/
   Source=(struct LineItem *)FindPrevNonCont(Source);

   item=(struct LineItem *)Source;
   while(item != Last->NextItem) /*Get the length of all the data*/
   {
      MakeTextLine(buffer,item);
      blocklen+=strlen(buffer);
      item=(struct LineItem *)item->NextItem;
   }

   /*Write out the IFF FORM and FTXT chunk header*/
   WriteClip(&ClipboardIO,"FORM",4,WCLIP_FIRST_WRITE);
   len=blocklen+12;
   WriteClip(&ClipboardIO,&len,4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,"FTXT",4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,"CHRS",4,WCLIP_CONT_WRITE);
   WriteClip(&ClipboardIO,&blocklen,4,WCLIP_CONT_WRITE);
   MakeTextLine(buffer,Source); /*Send the first line to the clipboard*/
   WriteClip(&ClipboardIO,buffer,strlen(buffer),WCLIP_CONT_WRITE);

   ClipStart=ClipEnd=Dest=(struct LineItem *)InsertItem(NULL,NULL);
   if(ClipStart==NULL)
   {
      Leave(0,"Memory too fragmented to perform CUT/COPY!");
      return(FALSE);
   }

   Dest->Level=Source->Level;
   strcpy(Dest->Text,Source->Text);
   Source=(struct LineItem *)Source->NextItem;

   while(Source != Last->NextItem) /*Go through the list*/
      {  /*and copy into the clip area*/
      ClipEnd=(struct LineItem *)Dest;
      Dest=(struct LineItem *)InsertItem(NULL,Dest);
      if(Dest==NULL)
      {
	 Leave(0,"Memory too fragmented to perform CUT/COPY!");
	 FreeListMem(ClipStart,ClipEnd);
	 return(FALSE);
      }

      Dest->Level=Source->Level;  /*Put lines into an internal clip area*/
      Dest->cont=Source->cont;
      strcpy(Dest->Text,Source->Text);
      MakeTextLine(buffer,Source);  /*And also sends them out to the clipboard*/
      WriteClip(&ClipboardIO,buffer,strlen(buffer),WCLIP_CONT_WRITE);
      Source=(struct LineItem *)Source->NextItem;
      }
   ClipEnd=Dest;
   WriteClip(&ClipboardIO,NULL,NULL,WCLIP_LAST_WRITE); /*Finish it off*/
   return(TRUE);
}

void AddBlock(Start) /*Insert a SnagBlocked item list into the main list*/
struct LineItem *Start; /*starting at Start*/
{
   struct LineItem *Item,*Dest;
   int TempX,TempY;
   UBYTE OrigLevel;

   Item=(struct LineItem *)ClipStart;  /*Start at the beginning*/
   Dest=(struct LineItem *)InsertItem(Start->NextItem,Start);
   if(Dest==NULL)
   {
      Leave(0,"Memory too fragmented to perform paste!");
      return;
   }

   OrigLevel=Item->Level;
   Dest->Level=5;
   Dest->ItemNumber=Item->ItemNumber;
   strcpy(Dest->Text,Item->Text);

   for(;Dest->Level > OrigLevel;Dest->Level--) /*Adjust the ItemNumbers*/
   {
      AddItem(Dest);
      RemItem(Dest);
   }

   AddItem(Dest);
   AddItem(Dest->NextItem);

   Item=(struct LineItem *)ClipStart->NextItem;
   while(Item != NULL)  /*Copy the lines to the main outline*/
   {
      Dest=(struct LineItem *)InsertItem(Dest->NextItem,Dest);
      if(Dest==NULL)
      {
	 Leave(0,"Memory too fragmented to continue with paste!");
	 PrintItemList(Start,1);
	 return;
      }

      Dest->Level=Item->Level;
      Dest->ItemNumber=Item->ItemNumber;
      Dest->cont=Item->cont;
      strcpy(Dest->Text,Item->Text);
      AddItem(Dest);
      Item=(struct LineItem *)Item->NextItem;
   }
   TempY=CurY;
   TempX=CurX;
   PrintItemList(CurrentItem,CurY); /*Redraw the screen*/
   PlotCursor(TempX,TempY);
   if(LastItem==Start)
      LastItem=(struct LineItem *)Dest;
}

/*~~~End of clip.c*/
