#include "globals.h"
#include "minrexx.h"
#include "NewARexxWdw.h"

extern struct RxsLib *RexxSysBase;
struct RexxMsg *LinerRexxMsg;
int LinerDispatch();

extern void ModSearchWdw();

/*Function definitions private to arexx.c*/
void DoOpen(),DoSave(),DoDoubClick(),DoSetTitleMsg();
void DoGetStats(),DoPrintDisk(),DoGetChar(),DoGetWord(),DoGetLineText();
void DoCursorRight(),DoCursorLeft(),DoDoubSpacing(),DoInterlaced();
void DoIcons(),DoScrnSize(),DoStartingLevel(),DoLoadPrefs(),DoARexxSearch();
void DoInsertText();
void DoGetLine(),DoStartLine(),DoEndLine(),DoPushIn(),DoPullOut();
void DoFakeReturn(),SpecReplyToRexx();
void DoGetFilename(),DoPutPrefs(),DoExtendedModes();

struct rexxCommandList rcl[]= /*The list of all the ARexx commands and*/
{	 /*their associated functions*/
   { "open" , (APTR)&DoOpen},
   { "save" , (APTR)&DoSave},
   { "getfilename" , (APTR)&DoGetFilename},
   { "new" , (APTR)&NewAll},
   { "printprinter", (APTR)&HandlePrintPrinter},
   { "printdisk" , (APTR)&DoPrintDisk},
   { "quit" , (APTR)&CloseStuff },
   { "doubclick" , (APTR) &DoDoubClick},
   { "settitlemsg" , (APTR) &DoSetTitleMsg},
   { "getstats" , (APTR) &DoGetStats},
   { "getchar" , (APTR) &DoGetChar},
   { "getword" , (APTR) &DoGetWord},
   { "getlinetext" , (APTR) &DoGetLineText},
   { "cut" , (APTR) &HandleCut},
   { "copy" , (APTR) &HandleCopy},
   { "paste" , (APTR) &HandlePaste},
   { "erase" , (APTR) &HandleErase},
   { "cursorup" , (APTR) &CursorUp},
   { "cursordown" , (APTR) &CursorDown},
   { "cursorright" , (APTR) &DoCursorRight},
   { "cursorleft" , (APTR) &DoCursorLeft},
   { "totop" , (APTR) &JumpToTop},
   { "tobottom" , (APTR) &JumpToBottom},
   { "upscreen" , (APTR) &WholeScreenUp},
   { "downscreen" , (APTR) &WholeScreenDown},
   { "doubspacing" , (APTR) &DoDoubSpacing},
   { "interlaced" , (APTR) &DoInterlaced},
   { "extmodes" , (APTR) &DoExtendedModes},
   { "icons" , (APTR) &DoIcons },
   { "scrnsize" , (APTR)&DoScrnSize},
   { "startinglevel" , (APTR)&DoStartingLevel},
   { "loadprefs" , (APTR)&HandleReloadPrefs},
   { "sveprefs" , (APTR)&DoPutPrefs},
   { "search" , (APTR)&DoARexxSearch},
   { "instext" , (APTR)&DoInsertText},
   { "getline" , (APTR)&DoGetLine},
   { "fakereturn" , (APTR)&DoFakeReturn},
   { "fakebs" , (APTR)&HandleBS},
   { "pushin" , (APTR)&DoPushIn},
   { "pullout" , (APTR)&DoPullOut},
   { "startline" , (APTR)&DoStartLine},
   { "endline" , (APTR) &DoEndLine},
   { NULL , NULL}
};

void OpenARexx() /*Open the ARexx port*/
{
   ARexxSigBit=upRexxPort("liner",rcl,"liner",&LinerDispatch);
}

void CloseARexx() /*Close the ARexx port*/
{
   dnRexxPort();
}

void CheckRexxPort() /*Check the ARexx port for commands*/
{
   dispRexxPort();
}

int LinerDispatch(msg,rcl,p) /*The minrexx userdisp function*/
struct RexxMsg *msg;
struct rexxCommandList *rcl;
char *p;
{

   LinerRexxMsg=(struct RexxMsg *)msg;

   ((int(*)())(rcl->userdata))(p); /*Call the function associated with the */
			   /*ARexx command received*/

      /*If the function is one of those that returns something to ARexx*/
   if(stricmp(rcl->name,"open")==0 || stricmp(rcl->name,"printdisk")==0 ||
	 stricmp(rcl->name,"getlinetext")==0 || stricmp(rcl->name,"getline")==0 ||
	 stricmp(rcl->name,"getchar")==0 || stricmp(rcl->name,"linersearch")==0 ||
	 stricmp(rcl->name,"getstats")==0 || stricmp(rcl->name,"getword")==0 ||
	 stricmp(rcl->name,"startinglevel")==0||stricmp(rcl->name,"fakereturn")==0
	 || stricmp(rcl->name,"pushin") || stricmp(rcl->name,"pullout") ||
	 stricmp(rcl->name,"getfilename") || stricmp(rcl->name,"sveprefs") )
      return(1);  /*Tell minrexx not to replyRexxCmd()*/
   else
      return(0);
}

void DoOpen(p)   /*Open a file under ARexx control*/
char *p;
{

   /*Setup the filename*/
   strcpy(FileName,&p[1]);
   if(ReadItemList(FileName,TRUE))  /*Do the read*/
   {
      Modified=FALSE;
      TitleErrorCancel();
      SplitFilename(FileName,SFileName,SDirName);
      replyRexxCmd(LinerRexxMsg,0,0,"true");
   }
   else
      replyRexxCmd(LinerRexxMsg,0,0,"false");
}

void DoSave(p)   /*Save a file under ARexx*/
char *p;
{
   strcpy(FileName,&p[1]);
   SplitFilename(FileName,SFileName,SDirName);
   Save(TRUE);  /*Write the file out*/
}

void DoGetFilename()
{
   char filename[183];

   strcpy(filename,SDirName);
   if(filename[strlen(filename)-1]!=':' && filename[strlen(filename)-1]!=NULL)
      strcat(filename,"/");   /*Append a / if not at the root*/
   strcat(filename,SFileName);
   replyRexxCmd(LinerRexxMsg,0,0,filename);
}

void DoPrintDisk(p)  /*Print a file to disk*/
char *p;
{
   SplitFilename(++p,PFileName,PDirName);
   SpecReplyToRexx(HandlePrintDisk(TRUE,p));
}

void DoDoubClick(p)  /*Fake a double click (good for highlighting blocks)*/
char *p;
{
   p++;
   PtrY=CurY;
   if(stricmp(p,"true")==0) /*if the click is meant to be outside a line*/
      PtrX=1;
   else
      PtrX=CurX;
   HandleInvs();
   BLastX=CurX;
}

void DoSetTitleMsg(p) /*Print message in 'p' in title bar*/
char *p;
{
   TitleError(&p[1]);
}

void DoGetStats()  /*Tell ARexx the CurrentItem's level, number, and */
{		     /*whether or not it's a continuation*/
   char buffer1[7];
   static char buffer2[12];

   stci_d(buffer2,CurrentItem->Level); /*Convert the numbers into text*/
   strcat(buffer2," ");
   stci_d(buffer1,CurrentItem->ItemNumber);
   strcat(buffer2,buffer1);
   if(CurrentItem->cont)
      strcat(buffer2," true");   /*true==continuation*/
   else
      strcat(buffer2," false");

   replyRexxCmd(LinerRexxMsg,0,0,buffer2);


}

void DoGetChar() /*Send the character under the cursor to ARexx*/
{
   char letter[2];

   letter[1]=NULL;
   letter[0]=CurrentItem->Text[PosInText(CurrentItem->Level)];/*Get the letter*/
   replyRexxCmd(LinerRexxMsg,0,0,letter);
}

void DoGetWord() /*Send the word under the cursor to ARexx*/
{
   static char result[80];
   BYTE c;

   for(c=0;c<80;result[c++]=NULL); /*Clear the string (weird things happen*/
		     /*if I don't, and I don't know why...)*/
   strcpy(result,"");
   GetWord(result,CurrentItem);
   replyRexxCmd(LinerRexxMsg,0,0,result);
}

void DoGetLineText() /*Send the current line's text to ARexx*/
{
   static char buffer[100];
   strcpy(buffer,CurrentItem->Text);
   replyRexxCmd(LinerRexxMsg,0,0,buffer);
}

void DoCursorRight()   /*Move the cursor to the right*/
{
   CursorRight(0);
}

void DoCursorLeft() /*Move the cursor to the left*/
{
   CursorLeft(0);
}

void DoDoubSpacing(p) /*Set the spacing*/
char *p;
{
   p++;
   if(stricmp(p,"true")==0) /*Set double spacing*/
   {
      if(!prefs.DS)  /*If not double spaced*/
      {
	 DoubleSpacing();
	 ModifyMenus(32+StartingLevel); /*Change menus appropriately*/
      }
   }
   else  /*Unset double spacing*/
      if(prefs.DS) /*If double spaced*/
      {
	 DoubleSpacing();
	 ModifyMenus(StartingLevel);
      }
}

void DoInterlaced(p) /*Determine whether the screen is/isn't interlaced*/
char *p;
{
   p++;

   if(stricmp(p,"true")==0)
      switch(prefs.ScreenType)
      {
	 case HIRES_KEY:
	    prefs.ScreenType=HIRESLACE_KEY;
	    break;
	 case VGAPRODUCT_KEY:
	    prefs.ScreenType=VGAPRODUCTLACE_KEY;
      }
   else
      switch(prefs.ScreenType)
      {
	 case HIRESLACE_KEY:
	    prefs.ScreenType=HIRES_KEY;
	    break;
	 case VGAPRODUCTLACE_KEY:
	    prefs.ScreenType=VGAPRODUCT_KEY;
      }

   PutScreenTypeInMenu();
   ChangeDisplay();
}

   /*Added in 'Liner 2.10:  used to choose between screen modes*/
void DoExtendedModes(p)
char *p;
{
   p++;

   switch(*(p+2))
   {
      case '0':
	 prefs.ScreenType |= DEFAULT_MONITOR_ID;
	 break;
      case '1':
	 prefs.ScreenType |= NTSC_MONITOR_ID;
	 break;
      case '2':
	 prefs.ScreenType |= PAL_MONITOR_ID;
   }

   switch(*p)
   {
      case '0':
	 prefs.ScreenType|=HIRES_KEY;
	 break;
      case '1':
	 prefs.ScreenType|=HIRESLACE_KEY;
	 break;
      case '2':
	 prefs.ScreenType=VGAPRODUCT_KEY;
	 break;
      case '3':
	 prefs.ScreenType=VGAPRODUCTLACE_KEY;
	 break;
      case '4':
	 prefs.ScreenType=A2024TENHERTZ_KEY;
	 break;
      case '5':
	 prefs.ScreenType=A2024FIFTEENHERTZ_KEY;
   }

   PutScreenTypeInMenu();
   ChangeDisplay();
}


void DoIcons(p)   /*Set program to create/not create icons*/
char *p;
{
   p++;
   prefs.Icons=(stricmp(p,"true")==0);
   ModifyIconMenu();
}


void DoScrnSize(p) /*In pre-2.10 versions of 'Liner, this was used to*/
char *p;	   /*toggle between standard-sized and workbench-sized */
{		   /*screens.  Under 2.10, it no longer has any meaning,*/
}		   /*but this routine remains for compatability reasons*/

void DoStartingLevel(p) /*Set the starting level*/
char *p;
{
   int level;
   p++;
   p[1]=NULL;
   stcd_i(p,&level); /*Get the level (as a number)*/
   if(level < 0 || level > 5)
      SpecReplyToRexx(FALSE);
   if(level == StartingLevel)
      SpecReplyToRexx(TRUE);

   if(prefs.DS)   /*If double spaced*/
      level+=32;  /*Alter level for ModifyMenus()*/
   ModifyMenus(level);
   StartingLevel=level; /*Record the new starting level*/
   Refresh();  /*And update the display*/
      SpecReplyToRexx(TRUE);

}

Interp(p) /*Used by DoARexxSearch.  Determines if a parameter sent by*/
char p;   /*ARexx specified setting a search variable to TRUE, FALSE, or*/
{	  /*leaving it unchanged*/
   switch(p)
   {
      case 't':
      case 'T':
	 return(TRUE);
      case 'f':
      case 'F':
	 return(FALSE);
      case 'u':
      case 'U':
	 return(100);   /*Unchanged*/
   }
   return(100); /*If none of the above, something's screwy.  Best to not*/
}		/*change anything*/

void DoInsertText(p) /*Insert a text string into the line after the cursor*/
char *p;
{
   char WorkString[160];
   UBYTE TempX;

   WorkString[0]=NULL;

   strcpy(WorkString,CurrentItem->Text);
   WorkString[PosInText(CurrentItem->Level)]=NULL;
   strcat(WorkString,&p[1]);
   strcat(WorkString,&CurrentItem->Text[PosInText(CurrentItem->Level)]);
   WorkString[MaxLen(CurrentItem->Level)]=NULL;
   strcpy(CurrentItem->Text,WorkString);
   TempX=CurX;
   PlotCursor(1,CurY);
   PrintItem(CurrentItem);
   PlotCursor(TempX,CurY);

}

void DoGetLine() /*Return an entire line to ARexx (incl. line number)*/
{
   static char buffer[100]; /*static to make sure it doesn't disappear*/
	     /*before the calling macro has had a chance to chew on it*/

   MakeTextLine(buffer,CurrentItem); /*ARexx gets it*/
   replyRexxCmd(LinerRexxMsg,0,0,buffer);
}

void DoFakeReturn(p) /*Let ARexx push the return button (i.e. create a line)*/
char *p;
{
   BYTE stat;
   p++;
   if(stricmp(p,"shift")==0 || stricmp(p,"true")==0)
      stat=HandleReturn(3);
   else
      stat=HandleReturn(0);
   SpecReplyToRexx(stat);
}

void DoStartLine()
{
   CursorLeft(8); /*Fake a SHIFT-CURSOR-LEFT*/
}

void DoEndLine()
{
   CursorRight(8); /*Fake a SHIFT-CURSOR-RIGHT*/
}

void DoPushIn()   /*Fake a TAB*/
{
   SpecReplyToRexx(HandleTAB(0));
}

void DoPullOut()  /*Fake a SHIFT-TAB*/
{
   SpecReplyToRexx(HandleTAB(3));
}

void DoPutPrefs()
{
   SpecReplyToRexx(PutPrefs("liner:liner.prefs",TRUE));
}

void SpecReplyToRexx(stat) /*Send a 'true' or 'false' to ARexx*/
BYTE stat;
{
   if(stat)
      replyRexxCmd(LinerRexxMsg,0,0,"true");
   else
      replyRexxCmd(LinerRexxMsg,0,0,"false");
}

void GetWord(result,item) /*Get the word under the cursor*/
char *result;
struct LineItem *item;
{
   BYTE start,end,pos;

   pos=PosInText(CurrentItem->Level);
   if(pos>=strlen(CurrentItem->Text))
   {
      strcpy(result,"");
      return;
   }

   start=pos;
   if(pos!=0)
   {
      for(start--;CurrentItem->Text[start]!=' ' && start >= 0;start--);
      start++;
   }

   if(CurrentItem->Text[pos]!=NULL) /*Not at the end of the line...*/
      for(end=pos;CurrentItem->Text[end]!=' ' && CurrentItem->Text[end]!=NULL;
	    end++);

   strncpy(result,&CurrentItem->Text[start],end-start);
}

void EngageMacro(name) /*Start an external ARexx macro ('ENGAGE!' - J-LP :-)*/
char *name;
{
   asyncRexxCmd(name);
}

void GetMacroInfo() /*Open the window to get the macro names*/
{
   struct Window *MacroWdw;
   struct IntuiMessage *mesg;
   struct Gadget junk,*gadg,*StrStart;
   struct StringInfo *si;
   BYTE c;
   ULONG add;

   add=Screen->Font->ta_YSize-Topaz.ta_YSize;

   gadg=(struct Gadget *)MakeButtonGadgets(&junk,ARexxButtons,VisInfo,
			      &Topaz,AREXXBUTTONS,add);
   MakeStringGadgets(gadg,ARexxStrings,VisInfo,&Topaz,AREXXSTRINGS,
		     ss,add);
   gadg=StrStart=(struct Gadget *)gadg->NextGadget;

   for(c=0;c<4;c++,gadg=(struct Gadget *)gadg->NextGadget->NextGadget)
   {
      si=(struct StringInfo *)gadg->SpecialInfo;
      strcpy(si->Buffer,prefs.Macro[c]);
      si=(struct StringInfo *)gadg->NextGadget->SpecialInfo;
      strcpy(si->Buffer,prefs.Name[c]);
   }

   NewWindowStructure1.Screen=(struct Screen *) Screen;
   NewWindowStructure1.FirstGadget=(struct Gadget *)junk.NextGadget;

      /*Make room for title bar*/
   NewWindowStructure1.Height+=add;

   MacroWdw=(struct Window *)OpenWindow(&NewWindowStructure1);
   if(MacroWdw==NULL)
   {
      Leave(0,"Couldn't open the window!");
      return;
   }

      /*Restore old value*/
   NewWindowStructure1.Height-=add;

   PrintIText(MacroWdw->RPort,&IntuiTextList1,4,4+add); /*Print the text*/

      /*Draw some bevel boxes*/
   DrawBevelBoxA(MacroWdw->RPort,10,14+add,430,71,&beveltag[0]);
   DrawBevelBoxA(MacroWdw->RPort,10,88+add,430,25,&beveltag[0]);

   ActivateGadget(StrStart,MacroWdw,NULL);
   Wait(1<<MacroWdw->UserPort->mp_SigBit);   /*Wait for a gadget to be*/
		    /*pressed, or return to be hit while in a string gadget*/
   mesg=(struct IntuiMessage *)GetMsg(MacroWdw->UserPort);
   gadg=(APTR)mesg->IAddress;
   ReplyMsg(mesg);

   while(gadg->GadgetID < 9)/*While the gadget is a string gadget*/
   {
      if(gadg->NextGadget != NULL) /*Advance to the next string gadget*/
	 ActivateGadget(gadg->NextGadget,MacroWdw,NULL); /*(if one exists)*/

      /*And wait again...*/
      Wait(1<<MacroWdw->UserPort->mp_SigBit);
      mesg=(struct IntuiMessage *)GetMsg(MacroWdw->UserPort);
      gadg=(APTR)mesg->IAddress;
      ReplyMsg(mesg);
   }

   if(gadg->GadgetID == 9) /*OK was pressed*/
   {
      for(gadg=(struct Gadget *)StrStart,c=0;c<4;
	       gadg=(struct Gadget *)gadg->NextGadget->NextGadget,c++)
      {
	 si=(struct StringInfo *)gadg->SpecialInfo;
	 strcpy(prefs.Macro[c],si->Buffer);
	 si=(struct StringInfo *)gadg->NextGadget->SpecialInfo;
	 strcpy(prefs.Name[c],si->Buffer);
      }
      CopyPrefsToMenus();
   }

   CloseWindow(MacroWdw);
   FreeGadgets(junk.NextGadget);
}

void SplitFilename(Filename,file,dir) /*Split a full filename into */
char *Filename,*file,*dir; /*path, filename, and extension*/
{
   char path[150];
   char ext[150];

   strsfn(Filename,dir,path,file,ext);
   strcat(dir,path);
   strcpy(file,&Filename[strlen(dir)+((Filename[strlen(dir)]=='/') ? 1 : 0)]);
}

void DoARexxSearch(p)   /*Do a search/replace*/
char *p;
{
   BYTE cse,partial,repl,c,i,old;
   char search[80],replace[80];
   search[0]=replace[0]=NULL;

   for(c=0;c<80;search[c++]=NULL)
      replace[c]=NULL;

   cse=Interp(p[1]);
   partial=Interp(p[2]);
   repl=Interp(p[3]);

   if(!(p[4]==NULL || p[5]==NULL)) /*If there is a word to search for*/
   {	 /*use it.  Otherwise, use what the user has specified*/
      for(c=5,i=0;p[c] != NULL && p[c]!=' ';i++,c++);
      strncpy(search,&p[5],i);
      if(p[c]!=NULL && p[c+1]!=NULL)
      {
	 for(old=++c,i=0;p[c]!=NULL && p[c]!=' ';++i,c++);
	 strncpy(replace,&p[old],i);
      }
   }

   /*Set the appropriate search variables*/
   ModifyParams(search,replace,cse,partial,repl);
   ModSearchWdw();

   if(DoSearch(TRUE,TRUE))  /*Do the actual search*/
      strcpy(search,"true");
   else
      strcpy(search,"false");

   /*Give ARexx the result*/
   replyRexxCmd(LinerRexxMsg,0,0,search);

}


/*~~~End of arexx.c*/

