/*----------------------------------------------------------------------------*
 *                                                                            *
 *  AGA-Morph-Disk.c V1.2                                                     *
 *                                                                            *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/

#include <libraries/diskfont.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/pointerclass.h>
#include <datatypes/pictureclass.h>
#include <datatypes/pictureclassext.h>
#include <graphics/gfx.h>
#include <exec/memory.h>
#include <libraries/asl.h>
#include <clib/macros.h>

#include "AGA-Morph-Language.h"
#include "AGA-Morph-Struct.h"

/*----------------------------------------------------------------------------*/

extern struct BitMap *BitMap;
extern struct BitMapHeader *BitMapHeader;
extern struct DPoint Points;
extern struct IntuiText FileError,LoadPicError,MemoryError;
extern struct MPoint *Point1,*Point2;
extern struct RastPort *VirtRast;
extern struct Window *CommandWindow;
extern BPTR file;
extern char *Name;
extern LONG NumColours,x,xmax,y,ymax,i,j,k;
extern Object LPicture;
extern UBYTE Compr,*PlaneBuf[24],*Colours;
extern ULONG b,c,g,ModeID,r,*PixelBuf;

/*----------------------------------------------------------------------------*/

void LoadPoints();
void SavePoints();
void RemLines(ULONG num);                                /* Internal use only */
BYTE AllocLines(ULONG num,ULONG w);                      /* Internal use only */
BYTE ReadLine(ULONG num,ULONG w);                        /* Internal use only */
BYTE LoadIlbm(struct Pic *Picture,char *Name);           /* Internal use only */
void LoadPic(struct Pic *Picture,STRPTR Title);
void SavePic(struct Pic *Picture,STRPTR Title);

/*----------------------------------------------------------------------------*/

void
LoadPoints()
{
  struct FileLock *lock;
  struct request *FileRequester;
  BPTR File;
  struct FPoint Buff;
  if (FileRequester=(struct request *)AllocAslRequestTags(ASL_FileRequest,
                                                          ASLFR_TitleText,  Load_Points,
                                                          ASLFR_Window,     CommandWindow,
                                                          ASLFR_DoPatterns, TRUE,
                                                          TAG_DONE))
  {
    if (AslRequest(FileRequester,0))
    {
      DeletePoints();
      lock=(struct FileLock *)CurrentDir(Lock(((struct FileRequester *) FileRequester)->rf_Dir,ACCESS_READ));
      Name=((struct FileRequester *) FileRequester)->rf_File;
      if (File=Open(Name,MODE_OLDFILE))
      {
        if (Read(File,&Buff,sizeof(Buff)))
        {
          if (Points.First=(struct MPoint *)AllocVec(sizeof(struct MPoint),0))
          {
            Point1=Points.First;
            Point1->P=Buff;
            Point1->Next=0;
            Points.NumPoints=1;
          }
          else
          {
            ShowError(&MemoryError);
          }
          while(Read(File,&Buff,sizeof(Buff)))
          {
            if (Point1->Next=(struct MPoint *)AllocVec(sizeof(struct MPoint),0))
            {
              Point1=Point1->Next;
              Point1->P=Buff;
              Point1->Next=0;
              Points.NumPoints++;
            }
            else
            {
              ShowError(&MemoryError);
            }
          }
        }
        Close(File);
      }
      else
      {
        ShowError(&FileError);
      }
      UnLock(CurrentDir(lock));
    }
    FreeAslRequest(FileRequester);
  }
  else
  {
    ShowError(&MemoryError);
  }
  RethinkSelectedPoint();
}

/*----------------------------------------------------------------------------*/

void
SavePoints()
{
  struct request *FileRequester;
  struct FileLock *lock;
  BPTR File;
  if (FileRequester=(struct request *)AllocAslRequestTags(ASL_FileRequest,
                                                          ASLFR_TitleText,  Save_Points,
                                                          ASLFR_Window,     CommandWindow,
                                                          ASLFR_DoPatterns, TRUE,
                                                          TAG_DONE))
  {
    if (AslRequest(FileRequester,0))
    {
      lock=(struct FileLock *)CurrentDir(Lock(((struct FileRequester *) FileRequester)->rf_Dir,ACCESS_READ));
      Name=((struct FileRequester *) FileRequester)->rf_File;
      if (File=Open(Name,MODE_NEWFILE))
      {
        Point1=Points.First;
        while(Point1)
        {
          Write(File,&(Point1->P),sizeof(Point1->P));
          Point1=Point1->Next;
        }
        Close(File);
      }
      else
      {
        ShowError(&FileError);
      }
      UnLock(CurrentDir(lock));
    }
    FreeAslRequest(FileRequester);
  }
  else
  {
    ShowError(&MemoryError);
  }
}

/*----------------------------------------------------------------------------*/

void
RemLines(ULONG num)
{
  for (i=0;i<num;i++)
  {
    FreeVec(PlaneBuf[i]);
    PlaneBuf[i]=0;
  }
  if (PixelBuf)
  {
    FreeVec(PixelBuf);
    PixelBuf=0;
  }
}

/*----------------------------------------------------------------------------*/

BYTE
AllocLines(ULONG num,ULONG w)
{
  for (i=0;i<num;i++)
  {
    if (!(PlaneBuf[i]=(UBYTE *)AllocVec(((w+15) >> 4) << 1,0)))
    {
      if (i>0) RemLines(i);
      return 0;
    }
  }
  if (!(PixelBuf=(ULONG *)AllocVec(((w+15) >> 4) << 6,0)))
  {
    RemLines(num);
    return 0;
  }
  return 1;
}

/*----------------------------------------------------------------------------*/

BYTE
ReadLine(ULONG num,ULONG w)
{
  LONG ww,l;
  BYTE code;
  UBYTE color;
  WORD cod;
  char text[10];
  ww=((w+15) >> 4) << 1;
  if (Compr)
  {
    for (j=0;j<num;j++)
    {
      k=0;
      while (k<ww)
      {
        Read(file,&code,1);
        if (code>=0)
        {
          cod=code+1;
          if (k+cod<=ww)
          {
            Read(file,(PlaneBuf[j]+k),cod);
          }
          k=k+cod;
        }
        else
        {
          if (code==-128)
          {
            /* NOP */
          }
          else
          {
            cod=1-code;
            Read(file,&color,1);
            if (k+cod<=ww)
            {
              for (l=0;l<cod;l++)
              {
                *(PlaneBuf[j]+k+l)=color;
              }
            }
            k=k+cod;
          }
        }
      }
      if (k>ww)
      {
        return 0;
      }
    }
  }
  else
  {
    for (j=0;j<num;j++)
    {
      Read(file,PlaneBuf[j],ww);
    }
  }
  for (j=0;j<ww;j++)
  {
    *(PixelBuf+j*8)=0;
    *(PixelBuf+j*8+1)=0;
    *(PixelBuf+j*8+2)=0;
    *(PixelBuf+j*8+3)=0;
    *(PixelBuf+j*8+4)=0;
    *(PixelBuf+j*8+5)=0;
    *(PixelBuf+j*8+6)=0;
    *(PixelBuf+j*8+7)=0;
    for (k=0;k<num;k++)
    {
      *(PixelBuf+j*8)=(*(PixelBuf+j*8)) | (*(PlaneBuf[k]+j) >> 7) << k;
      *(PixelBuf+j*8+1)=(*(PixelBuf+j*8+1)) | ((*(PlaneBuf[k]+j) >> 6) & 1) << k;
      *(PixelBuf+j*8+2)=(*(PixelBuf+j*8+2)) | ((*(PlaneBuf[k]+j) >> 5) & 1) << k;
      *(PixelBuf+j*8+3)=(*(PixelBuf+j*8+3)) | ((*(PlaneBuf[k]+j) >> 4) & 1) << k;
      *(PixelBuf+j*8+4)=(*(PixelBuf+j*8+4)) | ((*(PlaneBuf[k]+j) >> 3) & 1) << k;
      *(PixelBuf+j*8+5)=(*(PixelBuf+j*8+5)) | ((*(PlaneBuf[k]+j) >> 2) & 1) << k;
      *(PixelBuf+j*8+6)=(*(PixelBuf+j*8+6)) | ((*(PlaneBuf[k]+j) >> 1) & 1) << k;
      *(PixelBuf+j*8+7)=(*(PixelBuf+j*8+7)) | (*(PlaneBuf[k]+j) & 1) << k;
    }
  }
  return 1;
}

/*----------------------------------------------------------------------------*/

BYTE
LoadIlbm(struct Pic *Picture,char *Name)
{
  char text[10];
  UBYTE Buffer[5],Planes,ret;
  ULONG Chunk;
  WORD WBuffer[2],xdim,ydim;
  LONG Bmhd,Camg,Cmap,Body,Length,FLength,Pos;
  Bmhd=0; Camg=0; Cmap=0; Body=0;
  if (file=Open(Name,MODE_OLDFILE))
  {
    Read(file,&Chunk,4);
    if (Chunk==0x464F524D)
    {
      Read(file,&FLength,4);
      Read(file,&Chunk,4);
      if (Chunk==0x494C424D)
      {
        Pos=12;
        FLength=FLength-4;
        while((!Body) && (FLength>0))
        {
          Read(file,&Chunk,4);
          Pos=Pos+8;
          FLength=FLength-8;
          if (Chunk==0x424D4844) Bmhd=Pos;
          if (Chunk==0x43414D47) Camg=Pos;
          if (Chunk==0x434D4150) Cmap=Pos;
          if (Chunk==0x424F4459) Body=Pos;
          Read(file,&Length,4);
          Length=((Length+1) >> 1) << 1;
          Seek(file,Length,OFFSET_CURRENT);
          Pos=Pos+Length;
          FLength=FLength-Length;
        }
        if ((Bmhd) && (Body))
        {
          if (Camg)
          {
            Seek(file,Camg,OFFSET_BEGINNING);
            Read(file,&ModeID,4);
          }
          else
          {
            ModeID=0;
          }
          Seek(file,Bmhd,OFFSET_BEGINNING);
          Read(file,&WBuffer[0],4);
          xdim=WBuffer[0];
          ydim=WBuffer[1];
          Read(file,&Buffer[0],4);
          Read(file,&Buffer[0],4);
          Planes=Buffer[0];
          if (Planes>24) Planes=24;
          Compr=Buffer[2];
          if (AllocLines(Planes,xdim))
          {
            if (Planes==24)
            {
              if (Picture->r)
              {
                FreeVec(Picture->r);
                Picture->r=0;
              }
              if (Picture->g)
              {
                FreeVec(Picture->g);
                Picture->g=0;
              }
              if (Picture->b)
              {
                FreeVec(Picture->b);
                Picture->b=0;
              }
              Picture->width=xdim;
              Picture->height=ydim;
              Seek(file,Body,OFFSET_BEGINNING);
              if (Picture->r=(UBYTE *)AllocVec(xdim*ydim,0))
              {
                if (Picture->g=(UBYTE *)AllocVec(xdim*ydim,0))
                {
                  if (Picture->b=(UBYTE *)AllocVec(xdim*ydim,0))
                  {
                    for (i=0;i<ydim;i++)
                    {
                      if (!(ReadLine(Planes,xdim)))
                      {
                        Close(file);
                        return 0;
                      }
                      for (j=0;j<xdim;j++)
                      {
                        *(Picture->b+j+i*xdim)=(*(PixelBuf+j) >> 16) & 0xFF;
                        *(Picture->g+j+i*xdim)=(*(PixelBuf+j) >> 8) & 0xFF;
                        *(Picture->r+j+i*xdim)=*(PixelBuf+j) & 0xFF;
                      }
                    }
                  }
                  else
                  {
                    FreeVec(Picture->r); Picture->r=0;
                    FreeVec(Picture->g); Picture->g=0;
                    Picture->width=0;
                    Picture->height=0;
                    ShowError(&MemoryError);
                  }
                }
                else
                {
                  FreeVec(Picture->r); Picture->r=0;
                  Picture->width=0;
                  Picture->height=0;
                  ShowError(&MemoryError);
                }
              }
              else
              {
                Picture->width=0;
                Picture->height=0;
                ShowError(&MemoryError);
              }
              ret=1;
            }
            else
            {
              if (Cmap)
              {
                Seek(file,Cmap,OFFSET_BEGINNING);
                NumColours=2 << Planes;
                if (Colours=(UBYTE *)AllocVec(3*NumColours,0))
                {
                  Read(file,Colours,NumColours*3);
                  if (Picture->r)
                  {
                    FreeVec(Picture->r);
                    Picture->r=0;
                  }
                  if (Picture->g)
                  {
                    FreeVec(Picture->g);
                    Picture->g=0;
                  }
                  if (Picture->b)
                  {
                    FreeVec(Picture->b);
                    Picture->b=0;
                  }
                  Picture->width=xdim;
                  Picture->height=ydim;
                  Seek(file,Body,OFFSET_BEGINNING);
                  if (Picture->r=(UBYTE *)AllocVec(xdim*ydim,0))
                  {
                    if (Picture->g=(UBYTE *)AllocVec(xdim*ydim,0))
                    {
                      if (Picture->b=(UBYTE *)AllocVec(xdim*ydim,0))
                      {
                        for (i=0;i<ydim;i++)
                        {
                          if (!(ReadLine(Planes,xdim)))
                          {
                            Close(file);
                            return 0;
                          }
                          if (ModeID & HAM_KEY)
                          {
                            r=(*(Colours) >> 16) & 0xFF;
                            g=(*(Colours) >> 8) & 0xFF;
                            b=*(Colours) & 0xFF;
                            for (j=0;j<xdim;j++)
                            {
                              if (Planes==6)
                              {
                                if (*(PixelBuf+j)<16)
                                {
                                  r=*(Colours+*(PixelBuf+j)*3);
                                  g=*(Colours+*(PixelBuf+j)*3+1);
                                  b=*(Colours+*(PixelBuf+j)*3+2);
                                  *(Picture->r+j+i*xdim)=r;
                                  *(Picture->g+j+i*xdim)=g;
                                  *(Picture->b+j+i*xdim)=b;
                                }
                                else
                                {
                                  if (*(PixelBuf+j)<32)
                                  {
                                    b=(*(PixelBuf+j)-16) << 4;
                                    *(Picture->r+j+i*xdim)=r;
                                    *(Picture->g+j+i*xdim)=g;
                                    *(Picture->b+j+i*xdim)=b;
                                  }
                                  else
                                  {
                                    if (*(PixelBuf+j)<48)
                                    {
                                      r=(*(PixelBuf+j)-32) << 4;
                                      *(Picture->r+j+i*xdim)=r;
                                      *(Picture->g+j+i*xdim)=g;
                                      *(Picture->b+j+i*xdim)=b;
                                    }
                                    else
                                    {
                                      g=(*(PixelBuf+j)-48) << 4;
                                      *(Picture->r+j+i*xdim)=r;
                                      *(Picture->g+j+i*xdim)=g;
                                      *(Picture->b+j+i*xdim)=b;
                                    }
                                  }
                                }
                              }
                              else
                              {
                                if (*(PixelBuf+j)<64)
                                {
                                  r=*(Colours+*(PixelBuf+j)*3);
                                  g=*(Colours+*(PixelBuf+j)*3+1);
                                  b=*(Colours+*(PixelBuf+j)*3+2);
                                  *(Picture->r+j+i*xdim)=r;
                                  *(Picture->g+j+i*xdim)=g;
                                  *(Picture->b+j+i*xdim)=b;
                                }
                                else
                                {
                                  if (*(PixelBuf+j)<128)
                                  {
                                    b=(*(PixelBuf+j)-64) << 2;
                                    *(Picture->r+j+i*xdim)=r;
                                    *(Picture->g+j+i*xdim)=g;
                                    *(Picture->b+j+i*xdim)=b;
                                  }
                                  else
                                  {
                                    if (*(PixelBuf+j)<192)
                                    {
                                      r=(*(PixelBuf+j)-128) << 2;
                                      *(Picture->r+j+i*xdim)=r;
                                      *(Picture->g+j+i*xdim)=g;
                                      *(Picture->b+j+i*xdim)=b;
                                    }
                                    else
                                    {
                                      g=(*(PixelBuf+j)-192) << 2;
                                      *(Picture->r+j+i*xdim)=r;
                                      *(Picture->g+j+i*xdim)=g;
                                      *(Picture->b+j+i*xdim)=b;
                                    }
                                  }
                                }
                              }
                            }
                          }
                          else
                          {
                            for (j=0;j<xdim;j++)
                            {
                              *(Picture->r+j+i*xdim)=*(Colours+*(PixelBuf+j)*3);
                              *(Picture->g+j+i*xdim)=*(Colours+*(PixelBuf+j)*3+1);
                              *(Picture->b+j+i*xdim)=*(Colours+*(PixelBuf+j)*3+2);
                            }
                          }
                        }
                      }
                      else
                      {
                        FreeVec(Picture->r); Picture->r=0;
                        FreeVec(Picture->g); Picture->g=0;
                        Picture->width=0;
                        Picture->height=0;
                        ShowError(&MemoryError);
                      }
                    }
                    else
                    {
                      FreeVec(Picture->r); Picture->r=0;
                      Picture->width=0;
                      Picture->height=0;
                      ShowError(&MemoryError);
                    }
                  }
                  else
                  {
                    Picture->width=0;
                    Picture->height=0;
                    ShowError(&MemoryError);
                  }
                  FreeVec(Colours);
                  Colours=0;
                  ret=1;
                }
                else
                {
                  ShowError(&MemoryError);
                }
              }
              else
              {
                ret=0;
              }
            }
            RemLines(Planes);
          }
          else
          {
            ShowError(&MemoryError);
            ret=1;
          }
        }
        else
        {
          ret=0;
        }
      }
      else
      {
        ret=0;
      }
    }
    else
    {
      ret=0;
    }
    Close(file);
  }
  else
  {
    ret=0;
  }
  return(ret);
}

/*----------------------------------------------------------------------------*/

void
LoadPic(struct Pic *Picture,STRPTR Title)
{
  struct request *FileRequester;
  struct FileLock *lock;
  if (FileRequester=(struct request *)AllocAslRequestTags(ASL_FileRequest,
                                                          ASLFR_TitleText,  Title,
                                                          ASLFR_Window,     CommandWindow,
                                                          ASLFR_DoPatterns, TRUE,
                                                          TAG_DONE))
  {
    if (AslRequest(FileRequester,0))
    {
      lock=(struct FileLock *)CurrentDir(Lock(((struct FileRequester *) FileRequester)->rf_Dir,ACCESS_READ));
      Name=((struct FileRequester *) FileRequester)->rf_File;
      if (!(LoadIlbm(Picture,Name)))
      {
        if (LPicture=NewDTObject(Name,
                                 DTA_SourceType,  DTST_FILE,
                                 DTA_GroupID,     GID_PICTURE,
                                 PDTA_Remap,      FALSE,
                                 TAG_DONE))
        {
          if (DoMethod(LPicture,DTM_PROCLAYOUT,NULL,TRUE))
          {
            if (GetDTAttrs(LPicture,
                PDTA_BitMapHeader, &BitMapHeader,
                PDTA_ModeID,       &ModeID,
                TAG_DONE))
            {
              if (BitMapHeader->bmh_Depth<=8)
              {
                if (GetDTAttrs(LPicture,
                    PDTA_CRegs,        &Colours,
                    PDTA_NumColors,    &NumColours,
                    PDTA_BitMap,       &BitMap,
                    TAG_DONE))
                {
                  if (VirtRast=(struct RastPort *)AllocVec(sizeof(*VirtRast),0))
                  {
                    InitRastPort(VirtRast);
                    VirtRast->BitMap=BitMap;
                    Picture->width=BitMapHeader->bmh_Width;
                    Picture->height=BitMapHeader->bmh_Height;
                    xmax=Picture->width;
                    ymax=Picture->height;
                    if (Picture->r)
                    {
                      FreeVec(Picture->r);
                      Picture->r=0;
                    }
                    if (Picture->g)
                    {
                      FreeVec(Picture->g);
                      Picture->g=0;
                    }
                    if (Picture->b)
                    {
                      FreeVec(Picture->b);
                      Picture->b=0;
                    }
                    if (Picture->r=(UBYTE *)AllocVec((Picture->width)*(Picture->height),0))
                    {
                      if (Picture->g=(UBYTE *)AllocVec((Picture->width)*(Picture->height),0))
                      {
                        if (Picture->b=(UBYTE *)AllocVec((Picture->width)*(Picture->height),0))
                        {
                          if (BitMap->Depth<=24)
                          {
                            if (ModeID & HAM_KEY)
                            {
                              if (BitMap->Depth==8)
                              {
                                for (y=0;y<ymax;y++)
                                {
                                  r=*(Colours) >> 24;
                                  g=*(Colours+1) >> 24;
                                  b=*(Colours+2) >> 24;
                                  for (x=0;x<xmax;x++)
                                  {
                                    c=ReadPixel(VirtRast,x,y);
                                    if (c<64)
                                    {
                                      r=*(Colours+c*3) >> 24;
                                      *((Picture->r)+x+y*xmax)=r;
                                      g=*(Colours+c*3+1) >> 24;
                                      *((Picture->g)+x+y*xmax)=g;
                                      b=*(Colours+c*3+2) >> 24;
                                      *((Picture->b)+x+y*xmax)=b;
                                    }
                                    else
                                    {
                                      if (c<128)
                                      {
                                        b=(b & 3)+((c-64)*4);
                                        *((Picture->r)+x+y*xmax)=r;
                                        *((Picture->g)+x+y*xmax)=g;
                                        *((Picture->b)+x+y*xmax)=b;
                                      }
                                      else
                                      {
                                        if (c<192)
                                        {
                                          r=(r & 3)+((c-128)*4);
                                          *((Picture->r)+x+y*xmax)=r;
                                          *((Picture->g)+x+y*xmax)=g;
                                          *((Picture->b)+x+y*xmax)=b;
                                        }
                                        else
                                        {
                                          g=(g & 3)+((c-192)*4);
                                          *((Picture->r)+x+y*xmax)=r;
                                          *((Picture->g)+x+y*xmax)=g;
                                          *((Picture->b)+x+y*xmax)=b;
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                              else
                              {
                                for (y=0;y<ymax;y++)
                                {
                                  r=*(Colours) >> 24;
                                  g=*(Colours+1) >> 24;
                                  b=*(Colours+2) >> 24;
                                  for (x=0;x<xmax;x++)
                                  {
                                    c=ReadPixel(VirtRast,x,y);
                                    if (c<16)
                                    {
                                      r=*(Colours+c*3) >> 24;
                                      *((Picture->r)+x+y*xmax)=r;
                                      g=*(Colours+c*3+1) >> 24;
                                      *((Picture->g)+x+y*xmax)=g;
                                      b=*(Colours+c*3+2) >> 24;
                                      *((Picture->b)+x+y*xmax)=b;
                                    }
                                    else
                                    {
                                      if (c<32)
                                      {
                                        b=((c-16)*16);
                                        *((Picture->r)+x+y*xmax)=r;
                                        *((Picture->g)+x+y*xmax)=g;
                                        *((Picture->b)+x+y*xmax)=b;
                                      }
                                      else
                                      {
                                        if (c<48)
                                        {
                                          r=((c-32)*16);
                                          *((Picture->r)+x+y*xmax)=r;
                                          *((Picture->g)+x+y*xmax)=g;
                                          *((Picture->b)+x+y*xmax)=b;
                                        }
                                        else
                                        {
                                          g=((c-48)*16);
                                          *((Picture->r)+x+y*xmax)=r;
                                          *((Picture->g)+x+y*xmax)=g;
                                          *((Picture->b)+x+y*xmax)=b;
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                            else
                            {
                              for (y=0;y<ymax;y++)
                              {
                                for (x=0;x<xmax;x++)
                                {
                                  c=ReadPixel(VirtRast,x,y);
                                  *((Picture->r)+x+y*xmax)=*(Colours+c*3) >> 24;
                                  *((Picture->g)+x+y*xmax)=*(Colours+c*3+1) >> 24;
                                  *((Picture->b)+x+y*xmax)=*(Colours+c*3+2) >> 24;
                                }
                              }
                            }
                          }
                          else
                          {
                            ShowError(&LoadPicError);
                          }
                        }
                        else
                        {
                          FreeVec(Picture->r); Picture->r=0;
                          FreeVec(Picture->g); Picture->g=0;
                          ShowError(&MemoryError);
                        }
                      }
                      else
                      {
                        FreeVec(Picture->r); Picture->r=0;
                        ShowError(&MemoryError);
                      }
                    }
                    else
                    {
                      ShowError(&MemoryError);
                    }
                  }
                  else
                  {
                    ShowError(&MemoryError);
                  }
                  FreeVec(VirtRast);
                }
                else
                {
                  ShowError(&LoadPicError);
                }
              }
              else
              {
                ShowError(&LoadPicError);
              }
            }
            else
            {
              ShowError(&LoadPicError);
            }
          }
          else
          {
            ShowError(&LoadPicError);
          }
          DisposeDTObject(LPicture);
        }
        else
        {
          ShowError(&LoadPicError);
        }
      }
      UnLock(CurrentDir(lock));
    }
    FreeAslRequest(FileRequester);
  }
  else
  {
    ShowError(&MemoryError);
  }
}

/*----------------------------------------------------------------------------*/

void
SavePic(struct Pic *Picture,STRPTR Title)
{
  struct request *FileRequester;
  struct FileLock *lock;
  LONG ww,Length,Buff;
  BYTE cod;
  UWORD BMHD[]={0x0000,0x0014,0x0000,0x0000,0x0000,0x0000,0x1800,0x0100,0x0000,
                0x0000,0x0000,0x0000};
  if (FileRequester=(struct request *)AllocAslRequestTags(ASL_FileRequest,
                                                          ASLFR_TitleText,  Title,
                                                          ASLFR_Window,     CommandWindow,
                                                          ASLFR_DoPatterns, TRUE,
                                                          TAG_DONE))
  {
    if (AslRequest(FileRequester,0))
    {
      lock=(struct FileLock *)CurrentDir(Lock(((struct FileRequester *) FileRequester)->rf_Dir,ACCESS_READ));
      Name=((struct FileRequester *) FileRequester)->rf_File;
      if (file=Open(Name,MODE_NEWFILE))
      {
        Length=0;
        Buff=0x464F524D;
        Write(file,&Buff,4);
        Buff=0x00000000;
        Write(file,&Buff,4);
        Buff=0x494C424D;
        Write(file,&Buff,4);
        Buff=0x424D4844;
        Write(file,&Buff,4);
        BMHD[2]=Picture->width; BMHD[10]=Picture->width;
        BMHD[3]=Picture->height; BMHD[11]=Picture->height;
        Write(file,&BMHD[0],24);
        Buff=0x424F4459;
        Write(file,&Buff,4);
        Buff=0x00000000;
        Write(file,&Buff,4);
        ww=((Picture->width+15) >> 4) << 1;
        if (AllocLines(24,Picture->width))
        {
          for (y=0;y<Picture->height;y++)
          {
            for (x=0;x<ww;x++)
            {
              for (i=0;i<8;i++)
              {
                *(PixelBuf+x*8+i)=*(Picture->b+i+x*8+y*Picture->width) << 16;
                *(PixelBuf+x*8+i)=*(PixelBuf+x*8+i) | *(Picture->g+i+x*8+y*Picture->width) << 8;
                *(PixelBuf+x*8+i)=*(PixelBuf+x*8+i) | *(Picture->r+i+x*8+y*Picture->width);
              }
              for (i=0;i<24;i++)
              {
                *(PlaneBuf[i]+x)=(((*(PixelBuf+x*8) >> i) & 1) << 7);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+1) >> i) & 1) << 6);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+2) >> i) & 1) << 5);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+3) >> i) & 1) << 4);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+4) >> i) & 1) << 3);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+5) >> i) & 1) << 2);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+6) >> i) & 1) << 1);
                *(PlaneBuf[i]+x)=*(PlaneBuf[i]+x) | (((*(PixelBuf+x*8+7) >> i) & 1));
              }
            }
            for (i=0;i<24;i++)
            {
              x=0;
              while(x<ww)
              {
                if (x+1==ww)
                {
                  cod=0;
                  Write(file,&cod,1);
                  Write(file,PlaneBuf[i]+x,1);
                  x=x+cod+1;
                  Length=Length+2;
                }
                else
                {
                  if (*(PlaneBuf[i]+x)==*(PlaneBuf[i]+x+1))
                  {
                    cod=-1;
                    while ((cod >-127) && (x-cod+1<ww) && (*(PlaneBuf[i]+x-cod)==*(PlaneBuf[i]+x-cod+1)))
                    {
                      cod=cod-1;
                    }
                    Write(file,&cod,1);
                    Write(file,PlaneBuf[i]+x,1);
                    x=x-cod+1;
                    Length=Length+2;
                  }
                  else
                  {
                    cod=0;
                    while ((cod <126) && (x+cod+1<ww) && (!(*(PlaneBuf[i]+x+cod+1)==*(PlaneBuf[i]+x+cod+2))))
                    {
                      cod=cod+1;
                    }
                    Write(file,&cod,1);
                    Write(file,PlaneBuf[i]+x,cod+1);
                    x=x+cod+1;
                    Length=Length+cod+2;
                  }
                }
              }
            }
          }
          if (Length & 1)
          {
            cod=128;
            Write(file,&cod,1);
            Length=Length+1;
          }
          Seek(file,44,OFFSET_BEGINNING);
          Write(file,&Length,4);
          Seek(file,4,OFFSET_BEGINNING);
          Length=Length+40;
          Write(file,&Length,4);
          RemLines(24);
        }
        else
        {
          ShowError(&MemoryError);
        }
        Close(file);
      }
      else
      {
        ShowError(&FileError);
      }
      UnLock(CurrentDir(lock));
    }
    FreeAslRequest(FileRequester);
  }
  else
  {
    ShowError(&MemoryError);
  }
}

/*----------------------------------------------------------------------------*/

/* End of Text */
