/*
 * XMapEdit, the XPilot Map Editor.  Copyright (C) 1993 by
 *
 *      Aaron Averill           <averila@oes.orst.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Modifications to XMapEdit
 * 1996:
 *      Robert Templeman        <mbcaprt@mphhpd.ph.man.ac.uk>
 * 1997:
 *      William Docter          <wad2@lehigh.edu>
 *
 * $Id: tools.c,v 5.2 2001/06/01 21:45:28 millerjl Exp $
 */

#include                 "main.h"

Window                   changedwin;
int                      prefx = PREF_X, prefy = PREF_Y;
int                      prevdraw_x, prevdraw_y;
int                      prevline_x, prevline_y, prevlinend_x, prevlinend_y;
int                      selectfrom_x =-1,selectfrom_y,selectto_x,selectto_y;
undo_t                   *undolist = NULL;

/***************************************************************************/
/* DrawMapIcon                                                             */
/* Arguments :                                                             */
/*   win                                                                   */
/*   name                                                                  */
/*   x                                                                     */
/*   y                                                                     */
/*   count                                                                 */
/*   btn                                                                   */
/* Purpose :                                                               */
/***************************************************************************/
int DrawMapIcon(HandlerInfo info)
{
   char                  icon=' ';
   int                   deltax,deltay,sign,i,x2,y2,x,y,count;
   unsigned int          btn;


   x = info.x-info.field->x;
   y = info.y-info.field->y;
   btn = info.button;
   count = info.count;
   
   switch (drawmode) {
 
      case 1:
      if (btn == SELECT_BTN) {  
         SelectArea(x,y,count);
         return 0;
      }
      if ( btn == DRAW_ICON_BTN) {
         icon = iconmenu[drawicon];
      }
      if (x<0) {
         x=0;
      } else if (x>mapwin_width-TOOLSWIDTH) {
         x=mapwin_width-TOOLSWIDTH-map.view_zoom;
      }
      if (y<0) {
         y=0;
      } else if (y>mapwin_height) {
         y=mapwin_height-map.view_zoom;
      }
      ClearSelectArea();
      x /= map.view_zoom;
      y /= map.view_zoom;
      x += map.view_x;
      y += map.view_y;
      if ( count <= 0 ) return 0;
      if ( count == 1) {
         ClearUndo();
         prevdraw_x = x;
         prevdraw_y = y;
         ChangeMapData(x,y,icon,1);
         return 0;
      } else {
         if (prevdraw_x == x && prevdraw_y == y) {
            return 0;
         }
         deltax = x - prevdraw_x;
         deltay = y - prevdraw_y;
         if (abs(deltax) >= abs(deltay)) {
            sign = (deltax < 0) ? -1 : 1;
            for (i = sign; abs(i) <= abs(deltax); i += sign) {
               x2 = prevdraw_x + i;
               y2 = prevdraw_y + (i * deltay) / deltax;
               ChangeMapData(x2,y2,icon,1);
            }
            prevdraw_x = x;
            prevdraw_y = y;
         } else {
            sign = (deltay < 0) ? -1 : 1;
            for (i = sign; abs(i) <= abs(deltay); i += sign) {
               x2 = prevdraw_x + (i * deltax) / deltay;
               y2 = prevdraw_y + i;
               ChangeMapData(x2,y2,icon,1);
            }
            prevdraw_x = x;
            prevdraw_y = y;
         }
      }
      break;

      case 2:        
      if (btn == SELECT_BTN) {  
         SelectArea(x,y,count);
         return 0;
      }
      if ( btn == LINE_ICON_BTN) {
         icon = iconmenu[drawicon];
      }
      ClearSelectArea();
      if ( count == 0) {
         XDrawLine(display,mapwin, xorgc,
              (int)((prevline_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevline_y-map.view_y+.5)*map.view_zoom),
              (int)((prevlinend_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevlinend_y-map.view_y+.5)*map.view_zoom) );
         if ( (x<0) || (y<0) || (x>mapwin_width-TOOLSWIDTH) ||
              (y>mapwin_height) ) {
            return 0;
         } else {
            ClearUndo();
            deltax = prevlinend_x - prevline_x;
            deltay = prevlinend_y - prevline_y;
            if ( (deltax == 0) && (deltay == 0) ) {
               ChangeMapData(prevline_x,prevline_y,icon,1);
               return 0;
            }
            if (abs(deltax) >= abs(deltay)) {
               sign = (deltax < 0) ? -1 : 1;
               for (i = 0; abs(i) <= abs(deltax); i += sign) {
                  x2 = prevline_x + i;
                  y2 = prevline_y + (i * deltay) / deltax;
                  ChangeMapData(x2,y2,icon,1);
               }
            } else {
               sign = (deltay < 0) ? -1 : 1;
               for (i = 0; abs(i) <= abs(deltay); i += sign) {
                  x2 = prevline_x + (i * deltax) / deltay ;
                  y2 = prevline_y + i;
                  ChangeMapData(x2,y2,icon,1);
               }
            }
         }
         return 0;
      }
      x /= map.view_zoom;
      y /= map.view_zoom;
      x += map.view_x;
      y += map.view_y;
      if ( count == 1) {
         ClearSelectArea();
         prevline_x = prevlinend_x = x;
         prevline_y = prevlinend_y = y;
            XDrawLine(display,mapwin, xorgc,
                 (int)((prevline_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
                 (int)((prevline_y-map.view_y+.5)*map.view_zoom),
                 (int)((prevlinend_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
                 (int)((prevlinend_y-map.view_y+.5)*map.view_zoom) );
         return 0;
      } else {
         XDrawLine(display,mapwin, xorgc,
              (int)((prevline_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevline_y-map.view_y+.5)*map.view_zoom),
              (int)((prevlinend_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevlinend_y-map.view_y+.5)*map.view_zoom) );
         prevlinend_x = x;
         prevlinend_y = y;
         XDrawLine(display,mapwin, xorgc,
              (int)((prevline_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevline_y-map.view_y+.5)*map.view_zoom),
              (int)((prevlinend_x-map.view_x+.5)*map.view_zoom+TOOLSWIDTH),
              (int)((prevlinend_y-map.view_y+.5)*map.view_zoom) );
      }
      break;

      case 3:
         SelectArea(x,y,count);
         break;

   } /* end switch */
   return 0;
}

void SelectArea(int x, int y, int count)
{
   if (x<0) {
      x=0;
   } else if (x>mapwin_width-TOOLSWIDTH) {
      x=mapwin_width-TOOLSWIDTH-map.view_zoom;
   }
   if (y<0) {
      y=0;
   } else if (y>mapwin_height) {
      y=mapwin_height-map.view_zoom;
   }
   if ( count == 0) {
      return;
   }
   if ( count == 1) {
      ClearSelectArea();
      selectfrom_x = selectto_x = x/map.view_zoom;
      selectfrom_y = selectto_y = y/map.view_zoom;
      DrawSelectArea();
      return;
   }
   DrawSelectArea();
   x /= map.view_zoom;
   y /= map.view_zoom;
   selectto_x = x;
   selectto_y = y;
   DrawSelectArea();
}

/***************************************************************************/
/* ChangeMapData                                                           */
/* Arguments :                                                             */
/*   x                                                                     */
/*   y                                                                     */
/*   icon                                                                  */
/*   save                                                                  */
/* Purpose :                                                               */
/***************************************************************************/
/* RTT also made this do something too */
void ChangeMapData(int x, int y,char icon, int save)
{
   int                   x2,y2,xo=0,yo=0,wo=0,ho=0;
   char                  data;

   map.changed = 1;	
   x2 = (x - map.view_x)*map.view_zoom;
   y2 = (y - map.view_y)*map.view_zoom;

   if (x < 0) x += map.width;
   if (y < 0) y += map.height;
   if (x > (map.width-1)) x -= map.width;
   if (y > (map.height-1)) y -= map.height;
   if ( map.data[x][y] == icon ) return;
   if (save)
      SaveUndoIcon(x,y,map.data[x][y]);
   map.data[x][y] = icon;
   UpdateSmallMap(x,y);

   if ( x2<0 ) x2 += map.width*map.view_zoom;
   if ( y2<0 ) y2 += map.height*map.view_zoom;
   if ( x2>(mapwin_width-TOOLSWIDTH) ) x2 -= map.width*map.view_zoom;
   if ( y2>mapwin_height ) y2 -= map.width*map.view_zoom;
   if ( (x2<0) || (y2<0) || (x2>(mapwin_width-TOOLSWIDTH)) || (y2>mapwin_height) ) return;
   data = MapData(x-1,y);
   if ( (data == MAP_FILLED) || (data == MAP_FUEL) ||
        (data == MAP_REC_RU) || (data == MAP_REC_RD) || (data == MAP_DEC_RU) || (data == MAP_DEC_RD) || (data == MAP_DEC_FLD) ) {
      xo++;
      wo--;
   }
   data = MapData(x+1,y);
   if ( (data == MAP_FILLED) || (data == MAP_FUEL) ||
        (data == MAP_REC_LU) || (data == MAP_REC_LD) || (data == MAP_DEC_LU) || (data == MAP_DEC_LD) || (data == MAP_DEC_FLD) ) {
      wo--;
   }
   data = MapData(x,y-1);
   if ( (data == MAP_FILLED) || (data == MAP_FUEL) ||
        (data == MAP_REC_RD) || (data == MAP_REC_LD) || (data == MAP_DEC_RD) || (data == MAP_DEC_LD) || (data == MAP_DEC_FLD) ) {
      yo++;
      ho--;
   }
   data = MapData(x,y+1);
   if ( (data == MAP_FILLED) || (data == MAP_FUEL) ||
        (data == MAP_REC_RU) || (data == MAP_REC_LU) || (data == MAP_DEC_RU) || (data == MAP_DEC_LU) || (data == MAP_DEC_FLD) ) {
      ho--;
   }
   XFillRectangle(display,mapwin,Black_GC,x2+TOOLSWIDTH+xo,y2+yo,
        map.view_zoom+1+wo,map.view_zoom+1+ho);
   DrawMapSection(x,y,0,0,x2+TOOLSWIDTH,y2);
}

/***************************************************************************/
/* MoveMapView                                                             */
/* Arguments :                                                             */
/*   win                                                                   */
/*   name                                                                  */
/*   x                                                                     */
/*   y                                                                     */
/*   count                                                                 */
/*   btn                                                                   */
/* Purpose :                                                               */
/***************************************************************************/
int MoveMapView(HandlerInfo info)
{
   int                   oldx, oldy;
   int                   width,height, xclear, yclear;
   int                   xfrom, yfrom, xto, yto;
   int                   x,y,count;
   unsigned int          btn;

   x = info.x-info.field->x;
   y = info.y-info.field->y;
   count = info.count;
   btn = info.button;
   if ( count == 0 ) return 1;
   ClearSelectArea();
   oldx = map.view_x;
   oldy = map.view_y;
   DrawViewBox();
   map.view_x = (x*smlmap_xscale)-(mapwin_width-TOOLSWIDTH)/ (map.view_zoom*2);
   map.view_y = (y*smlmap_yscale)-mapwin_height/ (map.view_zoom*2);
   while ( map.view_x < 0 ) map.view_x+= map.width;
   while ( map.view_y < 0 ) map.view_y+= map.height;
   while ( map.view_x > map.width ) map.view_x-= map.width;
   while ( map.view_y > map.height ) map.view_y-= map.height;
   if ( (map.view_x != oldx) || (map.view_y != oldy) ) {
      width = mapwin_width - abs(oldx-map.view_x)*map.view_zoom - TOOLSWIDTH;
      height = mapwin_height - abs(oldy-map.view_y)*map.view_zoom;
      if (oldx < map.view_x ) {
         xfrom = (map.view_x - oldx)*map.view_zoom;
         xto = 0;
         xclear = width;
      }
      else {
         xfrom = 0;
         xto = (oldx - map.view_x)*map.view_zoom;
         xclear = 0;
      }
      if (oldy < map.view_y ) {
         yfrom = (map.view_y - oldy)*map.view_zoom;
         yto = 0;
         yclear = height;
      }
      else {
         yfrom = 0;
         yto = (oldy - map.view_y)*map.view_zoom;
         yclear = 0;
      }

      if ( (width >0) && (height > 0)) {
         XCopyArea(display, mapwin, mapwin, White_GC, xfrom+TOOLSWIDTH,
              yfrom, width, height, xto+TOOLSWIDTH, yto);
         if ((mapwin_width-TOOLSWIDTH) != width ) {
            XClearArea(display,mapwin,xclear+TOOLSWIDTH,0,
                 mapwin_width-width-TOOLSWIDTH,mapwin_height,0);
         DrawMap(xclear+TOOLSWIDTH-1,0,mapwin_width-width-TOOLSWIDTH+1,
              mapwin_height);
         }
         if (((mapwin_width-TOOLSWIDTH) != xto) && (mapwin_height != height)) {
            XClearArea(display,mapwin,xto+TOOLSWIDTH,yclear,
                 mapwin_width-xto-TOOLSWIDTH, mapwin_height-height,0);
         DrawMap(xto+TOOLSWIDTH-1,yclear-1,mapwin_width-xto-TOOLSWIDTH+1,
              mapwin_height-height+1);
         }
      } else {
         XClearArea(display,mapwin,TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,
              mapwin_height,0);
         DrawMap(TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,mapwin_height);
      }
   }
   DrawViewBox();
   return 0;
}

/***************************************************************************/
/* ZoomOut                                                                 */
/* Arguments :                                                             */
/*   win                                                                   */
/*   btnname                                                               */
/* Purpose :                                                               */
/***************************************************************************/
int ZoomOut(HandlerInfo info)
{
   int                   x,y, oldvx = 0, oldvy = 0;

   if (map.view_zoom < 2) return 1;
   DrawViewBox();
   if ( selectfrom_x >= 0 ) {
      x = map.view_x + (selectfrom_x + selectto_x)/2;
      y = map.view_y + (selectfrom_y + selectto_y)/2;
      oldvx = map.view_x;
      oldvy = map.view_y;
      DrawSelectArea();
   } else {
      x = map.view_x + (mapwin_width-TOOLSWIDTH)/(map.view_zoom*2);
      y = map.view_y + (mapwin_height)/(map.view_zoom*2);
   }
   if (map.view_zoom < 10) map.view_zoom--;
   else if (map.view_zoom < 20) map.view_zoom -= 2;
   else map.view_zoom -= 4;
   while ( (((mapwin_width-TOOLSWIDTH)/map.view_zoom) > map.width) ||
        ((mapwin_height/map.view_zoom) > map.height) )
   map.view_zoom++;
   map.view_x = x - (mapwin_width-TOOLSWIDTH)/(map.view_zoom*2);
   map.view_y = y - (mapwin_height)/(map.view_zoom*2);
   DrawViewBox();
   XClearArea(display,mapwin,TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,
        mapwin_height,0);
   DrawMap(TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,mapwin_height);
   T_SetWindowSizeLimits(mapwin,TOOLSWIDTH+50,TOOLSHEIGHT,
        TOOLSWIDTH+map.width*map.view_zoom,map.height*map.view_zoom,0,0); 
   SizeSelectBounds(oldvx,oldvy);
   return 0;
}

/***************************************************************************/
/* ZoomIn                                                                  */
/* Arguments :                                                             */
/*   win                                                                   */
/*   btnname                                                               */
/* Purpose :                                                               */
/***************************************************************************/
int ZoomIn(HandlerInfo info)
{
   int                   x,y,oldvx = 0, oldvy = 0;

   if (map.view_zoom > 46) return 1;
   DrawViewBox();
   if ( selectfrom_x >= 0 ) {
      x = map.view_x + (selectfrom_x + selectto_x)/2;
      y = map.view_y + (selectfrom_y + selectto_y)/2;
      oldvx = map.view_x;
      oldvy = map.view_y;
      DrawSelectArea();
   } else {
      x = map.view_x + (mapwin_width-TOOLSWIDTH)/(map.view_zoom*2);
      y = map.view_y + (mapwin_height)/(map.view_zoom*2);
   }
   if (map.view_zoom > 20 ) map.view_zoom +=4;
   else if (map.view_zoom > 10) map.view_zoom +=2;
   else map.view_zoom++;
   map.view_x = x - (mapwin_width-TOOLSWIDTH)/(map.view_zoom*2);
   map.view_y = y - (mapwin_height)/(map.view_zoom*2);
   DrawViewBox();
   XClearArea(display,mapwin,TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,
        mapwin_height,0);
   DrawMap(TOOLSWIDTH,0,mapwin_width-TOOLSWIDTH,mapwin_height);
   T_SetWindowSizeLimits(mapwin,TOOLSWIDTH+50,TOOLSHEIGHT,
        TOOLSWIDTH+map.width*map.view_zoom,map.height*map.view_zoom,0,0); 
   SizeSelectBounds(oldvx,oldvy);
   return 0;
}

void SizeSelectBounds(int oldvx, int oldvy)
{
   if (selectfrom_x < 0 ) return;
   selectfrom_x += (oldvx - map.view_x);
   selectfrom_y += (oldvy - map.view_y);
   selectto_x += (oldvx - map.view_x);
   selectto_y += (oldvy - map.view_y);
   if (selectfrom_x < 0) selectfrom_x = 0;
   if (selectfrom_y < 0) selectfrom_y = 0;
   if (selectto_x < 0) selectto_x = 0;
   if (selectto_y < 0) selectto_y = 0;
   if (selectfrom_x > (mapwin_width-TOOLSWIDTH)/map.view_zoom )
        selectfrom_x = (mapwin_width-TOOLSWIDTH)/map.view_zoom;
   if (selectfrom_y > (mapwin_height)/map.view_zoom )
        selectfrom_y = mapwin_height/map.view_zoom;
   if (selectto_x > (mapwin_width-TOOLSWIDTH)/map.view_zoom )
        selectto_x = (mapwin_width-TOOLSWIDTH)/map.view_zoom;
   if (selectto_y > (mapwin_height)/map.view_zoom )
        selectto_y = mapwin_height/map.view_zoom;
   DrawSelectArea();
}

/***************************************************************************/
/* ExitApplication                                                         */
/* Arguments :                                                             */
/*   win                                                                   */
/*   name                                                                  */
/* Purpose :                                                               */
/***************************************************************************/
int ExitApplication(HandlerInfo info)
{
   if (ChangedPrompt(ExitApplication)) return 0;
   if ( T_IsPopupOpen(changedwin) ) {
      T_PopupClose(changedwin);
      changedwin = (Window) NULL;
   }
   T_FormCloseWindow(mapwin);
   T_FormCloseWindow(prefwin);
   T_FormCloseWindow(filepromptwin);

   XFreeGC(display, White_GC);
   XFreeGC(display, Black_GC);
   XFreeGC(display, xorgc);
#ifndef MONO
XFreeGC(display, Wall_GC);
XFreeGC(display, Decor_GC);
XFreeGC(display, Fuel_GC);
XFreeGC(display, Treasure_GC);
XFreeGC(display, Target_GC);
XFreeGC(display, Item_Conc_GC);
XFreeGC(display, Gravity_GC);
XFreeGC(display, Current_GC);
XFreeGC(display, Wormhole_GC);
XFreeGC(display, Base_GC);
XFreeGC(display, Cannon_GC);
#endif
   T_CloseServerConnection();
   exit ( 1 );
}

/***************************************************************************/
/* SaveUndoIcon                                                            */
/* Arguments :                                                             */
/*   x                                                                     */
/*   y                                                                     */
/*   icon                                                                  */
/* Purpose :                                                               */
/***************************************************************************/
int SaveUndoIcon(int x, int y, char icon)
{
   struct undo_t        *undo = NULL;

   undo = (struct undo_t *) undolist;
   undolist = (undo_t *) malloc(sizeof(undo_t) );
   undolist->next = undo;
   undolist->x = x;
   undolist->y = y;
   undolist->icon = icon;
   return 0;
}

/***************************************************************************/
/* Undo                                                                    */
/* Arguments :                                                             */
/*   win                                                                   */
/*   btnname                                                               */
/* Purpose :                                                               */
/***************************************************************************/
int Undo(HandlerInfo info)
{
   undo_t                *traverse;

   ClearSelectArea();
   /* if the first icon is a breakpoint, skip it */
   if (undolist != NULL) {
      if (undolist->icon == '\n') {
         traverse = (undo_t *) undolist->next;
         free(undolist);
         undolist = traverse;
      }
   }
   while ( undolist != NULL ) {

      /* check if we are at a breakpoint */
      if ( undolist->icon == '\n' ) {
         return 0;
      }
      ChangeMapData(undolist->x, undolist->y, undolist->icon,0);
      traverse = (undo_t *) undolist->next;
      free(undolist);
      undolist = traverse;
   }
   return 0;
}

/***************************************************************************/
/* ClearUndo                                                               */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
void ClearUndo(void)
{
   /* insert a breakpoint */
   SaveUndoIcon(0,0,'\n');
}

/***************************************************************************/
/* NewMap                                                                  */
/* Arguments :                                                             */
/*   win                                                                   */
/*   btnname                                                               */
/* Purpose :                                                               */
/***************************************************************************/
int NewMap(HandlerInfo info)
{
   int                   i,j;

   ClearSelectArea();
   if (ChangedPrompt(NewMap)) return 1;
   if ( T_IsPopupOpen(changedwin) ) {
      T_PopupClose(changedwin);
      changedwin = (Window ) NULL;
   }
   free(map.comments);
   map.comments = (char *) NULL;
   map.mapName[0] = map.mapAuthor[0] = map.mapFileName[0] = map.gravity[0] = (char)NULL;
   map.shipMass[0] = map.maxRobots[0] = map.worldLives[0] = (char) NULL;
   map.width = DEFAULT_WIDTH;
   map.height = DEFAULT_HEIGHT;
   sprintf(map.width_str, "%d", map.width);
   sprintf(map.height_str, "%d", map.height);
   for ( i=0; i<MAX_MAP_SIZE; i++) 
   for ( j=0; j<MAX_MAP_SIZE; j++)
   map.data[i][j] = ' ';
   map.view_zoom = DEFAULT_MAP_ZOOM;
   map.changed = map.edgeWrap = map.edgeBounce = map.teamPlay = 0;
   map.timing = map.allowPlayerCrashes = map.allowPlayerKilling = 0;
   map.limitedVisibility = map.allowShields = 0;
   ResetMap();
   ClearUndo();
   return 0;
}

/***************************************************************************/
/* ResizeWidth                                                             */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int ResizeWidth(HandlerInfo info)
{
   int                   width;

   width = atoi(info.field->charvar);
   if (( width < 20 ) || ( width > MAX_MAP_SIZE ) ) {
      strcpy(info.field->charvar,info.form->entry_restore);
   }
   else {
      sprintf(info.field->charvar,"%d",width);
      map.width = width;
      ResetMap();
      ClearUndo();
   }
   return 0;
}

/***************************************************************************/
/* ResizeHeight                                                            */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int ResizeHeight(HandlerInfo info)
{
   int                   height;

   height = atoi(info.field->charvar);
   if (( height < 20 ) || ( height > MAX_MAP_SIZE ) ) {
      strcpy(info.field->charvar,info.form->entry_restore);
   }
   else {
      sprintf(info.field->charvar,"%d",height);
      map.height = height;
      ResetMap();
      ClearUndo();
   }
   return 0;
}

/***************************************************************************/
/* OpenPreferencesPopup                                                    */
/* Arguments :                                                             */
/*   win                                                                   */
/*   name                                                                  */
/* Purpose :                                                               */
/***************************************************************************/
int OpenPreferencesPopup(HandlerInfo info)
{
   XMapWindow(display,prefwin);
   return 0;
}
/***************************************************************************/
/* OpenMapInfoPopup                                                        */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenMapInfoPopup()
{
   Window *temp;

   switch (prefssheet){
   case 0: temp = &mapinfo;
   break;
   case 1: temp = &robots;
   break;
   case 2: temp = &visibility;
   break;
   case 3: temp = &cannons;
   break;
   case 4: temp = &rounds;
   break;
   case 5: temp = &inititems;
   break;
   case 6: temp = &maxitems;
   break;
   case 7: temp = &probs;
   break;
   case 8: temp = &scoring;
   break;
   }

   XMapWindow(display, mapinfo);
   return 0;
}
/***************************************************************************/
/* OpenRobotsPopup                                                         */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenRobotsPopup()
{
   XMapWindow(display, robots);
   return 0;
}
/***************************************************************************/
/* OpenVisibilityPopup                                                     */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenVisibilityPopup()
{
   XMapWindow(display, visibility);
   return 0;
}
/***************************************************************************/
/* OpenCannonsPopup                                                        */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenCannonsPopup()
{
   XMapWindow(display, cannons);
   return 0;
}
/***************************************************************************/
/* OpenRoundsPopup                                                         */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenRoundsPopup()
{
   XMapWindow(display, rounds);
   return 0;
}
/***************************************************************************/
/* OpenInitItemsPopup                                                      */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenInitItemsPopup()
{
   XMapWindow(display, inititems);
   return 0;
}
/***************************************************************************/
/* OpenMaxItemsPopup                                                       */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenMaxItemsPopup()
{
   XMapWindow(display, maxitems);
   return 0;
}
/***************************************************************************/
/* OpenProbsPopup                                                          */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenProbsPopup()
{
   XMapWindow(display, probs);
   return 0;
}
/***************************************************************************/
/* OpenScoringPopup                                                        */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int OpenScoringPopup()
{
   XMapWindow(display, scoring);
   return 0;
}
/***************************************************************************/
/* ValidateCoordHandler                                                    */
/* Arguments :                                                             */
/*   win                                                                   */
/*   name                                                                  */
/*   variable                                                              */
/* Purpose :                                                               */
/***************************************************************************/
int ValidateCoordHandler(HandlerInfo info)
{
   char                  *returnval;
   char                  *string,*start;
 
   returnval = malloc(strlen(info.field->charvar)+1);
   returnval[0] = (char) NULL;
   string = malloc(strlen(info.field->charvar)+1);
   start = string;
   strcpy(string,info.field->charvar);
 
   while (string[0] != (char) NULL) {
      if ( ( (string[0] >= '0') && (string[0] <= '9') ) || (string[0] == ',') )
      sprintf(returnval,"%s%c",returnval,string[0]);
      string++;
   }
 
   strcpy(info.field->charvar,returnval);
   free(returnval);
   free(start);
   return 0;
}

/***************************************************************************/
/* ShowHoles                                                               */
/* Arguments :                                                             */
/*   win                                                                   */
/*   btnname                                                               */
/* Purpose :                                                               */
/***************************************************************************/
int ShowHoles(HandlerInfo info)
{
   int i,j,w,h,x,y;

   ClearSelectArea();
   w = mapwin_width/map.view_zoom;
   h = mapwin_height/map.view_zoom;
   for (i=0; i<w; i++)
      for (j=0;j<w;j++) {
         x = i + map.view_x;
         y = j + map.view_y;
         if ( ( mapicon_ptr[ MapData(x,y) - 32] == 20 ) && 
              ( mapicon_ptr[ MapData(x-1,y) - 32] < 6 ) && 
              ( mapicon_ptr[ MapData(x,y-1) - 32] < 6 ) && 
              ( mapicon_ptr[ MapData(x+1,y) - 32] < 6 ) && 
              ( mapicon_ptr[ MapData(x,y+1) - 32] < 6 ) ) 
            XFillRectangle(display,mapwin,White_GC,TOOLSWIDTH+i*map.view_zoom+1,
                 j*map.view_zoom+1,map.view_zoom-1,map.view_zoom-1);
      }
   return 0;
}

/***************************************************************************/
/* MapData                                                                 */
/* Arguments :                                                             */
/*   x                                                                     */
/*   y                                                                     */
/* Purpose :                                                               */
/***************************************************************************/
char MapData(int x, int y)
{
   if ( x<0 ) {
      x += map.width;
   } else if (x>=map.width) {
      x -= map.width;
   }
   if ( y<0 ) {
      y += map.height;
   } else if (y>=map.height) {
      y -= map.height;
   }

   return map.data[x][y];
}

/***************************************************************************/
/* ChangedPrompt                                                           */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int ChangedPrompt(int (*handler)())
{
   if ( changedwin != (Window) NULL ) return 0;
   if ( map.changed == 0 ) return 0;
   map.changed = 0;
   changedwin = T_PopupAlert(2,"Would you like to save the changes made to this map?","Yes","No",SavePrompt,handler);
   return 1;
}

/***************************************************************************/
/* ClearSelectArea                                                         */
/* Arguments :                                                             */
/* Purpose : Remove the select rectangle and turn the select box off.      */
/***************************************************************************/
void ClearSelectArea(void)
{
   DrawSelectArea();
   selectfrom_x = -1;
}

/***************************************************************************/
/* DrawSelectArea                                                          */
/* Arguments :                                                             */
/* Purpose : Draw the select rectangle.                                    */
/***************************************************************************/
void DrawSelectArea(void)
{
   int                   x,y,w,h;
 
   if (selectfrom_x < 0) return;
   w = (selectto_x-selectfrom_x)*map.view_zoom;
   h = (selectto_y-selectfrom_y)*map.view_zoom;
   if ( w<0 ) {
      w = -w;
      x = selectto_x*map.view_zoom+TOOLSWIDTH;
   } else {
      x = selectfrom_x*map.view_zoom+TOOLSWIDTH;
   }
   if ( h<0 ) {
      h = -h;
      y = selectto_y*map.view_zoom;
   } else {
      y = selectfrom_y*map.view_zoom;
   }
 
   XDrawRectangle(display,mapwin,xorgc,x-1,y-1,w+map.view_zoom+2,
        h+map.view_zoom+2);
}

/***************************************************************************/
/* FillMapArea                                                             */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int FillMapArea(HandlerInfo info)
{
   int                   i,j,x1,y1,x2,y2;

   DrawSelectArea();
   ClearUndo();
   if (selectfrom_x < 0) return 1;
   if (selectfrom_x < selectto_x) {
      x1 = selectfrom_x+map.view_x;
      x2 = selectto_x+1+map.view_x;
   } else {
      x1 = selectto_x+map.view_x;
      x2 = selectfrom_x+1+map.view_x;
   }
   if (selectfrom_y < selectto_y) {
      y1 = selectfrom_y+map.view_y;
      y2 = selectto_y+1+map.view_y;
   } else {
      y1 = selectto_y+map.view_y;
      y2 = selectfrom_y+1+map.view_y;
   }
   for (i=x1;i<x2;i++)
      for(j=y1;j<y2;j++)
         ChangeMapData(i,j,iconmenu[drawicon],1);
   DrawSelectArea();
   return 0;
}

/***************************************************************************/
/* CopyMapArea                                                             */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int CopyMapArea(HandlerInfo info)
{
   int                   i,j,x1,y1,x2,y2;
 
   DrawSelectArea();
   if (selectfrom_x < 0) return 1;
   if (selectfrom_x < selectto_x) {
      x1 = selectfrom_x+map.view_x;
      x2 = selectto_x+1+map.view_x;
   } else {
      x1 = selectto_x+map.view_x;
      x2 = selectfrom_x+1+map.view_x;
   }
   if (selectfrom_y < selectto_y) {
      y1 = selectfrom_y+map.view_y;
      y2 = selectto_y+1+map.view_y;
   } else {
      y1 = selectto_y+map.view_y;
      y2 = selectfrom_y+1+map.view_y;
   }
   for (i=0;i<MAX_MAP_SIZE;i++)
      for (j=0;j<MAX_MAP_SIZE;j++)
         clipdata[i][j] = ' ';
   for (i=x1;i<x2;i++)
      for(j=y1;j<y2;j++)
         clipdata[i-x1][j-y1] = MapData(i,j);
   DrawSelectArea();
   return 0;
}

/***************************************************************************/
/* CutMapArea                                                              */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int CutMapArea(HandlerInfo info)
{
   int                   i,j,x1,y1,x2,y2;
 
   DrawSelectArea();
   ClearUndo();
   if (selectfrom_x < 0) return 1;
   if (selectfrom_x < selectto_x) {
      x1 = selectfrom_x+map.view_x;
      x2 = selectto_x+1+map.view_x;
   } else {
      x1 = selectto_x+map.view_x;
      x2 = selectfrom_x+1+map.view_x;
   }
   if (selectfrom_y < selectto_y) {
      y1 = selectfrom_y+map.view_y;
      y2 = selectto_y+1+map.view_y;
   } else {
      y1 = selectto_y+map.view_y;
      y2 = selectfrom_y+1+map.view_y;
   }
   for (i=0;i<MAX_MAP_SIZE;i++)
      for (j=0;j<MAX_MAP_SIZE;j++)
         clipdata[i][j] = ' ';
   for (i=x1;i<x2;i++)
      for(j=y1;j<y2;j++) {
         clipdata[i-x1][j-y1] = MapData(i,j);
         ChangeMapData(i,j,' ',1);
      }
   DrawSelectArea();
   return 0;
}

/***************************************************************************/
/* PasteMapArea                                                            */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int PasteMapArea(HandlerInfo info)
{
   int                   i,j,x1,y1,x2,y2;
 
   DrawSelectArea();
   ClearUndo();
   if (selectfrom_x < 0) return 1;
   if (selectfrom_x < selectto_x) {
      x1 = selectfrom_x+map.view_x;
      x2 = selectto_x+1+map.view_x;
   } else {
      x1 = selectto_x+map.view_x;
      x2 = selectfrom_x+1+map.view_x;
   }
   if (selectfrom_y < selectto_y) {
      y1 = selectfrom_y+map.view_y;
      y2 = selectto_y+1+map.view_y;
   } else {
      y1 = selectto_y+map.view_y;
      y2 = selectfrom_y+1+map.view_y;
   }
   for (i=x1;i<x2;i++)
      for(j=y1;j<y2;j++) 
         if (clipdata[i-x1][j-y1] != ' ')
            ChangeMapData(i,j,clipdata[i-x1][j-y1],1);
   DrawSelectArea();
   return 0;
}

/***************************************************************************/
/* NegativeMapArea                                                         */
/* Arguments :                                                             */
/* Purpose :                                                               */
/***************************************************************************/
int NegativeMapArea(HandlerInfo info)
{
   int                   i,j,x1,y1,x2,y2;
 
   DrawSelectArea();
   ClearUndo();
   if (selectfrom_x < 0) return 1;
   if (selectfrom_x < selectto_x) {
      x1 = selectfrom_x+map.view_x;
      x2 = selectto_x+1+map.view_x;
   } else {
      x1 = selectto_x+map.view_x;
      x2 = selectfrom_x+1+map.view_x;
   }
   if (selectfrom_y < selectto_y) {
      y1 = selectfrom_y+map.view_y;
      y2 = selectto_y+1+map.view_y;
   } else {
      y1 = selectto_y+map.view_y;
      y2 = selectfrom_y+1+map.view_y;
   }
   for (i=x1;i<x2;i++)
      for(j=y1;j<y2;j++) {
         switch(MapData(i,j)) {
  
            case MAP_SPACE:
               ChangeMapData(i,j,MAP_FILLED,1);
               break;

            case MAP_FILLED:
               ChangeMapData(i,j,MAP_SPACE,1);
               break;
  
            case MAP_REC_RD:
               ChangeMapData(i,j,MAP_REC_LU,1);
               break;
  
            case MAP_REC_LU:
               ChangeMapData(i,j,MAP_REC_RD,1);
               break;
  
            case MAP_REC_LD:
               ChangeMapData(i,j,MAP_REC_RU,1);
               break;
  
            case MAP_REC_RU:
               ChangeMapData(i,j,MAP_REC_LD,1);
               break;
         }
      }
   DrawSelectArea();
   return 0;
}
