/*Windows.c -- Includes all routines that access the stuff in Windows.h*/

extern struct MenuItem *ItemAddress();

#include "Globals.h"
#include "Windows.h"

#define ABOUT_Y_REG 42
#define ABOUT_Y_LACED 142

void OpenGraphics() /*Open screen, window, etc.*/
{
   /*Open screen*/
   NewWindow.Screen=Screen=(struct Screen *)OpenScreen(&NewScreen);
   if(Screen==NULL)
      Leave(50,"Can't open screen!!");

   LoadColors(&(Screen->ViewPort)); /*Set screen colors to those in prefs*/

   /*Open backdrop window & make requestors open onto it*/
   if((ThisProc->pr_WindowPtr=Window=
         (struct Window *)OpenWindow(&NewWindow))==NULL)
      {
      CloseScreen(Screen);
      Leave(60,"Can't open Window!");
      }
   /*Install menus*/
   SetMenuStrip(Window,&Menu1);

   /*Setup the console.device*/
   consoleWritePort=(struct Port *)CreatePort("mycon.write",0);
   if(consoleWritePort==NULL)
      Leave(70,"Couldn't open console.device!");

   consoleWriteMsg=(struct IOStdReq *)CreateStdIO(consoleWritePort);
   if(consoleWriteMsg==NULL)
      Leave(80,"Couldn't open console.device!");

   consoleReadPort=(struct Port *)CreatePort("mycon.read",0);
   if(consoleReadPort==NULL)
      Leave(90,"Can't create communications port!");

   consoleReadMsg=(struct IOStdReq *)CreateStdIO(consoleReadPort);
   if(consoleReadMsg==NULL)
      Leave(100,"Can't create standard IO!");

   consoleWriteMsg->io_Data=(struct Window *)Window;  /*Attach console*/
   consoleWriteMsg->io_Length=sizeof(struct Window);  /*device to window...*/
   OpenDevice("console.device",0,consoleWriteMsg,0); /*& open it*/

   ConsoleDevice=consoleReadMsg->io_Device=(APTR)consoleWriteMsg->io_Device;
   consoleReadMsg->io_Unit=consoleWriteMsg->io_Unit; /*Get the current keymap*/
   consoleReadMsg->io_Command=CD_ASKKEYMAP;
   consoleReadMsg->io_Length=sizeof(struct KeyMap);
   consoleReadMsg->io_Data=&keymap;
   DoIO(consoleReadMsg);
   TitleErrorCancel();
}

void CloseGraphics()   /*Close the window, screen, etc.*/
{
   CloseDevice(consoleWriteMsg);
   DeleteStdIO(consoleWriteMsg);
   DeleteStdIO(consoleReadMsg);
   DeletePort(consoleWritePort);
   DeletePort(consoleReadPort);
   ClearMenuStrip(Window);
   CloseWindow(Window);
   CloseScreen(Screen);
}

/*This is in liner.c and not menu.c because it needs to manipulate the*/
/*'Liner NewScreen and NewWindow information, which it can't do from*/
/*menu.c*/

void ChangeDisplay()
{
   UBYTE X,Y;
   BOOL stat1,stat2,stat3,stat4;
   
   
   X=CurX;
   Y=CurY;
   
   stat1=HandleInterlaced();
   stat2=SwapScrnSize();
   stat3=DoubleSpacing();
   stat4=HandleStartingLevel();
   
   if( stat1 || stat2 )
   {
      if( stat3 || stat4 )
         CheckModified();

      CloseGraphics();
      OpenGraphics();
      
      SetRowsInScreen();
      PrintItemList(FirstScrnItem,1);
      
      if( !stat3 )
      {
         if(Y > DispRows)  /*if the old laced Y is > the current possible rows*/
         {
            Y=DispRows;    /*Y now = the last screen item*/
            CurrentItem=(struct LineItem *)ScrnBtm;
         }
         if(X > MaxX(CurrentItem))  /*Out of bounds*/
            X=MaxX(CurrentItem);
         else if(X < MinX(CurrentItem))
            X=MinX(CurrentItem);

         PlotCursor(X,Y);     /*Restore cursor position*/
      }
      else
      {
         CurrentItem=(struct LineItem *)FirstScrnItem;
         PlotCursor(MinX(FirstScrnItem),1);
      }
   }
   else
      if( stat3 || stat4 )
      {
         SetRowsInScreen();
         PrintItemList(FirstScrnItem,1);
         if( !stat3 )
         {
            if(Y > DispRows)  /*if the old laced Y is > the current possible rows*/
            {
               Y=DispRows;    /*Y now = the last screen item*/
               CurrentItem=(struct LineItem *)ScrnBtm;
            }
            if(X > MaxX(CurrentItem))  /*Out of bounds*/
               X=MaxX(CurrentItem);
            else if(X < MinX(CurrentItem))
               X=MinX(CurrentItem);

            PlotCursor(X,Y);     /*Restore cursor position*/
         }
         else
         {
            CurrentItem=(struct LineItem *)FirstScrnItem;
            PlotCursor(MinX(FirstScrnItem),1);
            CheckModified();
         }
      }
}         

BOOL HandleStartingLevel() /*Change the starting level*/
{
   BYTE c;
   
   for(c=0;c<6 && (SubItems[c]->Flags & CHECKED) != CHECKED;c++);
   if(c==6)
   {
      c=0;
      SubItems[0]->Flags |= CHECKED;
   }
   
   if(c!=StartingLevel)
   {
      StartingLevel=c;
      return(TRUE);
   }
   
   return(FALSE);
}

BOOL DoubleSpacing() /*Toggle between single & double spacing*/
{
   if(prefs.DS==(( DOUBSPAC_MI.Flags & CHECKED)==CHECKED))
      return(FALSE);
   prefs.DS=!prefs.DS;
   return(TRUE);
}
   

BOOL HandleInterlaced()   /*Toggle between a normal and interlaced screen*/
{
   
   if(prefs.Laced == ((INTERLACE_MI.Flags & CHECKED) == CHECKED))
      return(FALSE);

   if(prefs.Laced)   /*If interlaced*/
      {
      NewScreen.Height/=2;
      NewWindow.Height=NewScreen.Height-11;
      NewScreen.ViewModes=HIRES; /*Remove LACE from screen description*/
      prefs.Laced=FALSE;         /*Status switch*/
      }
   else  /*not interlaced*/
      {
      NewScreen.Height*=2;
      NewWindow.Height=(NewScreen.Height-11);
      NewScreen.ViewModes=HIRES+LACE; /*Add LACE to screen description*/
      prefs.Laced=TRUE;
      }
   return(TRUE);
}

BOOL SwapScrnSize() /*Change a standard sized screen to Workbench sized & back*/
{

   UBYTE X,Y;
   BYTE stat;
   X=CurX;
   Y=CurY;  /*Store cursor position*/

   
   stat = FALSE;
   if(((WBENCH_SI.Flags & CHECKED) == CHECKED) && prefs.Screen==0)
   {
      prefs.Screen = 1;  /*Switch to Workbench sized screen*/
      NewScreen.Height=GetWBHeight(); /*Get height of Workbench screen*/
      if(NewScreen.Height > 300) /*Prob. interlaced*/
         NewScreen.Height /= 2;  /*Cut it down*/
      stat=TRUE;
   }
   
   if(((STANDARD_SI.Flags & CHECKED) == CHECKED) && prefs.Screen == 1)
   {
      prefs.Screen = 0;  /*Switch to standard screen*/
      NewScreen.Height=200;
      stat=TRUE;
   }

   if(!stat)
      return(FALSE);;
      
   if(prefs.Laced)
      NewScreen.Height*=2;
   
   NewWindow.Height=NewScreen.Height-11; /*'Liner's window is always 11*/
         /*lines shorter than the host screen*/
   
   return(TRUE);
}

void ModifyMenus(Flag)/*Modify Double Spacing and Starting Level menus for the*/
char Flag;            /*ReadItemList function*/
{
   if(Flag>=32)   /*If double spaced...*/
      {
      prefs.DS=TRUE;
      MenuItem1.Flags=CHECKIT+ITEMTEXT+COMMSEQ+MENUTOGGLE+
            ITEMENABLED+HIGHCOMP+CHECKED;
      Flag-=32;  /*Removed double spacing flag*/
      }
   else
      {
      prefs.DS=FALSE;
      MenuItem1.Flags=CHECKIT+ITEMTEXT+COMMSEQ+MENUTOGGLE+
         ITEMENABLED+HIGHCOMP;
      }

   SubItems[StartingLevel]->Flags-=CHECKED;
   StartingLevel=(Flag <= 5) ? Flag : 5;
   SubItems[StartingLevel]->Flags+=CHECKED;
}

void GetLinerPrefs(filename)
char *filename;
{
   struct FileHandle *fp;
   
   if((fp=(struct FileHandle *)Open(filename,MODE_OLDFILE))==NULL)
      return;             /*If no preferences file could be found*/
                          /*use the defaults*/

   Read(fp,&prefs,sizeof(struct LinerPrefs));  /*Read in the preferences*/
   Close(fp);        /*Close the file*/
}

void InterpretPrefs()   /*Install the preferences*/
{
   StartingLevel = 0;
   SubItems[StartingLevel]->Flags+=CHECKED;
   ModifyMenus(prefs.Level+((prefs.DS) ? 32 : 0)); /*Double spacing and*/
                                                   /*starting level*/
                                                   
   if(prefs.Icons)
      MenuItem3.Flags+=CHECKED;

   if(prefs.Screen == 0) /*Standard screen*/
   {
      SubItem1.Flags+=CHECKED;
      NewScreen.Height=200;
   }
   else /*Workbench screen*/
   {
      SubItem2.Flags+=CHECKED;
      NewScreen.Height=GetWBHeight(); /*Get the Workbench height*/
      if(NewScreen.Height > 300) /*Then it's interlaced*/
         NewScreen.Height/=2;    /*so cut it in half*/
   }         

   NewScreen.ViewModes=HIRES;
   if(prefs.Laced)
   {
      NewScreen.Height*=2;   /*Double the screen size*/
      NewScreen.ViewModes+=LACE;
      MenuItem2.Flags+=CHECKED;
   }
   else
      NewScreen.ViewModes=HIRES;
   
   NewWindow.Height=NewScreen.Height-11;

   prefs.Name[0][12]=NULL; /*Make sure none of the name >12 characters*/
   prefs.Name[1][12]=NULL;
   prefs.Name[2][12]=NULL;
   prefs.Name[3][12]=NULL;
   CopyPrefsToMenus();
   
   strcpy(SDirName,prefs.DefaultDir); /*Get the default disk directories*/
   strcpy(PDirName,prefs.DefPrintDir);
   
   strcpy(SExt,prefs.DefPattern);   /*And the default filepattern*/
   
   OpenGraphics();      /*And open the screen, window, etc...*/
   SetRowsInScreen();
}

PutPrefs(filename,AREXX)      /*Save the preferences to disk*/
char *filename;
BYTE AREXX;
{
   struct FileHandle *fp;
   
   if((fp=(struct FileHandle *)Open(filename,MODE_NEWFILE))==NULL)
   {
      if(!AREXX)
         TitleError("Couldn't save the preferences!");
      return(FALSE);
   }

   strcpy(prefs.Name[0],IText21.IText);   /*Copy ARexx macro info*/
   strcpy(prefs.Name[1],IText20.IText);
   strcpy(prefs.Name[2],IText19.IText);
   strcpy(prefs.Name[3],IText18.IText);
   
   strcpy(prefs.DefaultDir,SDirName);
   strcpy(prefs.DefPrintDir,PDirName);
   strcpy(prefs.DefPattern,SExt);
   
   prefs.Level=StartingLevel;
   
   
   Write(fp,&prefs,sizeof(struct LinerPrefs));
   Close(fp);  /*Done*/
   CreatePrefsIcon();   /*Make the icon for liner.prefs*/
   return(TRUE);
}

void CopyPrefsToMenus()
{
   strcpy(IText21.IText,prefs.Name[0]); /*Copy ARexx info to the menus*/
   strcpy(IText20.IText,prefs.Name[1]);
   strcpy(IText19.IText,prefs.Name[2]);
   strcpy(IText18.IText,prefs.Name[3]);
}

GetWBHeight()     /*Get the height of the Workbench screen*/
{
   int height;
   ULONG ILock;
   struct Screen *s;
   
   ILock=LockIBase(0);  /*Lock IntuitionBase while I find the WB screen size*/
   
   s=(struct Screen *)IntuitionBase->FirstScreen;
   while( (s != NULL) && ((s->Flags & CUSTOMSCREEN) == CUSTOMSCREEN) )
      s=(struct Screen *)s->NextScreen; /*Search to end of list or first*/
                           /*non CUSTOMSCREEN screen (ie WBENCHSCREEN)*/
   if(s==NULL)    /*If not found, give a default height of 200*/
      height=200;
   else
      height=s->Height;
      
   UnlockIBase(ILock); /*Unlock IntuitionBase*/
   
   return(height);      /*And we're done*/
}

struct MenuItem *GetFirstItemAddress(code) /*Get a MenuItem associated*/
USHORT code;   /*with the menu's number*/
{
   return(ItemAddress(&Menu1,code));
}

void SaveColors(vp)  /*Save the screen's colors to prefs*/
struct ViewPort *vp;
{
   ULONG c,rgb;
   
   for(c=0; c < 4 ; c++)   /*Get screen colors*/
   {
      rgb=GetRGB4(vp->ColorMap,c);

      prefs.Color[c][0]=(rgb >> 8) & 0xF;
      prefs.Color[c][1]=(rgb >> 4) & 0xF;
      prefs.Color[c][2]= rgb & 0xF;

   }
}

void LoadColors(vp)  /*Change the screen colors to those in prefs*/
struct ViewPort *vp;
{
   ULONG c;
   
   for(c=0; c < 4; c++)
      SetRGB4(vp,c,prefs.Color[c][0],prefs.Color[c][1],prefs.Color[c][2]);
}

void ClearMenus()/*Set the menus to state they are in when 'Liner is first run*/
{
   if(MenuItem3.Flags & CHECKED) /*Icons*/
      MenuItem3.Flags-=CHECKED;
      
   if(SubItem1.Flags & CHECKED) /*Standard/Workbench screen*/
      SubItem1.Flags-=CHECKED;
   else
      SubItem2.Flags-=CHECKED;
   
   ModifyMenus(0);   /*Set Double spacing and Starting level menus*/
   
   SubItems[StartingLevel]->Flags-=CHECKED;
   
   if(MenuItem2.Flags & CHECKED)
      MenuItem2.Flags-=CHECKED;
}

void SetRowsInScreen() /*Determine the # of text rows in a screen*/
{
   int temp;
                  /*Divide the height of the window by the current font's*/
   temp=(Window->Height)/Window->IFont->tf_YSize; /*height*/
                        
   if(prefs.DS)      /*If double spaced*/
   {
      RowsInScreen=(Window->Height)/(Window->IFont->tf_YSize*2);
      if(temp != RowsInScreen*2) /*Needed to keep extra lines from showing*/
         Odd=TRUE;               /*up in some circumstances*/
      else
         Odd=FALSE;
   }
   else
      RowsInScreen=temp;
}

void ModifyOtherMenus(menu) /*Change Interlaced, Icon, and screen size */
BYTE menu;     /*menus where appropriate*/
{
   switch(menu)
   {
      case 1:  /*Interlaced menu*/
         if(prefs.Laced)
            MenuItem2.Flags-=CHECKED;
         else
            MenuItem2.Flags+=CHECKED;
         break;
         
      case 2:  /*Icon creation*/
         if(prefs.Icons)
            MenuItem3.Flags-=CHECKED;
         else
            MenuItem3.Flags+=CHECKED;
         break;
         
      case 3:  /*Screen size manipulation*/
         if(prefs.Screen==0) /*Standard screen*/
         {
            SubItem2.Flags+=CHECKED;
            SubItem1.Flags-=CHECKED;
         }
         else
         {
            SubItem2.Flags-=CHECKED;
            SubItem1.Flags+=CHECKED;
         }
   }
}

HandleAbout()  /*Displays the 'About' window*/
{     /*It's here because it needs to access Windows.h*/
   struct Window *AboutWdw;

   NewAboutWindow.Screen=Screen;    /*Pointer to window's screen*/

   if(prefs.Laced)
      NewAboutWindow.TopEdge=ABOUT_Y_LACED;
   else
      NewAboutWindow.TopEdge=ABOUT_Y_REG;

   if((AboutWdw=(struct Window *)OpenWindow(&NewAboutWindow))==NULL)
      return(FALSE);

   SetWindowTitles(AboutWdw,-1,"For your information...");
   SetAPen(AboutWdw->RPort,1);
   PrintIText(AboutWdw->RPort,&IntuiTextList2,0,0);

         /*Wait for the user to press the Continue... gadget*/
   Wait(1<<AboutWdw->UserPort->mp_SigBit);

   CloseWindow(AboutWdw);     /*Close the window*/
}

NewAll() /*Get rid of all the Items*/
{
   char Buffer[10];

   FreeListMem(FirstItem,LastItem);

   prefs.DS=FALSE;
   SetRowsInScreen();
   
   ModifyMenus(0); /*Set menus (Double Spacing & Starting Level) to defaults*/
   StartingLevel=0;
   SubItems[0]->Flags|=CHECKED;

      /*Setup a fresh outline*/
   FirstItem=LastItem=FirstScrnItem=ScrnBtm=CurrentItem=
         (struct LineItem *)InsertItem(NULL,NULL);
   if(FirstItem==NULL)
   {
      CloseGraphics();
      CloseLibrary(IconBase);
      CloseLibrary(DosBase);
      Leave(1000,"Out of memory!");
   }
   
   CurrentItem->Level=1;
   Buffer[0]=0x0c;
   WriteConsole(Buffer,1);
   
   Buffer[0]=CSI;
   Buffer[1]='0';
   Buffer[2]=0x6d;
   
   WriteConsole(Buffer,3); /*Cancel any highlighting*/
   InvsMode=NOINV;
   PrintItemList(CurrentItem,1);
   PlotCursor(MinX(CurrentItem),CurY);
   Modified=FALSE;
   TitleErrorCancel();
   MenuItem1.Flags=CHECKIT+ITEMTEXT+COMMSEQ+MENUTOGGLE+ITEMENABLED+HIGHCOMP;

   FileName[0]=NULL;     /*Remove default filenames*/
   SFileName[0]=NULL;
   PDName[0]=NULL;
   PFileName[0]=NULL;
   TitleErrorCancel();

   return(TRUE);
}

void HandleIcons()
{
   prefs.Icons = ((ICON_MI.Flags & CHECKED)==CHECKED);
}

void HandleEvent(object)
APTR object;
{
  if (object == (APTR)&MenuItem21) { HandleNew(object); return; }
  if (object == (APTR)&MenuItem22) { HandleOpen(FALSE); return; }
  if (object == (APTR)&MenuItem23) { Save(FALSE); return; }
  if (object == (APTR)&MenuItem24) { HandleSaveAs(FALSE); return; }
  if (object == (APTR)&SubItem11) { HandlePrintPrinter(FALSE); return; }
  if (object == (APTR)&SubItem12) { HandlePrintDisk(FALSE,""); return; }
  if (object == (APTR)&MenuItem26) { HandleAbout(FALSE); return; }
  if (object == (APTR)&MenuItem27) { HandleQuit(FALSE); return; }
  if (object == (APTR)&MenuItem17) { HandleCut(FALSE); return; }
  if (object == (APTR)&MenuItem18) { HandleCopy(FALSE); return; }
  if (object == (APTR)&MenuItem19) { HandlePaste(FALSE); return; }
  if (object == (APTR)&MenuItem20) { HandleErase(FALSE); return; }
  if (object == (APTR)&MenuItem14) { DoSearch(FALSE,FALSE); return; }
  if (object == (APTR)&MenuItem15) { DoSearch(TRUE,FALSE); return; }
  if (object == (APTR)&MenuItem10) { EngageMacro(prefs.Macro[0]); return; }
  if (object == (APTR)&MenuItem11) { EngageMacro(prefs.Macro[1]); return; }
  if (object == (APTR)&MenuItem12) { EngageMacro(prefs.Macro[2]); return; }
  if (object == (APTR)&MenuItem13) { EngageMacro(prefs.Macro[3]); return; }
  if (object == (APTR)&MenuItem1) { ChangeDisplay(); return; }
  if (object == (APTR)&MenuItem2) { ChangeDisplay(); return; }
  if (object == (APTR)&MenuItem3) { HandleIcons(object); return; }
  if (object == (APTR)&SubItem3) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem4) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem5) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem6) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem7) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem8) { ChangeDisplay(); return; }
  if (object == (APTR)&MenuItem5) { HandlePalette(object); return; }
  if (object == (APTR)&SubItem1) { ChangeDisplay(); return; }
  if (object == (APTR)&SubItem2) { ChangeDisplay(); return; }
  if (object == (APTR)&MenuItem7) { GetMacroInfo(); return; }
  if (object == (APTR)&MenuItem8) { HandleReloadPrefs(object); return; }
  if (object == (APTR)&MenuItem9) { PutPrefs("liner:liner.prefs",FALSE);return;}
  if (object == (APTR)&SubItem9) { ReplaceAll(TRUE); return; }
  if (object == (APTR)&SubItem10) { ReplaceAll(FALSE); return; }
}

/*End of Windows.c*/