/*
   ImageRout.c - include file for routines.

   (c)1990 Olaf Leimann
*/

/*#FOLD: definitions, structures, data */
#define IMAGE_FROM_LEFT     8
#define IMAGE_FROM_TOP     34
#define COLOUR_FROM_LEFT  296
#define COLOUR_FROM_TOP    12
#define X_BORDERWIDTH       4
#define Y_BORDERWIDTH       2
#define NUMBER_OF_INFO      5
#define NUMBER_OF_SAVE      5

char ExtraInfo1[32] = "Width :       Depth:   " ;
char ExtraInfo2[32] = "Height:       Size :       " ;
char ExtraName[128] ;

char *Info_Lines[NUMBER_OF_INFO] = {
   "Image Editor Version 1.0",
   "(c) 1990 by Olaf Leimann",
   "data of current Image :"
};
char *Save_Lines[NUMBER_OF_SAVE] = {
   "/*\n   Image source from ImageEd 1.0 (c)1990 Olaf Leimann\n*/",
   "\nUSHORT ImEd_Data[] = {",
   "\n};\n\nstruct Image ImEd_Image = {\n   ",
   "0,0,   ,   , ,&ImEd_Data[0],\n",
   "      ,   ,NULL\n};\n"
};
char *ImageEdID   = "IMED";
char  ImageSize[] = "   ,   ";
char ImageFileName[128] ;
char UndoBuffer[128] ;

UBYTE ImageMultiplier = 2 ;
UBYTE CurrentColour   = 1 ;
UBYTE ImageDrawing    = 0 ;

struct Image *ColourImages[4] =
{
   &GadImage0,
   &GadImage1,
   &GadImage2,
   &GadImage3
};

struct Image *CurrentImage = NULL ;
struct Image  FirstImage = { 0 } ;
struct Image  BackImage  = { 0 } ;

SHORT NameData[10] = {
   -4,-2,
   371-24,-2,
   371-24, 9,
   -4, 9,
   -4,-2
};

struct Border NameBorder = {
   0,0, 1,0, JAM1, 5, &NameData[0], NULL
};

struct StringInfo NameInfo = {
   (UBYTE *)&ImageFileName[0],
   (UBYTE *)&UndoBuffer[0],
   0, 128, 0
};

struct Gadget NameGadget = {
   NULL,
   12,      IMAGE_FROM_TOP + 2,
   370-24,  8,
   GADGHCOMP,
   RELVERIFY|STRINGCENTER,
   STRGADGET,
   (APTR)&NameBorder,
   NULL, NULL, 0L,
   (APTR)&NameInfo,
   100,NULL
};
/*#ENDFD*/

LONG CalcPlaneSize(struct Image *im)
/*#FOLD:*/
{
   if(im)
      if(im->PlanePick > 0)
         return ((im->Width + 0x000F)>> 4) * im->Height ;
   return 0L ;
}
/*#ENDFD*/

UBYTE CalcDepth(struct Image *im)
/*#FOLD:*/
{
   UBYTE retval,i,j ;

   retval = 0 ;
   if(im){
      j = im->PlanePick ;
      for(i=0;i<im->Depth;i++,j >>= 1)
         if(j & 0x01) retval++;
   }
   return retval ;
}
/*#ENDFD*/

#define CalcImageSize(im) (CalcPlaneSize(im) * CalcDepth(im))

VOID PutNumber(s,n,w)
   char *s ;
   LONG  n ;
   UBYTE w ;
/*#FOLD:*/
{
   if(s){
      if(n==0 && w>0) s[--w] = (n % 10) + 48 ;
      while(w>0 && n>0){
         s[--w] = (n % 10) + 48 ;
         n /= 10 ;
      }
      while(w>0) s[--w] = 32 ;
   }
}
/*#ENDFD*/

struct Image *CopyImage(im,imto)
   struct Image *im,*imto ;
/*#FOLD:*/
{
   LONG    Size,sizeto ;
   USHORT *Data ;

   if(im != NULL && imto != NULL){
      Size   = CalcImageSize(im)  << 1 ;
      sizeto = CalcImageSize(imto)<< 1 ;
      Data = imto->ImageData ;

      if(Size){
         if(Data!=NULL && Size!=sizeto){
            FreeMem((UBYTE *)Data,sizeto);
            Data = NULL ;
         }
         if(Data==NULL)
            Data=(USHORT *)AllocMem(Size,MEMF_CLEAR|MEMF_CHIP);
      }
      else if(Data){
         FreeMem((UBYTE *)Data,sizeto);
         Data = NULL ;
      }

      if(Data)
         memcpy((char *)Data,(char *)im->ImageData,Size);

      memcpy((char *)imto,(char *)im,sizeof(struct Image));

      imto->ImageData = Data ;
      imto->NextImage = NULL ;

      return(imto);
   }
   if(im==NULL && imto!=NULL){
      if(Size=(CalcImageSize(imto) << 1))
         FreeMem((UBYTE *)imto->ImageData,Size);
      imto->ImageData = NULL ;
      imto->Width = 0 ;
      imto->Height = 0 ;
      imto->Depth = 0 ;
      imto->PlanePick = 0 ;
   }
   return(NULL);
}
/*#ENDFD*/

VOID XImage(im1,im2)
   struct Image *im1,*im2 ;
/*#FOLD:*/
{
   struct Image inter ;
   if(im1!=NULL && im2!=NULL){
      memcpy((char *)&inter,(char *)im1,   sizeof(struct Image));
      memcpy((char *)im1,   (char *)im2,   sizeof(struct Image));
      memcpy((char *)im2,   (char *)&inter,sizeof(struct Image));
   }
}
/*#ENDFD*/

#define CopyBackup(im)     CopyImage(im,&BackImage)
#define ReadImage(im)      CopyImage(im,&FirstImage)
#define CopyBackImage(im)  CopyImage(&FirstImage,im)

VOID FreeData()
/*#FOLD:*/
{
   LONG Size ;

   if(FirstImage.ImageData && (Size= (CalcImageSize(&FirstImage) << 1))){
      FreeMem((UBYTE *)FirstImage.ImageData,Size);
      FirstImage.ImageData = NULL ;
   }
   if(BackImage.ImageData  && (Size= (CalcImageSize(&BackImage)  << 1))){
      FreeMem((UBYTE *)BackImage.ImageData,Size);
      BackImage.ImageData = NULL ;
   }
}
/*#ENDFD*/

VOID ChangeImage(mode)
   int mode ;
/*#FOLD:*/
{
   int Size,i ;

   if(CurrentImage){
      if(CurrentImage->ImageData){
         Size = CalcImageSize(CurrentImage);
         switch(mode){
         case 0:  /* Clear */
            for(i=0;i<Size;i++){
               CurrentImage->ImageData[i] = 0 ;
            }
            break ;
         case 1:  /* Invert */
            for(i=0;i<Size;i++){
               CurrentImage->ImageData[i] = ~ CurrentImage->ImageData[i];
            }
         }
      }
      else{
         CurrentImage->PlaneOnOff =
            (~CurrentImage->PlaneOnOff) &
            (~((-1)<< CurrentImage->Depth)) &
            (~CurrentImage->PlanePick);
      }
   }
}
/*#ENDFD*/

VOID ClearArea(win)
   struct Window *win ;
/*#FOLD:*/
{
   if(win){
      SetAPen(win->RPort,0);
      SetDrMd(win->RPort,JAM1);
      RectFill(win->RPort,
         IMAGE_FROM_LEFT - X_BORDERWIDTH,
         IMAGE_FROM_TOP  - Y_BORDERWIDTH,
         win->Width-4,win->Height-14);
      RectFill(win->RPort,
         IMAGE_FROM_LEFT - X_BORDERWIDTH,
         win->Height-13,
         win->Width -20,win->Height-2);
   }
}
/*#ENDFD*/

VOID RefreshImage(win)
   struct Window *win ;
/*#FOLD:*/
{
   int x,y,rx,ry ;
   if(win){
      ClearArea(win);
      if(CurrentImage){
         SetAPen(win->RPort,2);
         RectFill(win->RPort,
            IMAGE_FROM_LEFT - X_BORDERWIDTH,
            IMAGE_FROM_TOP  - Y_BORDERWIDTH,
            CurrentImage->Width * ImageMultiplier
               + IMAGE_FROM_LEFT + X_BORDERWIDTH,
            CurrentImage->Height * ImageMultiplier
               + IMAGE_FROM_TOP  + Y_BORDERWIDTH);
         DrawImage(win->RPort,CurrentImage,
            IMAGE_FROM_LEFT-CurrentImage->LeftEdge,
            IMAGE_FROM_TOP -CurrentImage->TopEdge);
         if(ImageMultiplier > 1){
            for(y=CurrentImage->Height;y>0;y--){
               ry = (y-1)*ImageMultiplier + IMAGE_FROM_TOP ;
               for(x=CurrentImage->Width;x>0;x--){
                  SetAPen(win->RPort,
                     ReadPixel(win->RPort,
                        x+IMAGE_FROM_LEFT-1,
                        y+IMAGE_FROM_TOP-1));
                  rx = (x-1)*ImageMultiplier + IMAGE_FROM_LEFT ;
                  RectFill(win->RPort,rx,ry,
                     rx+ImageMultiplier-1,
                     ry+ImageMultiplier-1);
               }
            }
         }
      }
   }
}
/*#ENDFD*/

VOID ShowColour(win)
   struct Window *win ;
/*#FOLD:*/
{
   if(win){
      CurrentColour &= 0x03 ;
      SetAPen(win->RPort,ColourImages[CurrentColour]->PlaneOnOff);
      SetDrMd(win->RPort,JAM1);
      RectFill(win->RPort,
         COLOUR_FROM_LEFT - 4,
         COLOUR_FROM_TOP  - 1,
         COLOUR_FROM_LEFT + 27,
         COLOUR_FROM_TOP  + 12);
      DrawImage(win->RPort,
         ColourImages[CurrentColour],
         COLOUR_FROM_LEFT,
         COLOUR_FROM_TOP);
   }
}
/*#ENDFD*/

VOID RefreshMul(win)
   struct Window *win ;
/*#FOLD:*/
{
   UBYTE Number ;
   if(win){
      SetAPen(win->RPort,1);
      SetBPen(win->RPort,2);
      SetDrMd(win->RPort,JAM2);
      Number = ImageMultiplier + 48 ;
      Move(win->RPort,334,12+win->RPort->TxBaseline);
      Text(win->RPort,&Number,1L);
   }
}
/*#ENDFD*/

VOID RefreshName(win)
   struct Window *win ;
/*#FOLD:*/
{
   strcpy(&CurrentWindowTitle[0],&FirstWindowTitle[0]);
   strcat(&CurrentWindowTitle[0]," - ");
   strncat(&CurrentWindowTitle[0],&ImageFileName[0],127);
   SetWindowTitles(win,&CurrentWindowTitle[0],(char *)-1L);
}
/*#ENDFD*/

VOID PlotImage(win,im,x,y,c)
   struct Window *win ;
   struct Image *im ;
   SHORT  x,y ;
   UBYTE  c ;
/*#FOLD:*/
{
   int    PlaneSize,Plane,index,rx,ry ;
   USHORT bit,*PlaneData ;
   UBYTE  pick ;

   if(im){
      if(x>=0 && y>=0 && x<im->Width && y<im->Height){
         if(c != (c & im->PlanePick) | im->PlaneOnOff) return ;
         SetAPen(win->RPort,c);
         SetDrMd(win->RPort,JAM1);
         PlaneSize = CalcPlaneSize(im) ;
         index = y * ((im->Width + 0x000F)>> 4) + (x >> 4);
         bit   = 1 << (15 - (x & 15));
         pick  = im->PlanePick ;
         for(Plane = 0,PlaneData = im->ImageData ;
             Plane < im->Depth ;
             Plane++,PlaneData += PlaneSize){
            if(pick & 0x01){
               if(c & 0x01)
                  PlaneData[index] |=  bit ;
               else
                  PlaneData[index] &= ~bit ;
            }
            pick >>= 1 ;
            c    >>= 1 ;
         }
         if(ImageMultiplier > 1){
            ry = y * ImageMultiplier + IMAGE_FROM_TOP ;
            rx = x * ImageMultiplier + IMAGE_FROM_LEFT ;
            RectFill(win->RPort,rx,ry,
               rx+ImageMultiplier-1,
               ry+ImageMultiplier-1);
         }
         else
            WritePixel(win->RPort,
               x + IMAGE_FROM_LEFT,
               y + IMAGE_FROM_TOP);
      }
   }
}
/*#ENDFD*/

VOID WriteHexData(file,data,length)
   BPTR    file ;
   USHORT *data ;
   LONG    length ;
/*#FOLD:*/
{
   int  c=0,c2 ;
   USHORT d;
   UBYTE  e;
   LONG buffer=0L ;

   if(file!=NULL && data!=NULL && length>0){
      while(length > 0){
         if((c % 8)==0 && c>0 && length > 1)
            Write(file,(UBYTE *)",\n   0x",7L);
         else if(c>0)
            Write(file,(UBYTE *)",0x",3L);
         else
            Write(file,(UBYTE *)"\n   0x",6L);
         d = *data ;
         for(c2=0;c2<4;c2++){
            e=(d & 0xF000) >> 12;
            d <<= 4 ;
            e  |= 0x30 ;
            if(e > 0x39) e += 7 ;
            buffer <<= 8 ;
            buffer |= e ;
         }
         Write(file,(UBYTE *)&buffer,4L);
         data ++ ;
         length --;
         c ++;
      }
   }
}
/*#ENDFD*/

VOID SaveUnder(name,mode)
   char  *name ;
   USHORT mode ;
/*#FOLD:*/
{
   BPTR file ;
   int  i;

   if(mode>=0 && mode < 2 && name!=NULL){
      if(mode>0){
         strcpy(&ExtraName[0],name);
         strncat(&ExtraName[0],".h",128);
         name = &ExtraName[0];
      }
      file=Open((UBYTE *)name,MODE_NEWFILE);
      if(file){
         if(CurrentImage){
            if(mode==0){
               Write(file,(UBYTE *)ImageEdID,4L);
               Write(file,(UBYTE *)CurrentImage,sizeof(struct Image));
               Write(file,(UBYTE *)CurrentImage->ImageData,
                  CalcImageSize(CurrentImage)<< 1);
            }
            else{
               for(i=0;i<NUMBER_OF_SAVE;i++){
                  Write(file,(UBYTE *)Save_Lines[i],
                     strlen(Save_Lines[i]));
                  switch(i){
                  case 1:
                     WriteHexData(file,CurrentImage->ImageData,
                        CalcImageSize(CurrentImage));
                     break ;
                  case 2:
                     PutNumber(&Save_Lines[3][4],
                        (LONG)CurrentImage->Width,3);
                     PutNumber(&Save_Lines[3][8],
                        (LONG)CurrentImage->Height,3);
                     PutNumber(&Save_Lines[3][12],
                        (LONG)CurrentImage->Depth,1);
                     break ;
                  case 3:
                     PutNumber(&Save_Lines[4][3],
                        (LONG)CurrentImage->PlanePick,3);
                     PutNumber(&Save_Lines[4][7],
                        (LONG)CurrentImage->PlaneOnOff,3);
                     break ;
                  }
               }
            }
         }
         Close(file);
      }
   }
}
/*#ENDFD*/

struct Image *LoadUnder(name)
   char *name ;
/*#FOLD:*/
{
   BPTR file ;
   LONG id=0,Size ;
   USHORT *buffer=NULL ;
   struct Image im,*retval ;
   if(name){
      retval = NULL ;
      file=Open(name,MODE_OLDFILE);
      if(file){
         Read(file,(UBYTE *)&id,4L);
         if(strcmp((char *)&id,ImageEdID)==0){
            Read(file,(UBYTE *)&im,sizeof(struct Image));
            im.ImageData = NULL ;
            Size=CalcImageSize(&im);
            if(Size){
               buffer = (USHORT *)AllocMem(
                  Size << 1,MEMF_CLEAR|MEMF_CHIP);
               if(buffer){
                  im.ImageData = buffer ;
                  Read(file,(UBYTE *)buffer,Size << 1);
               }
            }
            retval = ReadImage(&im) ;
            if(im.ImageData){
               FreeMem((UBYTE *)im.ImageData,Size);
               im.ImageData = NULL ;
            }
         }
         Close(file);
      }
   }
   return(retval);
}
/*#ENDFD*/

VOID Rectangle(win,im,c)
   struct Window *win ;
   struct Image  *im ;
   UBYTE          c ;
/*#FOLD:*/
{
   SetAPen(win->RPort,c);
   SetDrMd(win->RPort,JAM1);
   Move(win->RPort,
      IMAGE_FROM_LEFT,                 IMAGE_FROM_TOP);
   Draw(win->RPort,
      im->Width + IMAGE_FROM_LEFT - 1, IMAGE_FROM_TOP);
   Draw(win->RPort,
      im->Width + IMAGE_FROM_LEFT - 1, im->Height + IMAGE_FROM_TOP - 1);
   Draw(win->RPort,
      IMAGE_FROM_LEFT,                 im->Height + IMAGE_FROM_TOP - 1);
   Draw(win->RPort,
      IMAGE_FROM_LEFT,                 IMAGE_FROM_TOP);
   PutNumber(&ImageSize[0],im->Width,3);
   PutNumber(&ImageSize[4],im->Height,3);
   Move(win->RPort,
      IMAGE_FROM_LEFT + 8,
      IMAGE_FROM_TOP + 8 + win->RPort->TxBaseline);
   Text(win->RPort,&ImageSize[0],7L);
}
/*#ENDFD*/

struct Image *GetNewImage(win,msg)
   struct Window *win ;
   struct IntuiMessage *msg ;
/*#FOLD:*/
{
   struct Image im,*retval ;
   int   quit=0,Drawing=0;
   ULONG  class,Size ;
   USHORT code ;
   SHORT  Mx,My ;

   im.LeftEdge =  0 ;
   im.TopEdge  =  0 ;
   im.Width    = 16 ;
   im.Height   = 16 ;
   im.Depth    =  2 ;
   im.PlanePick   = 3 ;
   im.PlaneOnOff  = 0 ;
   im.NextImage   = NULL ;

   ClearArea(win);
   Rectangle(win,&im,1);
   while(quit==0){
      msg=(struct IntuiMessage *)GetMsg(win->UserPort);
      if(msg==NULL){
         WaitPort(win->UserPort);
         msg=(struct IntuiMessage *)GetMsg(win->UserPort);
      }
      class = msg->Class ;
      if(class==GADGETUP || class==GADGETDOWN)
         code = ((struct Gadget *)msg->IAddress)->GadgetID ;
      else
         code = msg->Code ;
      Mx = msg->MouseX ;
      My = msg->MouseY ;
      ReplyMsg((struct Message *)msg);
      switch(class){
      case CLOSEWINDOW:
            quit=-1;
            break ;
      case GADGETUP:
            if(code == 3) /* Refresh Gadget */
               quit=1;
            break ;
      case MOUSEMOVE:
            if(Drawing)
               code = SELECTDOWN ;
            else
               break ;
      case MOUSEBUTTONS:
            if(code==SELECTDOWN){
               if(Mx > IMAGE_FROM_LEFT && My > IMAGE_FROM_TOP){
                  Rectangle(win,&im,0);
                  im.Width = Mx-IMAGE_FROM_LEFT ;
                  im.Height= My-IMAGE_FROM_TOP  ;
                  Rectangle(win,&im,1);
               }
               Drawing = 1;
            }
            else
               Drawing = 0;
            break;
      }
   }
   if(quit>0){
      im.ImageData = (USHORT *)AllocMem(
         Size=(CalcImageSize(&im) << 1),MEMF_CLEAR|MEMF_CHIP);
      if(CurrentImage) CopyBackup(CurrentImage);
      if(im.ImageData) retval = ReadImage(&im);
      FreeMem((UBYTE *)im.ImageData,Size);
      im.ImageData = NULL ;
   }
   else
      retval = CurrentImage ;
   return(retval);
}
/*#ENDFD*/

VOID GetName(win,msg)
   struct Window *win ;
   struct IntuiMessage *msg ;
/*#FOLD:*/
{
   int   quit=0;
   ULONG  class ;
   USHORT code ;

      if(strlen(ImageFileName)==0)
         strcpy(ImageFileName,"WorkingImage");
      NameInfo.DispPos = 0 ;
      NameInfo.BufferPos = 0 ;
      NameGadget.Height = win->RPort->TxHeight ;
      NameData[5]= NameGadget.Height + 1 ;
      NameData[7]= NameGadget.Height + 1 ;
      ClearArea(win);
      AddGadget(win,&NameGadget,-1);
      RefreshGadgets(&NameGadget,win,NULL);
      ActivateGadget(&NameGadget,win,NULL);
      while(quit==0){
         msg=(struct IntuiMessage *)GetMsg(win->UserPort);
         if(msg==NULL){
            WaitPort(win->UserPort);
            msg=(struct IntuiMessage *)GetMsg(win->UserPort);
         }
         class = msg->Class ;
         if(class==GADGETUP || class==GADGETDOWN)
            code = ((struct Gadget *)msg->IAddress)->GadgetID ;
         else
            code = msg->Code ;
         ReplyMsg((struct Message *)msg);
         if(class==GADGETUP && code==100) quit = 1 ;
         if(class==CLOSEWINDOW) quit = 1 ;
      }
      RemoveGadget(win,&NameGadget);
}
/*#ENDFD*/

VOID ShowInfo(win)
   struct Window *win ;
/*#FOLD:*/
{
   int i,y,max;
   if(win){
      ClearArea(win);
      y   = IMAGE_FROM_TOP + win->RPort->TxBaseline ;
      max = NUMBER_OF_INFO - 3 ;
      if(CurrentImage){
         PutNumber(&ExtraInfo1[8],(LONG)CurrentImage->Width,3);
         PutNumber(&ExtraInfo2[8],(LONG)CurrentImage->Height,3);
         PutNumber(&ExtraInfo1[21],(LONG)CurrentImage->Depth,1);
         PutNumber(&ExtraInfo2[21],(LONG)CalcImageSize(CurrentImage),6);
         Info_Lines[3] = &ExtraInfo1[0] ;
         Info_Lines[4] = &ExtraInfo2[0] ;
         max = NUMBER_OF_INFO ;
      }
      for(i=0; i < max;i++,y+=win->RPort->TxHeight){
         SetAPen(win->RPort,1);
         Move(win->RPort,IMAGE_FROM_LEFT,y);
         Text(win->RPort,Info_Lines[i],strlen(Info_Lines[i]));
      }
   }
}
/*#ENDFD*/

VOID HandleImaging(win)
   struct Window *win ;
/*#FOLD:*/
{
   struct IntuiMessage *msg ;
   struct Gadget       *gad=NULL ;
   struct Image        *im ;
   int    quit = 0 ;
   ULONG  class ;
   SHORT  Mx,My ;
   USHORT code,id ;
   if(win){
      ShowColour(win);
      RefreshMul(win);
      RefreshImage(win);
      while(quit==0){
         msg = (struct IntuiMessage *)GetMsg(win->UserPort);
         if(msg==NULL){
            WaitPort(win->UserPort);
            msg = (struct IntuiMessage *)GetMsg(win->UserPort);
         }
          class = msg->Class ;
          code = msg->Code ;
          Mx = msg->MouseX ;
          My = msg->MouseY ;
          if(class == GADGETUP || class == GADGETDOWN)
             id = ((struct Gadget *)msg->IAddress)->GadgetID ;
         ReplyMsg((struct Message *)msg);
         switch(class){
/*#FOLD:*/
         case CLOSEWINDOW:
            quit=1;
            break;
         case GADGETUP:
            switch(id){
            case 1:         /* Clear */
               ChangeImage(0);
               break;
            case 2:         /* Invert */
               ChangeImage(1);
               break;
            case 3:
               break;
            }
            CopyBackup(CurrentImage);
            RefreshImage(win);
            break;
         case GADGETDOWN:
            CurrentColour=id-4;
            ShowColour(win);
            break;
         case MOUSEMOVE:
            if(ImageDrawing)
               code = SELECTDOWN ;
            else
               break ;
         case MOUSEBUTTONS:
            if(code == SELECTDOWN){    /* SetPoint */
               if(CurrentImage){
                  if(Mx > IMAGE_FROM_LEFT &&
                     My > IMAGE_FROM_TOP){
                     PlotImage(win,CurrentImage,
                        (Mx - IMAGE_FROM_LEFT)/ImageMultiplier,
                        (My - IMAGE_FROM_TOP)/ImageMultiplier,
                        CurrentColour);
                  }
                  ImageDrawing = 1 ;
               }
            }
            else ImageDrawing = 0 ;
            break;
         case MENUPICK:
            if(code!=MENUNULL)
            switch(MENUNUM(code)){
            case 0:
               switch(ITEMNUM(code)){
               case 0:
                  CurrentImage = GetNewImage(win,msg);
                  RefreshImage(win);
                  break;
               case 1:
                  if(CurrentImage) CopyBackup(CurrentImage);
                  GetName(win,msg);
                  CurrentImage = LoadUnder(&ImageFileName[0]);
                  RefreshImage(win);
                  RefreshName(win);
                  break;
               case 2:
                  if(strlen(&ImageFileName[0])){
                     if(CurrentImage)
                        SaveUnder(&ImageFileName[0],SUBNUM(code));
                     break ;
                  }
               case 3:
                  if(CurrentImage){
                     GetName(win,msg);
                     if(strlen(&ImageFileName[0]))
                        SaveUnder(&ImageFileName[0],SUBNUM(code));
                     RefreshImage(win);
                     RefreshName(win);
                  }
                  break;
               case 4:
                  quit=1;
                  break;
               case 5:
                  ShowInfo(win);
                  break;
               }
               break ;
            case 1:
               switch(ITEMNUM(code)){
               case 0:        /* Image from first gadget */
                  gad = win->FirstGadget ;
                  if(gad){
                     CopyBackup(CurrentImage);
                     im = NULL ;
                     while(gad != NULL && im == NULL){
                        if((gad->Flags & GADGIMAGE) &&
                           (gad->GadgetType & SYSGADGET))
                           im = (struct Image *)gad->GadgetRender ;
                        else
                           gad = gad->NextGadget ;
                     }
                     CurrentImage = ReadImage(im);
                     RefreshImage(win);
                  }
                  else DisplayBeep(win->WScreen);
                  break ;
               case 1:        /* Image from next gadget */
                  if(gad)       gad = gad->NextGadget ;
                  if(gad==NULL) gad = win->WScreen->FirstGadget ;
                  if(gad){
                     CopyBackup(CurrentImage);
                     im = NULL ;
                     while(gad != NULL && im == NULL){
                        if((gad->Flags & GADGIMAGE) &&
                           (gad->GadgetType & 0x00F0))
                           im = (struct Image *)gad->GadgetRender ;
                        else
                           gad = gad->NextGadget ;
                     }
                     CurrentImage = ReadImage(im);
                     RefreshImage(win);
                  }
                  else DisplayBeep(0);
                  break;
               case 2:        /* Copy back to real gadget */
                  if(gad){
                     if(gad->Flags & GADGIMAGE){
                        CopyBackImage((struct Image *)gad->GadgetRender);
                        RefreshGadgets(win->FirstGadget,win,NULL);
                     }
                  }
                  else DisplayBeep(win->WScreen);
                  break;
               }
               break ;
            case 2:
               switch(ITEMNUM(code)){
               case 0:
                  if(CalcImageSize(&BackImage)){
                     XImage(&BackImage,&FirstImage);
                     CurrentImage = &FirstImage ;
                     RefreshImage(win);
                  }
                  break;
               case 1:
                  if(ImageMultiplier < 8){
                     ImageMultiplier++;
                     RefreshMul(win);
                     if(CurrentImage)
                        RefreshImage(win);
                  }
                  break ;
               case 2:
                  if(ImageMultiplier > 1){
                     ImageMultiplier--;
                     RefreshMul(win);
                     if(CurrentImage)
                        RefreshImage(win);
                  }
                  break ;
               case 3:
                  ImageMultiplier = 1;
                  RefreshMul(win);
                  if(CurrentImage)
                     RefreshImage(win);
                  break ;
               case 4:
                  ImageMultiplier = 8;
                  RefreshMul(win);
                  if(CurrentImage)
                     RefreshImage(win);
                  break ;
               }
            }
            break;
/*#ENDFD*/
         }
      }
   }
   FreeData();
}
/*#ENDFD*/

