/* ==== ICONEDIT.c --- A basic Icon Editor ====  */

#include "iconedit.h"
#include "stdio.h"
#include "mouse.h"

#define GRIDWIDTH  8
#define ICONSIZE  16


                                   /* Default Icon Data                 */
Icon Icon1 = {
               0x03,0x00,0x00,0x00,0x00, 0xF8,0x00,0x00,0x00,0x00,
               0x07,0x00,0x03,0x03,0x03, 0xFC,0x00,0xF8,0xF8,0xF8,
               0x0F,0x00,0x07,0x07,0x07, 0xF8,0x70,0x70,0x70,0x80,
               0x0F,0x00,0x06,0x06,0x07, 0xF8,0xF0,0xD0,0xD0,0x40,
               0x0F,0x00,0x06,0x06,0x07, 0xFC,0xF8,0xF8,0xF8,0x00,
               0x0F,0x01,0x05,0x05,0x06, 0xF8,0xE0,0xE0,0xE0,0x10,
               0x0F,0x01,0x05,0x05,0x06, 0xF8,0x70,0x70,0x50,0xB0,
               0x0F,0x01,0x01,0x01,0x00, 0xFC,0xB8,0xB8,0xB8,0x40,
               0x3F,0x00,0x00,0x0F,0x02, 0xFE,0x00,0x00,0xCC,0x0C,
               0x7F,0x00,0x00,0x3F,0x21, 0xFE,0x00,0x00,0xFC,0x0C,
               0x7F,0x00,0x00,0x33,0x30, 0xFC,0x00,0x00,0xF0,0xC0,
               0x3F,0x00,0x00,0x03,0x00, 0xFC,0x00,0x00,0xC0,0x00,
               0x3F,0x18,0x18,0x1B,0x1B, 0xFE,0x04,0x04,0xF4,0x04,
               0x7F,0x30,0x30,0x3F,0x30, 0xFE,0x0C,0x0C,0xFC,0xCC,
               0x7F,0x20,0x20,0x27,0x20, 0xFC,0x18,0x18,0x18,0x18,
               0x27,0x00,0x00,0x00,0x00, 0x18,0x00,0x00,0x00,0x00 
             };


void far Gxy(int x,int y)          /* Set BIOS current text position    */
{
 union REGS Regs;                  /* Registers to use with int86       */

 Regs.h.ah=2;
 Regs.h.al=0;
 Regs.x.bx=0;
 Regs.h.dh=y-1;
 Regs.h.dl=x-1;
 int86(0x10,&Regs,&Regs);
};


void Open_File()                   /* Prompt & save icon to a file      */
{
 FILE *In_Block;
 char Filename[80];
 int i; 
                         
 Gxy(1,23);                        /* Locate and place prompt           */
 printf("Enter Filename : ");
 scanf ("%s",Filename);            /* Get the filename                  */
 Gxy(1,23);
 for (i=0; i<40; i++) printf(" "); /* Wipe out the prompt line          */
                                             
 In_Block=fopen(Filename,"rb");                                     
 fread(&Icon1,sizeof(Icon),1,In_Block);                               
 fclose(In_Block);                                                    
};


void Save_File()                   /* Prompt & retrieve icon from a file*/
{
 FILE *Out_Block;
 char Filename[80];
 int i;

 Gxy(1,23);                        /* Locate and place prompt           */
 printf("Enter Filename : ");
 scanf ("%s",Filename);            /* Get the filename                  */
 Gxy(1,23);
 for (i=0; i<40; i++) printf(" "); /* Wipe out the prompt line          */
                         
 Out_Block=fopen(Filename,"wb");
 fwrite(&Icon1,sizeof(Icon),1,Out_Block);
 fclose(Out_Block);                                                    
};


void Draw_Grid(int CX,int CY, int GRIDCOLOR, int Cursor)
{
 int i,j;                          /* Loop variables                    */

 for (j=0; j<=ICONSIZE; j++)       /* Generate the grid for editor      */
  for (i=0; i<=ICONSIZE*GRIDWIDTH; i++)
    {
     Set_Pixel(i,j*GRIDWIDTH,GRIDCOLOR);
     Set_Pixel(j*GRIDWIDTH,i,GRIDCOLOR);
    };

 if (Cursor==TRUE)
  for (i=0; i<=GRIDWIDTH; i++)     /* Draw the cursor position          */
    {
     Set_Pixel(CX*GRIDWIDTH+i,CY*GRIDWIDTH,GRIDCOLOR+1);   
     Set_Pixel(CX*GRIDWIDTH+i,CY*GRIDWIDTH+GRIDWIDTH,GRIDCOLOR+1);
     Set_Pixel(CX*GRIDWIDTH,CY*GRIDWIDTH + i,GRIDCOLOR+1);
     Set_Pixel(CX*GRIDWIDTH+GRIDWIDTH,CY*GRIDWIDTH + i,GRIDCOLOR+1);
    };
};


void Update_Status(int CC, int BC) /* Display Current and Bkgnd Color   */
{
 int i,j;                          /* Loop variables                    */

 for (j=0; j<=7; j++)              /* Small Sample Color Blocks         */
  for (i=0; i<=7; i++)
    {
     Set_Pixel(i+168,j+16,CC);     /* Current Drawing Color             */
     Set_Pixel(i+204,j+16,BC);     /* Background Color for Masking      */
    };
};

void SetColor(int CX, int CY, int CCOLOR) /* Draw color block in grid   */
{
 int i,j;                          /* Loop variables                    */

 for (i=0; i<GRIDWIDTH; i++)       /* Fill Color Block in Grid          */
  for (j=0; j<GRIDWIDTH; j++)
   {                               /* If Masking Draw an X              */
    if (CCOLOR==-1)
     {
      if (((i+j+1)==GRIDWIDTH) || (i==j)) /* Is Position in the X       */
       {
        Set_Pixel(CX*GRIDWIDTH+i,CY*GRIDWIDTH+i,8);   
        Set_Pixel(CX*GRIDWIDTH+(GRIDWIDTH-i-1),CY*GRIDWIDTH+i,8);   
       }                                  /* Black out other not in X   */
      else Set_Pixel(CX*GRIDWIDTH + i,CY*GRIDWIDTH + j,0);   
     }
    else                           /* Not Masking, Fill all pixels      */
     Set_Pixel(CX*GRIDWIDTH + i,CY*GRIDWIDTH + j,CCOLOR);   
   };
};



void SetPos(int CX, int CY, int CCOLOR)  /* Draw color block and set    */
{                                  /*       data bits in icon data      */
 int i,j,HByte;                    /* Loop variables                    */

 HByte=CX / 8;                     /* Which Horizontal Byte??           */
                                   
 SetColor(CX,CY,CCOLOR);           /* Color the block in the grid       */

 /* Set the bits in the icon data */

 if (CCOLOR==-1)                   /* === Masking ===                   */
  {
   for (i=0; i<=3; i++)
      Icon1[CY].Pos[HByte].Plane[i] &= (char) ((0x01 << (7+(HByte*8)-CX)) ^ 0xff);
   Icon1[CY].Pos[HByte].MaskByte &= (char) ((0x01 << (7+(HByte*8)-CX)) ^ 0xff);
  }
 else                              /* === No Masking ===                */
  {
   for (i=0; i<=3; i++)
   {
    j=1 << i;
    if (j & CCOLOR)                /* Is this bit set                   */
      Icon1[CY].Pos[HByte].Plane[i] |=  (0x01 << (7+(HByte*8)-CX)); 
    else                           /* Bit not set                       */
      Icon1[CY].Pos[HByte].Plane[i] &= (char) ((0x01 << (7+(HByte*8)-CX)) ^ 0xff);
   };                              /* Turn off masking since color      */
   Icon1[CY].Pos[HByte].MaskByte |= (char) (0x01 << (7+(HByte*8)-CX));
  };
};


void Scan_Icon()                   /* Redraw grid display from icon data*/
{
 int i,j;                          /* Loop variables                    */
 int CX,CY,CCOLOR;                 /* Current X,Y, and Color            */
 int HByte;                        /* Current Horizontal Byte           */
 
 for (CX=0; CX<ICONSIZE; CX++)     /* Scan through each pixel location  */
  for (CY=0; CY<ICONSIZE; CY++)
   {
    CCOLOR=0;                      /* Start with Black                  */
    HByte=CX / 8;                  /* Which Horizontal Position (Byte)  */

    if ((Icon1[CY].Pos[HByte].MaskByte & (0x01 << (7+(HByte*8)-CX))) == 0)
     CCOLOR = -1;                  /* Its masked out                    */

    if (CCOLOR==0)                 /* Not Masked                        */
     {
      for (i=0; i<=3; i++)         /* Determine color from the planes   */
      {
       j=1 << i;
       if ((Icon1[CY].Pos[HByte].Plane[i] & (0x01 << (7+(HByte*8)-CX))) != 0)
        CCOLOR |= j;               /* If bit set, set bit in color      */
      };
     };
   
    SetColor(CX,CY,CCOLOR);        /* Set the block in the grid         */
   };
};



void Update_Icon(int BCOLOR)       /* Redraw the icon displays at right */
{
 int i,j;                          /* Loop variables                    */

 Copy_Icon   (36,24,36,40);        /* Clear Display Position(Copy Black)*/
 Display_Icon(36,40,Icon1);        /* Draw the icon on Black Background */

 for (i=0; i<ICONSIZE; i++)        /* Draw a region in the BackColor    */
  for (j=0; j<ICONSIZE; j++)
   {
    Set_Pixel(36*8 + i,56 + j,BCOLOR);   
   };
 Display_Icon(36,56,Icon1);        /* Draw the icon masked on BackColor */
};


void Draw_Text()                   /* Draw all screen text              */
{
 int i;

 Gxy(21,1);  printf("CUR BACK");

 Gxy(21,6);  printf("C olor");
 Gxy(21,7);  printf("B kgnd Color");
 Gxy(21,8);  printf("G rid Color");
 Gxy(21,9);  printf("O pen");
 Gxy(21,10); printf("S ave");

 Gxy(21,12); printf("Q uit");

 Gxy(12,19);  printf("Icon Editor");
 Gxy(10,20); printf("By Peder Jungck");
 Gxy(10,21); printf("Copyright  1991");
};


void main ()
{
 char ch;                          /* User Input Variable               */
 int CurX,CurY;                    /* Current Cursor X,Y Offset         */
 int CurColor,GridColor,BackColor; /* Colors                            */
 char Quit = FALSE;                /* Main Event Loop Status            */
 int i;                            /* Loop Variable                     */
 int Button;                       /* Which Mouse Button was pressed    */
 int MouseSupport;                 /* Is a mouse driver resident        */

 CurX=CurY=0;                      /* Cursor Position                   */
 BackColor=1;                      /* Color of Background for Mask Test */
 CurColor=15;                      /* Current Drawing Color             */
 GridColor=8;                      /* Color of Grid,Cursor Color=Grid+1 */

 Video_Mode ( 0x0d );              /* Set the video mode to 320x200x16  */

 Draw_Text();                      /* Draw the text elements of screen  */

 Update_Status(CurColor,BackColor);/* Sample Drawing & Background Color */
 Scan_Icon();                      /* Read Data and Create Enlargement  */

 if (Mouse_Exists()==TRUE)         /* Is there a mouse available        */
   {
    Draw_Grid(0,0,GridColor,FALSE);
    MouseSupport = TRUE;
    Mouse_Init();                  /* Initialize the Mouse Driver       */
    Mouse_On();
   }
 else
   {
    Draw_Grid(CurX,CurY,GridColor,TRUE);
    MouseSupport = FALSE;
   };

if (MouseSupport==TRUE) /* ============ Mouse Support ================= */
 {
 do                                /* Main Event Loop                   */
  {
   Update_Icon(BackColor);         /* Display View                      */
   Button = 0;
   do
    {
     Button = Get_Mouse_Button();  /* Wait until mouse button pressed.  */
    } while (Button == 0);         /* Some commands may need to wait    */
                                   /* until lift up, but handle later.  */

   Get_Mouse_Position(&CurX,&CurY);/* Where is the mouse?               */

   /* Are we in the grid to set the Contents */
   if ((CurX < ICONSIZE*GRIDWIDTH*2) && (CurY < ICONSIZE*GRIDWIDTH))
    {
     Mouse_Off();
     if (Button == 1)                           /* Left Button ??       */
      SetPos(CurX >> 4, CurY >> 3, CurColor);   /*  then set to Color   */
     else                                       /* Right Button ??      */
      SetPos(CurX >> 4, CurY >> 3, -1 );        /*  then set to Masking */
     Mouse_On();
    }
   else if ((CurX >= 320) && (CurX <= 332) && (CurY >= 40) && (CurY <= 96))
    {                              /* Are we in the command block ???   */
     if (CurY < 48)                /* Change the current drawing color  */
      {
       CurColor = CurColor==15 ? 0 : ++CurColor;
       Mouse_Off();
       Update_Status(CurColor,BackColor);
       Mouse_On();
       do                          /* Wait for the mouse button to be   */
         {                         /* let up in order not to auto repeat*/
          Button = Get_Mouse_Button();
         } while (Button != 0);
      }
     else if (CurY < 56)           /* Toggle the Background Color       */
      {                            
       BackColor = BackColor==15 ? 0 : ++BackColor;
       Mouse_Off();
       Update_Status(CurColor,BackColor);
       Mouse_On();
       do                          /* Wait for the mouse button to be   */
         {                         /* let up in order not to auto repeat*/
          Button = Get_Mouse_Button();
         } while (Button != 0);
      }
     else if (CurY < 64 )          /* Toggle the Grid Color             */
      {
       GridColor = GridColor==15 ? 0 : ++GridColor; 
       do                          /* Wait for the mouse button to be   */
         {                         /* let up in order not to auto repeat*/
          Button = Get_Mouse_Button();
         } while (Button != 0);
      } 
     else if (CurY < 72)           /* Open an icon file                 */
      {
       Open_File();
       Mouse_Off();
       Scan_Icon();                /* Read Data and Create Enlargement  */
       Mouse_On();
      }
     else if (CurY < 80)
      {
       Save_File();                /* Save an icon file                 */
      }
     else if (CurY > 88) Quit=TRUE;
    };

   Mouse_Off();
   Draw_Grid(0,0,GridColor,FALSE); /* Draw the Grid after update        */
   Mouse_On();
  } while (!Quit);
 }
else /* ===============  No Mouse Support ============================= */
 {
 do                                /* Main Event Loop                   */
  {
   Update_Icon(BackColor);         /* Display View                      */
   ch=getch();                     /* Wait for User Input               */

   switch (toupper(ch))            /* Select function per User Input    */
    {
     case ' ': SetPos(CurX,CurY,CurColor); break;
     case 'B': BackColor = BackColor==15 ? 0 : ++BackColor; 
               Update_Status(CurColor,BackColor);
               break;
     case 'C': CurColor = CurColor==15 ? 0 : ++CurColor; 
               Update_Status(CurColor,BackColor);
               break;
     case 'G': GridColor = GridColor==15 ? 0 : ++GridColor; 
               break;
     case 'I': CurY = CurY==0  ? CurY : --CurY; break;
     case 'J': CurX = CurX==0  ? CurX : --CurX; break;
     case 'K': CurY = CurY==15 ? CurY : ++CurY; break;
     case 'L': CurX = CurX==15 ? CurX : ++CurX; break;
     case 'M': SetPos(CurX,CurY,-1); break;
     case 'Q': Quit=TRUE; break;    /* Quit Icon Editor                 */
     case 'O': Open_File(); Scan_Icon(); break;
     case 'S': Save_File(); break;
    };
   Draw_Grid(CurX,CurY,GridColor,TRUE); /* Draw the Grid and Cursor     */
  } while (!Quit);
 };

 Video_Mode ( 3 );                  /* Properly restore text mode prior */
                                    /* to exiting to DOS.               */
};

