/*=========================================================================
 *           Envision: Font editor for Atari                              *
 ==========================================================================
 * File: envision.c                                                       *
 * Author: Mark Schmelzenbach                                             *
 * Started: 07/28/97                                                      *
 =========================================================================*/
  
#include <stdio.h>
#include <string.h>

#include <grx20.h>

#ifdef __linux__
#include <vga.h>
#include <unistd.h>
#include <fcntl.h>
#else
#include <dos.h>
#endif

#include "colours.h"
#include "font.h"
#include "envision.h"

unsigned char *dfont, *font, *copy_from, *fontbank[10];
char bank_mod[10];
int echr, bank, copy_size, values;
GrContext *upd, *dialog;

int cmds[12];
unsigned char undo[8];
opt options;
unsigned char clut[5]={0,40,202,148,70};
int orit[8]={128,64,32,16,8,4,2,1};
int andit[8]={127,191,223,239,247,251,253,254};

int corner(int all); 
/*=========================================================================*
 * Define rotation look-up tables.
 * The rotate routine is taken from a Graphics Gems II article by
 * Ken Yap (Centre for Spatial Information Systems, CSIRO DIT, Australia)
 * entitled "A Fast 90-Degree Bitmap Rotator" pp. 84-85
 * Code from this article is in the routine rotate8x8()
 *=========================================================================*/
typedef long bit32;

#define table(name,n)\
  static bit32 name[16]={\
    0x00000000<<n, 0x00000001<<n, 0x00000100<<n, 0x00000101<<n,\
    0x00010000<<n, 0x00010001<<n, 0x00010100<<n, 0x00010101<<n,\
    0x01000000<<n, 0x01000001<<n, 0x01000100<<n, 0x01000101<<n,\
    0x01010000<<n, 0x01010001<<n, 0x01010100<<n, 0x01010101<<n,\
  };
table(ltab0,7)
table(ltab1,6)
table(ltab2,5)
table(ltab3,4)
table(ltab4,3)
table(ltab5,2)
table(ltab6,1)
table(ltab7,0)
/*=========================================================================*/
char txterr(char *txt)  
{
 GrSetMode(GR_default_text);
 if (txt) printf("Fatal Error: %s",txt);
 printf("\n\nPress any key to continue...\n");
 getch();
 exit(1);
} 
/*=========================================================================*/
void setpal()
{
 unsigned char r,g,b;
 int x;

#ifdef __linux__ 
 for(x=0;x<256;x++) {
   r=(colortable[x]>>18) & 0x3f;
   g=(colortable[x]>>10) & 0x3f;
   b=(colortable[x]>>2) & 0x3f;
   vga_setpalette(x,r,g,b);
 }
#else 
 for(x=0;x<256;x++) { 
   outportb(0x3c8,x);
   r=(colortable[x]>>18) & 0x3f;
   g=(colortable[x]>>10) & 0x3f;
   b=(colortable[x]>>2) & 0x3f;
   outportb(0x3c9,r);
   outportb(0x3c9,g);
   outportb(0x3c9,b);
 } 
#endif 
}
/*=========================================================================*/
void bye(void)           
{
 int i;
#ifdef __linux__
 int con_fd;
 char *txt="EnvisionPC - v0.5";
 unsigned char buffer[40];
#endif
 
  GrSetMode(GR_default_text);
#ifdef __linux__
  printf("\x1b[H\x1b[J");
  fflush(stdout);
  if ((con_fd = open("/dev/vcsa0", O_WRONLY))) {
   for(i=0;i<strlen(txt);i++)
   { buffer[i*2]=txt[i];
     if (i>7) buffer[i*2+1]=0x07;
      else buffer[i*2+1]=0x09; }
   lseek(con_fd,4,SEEK_SET);
   write(con_fd,buffer,strlen(txt)*2); 
 } else
 printf("%s",txt);
 for(i=0;i<2;i++) {
  printf("\n");
  fflush(stdout);
 } 
#else
 textcolor(9);
 cprintf("Envision");
 textcolor(7);
 cprintf("PC - v0.5\n\r");
#endif
 exit(1);
}
/*=========================================================================*/
int topos(int c, int *sx, int *sy)
{
 *sx=(c%32)*8+8;
 *sy=160+(c>>5)*8;
}
/*=========================================================================*/
int grid(int chr, int rem)
{
 unsigned char *dat,c;
 char num[16];
 int x,y,clr;

 if (chr==echr) return 0;
 
 dat=font+(chr*8);
 
 if (rem) {
   memcpy(undo,dat,8);
 } 
 
 for(y=0;y<8;y++) {
   c=*(dat+y);
   for(x=0;x<8;x++) {
     if ((x+y)&1) clr=144; else clr=148;
     if (c&128) clr=10;
     GrFilledBox(192+x*8,32+y*8,192+x*8+7,39+y*8,clr);
     c=c<<1;
   }
 }
 topos(echr,&x,&y);
 GrFilledBox(x,y,x+7,y+7,0);
 plotchr(x,y,echr,2,font);
 echr=chr;
 topos(echr,&x,&y);
 GrFilledBox(x,y,x+7,y+7,148);
 plotchr(x,y,echr,2,font);  
 
 GrFilledBox(264,32,280,64,0);
 plotchr(264,32,echr,6,font);
 plotchr(264,40,echr,7,font);
 plotchr(264,56,echr,4,font);
 
 GrFilledBox(224,104,272,111,0);
 sprintf(num,": %d",echr);
 string(224,104,num);
 plotchr(264,104,echr,2,dfont);
 corner(0);
}
/*=========================================================================*/
int panel(int tp)
{
 GrSetContext(upd);
 GrClearContext(0);
 switch(tp) {
  case 1: {
    GrFilledBox(14,2,25,7,147);
    plotchr(16,2,36,2,dfont);
    drawbutton(0,8,"*Blank"); cmds[1]='b';
    drawbutton(0,18,"*Inverse"); cmds[2]='i';
    drawbutton(0,28,"*Undo"); cmds[3]='u';
    drawbutton(0,38,"*Atari"); cmds[4]='a';
    drawbutton(0,48,"Flip *H"); cmds[5]='h';
    drawbutton(0,58,"Flip *V"); cmds[6]='v';
    drawbutton(0,68,"*Rotate"); cmds[7]='r';
    drawbutton(0,78,"*Copy"); cmds[8]='c';
    drawbutton(0,88,"*X-copy"); cmds[9]='x';
    /*
    drawbutton(0,78,"Left *\0x7e"); cmds[8]=587;
    drawbutton(0,88,"Right *\0x7f"); cmds[9]=589; 
    drawbutton(0,98,"Up *\0x7c"); cmds[10]=584;
    drawbutton(0,108,"Down *\0x7d"); cmds[11]=592; 
    */
    drawbutton(0,98,"*T-copy"); cmds[10]='t';
    drawbutton(0,108,"*Poke"); cmds[11]='p';
    
    GrFilledBox(1,1,12,8,148);
    GrLine(0,1,0,8,144);
    GrLine(0,0,13,0,152);
    GrLine(13,1,13,7,152);
    plotchr(3,1,37,2,dfont);    
    cmds[0]=142;
    break;
  }
  case 2: {
    GrFilledBox(1,2,12,7,147);
    plotchr(3,2,37,2,dfont);
    drawbutton(0,8,"Restore"); cmds[1]='A';
    drawbutton(0,18,"*Save"); cmds[2]='s';
    drawbutton(0,28,"*Load"); cmds[3]='l';
    drawbutton(0,38,"*Export"); cmds[4]='e';
    drawbutton(0,48,"*Options"); cmds[5]='o';
    drawbutton(0,58,"Quit"); cmds[6]=17;
    GrFilledBox(14,1,24,8,148);
    GrLine(13,1,13,8,144);
    GrLine(13,0,25,0,152);
    GrLine(25,1,25,7,152);
    plotchr(16,1,36,2,dfont);    
    cmds[0]=92;
    break;
  }
 }
 GrSetContext(NULL);
 GrBitBlt(NULL,8,24,upd,0,0,64,142,GrWRITE);
}
/*=========================================================================*/
int corner(int all)
{
 int x,y,w,h,f;
 int ox,ofs;
 unsigned char *look, i, match, msk, rot;
 
 f=y=0;
 rot=6;
 if ((mode==4)||(mode==3)||(mode==2)||(mode==5)) {
  w=h=8;
  if (mode==3) h=10;
  else if (mode==5) h=16;
  msk=127;
  rot=7;
 } else if (mode==7) {
  w=h=16; msk=63;
 } else { w=16; h=8; msk=63; } 
 
 match=echr&msk;
 
 if (all) {
   GrSetContext(back);
   GrFilledBox(0,0,63,63,clut[0]);
 } else {
   GrSetContext(upd);
   GrFilledBox(0,0,w*4,h,clut[0]);
   map_plotchr(0,0,match,mode,font);
   map_plotchr(w,0,match+64,mode,font);
   map_plotchr(w*2,0,match+128,mode,font);
   map_plotchr(w*3,0,match+192,mode,font);
 }
 look=map;
 ofs=sx-64/w; 
 
 while (y<64) {
  x=0;
  while (x<64) {
    i=*look++;
    if (all) {
      f=1;
      map_plotchr(x,y,i,mode,font);
    } else if ((i&msk)==match) {
      f=1;
      ox=i>>rot;
      if (mode<6) ox=ox<<1;
      GrBitBlt(back,x,y,upd,ox*w,0,ox*w+w-1,h-1,GrWRITE);
    }
    x+=w;
  } 
  look=look+ofs;
  y+=h;
 }
 GrSetContext(NULL);
 if (f) 
   GrBitBlt(NULL,96,32,back,0,0,63,63,GrWRITE);
}
/*=========================================================================*/
int update_font(int b)
{
 int i,sx,sy;
 
 font=fontbank[b];
 bank=b;
 GrSetContext(dialog);
 GrClearContext(0);
 sx=0; sy=0;
 for(i=0;i<128;i++) {
   plotchr(sx,sy,i,2,font);
   sx+=8; 
   if (sx>248) { sx=0; sy+=8; }
 }
 GrSetContext(NULL);
 GrBitBlt(NULL,8,160,dialog,0,0,256,32,GrWRITE); 
 GrFilledBox(284,168,292,175,144);
 plotchr(284,168,16+b,2,dfont);
 corner(1);
}
/*=========================================================================*/
int draw_edit()
{
  GrMouseEvent evt;
  int i;
  
  GrMouseEraseCursor();
  GrClearContext(0); 
  string(192,104,"Char");
  GrFilledBox(271,159,305,175,144);
  string(272,160,"Font");
  plotchr(272,168,126,1,dfont);
  plotchr(296,168,127,1,dfont);
  update_font(bank);
  i=echr;
  echr=0;
  grid(i,1);
  panel(1);  
  GrMouseDisplayCursor();
  GrMouseGetEvent(GR_M_POLL, &evt);
}
/*=========================================================================*/
int setup(void)         
{
  int i;
  
  dfont=FONT;
  font=fontbank[0];
  
  for(i=0;i<10;i++) {
    fontbank[i]=(unsigned char *)malloc(1024);
    bank_mod[i]=0;
    memcpy(fontbank[i],dfont,1024);
  }  
  GrSetMode(GR_width_height_color_graphics,320,200,256);
  if ((GrScreenX()<320)|(GrScreenY()<200)|(GrNumColors()<256)) {
    txterr("Graphics driver does not support 320x200x256\n");
  }
  upd=GrCreateContext(68,136,NULL,NULL);  
  dialog=GrCreateContext(256,32,NULL,NULL);  
  back=GrCreateContext(320,192,NULL,NULL);   
  
  chars=NULL;
  copy_from=map=NULL;
  options.disk_image=NULL;
  options.base=options.step=0;
  options.write_tp=1;
  base=bank=scx=scy=cx=cy=0;
  ratio=100;
  sx=40; sy=24;
  dc=1;
  mode=2;
  echr=33;
  
  map=(unsigned char *)malloc(sx*sy);
  memset(map,0,sx*sy);
  for(i=0;i<256;i++)
    map[i]=i;
  
  title();

  setpal();
  draw_edit();
  GrMouseEraseCursor();
  #ifdef __linux__
  GrMouseSetColors(14,1); 
  #else
  FixMouse();
  #endif
  GrMouseDisplayCursor();
}
/*=========================================================================*/
int plotchr(int sx, int sy, int chr, int typ, unsigned char *fnt)
{
  unsigned char *dat,c,l;
  int x,y;
  
  dat=fnt+(chr*8);
  
  switch (typ) {
     case 1: { /* Gr. 0, button color */
    for(y=0;y<8;y++) {
     c=*(dat+y);
     for(x=0;x<8;x++) {
      if (c&128) GrPlot(sx+x,sy+y,46);
      c=c<<1;
     }
    }
    break;
   }
   case 2: { /* Gr. 0 */
    for(y=0;y<8;y++) {
     c=*(dat+y);
     for(x=0;x<8;x++) {
      if (c&128) GrPlot(sx+x,sy+y,10);
      c=c<<1;
     }
    }
    break;
   }
   case 4: { 
   for(y=0;y<8;y++) {
     c=*(dat+y);
     for(x=0;x<4;x++) {
      l=(c&192)>>6;
      if (l) { 
       GrPlot(sx+x*2,sy+y,clut[l]);
       GrPlot(sx+(x*2+1),sy+y,clut[l]);
      }
      c=c<<2;
     }
    }
    break;
   }
   case 6: { /* Gr. 1 */
    for(y=0;y<8;y++) {
     c=*(dat+y);
     for(x=0;x<8;x++) {
      if (c&128) { 
        GrPlot(sx+x*2,sy+y,clut[1]);
        GrPlot(sx+(x*2+1),sy+y,clut[1]);
      }
      c=c<<1;
     }
    }
    break;
   }
  case 7: { /* Gr. 2 */
    for(y=0;y<8;y++) {
     c=*(dat+y);
     for(x=0;x<8;x++) {
      if (c&128) { 
        GrPlot(sx+x*2,sy+y*2,clut[1]);
        GrPlot(sx+(x*2+1),sy+y*2,clut[1]);
        GrPlot(sx+x*2,sy+y*2+1,clut[1]);
        GrPlot(sx+(x*2+1),sy+y*2+1,clut[1]);
      }
      c=c<<1;
     }
    }
    break;
   }  
  default: {
    txterr("Unknown ANTIC mode requested.\n");
  }
 }
}
/*=========================================================================*/
int update(int x, int y, int c)
{
 unsigned char *dat;
 
 dat=font+echr*8+y;
 if (c) *dat=*dat|orit[x];
  else *dat=*dat&andit[x];
  
 topos(echr,&x,&y);
 GrSetContext(upd);
 GrFilledBox(0,0,7,7,148);
 plotchr(0,0,echr,2,font);  
 GrSetContext(NULL);
 GrBitBlt(NULL,x,y,upd,0,0,7,7,GrWRITE);

 GrSetContext(upd); 
 GrClearContext(0);
 plotchr(0,0,echr,6,font);
 plotchr(0,8,echr,7,font);
 plotchr(0,24,echr,4,font); 
 GrSetContext(NULL);
 GrBitBlt(NULL,264,32,upd,0,0,32,56,GrWRITE);
 corner(0);
}
/*=========================================================================*/
int click(int x, int y, int b)
{
 GrMouseEvent evt;
 int i,ox,oy;

 if (b&GR_M_LEFT_DOWN) b=1; else b=0;
  
 if ((cmds[0]==142)&&(x>=22)&&(x<=33)&&(y>=26)&&(y<=31)) {
   panel(2);
   return 0;
 } else if ((cmds[0]==92)&&(x>=9)&&(x<=20)&&(y>=26)&&(y<=31)) {
   panel(1);
   return 0;
 } else if ((x>=272)&&(x<=280)&&(y>=168)&&(y<=176)) { 
   bank--;
   if (bank<0) bank=9;
   command(48+bank,0);
   return 0;
 } else if ((x>=296)&&(x<=304)&&(y>=168)&&(y<=176)) { 
   bank++;
   if (bank>9) bank=0;
   command(48+bank,0);
   return 0;
 } else if ((x>=8)&&(x<=72)&&(y>=32)&&(y<=cmds[0])) {
   i=(y-22)/10;
   y=(y/10)*10;
   do {
     GrMouseGetEvent(GR_M_EVENT, &evt);
   } while(!(evt.flags&GR_M_BUTTON_UP));  
   if (cmds[i]) command(cmds[i],0);
   return 0;
 }
 
 if ((x>=96)&&(x<=159)&&(y>=32)&&(y<=95)) {
  x=(x-96)/8; 
  if (mode==3) y=(y-32)/10;
    else y=(y-32)/8;
  if (mode>=6) x=x/2;
  if ((mode==7)||(mode==5)) y=y/2;
  i=*(map+y*sx+x)&127;
  if (mode>=6) i=(i&63)+base/8;
  grid(i,1);
  return 0;
 }
 
 ox=x/8; oy=y/8;
 do {
  if ((x>=8)&&(x<264)&&(y>=160)&&(y<192)) {
   x=(x-8)/8; y=(y-160)/8;
   i=y*32+x;
   if (copy_from) {
     if (copy_size) {
       memcpy(undo,font+i*8,8);
       if (i*8+copy_size>1024)
         copy_size=1024-i*8;
       if (copy_size<0) {
         for(y=0;y<8;y++) 
           *(font+i*8+y)=*(font+i*8+y)|*(copy_from+y);
       } else memmove(font+i*8,copy_from,copy_size);
       GrFilledBox(8,152,160,159,0);
       if (copy_size>8) update_font(bank);
       grid(i,0);
       copy_from=NULL;
       copy_size=0;
       return 0;
     } else {
       x=font+i*8-copy_from+8;
       if ((x<0)||(x>1024)) return 0;
       else if (x==0) { 
         GrFilledBox(8,152,160,159,0);
         copy_from=NULL;
         copy_size=0;
         return 0;
       }
       copy_size=x;
       GrFilledBox(8,152,160,159,0);       
       string(8,152,"Copy range to:");
     }
     return 0;
   }
   grid(i,1);
  } else
  if ((x>=192)&&(x<256)&&(y>=32)&&(y<96)) {
   x=(x/8)*8; y=(y/8)*8;
   if (b)
     GrFilledBox(x,y,x+7,y+7,10);
   else {
     if ((x/8+y/8)&1) i=144; else i=148;
     GrFilledBox(x,y,x+7,y+7,i);
   }
   update((x-192)/8,(y-32)/8,b);
  }
  do {
   GrMouseGetEvent(GR_M_EVENT, &evt);
   x=evt.x/8; y=evt.y/8;
  } while((x==ox)&&(y==oy)&&(!(evt.flags&GR_M_BUTTON_UP)));
  ox=x; oy=y; 
  x=evt.x; y=evt.y;
 } while (!(evt.flags&GR_M_BUTTON_UP));
 
}
/*=========================================================================*/
void rotate8x8(unsigned char *src, int srcstep, unsigned char *dst, int dststep) 
{
 unsigned char *p;
 int pstep, lownyb, hinyb;
 bit32 low, hi;

 low=hi=0;

 #define extract(d,t)\
   lownyb = *d & 0xf; hinyb = *d >> 4;\
   low |= t[lownyb]; hi |= t[hinyb]; d += pstep;

 p=src; pstep=srcstep;
 extract(p,ltab0) extract(p,ltab1) extract(p,ltab2) extract(p,ltab3)
 extract(p,ltab4) extract(p,ltab5) extract(p,ltab6) extract(p,ltab7)

 #define unpack(d,w)\
   *d=w & 0xff; d+=pstep;\
   *d=(w>>8)&0xff; d+=pstep;\
   *d=(w>>16)&0xff; d+=pstep;\
   *d=(w>>24)&0xff;

  p=dst; pstep=dststep;
  unpack(p,low) p+=pstep; unpack(p,hi)
}
/*=========================================================================*/
int left(unsigned char *dat, unsigned char *work)
{
 int i;
 
 for(i=0;i<8;i++) {
  dat[i]=dat[i]*2;
  if (work[i]&128) dat[i]+=1;
 }
}
/*=========================================================================*/
int right(unsigned char *dat, unsigned char *work)
{
 int i;
 
 for(i=0;i<8;i++) {
  dat[i]=dat[i]/2;
  if (work[i]&1) dat[i]+=128;
 }
}
/*=========================================================================*/
int up(unsigned char *dat, unsigned char *work)
{
 int i;
 for(i=1;i<8;i++)
  dat[i-1]=work[i];
 dat[7]=work[0];
}
/*=========================================================================*/
int down(unsigned char *dat, unsigned char *work)
{
 int i;
 for(i=1;i<8;i++)
  dat[i]=work[i-1];
 dat[0]=work[7];
}
/*=========================================================================*/
int command(int cmd, int stat)
{
 GrMouseEvent evt;
 unsigned char *dat, l, work[8];
 int i,j;
 char buf[4], *fname;
 
 dat=font+echr*8;
 memcpy(work,dat,8);
 
 switch (cmd) {
  case '0':
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
  case '7':
  case '8':
  case '9': {
    update_font(cmd-'0');
    break;
  }
  case 'b': {
    memset(dat,0,8);
    break;
  }
  case 'i': {
    for(i=0;i<8;i++) 
     *(dat+i)=255-*(dat+i);
    break; 
  }
  case 'a': {
    memcpy(dat,dfont+echr*8,8);
    break;
  }
  case 'v': {
    for(i=0;i<8;i++)
     *(dat+i)=work[7-i];
    break;   
  }
  case 17: {
    bye();
  }
  #ifdef __linux__
  case 27: {
    buf[0]=27;
    buf[1]=buf[2]=0;
    GrMouseGetEvent(GR_M_EVENT, &evt);
    if ((evt.key==27)||(!evt.key)) bye();
      else buf[1]=evt.key;
    GrMouseGetEvent(GR_M_EVENT, &evt);
    if (evt.key) buf[2]=evt.key;
    
    if (buf[1]==91) {
      if (buf[2]==68) left(dat,work);
      else if (buf[2]==67) right(dat,work);
      else if (buf[2]==65) up(dat,work);
      else if (buf[2]==66) down(dat,work);
      else return 0;
    } else return 0;
    break;
  }
  #else
  case 27: {
    bye();
  }
  #endif
  
  case 587: {
    left(dat,work);
    break;
  }
  case 589: {
    right(dat,work);
    break;
  }
  case 584: {
    up(dat,work);
    break;
  }
  case 592: {
    down(dat,work);
    break;
  }
  case 'r': {
    rotate8x8(work,1,dat,1);
    break;
  }
  case 'u': {
    memcpy(dat,undo,8);
    memcpy(undo,work,8);
    break;
  }
  case 'h': {
    for(i=0;i<8;i++) {
      l=work[i];
      *(dat+i)=0;
      for(j=0;j<8;j++) 
        if (l&orit[j]) *(dat+i)+=orit[7-j];
    }
    break;
  }
  case 'c': {
    copy_from=dat;
    copy_size=8;
    string(8,152,"Copy to:");
    break;
  }
  case 'x': {
    copy_from=dat;
    copy_size=0;
    string(8,152,"Copying from,to:");
    break;
  }
  case 't': {
    copy_from=dat;
    copy_size=-8;
    string(8,152,"Transcopy to:");
    break;
  }
  case 'A': {
    memcpy(font,dfont,1024);
    update_font(bank);
    break;
  }
  case 'n': {
    values++;
    if (values==3) values=0;
    GrFilledBox(168,32,191,96,0);
    if (values) {
      for(i=0;i<8;i++) {
        if (values==2)
         sprintf(buf," %0.2x",work[i]);
        else
         sprintf(buf,"%3d",work[i]);
        string(168,32+i*8,buf);
      }
    }
    break;
  }
  case 's': {
    fname=get_filename("Save font:",options.disk_image);
    if (fname) {
      if (options.disk_image)
        i=write_xfd_font(options.disk_image,fname,font,1024,NULL);
      else 
        i=write_font(fname,font);
      free(fname);
    }
    break;
  }
  case 'l': {
    fname=get_filename("Load font:",options.disk_image);
    if (fname) {
      if (options.disk_image)
        i=read_xfd_font(options.disk_image,fname,font,1024);
      else 
        i=read_font(fname,font);
      free(fname); 
      update_font(bank);
    }
    break;
  }
  case 'e': {
    fname=get_filename("Export font:",options.disk_image);
    if (fname) {
      if (options.disk_image)
        i=write_xfd_data(options.disk_image,fname,font,0,127);
      else 
        i=write_data(fname,font,0,127,0);
      free(fname);
    }
    break;
  }
  case 'o': {
    do_options();
    break;
  }
  case 'p': {
    do_colors();
    corner(1);
    break;
  }
  case 'm': {
        do_map();
        draw_edit();
        return 0;
  }
  default: {
/*  printf("%d ",cmd); */
    return 0;
  }
 }
 i=echr; echr=0; grid(i,0);
 return 0;
}
/*=========================================================================*/
int edit()
{
 GrMouseEvent evt;
 int done=0;
 
 do {
  GrMouseGetEvent(GR_M_EVENT, &evt);
  if (evt.flags&GR_M_BUTTON_DOWN) 
    click(evt.x,evt.y,evt.flags);
  if (evt.flags&GR_M_KEYPRESS) 
    command(evt.key,evt.kbstat);
 } while (!done);

}
/*=========================================================================*/
int main()
{
 int i;
 
#ifndef __linux__
 atexit(bye);
#endif

 setup();
 edit();
 return 0;
}
/*=========================================================================*/
