/*EdQuake v0.50 source code
  (c) Copyright 1996 Scott Mitting
  email:smitting@netusa1.net
  ----------------------------------
  MAPEDIT.C  -  The heart of EdQuake
		These functions do not work
		they are under developement

  __variables:
  __functions:
  ----------------------------------
  the entire source code is under renovation to make it easier
  to understand.  happy coding.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include "svgacc.h"
#include "grfx.h"
#include "pak.h"
#include "disk.h"
#include "mapedit.h"
#include "input.h"
#include "ripper.h"
#include "viewer.h"
#include "wadmap.h"
#include "bsp.h"

extern void setquakecolors();
extern MouseCursor mymousecursor;

/*mapvertex_t mapvertex[2000];
  mapline_t mapline[1000];
  maproom_t maproom[300];*/
mapvertex_t far *mapvertex;
  mapline_t far *mapline;
  maproom_t far *maproom;

int needsave = 0;
int showgrid = 1;

int numvertex=0;
int numlines=0;
int numrooms=0;

int curvertex=1;
int curline=1;
int curroom=1;

int curmode = 0; //0=rooms 1=line 2=vertex
long mapx=0, mapy=0;
float zoom;
//defaults
char mapname[54] = "Untitled map";

void notdone()
{
   query("Not implemented");
}

//this is DA-SHIT here!!!
void savemap(char *filename)
{


}

void saveeqm(char *filename)
{
    FILE *f;
    char magic[10];
    int t;
    int version; //0 = no things
    f = fopen(filename, "wb");
    if (!f) return;
    fwrite("EdQuakeMap",10,1,f);
//    if (magic != "EdQuakeMap") return;
    fwrite(&version,2,1,f);
    fwrite(mapname,52,1,f);
    fwrite(&mapx,4,1,f);
    fwrite(&mapy,4,1,f);
    fwrite(&zoom,4,1,f);
    fwrite(&numvertex,2,1,f);
    for (t = 1; t <= numvertex; t++)
      fwrite(&mapvertex[t],sizeof(mapvertex_t),1,f);
    fwrite(&numlines,2,1,f);
    for (t = 1; t <= numlines; t++)
      fwrite(&mapline[t],sizeof(mapline_t),1,f);
    fwrite(&numrooms,2,1,f);
    for (t = 1; t <= numrooms; t++)
      fwrite(&maproom[t],sizeof(maproom_t),1,f);
    needsave = 0;
}


void loadeqm(char *filename)
{
    FILE *f;
    char magic[10];
    int t;
    int version; //0 = no things
    f = fopen(filename, "rb");
    if (!f) return;
    fread(magic,10,1,f);
//    if (magic != "EdQuakeMap") return;
    fread(&version,2,1,f);
    fread(mapname,52,1,f);
    fread(&mapx,4,1,f);
    fread(&mapy,4,1,f);
    fread(&zoom,4,1,f);
    fread(&numvertex,2,1,f);
    for (t = 1; t <= numvertex; t++)
      fread(&mapvertex[t],sizeof(mapvertex_t),1,f);
    fread(&numlines,2,1,f);
    for (t = 1; t <= numlines; t++)
      fread(&mapline[t],sizeof(mapline_t),1,f);
    fread(&numrooms,2,1,f);
    for (t = 1; t <= numrooms; t++)
      fread(&maproom[t],sizeof(maproom_t),1,f);
    needsave = 0;
}


void help()
{
   int mx,my,mbuts = 1;
   while (mbuts) mousestatus(&mx,&my,&mbuts);
   if (curmode == 0)
   {
     drwfillbox(SET,BLACK,0,120,640,600);
     drwstring(SET,YELLOW,BLACK,"Help on Rooms:",10,130);
     drwstring(SET,WHITE,BLACK,"Room - An entity made up of a set of walls where the main action takes",10,150);
     drwstring(SET,WHITE,BLACK,"       place.  Can also split up a wall for detail, like using a cube",10,170);
     drwstring(SET,WHITE,BLACK,"       for a railing on a bridge.",10,190);
     drwstring(SET,YELLOW,BLACK,"Some Basic Usage:",10,210);
     drwstring(SET,WHITE,BLACK,"Left Click and drag a box to create a new room at the default settings.",10,230);
     drwstring(SET,WHITE,BLACK,"Settings are updated by clicking on the number that needs to be changed.",10,250);
     drwstring(SET,WHITE,BLACK,"Rooms are selected by clicking on the arrows next to the room#",10,270);
     drwstring(SET,WHITE,BLACK,"The delete button removels the floor and ceiling of the room and all of",10,290);
     drwstring(SET,WHITE,BLACK,"   the walls that are not being used elsewhere in the level.",10,310);
   }
   if (curmode == 1)
   {
     drwfillbox(SET,BLACK,0,120,640,600);
     drwstring(SET,YELLOW,BLACK,"Help on Walls:",10,130);
     drwstring(SET,WHITE,BLACK,"Wall - A connection between 2 vertices with a texture and slant.",10,150);
     drwstring(SET,WHITE,BLACK,"       The top and bottom values are optional for holes in walls.",10,170);
     drwstring(SET,YELLOW,BLACK,"Some Basic Usage:",10,190);
     drwstring(SET,WHITE,BLACK,"Click near a line or use the arrows near the wall#(less buggy) to",10,210);
     drwstring(SET,WHITE,BLACK,"      select a wall.",10,230);
     drwstring(SET,WHITE,BLACK,"Click on the data to change it.",10,250);
   }
   if (curmode == 2)
   {
     drwfillbox(SET,BLACK,0,120,640,600);
     drwstring(SET,YELLOW,BLACK,"Help on Vertices:",10,130);
     drwstring(SET,WHITE,BLACK,"Vertex - A 2d point by which all other map intities are attached to. ",10,150);
     drwstring(SET,WHITE,BLACK,"         What's that you say?  It's not possible to make 3D levels in",10,170);
     drwstring(SET,WHITE,BLACK,"         a 2d editor? :)",10,190);
     drwstring(SET,YELLOW,BLACK,"Some Basic Usage:",10,210);
     drwstring(SET,WHITE,BLACK,"Left Click and drag to move a vertex",10,230);
     drwstring(SET,WHITE,BLACK,"Right Click selects a vertex",10,230);
     drwstring(SET,WHITE,BLACK,"Delete removes a vertex and forces the walls attached to it to merge.",10,270);
     drwstring(SET,WHITE,BLACK,"    You can't delete a vertex with more than 2 wall attached.",10,290);
     drwstring(SET,WHITE,BLACK,"Click on the coord value if you want to specify an x or y value,",10,310);
   }
   mbuts = 0;
   while (!mbuts) mousestatus(&mx, &my, &mbuts);
}

void blankback()
{
   char buf[20];
   int t;
   drwfillbox(SET,BLACK,0,120,655,600);
if (showgrid == 1)
{
   for (t = 0; t < 655; t+=8)
     drwline(SET,BLUE,t,120,t,600);
   for (t = 120; t < 600; t+=8)
     drwline(SET,BLUE,0,t,655,t);
}
   sprintf(buf,"(%05i,",mapx);
   drwstring(SET,WHITE,BLACK,buf,5,125);
   sprintf(buf,"%05i)",mapy);
   drwstring(SET,WHITE,BLACK,buf,60,125);
}

void drawvertex()
{
   int t;
   for (t = 1; t <= numvertex; t++)
     if (t==curvertex)
       drwbox(SET,RED, mapvertex[t].x-2+mapx,mapvertex[t].y-2+mapy,mapvertex[t].x+2+mapx,mapvertex[t].y+2+mapy);
     else
       drwbox(SET,YELLOW, mapvertex[t].x-2+mapx,mapvertex[t].y-2+mapy,mapvertex[t].x+2+mapx,mapvertex[t].y+2+mapy);
}

void drawroom()
{
   int t;
   for (t = 1; t <= maproom[curroom].numsides; t++)
  drwline(SET,YELLOW,mapvertex[mapline[maproom[curroom].line[t]].v1].x+mapx,
		     mapvertex[mapline[maproom[curroom].line[t]].v1].y+mapy,
		     mapvertex[mapline[maproom[curroom].line[t]].v2].x+mapx,
		     mapvertex[mapline[maproom[curroom].line[t]].v2].y+mapy);
}

void eraseroom()
{
   int t;
   for (t = 1; t <= maproom[curroom].numsides; t++)
  drwline(SET,WHITE,mapvertex[mapline[maproom[curroom].line[t]].v1].x+mapx,
		     mapvertex[mapline[maproom[curroom].line[t]].v1].y+mapy,
		     mapvertex[mapline[maproom[curroom].line[t]].v2].x+mapx,
		     mapvertex[mapline[maproom[curroom].line[t]].v2].y+mapy);
}

void drawline()
{
  drwline(SET,RED,mapvertex[mapline[curline].v1].x+mapx,
		  mapvertex[mapline[curline].v1].y+mapy,
		  mapvertex[mapline[curline].v2].x+mapx,
		  mapvertex[mapline[curline].v2].y+mapy);
}

void eraseline()
{
  if (mapline[curline].visible)
  drwline(SET,WHITE,mapvertex[mapline[curline].v1].x+mapx,
		  mapvertex[mapline[curline].v1].y+mapy,
		  mapvertex[mapline[curline].v2].x+mapx,
		  mapvertex[mapline[curline].v2].y+mapy);
  else
  drwline(SET,BLUE,mapvertex[mapline[curline].v1].x+mapx,
		  mapvertex[mapline[curline].v1].y+mapy,
		  mapvertex[mapline[curline].v2].x+mapx,
		  mapvertex[mapline[curline].v2].y+mapy);

}

void roomtext()
{
   char buf[20];
   mousehide();
   drwfillbox(SET,BLACK,145,19,170,35);
   impress(145,19,170,35);
   sprintf(buf,"%3i",curroom);
   drwstring(SET,WHITE,BLACK,buf,146,20);
   drwfillbox(SET,BLACK,235,39,269,55);
   impress(235,39,269,55);
   drwfillbox(SET,BLACK,235,59,269,75);
   impress(235,59,269,75);
   drwfillbox(SET,BLACK,340,39,374,55);
   impress(340,39,374,55);
   drwfillbox(SET,BLACK,340,59,374,75);
   impress(340,59,374,75);
   drwfillbox(SET,BLACK,235,79,340,95);
   impress(235,79,340,95);
   drwfillbox(SET,BLACK,345,79,360,95);
   impress(345,79,360,95);
   if (maproom[curroom].fvis)
   {
      drwline(SET,WHITE,345,79,360,95);
      drwline(SET,WHITE,345,95,360,79);
   }
   drwfillbox(SET,BLACK,235,99,340,115);
   impress(235,99,340,115);
   drwfillbox(SET,BLACK,345,99,360,115);
   impress(345,99,360,115);
   if (maproom[curroom].cvis)
   {
      drwline(SET,WHITE,345,99,360,115);
      drwline(SET,WHITE,345,115,360,99);
   }
   sprintf(buf,"%4i",maproom[curroom].floor);
   drwstring(SET,WHITE,BLACK,buf,236,40);
   sprintf(buf,"%4i",maproom[curroom].ceiling);
   drwstring(SET,WHITE,BLACK,buf,236,60);
   sprintf(buf,"%4i",config.dfloor);
   drwstring(SET,WHITE,BLACK,buf,341,40);
   sprintf(buf,"%4i",config.dceil);
   drwstring(SET,WHITE,BLACK,buf,341,60);
   drwstring(SET,WHITE,BLACK,texture[maproom[curroom].ftext].name,236,80);
   drwstring(SET,WHITE,BLACK,texture[maproom[curroom].ctext].name,236,100);
   drawroom();
   mouseshow();
}

void drawback()
{
   int t;
   mousehide();
   setview(0,120,655,599);
   blankback();
   drawvertex();
   for (t = 1; t <= numlines; t++)
     if (t == curline)
       drwline(SET,RED, mapvertex[mapline[t].v1].x+mapx,mapvertex[mapline[t].v1].y+mapy,mapvertex[mapline[t].v2].x+mapx,mapvertex[mapline[t].v2].y+mapy);
     else
     if (mapline[t].visible)
       drwline(SET,WHITE, mapvertex[mapline[t].v1].x+mapx,mapvertex[mapline[t].v1].y+mapy,mapvertex[mapline[t].v2].x+mapx,mapvertex[mapline[t].v2].y+mapy);
     else
       drwline(SET,BLUE, mapvertex[mapline[t].v1].x+mapx,mapvertex[mapline[t].v1].y+mapy,mapvertex[mapline[t].v2].x+mapx,mapvertex[mapline[t].v2].y+mapy);
   if (curmode == 0) drawroom();
   mouseshow();
   setview(0,0,799,599);
}

void roominfo()
{
   char buf[20];
   mousehide();
   drwfillbox(SET,LTGRAY,105,18,594,117);
   drwstring(SET,BLACK,LTGRAY,"room#",105,20);
   drwfillbox(SET,BLACK,145,19,170,35);
   impress(145,19,170,35);
   sprintf(buf,"%3i",curroom);
   drwstring(SET,WHITE,BLACK,buf,146,20);
   scrollbutton(172,21,"");
   scrollbutton(184,21,"");
   drwstring(SET,BLACK,LTGRAY,"   floor height:",105,40);
   drwfillbox(SET,BLACK,235,39,269,55);
   impress(235,39,269,55);
   drwstring(SET,BLACK,LTGRAY," ceiling height:",105,60);
   drwfillbox(SET,BLACK,235,59,269,75);
   impress(235,59,269,75);
   drwstring(SET,BLACK,LTGRAY,"default:",275,40);
   drwfillbox(SET,BLACK,340,39,374,55);
   impress(340,39,374,55);
   drwstring(SET,BLACK,LTGRAY,"default:",275,60);
   drwfillbox(SET,BLACK,340,59,374,75);
   impress(340,59,374,75);
   drwstring(SET,BLACK,LTGRAY,"  floor texture:",105,80);
   drwfillbox(SET,BLACK,235,79,340,95);
   impress(235,79,340,95);
   drwfillbox(SET,BLACK,345,79,360,95);
   impress(345,79,360,95);
   if (maproom[curroom].fvis)
   {
      drwline(SET,WHITE,345,79,360,95);
      drwline(SET,WHITE,345,95,360,79);
   }
   drwstring(SET,BLACK,LTGRAY,"ceiling texture:",105,100);
   drwfillbox(SET,BLACK,235,99,340,115);
   impress(235,99,340,115);
   drwfillbox(SET,BLACK,345,99,360,115);
   impress(345,99,360,115);
   if (maproom[curroom].fvis)
   {
      drwline(SET,WHITE,345,99,360,115);
      drwline(SET,WHITE,345,115,360,99);
   }
   drwstring(SET,BLACK,LTGRAY,"visible",365,80);
   drwstring(SET,BLACK,LTGRAY,"visible",365,100);
   button(520,20,585,35," Delete");
   button(520,40,585,55," Brush");
   button(520,100,585,115,"  Help");

   sprintf(buf,"%4i",maproom[curroom].floor);
   drwstring(SET,WHITE,BLACK,buf,236,40);
   sprintf(buf,"%4i",maproom[curroom].ceiling);
   drwstring(SET,WHITE,BLACK,buf,236,60);
   sprintf(buf,"%4i",config.dfloor);
   drwstring(SET,WHITE,BLACK,buf,341,40);
   sprintf(buf,"%4i",config.dceil);
   drwstring(SET,WHITE,BLACK,buf,341,60);
   drwstring(SET,WHITE,BLACK,texture[maproom[curroom].ftext].name,236,80);
   drwstring(SET,WHITE,BLACK,texture[maproom[curroom].ctext].name,236,100);
   drawroom();
   mouseshow();
}

void wallinfo()
{
   char buf[20];
   drwfillbox(SET,LTGRAY,105,18,594,117);
   drwstring(SET,BLACK,LTGRAY,"wall#",105,20);
   drwfillbox(SET,BLACK,145,19,170,35);
   impress(145,19,170,35);
   sprintf(buf,"%3i",curline);
   drwstring(SET,WHITE,BLACK,buf,146,20);
   scrollbutton(172,21,"");
   scrollbutton(184,21,"");
   drwstring(SET,BLACK,LTGRAY,"    hole bottom:",105,40);
   drwfillbox(SET,BLACK,235,39,269,55);
   impress(235,39,269,55);
   drwstring(SET,BLACK,LTGRAY,"       hole top:",105,60);
   drwfillbox(SET,BLACK,235,59,269,75);
   impress(235,59,269,75);
   drwstring(SET,BLACK,LTGRAY,"default:",275,40);
   drwfillbox(SET,BLACK,340,39,374,55);
   impress(340,39,374,55);
   drwstring(SET,BLACK,LTGRAY,"default:",275,60);
   drwfillbox(SET,BLACK,340,59,374,75);
   impress(340,59,374,75);
   drwstring(SET,BLACK,LTGRAY,"   wall texture:",105,100);
   drwfillbox(SET,BLACK,235,99,340,115);
   impress(235,99,340,115);
   drwfillbox(SET,BLACK,345,99,360,115);
   impress(345,99,360,115);
   if (mapline[curline].visible)
   {
      drwline(SET,WHITE,345,99,360,115);
      drwline(SET,WHITE,345,115,360,99);
   }
   drwstring(SET,BLACK,LTGRAY,"   hole enabled:",105,80);
   drwfillbox(SET,BLACK,235,79,250,95);
   impress(235,79,250,95);
   if (mapline[curline].hole)
   {
      drwline(SET,WHITE,235,79,250,95);
      drwline(SET,WHITE,235,95,250,79);
   }
   drwstring(SET,BLACK,LTGRAY,"visible",365,100);
   button(520,20,585,35," Split");
   button(520,100,585,115,"  Help");

   sprintf(buf,"%4i",mapline[curline].bottom);
   drwstring(SET,WHITE,BLACK,buf,236,40);
   sprintf(buf,"%4i",mapline[curline].top);
   drwstring(SET,WHITE,BLACK,buf,236,60);
   sprintf(buf,"%4i",config.dbottom);
   drwstring(SET,WHITE,BLACK,buf,341,40);
   sprintf(buf,"%4i",config.dtop);
   drwstring(SET,WHITE,BLACK,buf,341,60);
   drwstring(SET,WHITE,BLACK,texture[mapline[curline].texture].name,236,100);
   drawline();
}

void vertextext()//faster redraw
{
   char buf[20];
   drwfillbox(SET,BLACK,165,19,190,35);
   impress(165,19,190,35);
   sprintf(buf,"%3i",curvertex);
   drwstring(SET,WHITE,BLACK,buf,166,20);
   drwfillbox(SET,BLACK,235,39,269,55);
   impress(235,39,269,55);
   drwfillbox(SET,BLACK,235,59,269,75);
   impress(235,59,269,75);
   sprintf(buf,"%4i",mapvertex[curvertex].x);
   drwstring(SET,WHITE,BLACK,buf,236,40);
   sprintf(buf,"%4i",mapvertex[curvertex].y);
   drwstring(SET,WHITE,BLACK,buf,236,60);
}


void vertexinfo()
{
   char buf[20];
   drwfillbox(SET,LTGRAY,105,18,594,117);
   drwstring(SET,BLACK,LTGRAY,"vertex#",105,20);
   drwfillbox(SET,BLACK,165,19,190,35);
   impress(165,19,190,35);
   sprintf(buf,"%3i",curvertex);
   drwstring(SET,WHITE,BLACK,buf,166,20);
   scrollbutton(192,21,"");
   scrollbutton(204,21,"");
   drwstring(SET,BLACK,LTGRAY,"       X coord:",105,40);
   drwfillbox(SET,BLACK,235,39,269,55);
   impress(235,39,269,55);
   drwstring(SET,BLACK,LTGRAY,"       Y coord:",105,60);
   drwfillbox(SET,BLACK,235,59,269,75);
   impress(235,59,269,75);
   button(520,20,585,35," Delete");
   button(520,100,585,115,"  Help");

   sprintf(buf,"%4i",mapvertex[curvertex].x);
   drwstring(SET,WHITE,BLACK,buf,236,40);
   sprintf(buf,"%4i",mapvertex[curvertex].y);
   drwstring(SET,WHITE,BLACK,buf,236,60);
}

void objectinfo()
{
   drwfillbox(SET,LTGRAY,105,18,594,117);
   drwstring(SET,BLACK,LTGRAY,"not implemented",105,20);
}

void setcircles()
{
   int t;
   mousehide();
   for (t = 0; t < 4; t ++)
     if (t == curmode) drwfillcircle(SET,BLACK,15,27+(t*20),2);
		  else drwfillcircle(SET,LTGRAY,15,27+(t*20),2);
   mouseshow();
}


void setmapscreen()
{
   int k;
   drwfillbox(SET,LTGRAY,0,0,800,600);
   drawback();
   impress(-1,119,655,601);//around map
   impress(671,119,801,248);//around texture
   impress(677,255,792,270);//around textbox
   drwline(SET,WHITE,100,20,100,115);
   drwline(SET,BLACK,101,20,101,115);
   drwline(SET,WHITE,595,20,595,115);
   drwline(SET,BLACK,596,20,596,115);
   drwfillbox(SET,BLUE,0,0,800,15);
   drwstring(SET,WHITE,BLUE,"EdQuake v0.49.00    (c) copyright 1996 CircleA Entertainment  ",25,1);
   drwfillbox(SET,BLACK,678,256,791,269);
   drwfillbox(SET,BLACK,672,120,800,247);
   drwline(SET,WHITE,657,276,797,276);
   drwline(SET,BLACK,657,275,797,275);
   drwline(SET,WHITE,657,380,797,380);
   drwline(SET,BLACK,657,379,797,379);
   //draws buttons, but doesn't make them function
   //(for redraws of screen)
   button(680,390,700,410,"");
   button(680,411,700,431,"");
   button(659,400,679,420,"");
   button(702,400,722,420,"");
   drwstring(SET,BLACK,LTGRAY,"",686,393);
   drwstring(SET,BLACK,LTGRAY,"",686,413);
   k = 17; drwstring(SET,BLACK,LTGRAY,&k,665,404);
   k = 16; drwstring(SET,BLACK,LTGRAY,&k,709,404);
   scrollbutton(657,246,"");
   scrollbutton(657,260,"");
   button(670,280,785,295,"Console Editor");
   button(670,300,785,315,"    Ripper");
   button(670,320,785,335,"  Wave Editor");
   button(670,340,785,355,"   LMP Viewer");
   button(670,360,785,375,"     Quit");
   button(670,460,785,475,"     About");
   button(670,480,785,495,"  Clear Level ");
   button(670,500,785,515,"  Load Level");
   button(670,520,785,535,"  Save Level");
   button(670,540,785,555,"  .MAP Import");
   button(670,560,785,575,"  .MAP Export");
   button(670,580,785,595,"   Process");
   drwstring(SET,BLACK,LTGRAY,"Room",25,21);
   drwcircle(SET,BLACK,15,27,4);
   drwcircle(SET,WHITE,15,27,5);
   drwstring(SET,BLACK,LTGRAY,"Wall",25,41);
   drwcircle(SET,BLACK,15,47,4);
   drwcircle(SET,WHITE,15,47,5);
   drwstring(SET,BLACK,LTGRAY,"Vertex",25,61);
   drwcircle(SET,BLACK,15,67,4);
   drwcircle(SET,WHITE,15,67,5);
   drwstring(SET,BLACK,LTGRAY,"Object",25,81);
   drwcircle(SET,BLACK,15,87,4);
   drwcircle(SET,WHITE,15,87,5);
   drwfillcircle(SET,BLACK,15,27,2);
   drwstring(SET,RED,LTGRAY,"Default Textures",650,18);
   drwstring(SET,BLACK,LTGRAY,"   Wall:",605,35);
   drwstring(SET,BLACK,LTGRAY,"  Floor:",605,55);
   drwstring(SET,BLACK,LTGRAY,"Ceiling:",605,75);
   drwfillbox(SET,BLACK,670,34,795,50);
   impress(670,34,795,50);
   drwstring(SET,WHITE,BLACK,texture[config.dwalltext].name,675,35);
   drwfillbox(SET,BLACK,670,54,795,70);
   impress(670,54,795,70);
   drwstring(SET,WHITE,BLACK,texture[config.dfloortext].name,675,55);
   drwfillbox(SET,BLACK,670,74,795,90);
   impress(670,74,795,90);
   drwstring(SET,WHITE,BLACK,texture[config.dceiltext].name,675,75);
   drwfillbox(SET,BLACK,735,389,750,405);
   impress(735,389,750,405);
   if (showgrid == 1)
   {
      drwline(SET,WHITE,735,389,750,405);
      drwline(SET,WHITE,735,405,750,389);
   }
   drwstring(SET,BLACK,LTGRAY,"grid",755,390);
   if (curmode == 0) roominfo();
   if (curmode == 1) wallinfo();
   if (curmode == 2) vertexinfo();
   if (curmode == 3) objectinfo();
   setcircles();

}

long calcdist(long x0, long y0, long x1, long y1)
{ // I know, not a real distance, but works for our purposes and faster
   return abs(x1-x0)+abs(y1-y0);
}

void getvertex(long x, long y)
{
   long smalldist = 100000;
   long cur;
   int t;
   for (t = 1; t <= numvertex; t++)
   {
      cur = calcdist(x-mapx,y-mapy,mapvertex[t].x,mapvertex[t].y);
      if (cur < smalldist)
      {
	 smalldist = cur;
	 curvertex = t;
      }
   }
}

void getline(long x, long y)
{//finds closest vertex and then determines closest line
   long smalldist = 100000;
   long cur;
   long small;
   int t;
   for (t = 1; t <= numvertex; t++)
   {
      cur = calcdist(x-mapx,y-mapy,mapvertex[t].x,mapvertex[t].y);
      if (cur < smalldist)
      {
	 smalldist = cur;
	 small = t;
      }
   }
   //check all lines for that vertex, find closest line
   smalldist = 100000;
   for (t = 1; t <= numlines; t++)
   {
      if (mapline[t].v1 == small)
      {
	 cur = calcdist(x,y,mapvertex[mapline[t].v2].x,mapvertex[mapline[t].v2].y);
	 if (cur < smalldist)
	 {
	    smalldist = cur;
	    curline = t;
	 }
      }
      if (mapline[t].v2 == small)
      {
	 cur = calcdist(x,y,mapvertex[mapline[t].v1].x,mapvertex[mapline[t].v1].y);
	 if (cur < smalldist)
	 {
	    smalldist = cur;
	    curline = t;
	 }
      }
   }
}

void removevertex(int x)
{
   int t;
   numvertex--;
   for (t = x; t <= numvertex; t++)  //remove vertex
      mapvertex[t] = mapvertex[t+1];
   for (t = 1; t <= numlines; t++)   //remap line-vertex pointers
   {
      if (mapline[t].v1 > x) mapline[t].v1--;
      if (mapline[t].v2 > x) mapline[t].v2--;
   }
}

//eliminated unneeded vertices
void unchainedvertex()
{
   int t, t2, found;
     for (t = 1; t <= numvertex; t++)
     {
       found = 0;
       for (t2 = 1; t2 <= numlines; t2++)
       {
	 if (mapline[t2].v1==t) {found = 1; t2 = numlines + 1;}
	 if (mapline[t2].v2==t) {found = 1; t2 = numlines + 1;}
       }
       if (!found) //remove vertex;
       {
	 removevertex(t);
	 t--;
       }
     }
  if (curvertex > numvertex) curvertex=numvertex;
  vertexinfo();
}

void cleanvertex()
{
   int t;
   int merge = 0;
   //check for vertices within 5
   for (t = 1; t <= numvertex; t++)
      if((abs(mapvertex[curvertex].x-mapvertex[t].x) < 5) && (abs(mapvertex[curvertex].y-mapvertex[t].y) < 5) && (t != curvertex)) merge = t;
   if (merge == 0) return;
   if (!query("Merge vertices?")) return;
   for (t = 1; t <= numlines; t++)
   {
      if (mapline[t].v1 == curvertex) mapline[t].v1 = merge;
      if (mapline[t].v2 == curvertex) mapline[t].v2 = merge;
   }
   unchainedvertex();
   needsave = 1;
}

void movevertex(int x, int y)
{
   int lineptr[100];  //limited to 100 lines per vertex;
   int numptr = 0;
   int mx, my, mbuts = 1;
   int t;
   getvertex(x, y);
   mousehide();
   mapvertex[curvertex].x -= mapx;
   mapvertex[curvertex].y -= mapy;
   while (mbuts)
   {
       mousestatus(&mx,&my,&mbuts);
       drwbox(SET,BLACK, mapvertex[curvertex].x-2,mapvertex[curvertex].y-2,mapvertex[curvertex].x+2,mapvertex[curvertex].y+2);
       mapvertex[curvertex].x = mx;
       mapvertex[curvertex].y = my;
       drwbox(SET,RED, mapvertex[curvertex].x-2,mapvertex[curvertex].y-2,mapvertex[curvertex].x+2,mapvertex[curvertex].y+2);
   }
       mapvertex[curvertex].x -= mapx;
       mapvertex[curvertex].y -= mapy;
   mbuts = 1;
   while (mbuts) mousestatus(&mx,&my,&mbuts);
   cleanvertex();
   mouseshow();
   needsave = 1;
}

void screenshot()
{
   pcxmake(0,0,799,599,"screen.pcx");
}

void splitline()
{
   int t, t2;
   numvertex++;
   mapvertex[numvertex].x = (mapvertex[mapline[curline].v1].x + mapvertex[mapline[curline].v2].x)/2;
   mapvertex[numvertex].y = (mapvertex[mapline[curline].v1].y + mapvertex[mapline[curline].v2].y)/2;
   numlines++;
   mapline[numlines].v1 = numvertex;
   mapline[numlines].v2 = mapline[curline].v2;
   mapline[curline].v2 = numvertex;
   mapline[numlines].visible = mapline[curline].visible;
   mapline[numlines].texture = mapline[curline].texture;
   mapline[numlines].top = mapline[curline].top;
   mapline[numlines].bottom = mapline[curline].bottom;
   mapline[numlines].hole = mapline[curline].hole;
   for (t = 1; t <= numrooms; t++)
      for (t2 = 1; t2 <= maproom[t].numsides; t2++)
	if (maproom[t].line[t2] == curline)
	{
	   maproom[t].numsides++;
	   maproom[t].line[maproom[t].numsides] = numlines;
	}
   needsave = 1;
}

void newroom(int mx, int my)
{
   int mx2, my2, mbuts = 1;
	  drwline(SET,YELLOW,mx-5,my+5,mx+5,my-5);
	  drwline(SET,YELLOW,mx-5,my-5,mx+5,my+5);
	  while (mbuts)
	    mousestatus(&mx2,&my2,&mbuts);
	  if ((abs(mx2-mx) > 5) && (abs(my2-my) > 5))
	  {
	      mapvertex[numvertex+1].x=mx-mapx;
	      mapvertex[numvertex+1].y=my-mapy;
	      mapvertex[numvertex+2].x=mx2-mapx;
	      mapvertex[numvertex+2].y=my-mapy;
	      mapvertex[numvertex+3].x=mx2-mapx;
	      mapvertex[numvertex+3].y=my2-mapy;
	      mapvertex[numvertex+4].x=mx-mapx;
	      mapvertex[numvertex+4].y=my2-mapy;
	      mapline[numlines+1].v1 = numvertex+1;
	      mapline[numlines+1].v2 = numvertex+2;
	      mapline[numlines+1].visible = 1;
	      mapline[numlines+1].texture = config.dwalltext;
	      mapline[numlines+1].top = config.dtop;
	      mapline[numlines+1].bottom = config.dbottom;
	      mapline[numlines+1].hole = 0;
	      mapline[numlines+2].v1 = numvertex+2;
	      mapline[numlines+2].v2 = numvertex+3;
	      mapline[numlines+2].visible = 1;
	      mapline[numlines+2].texture = config.dwalltext;
	      mapline[numlines+2].top = config.dtop;
	      mapline[numlines+2].bottom = config.dbottom;
	      mapline[numlines+2].hole = 0;
	      mapline[numlines+3].v1 = numvertex+3;
	      mapline[numlines+3].v2 = numvertex+4;
	      mapline[numlines+3].visible = 1;
	      mapline[numlines+3].texture = config.dwalltext;
	      mapline[numlines+3].top = config.dtop;
	      mapline[numlines+3].bottom = config.dbottom;
	      mapline[numlines+3].hole = 0;
	      mapline[numlines+4].v1 = numvertex+4;
	      mapline[numlines+4].v2 = numvertex+1;
	      mapline[numlines+4].visible = 1;
	      mapline[numlines+4].texture = config.dwalltext;
	      mapline[numlines+4].top = config.dtop;
	      mapline[numlines+4].bottom = config.dbottom;
	      mapline[numlines+4].hole = 0;
	      maproom[numrooms+1].numsides = 4;
	      maproom[numrooms+1].line[1] = numlines+1;
	      maproom[numrooms+1].line[2] = numlines+2;
	      maproom[numrooms+1].line[3] = numlines+3;
	      maproom[numrooms+1].line[4] = numlines+4;
	      maproom[numrooms+1].ctext = config.dceiltext;
	      maproom[numrooms+1].ftext = config.dfloortext;
	      maproom[numrooms+1].ceiling = config.dceil;
	      maproom[numrooms+1].floor = config.dfloor;
	      maproom[numrooms+1].cvis = 1;
	      maproom[numrooms+1].fvis = 1;
	      numvertex+=4;
	      numlines+=4;
	      numrooms++;
	      curroom = numrooms;
	  }
   needsave = 1;
}

void mapedit(int e)
{
   button_t up, down, left, right;
   button_t textureup, texturedown;
   button_t gfx, ripperb, wave, quit;
   button_t gotexture, golmp, goedit;
   button_t editroom, editwall, editvert, editthings;
   button_t walldefbut, floordefbut, ceildefbut;
   button_t panel1, panel2;
   button_t helpbut;
   button_t vup, vdown, vxbut, vybut, vselect;
   button_t rup, rdown, rselect;
   button_t fhbut, chbut, fdbut, cdbut, ftbut, fvbut, ctbut, cvbut;
   button_t gridbut, aboutbut, holebut;
   button_t clearbut, loadbut, savebut, importbut, exportbut, processbut;
   int curtexture = 1, k;
   int mbuts, mx, my, mx2, my2;
   char buf[20];
   char *p;
   mapvertex = farmalloc(8 * 1000);
   mapline = farmalloc(24 * 1000);
   maproom = farmalloc(56 * 100);

   loadeqm("test.eqm");
   loadbsp(e);
   gettexture();
   setquakecolors();
   res800();
   mouseenter();
   mousecursorset(&mymousecursor);
   loadpcx(0,0,"quakepal.pcx");
   mousehide();
   //buttons
   helpbut = button(520,100,585,115,"  Help");
   up    = button(680,390,700,410,"");
   down  = button(680,411,700,431,"");
   left  = button(659,400,679,420,"");
   right = button(702,400,722,420,"");
   gridbut = clearbutton(735,389,750,405);
   textureup = scrollbutton(657,246,"");
   texturedown = scrollbutton(657,260,"");
   gfx = button(670,280,785,295,"Console Editor");
  ripperb = button(670,300,785,315,"    Ripper");
     wave = button(670,320,785,335,"  Wave Editor");
    golmp = button(670,340,785,355,"   LMP Viewer");
     quit = button(670,360,785,375,"     Quit");
 aboutbut = button(670,460,785,475,"     About");
 clearbut = button(670,480,785,495,"  Clear Level ");
  loadbut = button(670,500,785,515,"  Load Level");
  savebut = button(670,520,785,535,"  Save Level");
importbut = button(670,540,785,555,"  .MAP Import");
exportbut = button(670,560,785,575,"  .MAP Export");
processbut =button(670,580,785,595,"   Process");

   gotexture = clearbutton(672,120,800,247);
   goedit = clearbutton(0,120,655,600);
   editroom = clearbutton(0,21,100,40);
   editwall = clearbutton(0,41,100,60);
   editvert = clearbutton(0,61,100,80);
   editthings = clearbutton(0,81,100,100);
   walldefbut = clearbutton(670,34,795,50);
   floordefbut = clearbutton(670,54,795,70);
   ceildefbut = clearbutton(670,74,795,90);
   panel1 = clearbutton(520,20,585,35);
   panel2 = clearbutton(520,40,585,55);
   //vertexbuttons
     vup = scrollbutton(192,21,"");
   vdown = scrollbutton(204,21,"");
   vxbut = clearbutton(235,39,269,55);
   vybut = clearbutton(235,59,269,75);
   vselect = clearbutton(165,19,190,35);
   //wall buttons
   holebut = clearbutton(235,79,250,95);
   //room buttons
   rselect = clearbutton(145,19,170,35);
   rup = scrollbutton(172,21,"");
   rdown = scrollbutton(184,21,"");
   fhbut = clearbutton(235,39,269,55);//floor height
   chbut = clearbutton(235,59,269,75);//ceiling height
   fdbut = clearbutton(340,39,374,55);//floor def
   cdbut = clearbutton(340,59,374,75);//ceiling def
   ftbut = clearbutton(235,79,340,95);//floor texture
   fvbut = clearbutton(345,79,360,95);//floor vis
   ctbut = clearbutton(235,99,340,115);//ceiling texture
   cvbut = clearbutton(345,99,360,115);//ceiling vis

   //init texture
   setmapscreen();
   showtexture(curtexture);
   drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
   mouseshow();
   while (k != 27)
   {
     scrollbar(657,120,245,curtexture,numtex);
     k = 0;
	    while (!kbhit() && !mbuts)
	    {
	       mousestatus(&mx,&my,&mbuts);
	       if (mbuts & 1)//scroll
	       {
		  if (hitbutton(mx,my,gridbut))
		  {
		     if (showgrid == 0) showgrid = 1; else showgrid = 0;
		     drawback();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		   mousehide();
		   drwfillbox(SET,BLACK,735,389,750,405);
		   impress(735,389,750,405);
		   if (showgrid == 1)
		   {
		      drwline(SET,WHITE,735,389,750,405);
		      drwline(SET,WHITE,735,405,750,389);
		   }
		   mouseshow();
		  }
		  if (hitbutton(mx,my,up))
		  {
		     mapy+=5;
		     drawback();
		  }
		  if (hitbutton(mx,my,down))
		  {
		     mapy-=5;
		     drawback();
		  }
		  if (hitbutton(mx,my,right))
		  {
		     mapx-=5;
		     drawback();
		  }
		  if (hitbutton(mx,my,left))
		  {
		     mapx+=5;
		     drawback();
		  }
		  if (hitbutton(mx,my,helpbut))
		  {
		     help();
		     drawback();
		  }
		  if (hitbutton(mx,my,editroom))
		  {
		     curmode = 0;
		     roominfo();
		     setcircles();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,editwall))
		  {
		     curmode = 1;
		     wallinfo();
		     setcircles();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,editvert))
		  {
		     curmode = 2;
		     vertexinfo();
		     setcircles();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,editthings))
		  {
		     curmode = 3;
		     objectinfo();
		     setcircles();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,texturedown))
		  {
		      if (curtexture++ >= numtex) curtexture = numtex - 1;
		      mousehide();
		      drwfillbox(SET,BLACK,678,256,791,269);
		      drwfillbox(SET,BLACK,672,120,800,247);
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,textureup))
		  {
		      if (curtexture-- < 1) curtexture = 1;
		      mousehide();
		      drwfillbox(SET,BLACK,678,256,791,269);
		      drwfillbox(SET,BLACK,672,120,800,247);
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,quit)) k = 27;
		  if (hitbutton(mx,my,ripperb))
		  {
		      while (ripper() != -1);
		      mousehide();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,walldefbut))
		  {
		      config.dwalltext = curtexture;
		      mousehide();
		      drwfillbox(SET,BLACK,670,34,795,50);
		      impress(670,34,795,50);
		      drwstring(SET,WHITE,BLACK,texture[config.dwalltext].name,675,35);
		      mouseshow();
		  }
		  if (hitbutton(mx,my,floordefbut))
		  {
		      config.dfloortext = curtexture;
		      mousehide();
		      drwfillbox(SET,BLACK,670,54,795,70);
		      impress(670,54,795,70);
		      drwstring(SET,WHITE,BLACK,texture[config.dfloortext].name,675,55);
		      mouseshow();
		  }
		  if (hitbutton(mx,my,ceildefbut))
		  {
		      config.dceiltext = curtexture;
		      mousehide();
		      drwfillbox(SET,BLACK,670,74,795,90);
		      impress(670,74,795,90);
		      drwstring(SET,WHITE,BLACK,texture[config.dceiltext].name,675,75);
		      mouseshow();
		  }
		  if (hitbutton(mx,my,gotexture))
		  {
		      selecttextures();
		      mousehide();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,gfx))
		  {
//		      gfxwad();
		      setmapscreen();
		      mousehide();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,golmp))
		  {
		      lmp();
		      mousehide();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,aboutbut))
		  {
		      notdone();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,importbut))
		  {
		      notdone();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,exportbut))
		  {
		      notdone();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,clearbut))
		  {
		      if (needsave)
		      {
			  query("Save changes to level?");
		      }
		      numrooms = 0;
		      curroom = 0;
		      numlines = 0;
		      curline = 1;
		      numvertex = 1;
		      curvertex = 1;
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,processbut))
		  {
		      notdone();
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,savebut))
		  {
		      p = wgetstringbox("Save File As", "Save as (.eqm):","");
		      if (p) saveeqm(p);
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (hitbutton(mx,my,loadbut))
		  {
		      p = wgetstringbox("Load EQM File", "Load file (.eqm):","");
		      if (p) loadeqm(p);
		      setmapscreen();
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		  }
		  if (curmode == 0)
		  {
		     if (hitbutton(mx,my,goedit))
		     {
		       newroom(mx, my);
		       drawback();
		       roominfo();
		     }
		     if (hitbutton(mx,my,rselect))
		     {
			 eraseroom();
			 curroom = wgetintbox("Select Room Number","Room Number",curroom);
			 drawback();
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rup))
		     {
			 eraseroom();
			 curroom++;
			 if (curroom > numrooms) curroom = numrooms;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rdown))
		     {
			 eraseroom();
			 curroom--;
			 if (curroom < 1) curroom = 1;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,fhbut))
		     {
			 maproom[curroom].floor = wgetintbox("Change Floor Height","Floor Height",maproom[curroom].floor);
			 drawback();
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,chbut))
		     {
			 maproom[curroom].ceiling = wgetintbox("Change Ceiling Height","Ceiling Height",maproom[curroom].ceiling);
			 drawback();
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,fdbut))
		     {
			 config.dfloor = wgetintbox("Change Floor Default","Floor Height",config.dfloor);
			 drawback();
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,cdbut))
		     {
			 config.dceil = wgetintbox("Change Ceiling Default","Ceiling Height",config.dceil);
			 drawback();
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,fvbut))
		     {
			 if (maproom[curroom].fvis == 0) maproom[curroom].fvis = 1;
				else maproom[curroom].fvis = 0;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,cvbut))
		     {
			 if (maproom[curroom].cvis == 0) maproom[curroom].cvis = 1;
				else maproom[curroom].cvis = 0;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,ctbut))
		     {
			 maproom[curroom].ctext = curtexture;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,ftbut))
		     {
			 maproom[curroom].ftext = curtexture;
			 roomtext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		  }
		  if (curmode == 1)
		  {
		     if (hitbutton(mx,my,panel1))
		     {
			 splitline();
		     drawback();
		     wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,goedit))
		     {
			 getline(mx,my);
		     drawback();
		     wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rselect))
		     {
			 eraseline();
			 curroom = wgetintbox("Select Wall Number","Wall Number",curline);
			 drawback();
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rup))
		     {
			 eraseline();
			 curline++;
			 if (curline > numlines) curline = numlines;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rdown))
		     {
			 eraseline();
			 curline--;
			 if (curline < 1) curline = 1;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,chbut))
		     {
			 mapline[curline].top = wgetintbox("Change Hole Top Height","Hole Top Height",mapline[curline].top);
			 drawback();
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,fhbut))
		     {
			 mapline[curline].bottom = wgetintbox("Change Hole Bottom Height","Hole Bottom Height",mapline[curline].bottom);
			 drawback();
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,cdbut))
		     {
			 config.dtop = wgetintbox("Change Hole Top Default","Hole Top Height",config.dtop);
			 drawback();
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,fdbut))
		     {
			 config.dbottom = wgetintbox("Change Hole Bottom Default","Hole Bottom Height",config.dbottom);
			 drawback();
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,holebut))
		     {
			 if (mapline[curline].hole == 0) mapline[curline].hole = 1;
				else mapline[curline].hole = 0;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,ctbut))
		     {
			 mapline[curline].texture = curtexture;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,cvbut))
		     {
			 if (mapline[curline].visible == 0) mapline[curline].visible = 1;
			   else mapline[curline].visible = 0;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		  }
		  if (curmode == 2)
		  {
		     if (hitbutton(mx,my,goedit))
		     {
			 movevertex(mx, my);
			 drawback();
			     vertexinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vup))
		     {
			 curvertex++;
			 if (curvertex > numvertex) curvertex = numvertex;
			 drawvertex();
			 vertextext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vdown))
		     {
			 curvertex--;
			 if (curvertex < 1) curvertex = 1;
			 drawvertex();
			     vertextext();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vxbut))
		     {
			 mapvertex[curvertex].x = wgetintbox("Change Vertex X Coord","Vertex X Coord",mapvertex[curvertex].x);
			 drawback();
			     vertexinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vybut))
		     {
			 mapvertex[curvertex].y = wgetintbox("Change Vertex Y Coord","Vertex Y Coord",mapvertex[curvertex].y);
			 drawback();
			     vertexinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vselect))
		     {
			 curvertex = wgetintbox("Select Vertex","Vertex Number",curvertex);
			 drawback();
			     vertexinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		  }
	       }
	       if (mbuts & 2)//scroll fast
	       {
		  if (hitbutton(mx,my,up))
		  {
		     mapy+=20;
		     drawback();
		  }
		  if (hitbutton(mx,my,down))
		  {
		     mapy-=20;
		     drawback();
		  }
		  if (hitbutton(mx,my,right))
		  {
		     mapx-=20;
		     drawback();
		  }
		  if (hitbutton(mx,my,left))
		  {
		     mapx+=20;
		     drawback();
		  }
		  if (hitbutton(mx,my,texturedown))
		  {
		      if (curtexture++ >= numtex) curtexture = numtex - 1;
		      mousehide();
		      drwfillbox(SET,BLACK,678,256,791,269);
		      drwfillbox(SET,BLACK,672,120,800,247);
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
		  }
		  if (hitbutton(mx,my,textureup))
		  {
		      if (curtexture-- < 1) curtexture = 1;
		      mousehide();
		      drwfillbox(SET,BLACK,678,256,791,269);
		      drwfillbox(SET,BLACK,672,120,800,247);
		      showtexture(curtexture);
		      drwstring(SET,WHITE,BLACK,texture[curtexture].name,678,256);
		      mouseshow();
		  }
		  if (curmode==0)
		  {
		     if (hitbutton(mx,my,rup))
		     {
			 curroom++;
			 if (curroom > numrooms) curroom = numrooms;
			 eraseroom();
			 roomtext();
		     }
		     if (hitbutton(mx,my,rdown))
		     {
			 curroom--;
			 if (curroom < 1) curroom = 1;
			 eraseroom();
			 roomtext();
		     }
		  }
		  if (curmode == 1) //move vertex
		  {
		     if (hitbutton(mx,my,rup))
		     {
			 eraseline();
			 curline++;
			 if (curline > numlines) curline = numlines;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,rdown))
		     {
			 eraseline();
			 curline--;
			 if (curline < 1) curline = 1;
			 wallinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		  }
		  if (curmode == 2) //move vertex
		  {
		     if (hitbutton(mx,my,goedit))
		     {
			 getvertex(mx,my);
			 drawback();
			     vertexinfo();
			 while (mbuts)
			    mousestatus(&mx,&my,&mbuts);
			 mbuts = 1;
		     }
		     if (hitbutton(mx,my,vup))
		     {
			 curvertex++;
			 if (curvertex > numvertex) curvertex = numvertex;
			 drawvertex();
			 vertextext();
		     }
		     if (hitbutton(mx,my,vdown))
		     {
			 curvertex--;
			 if (curvertex < 1) curvertex = 1;
			 drawvertex();
			     vertextext();
		     }
		  }
	       }

	    }
	    if (!mbuts) k = getkey();
	    if (k == a_F1) screenshot();
	    if (k == a_UP)
	    {
		 mapy+=5;
		 drawback();
	    }
	    if (k == a_DOWN)
	    {
		 mapy-=5;
		 drawback();
	    }
	    if (k == a_LEFT)
	    {
		 mapx+=5;
		 drawback();
	    }
	    if (k == a_RIGHT)
	    {
		 mapx-=5;
		 drawback();
	    }
	    mbuts = 0;
   }
   saveeqm("test.eqm");
  farfree(mapvertex);
  farfree(mapline);
  farfree(maproom);
}