/*----------------------------------------------------------------------------*
 | This file is part of DEU (Doom Editing Utilities), created by the DEU team:|
 | Raphael Quinet, Brendon Wyber, Ted Vessenes and others.  See README.1ST or |
 | the "about" dialog box for full credits.                                   |
 |                                                                            |
 | DEU is an open project: if you think that you can contribute, please join  |
 | the DEU team.  You will be credited for any code (or ideas) included in    |
 | the next version of the program.                                           |
 |                                                                            |
 | If you want to make any modifications and re-distribute them on your own,  |
 | you must follow the conditions of the DEU license.  Read the file LICENSE  |
 | in this directory or README.1ST in the top directory.  If do not have a    |
 | copy of these files, you can request them from any member of the DEU team, |
 | or by mail: Raphael Quinet, Rue des Martyrs 9, B-4550 Nandrin (Belgium).   |
 |                                                                            |
 | This program comes with absolutely no warranty.  Use it at your own risks! |
 *----------------------------------------------------------------------------*

 M_EDOBJ.C - Edit object properties

*/

/* the includes */
#include "deu.h"
#include "d_main.h"
#include "d_config.h"
#include "d_misc.h"
#include "g_gfx.h" /* color names */
#include "w_struct.h"
#include "w_levels.h"
#include "w_object.h"
#include "w_names.h"
#include "w_things.h"
#include "i_dialog.h"
#include "m_edobj.h"

/*
   Store the number and type of the objects being edited in "title".
*/

static void GetEditTitle(char *title, int maxlen, int objtype, SelPtr list)
{
  SelPtr cur;
  int    n;
  char   nbuf[10];
  char  *objname;

  if (objtype == OBJ_LINEDEFS)
    maxlen -= 11;
  objname = GetObjectTypeName(objtype);
  n = 0;
  for (cur = list; cur; cur = cur->next)
    n++;
  if (n == 1)
    sprintf(title, "Edit %s #%d", objname, list->objnum);
  else
    {
      if (objtype == OBJ_VERTEXES)
        objname = "Vertice"; /* hack */
      sprintf(title, "Edit %d %ss: #%d", n, objname, list->objnum);
      for (cur = list->next; cur; cur = cur->next)
        {
          sprintf(nbuf, ", #%d", cur->objnum);
          if (cur->next != NULL && (strlen(title) + strlen(nbuf) + 5) > maxlen)
            {
              strcat(title, ", ...");
              break;
            }
          strcat(title, nbuf);
        }
      if (objtype == OBJ_LINEDEFS)
        strcat(title, " & SideDefs");
    }
}



/*
   Function to add a new SideDef.
*/

static UInt16 InsertSidedef(LevelPtr level, Int16 *ref, Int16 xoff, Int16 yoff,
                            char *utex, char *mtex, char *ltex)
{
  UInt16 last;

  *ref = last = level->num_sidedefs;
  InsertObject(level, OBJ_SIDEDEFS, -1, 0, 0);

  level->sidedefs[last].xoff = xoff;
  level->sidedefs[last].yoff = yoff;
  strcpy(level->sidedefs[last].tex1, utex);
  strcpy(level->sidedefs[last].tex2, ltex);
  strcpy(level->sidedefs[last].tex3, mtex);

  return last;
}


/*
   Function to delete an old SideDef.
*/

static void DeleteSidedef(LevelPtr level, Int16 *ref)
{
  DeleteObject(level, OBJ_SIDEDEFS, *ref);
  *ref = -1;
}


/*
   Edit an object or a group of objects.
*/
/*! This function could be easily optimised if direct pointers were used
    instead of index numbers (especially for sidedef[...linedef...]) */
void EditObjectsInfo(LevelPtr level, Int16 x0, Int16 y0, int objtype, SelPtr list)
{
  char   utex1[9] = "", mtex1[9] = "", ltex1[9] = "";
  char   utex2[9] = "", mtex2[9] = "", ltex2[9] = "";
  Int16  i, tclass;
  Int16  when, type, angle, xpos, ypos, dx, dy;
  Int16  flags, bkflags, v1, v2, tag, sidedef1, sidedef2;
  Int16  xoff1, yoff1, sect1, xoff2, yoff2, sect2;
  Int16  floorh, ceilh, light;
  UInt32 changes;
  SelPtr cur;
  DB    *db_main, *db_linetype, *db_linedef, *db_sidedef1, *db_sidedef2;
  static Int16 *things[9], thinglen[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  static Bool thinginit = FALSE;
  char   title[80];
  char   kludge1[22], kludge2[22];

  /*! DBUpdateSidedef() writes directly in those strings in order to toggle
      between "Insert" and "Delete".  They have to be copied into some
      variable or else we get a segmentation fault (strings in code segment).
      Later, modify DBUpdateSidedef() and InsDelSidedef() so that they do not
      write in fixed strings.
  */
  strcpy(kludge1, "Insert First Sidedef");
  strcpy(kludge2, "Insert Second Sidedef");
  if (list == NULL)
    ProgError("BUG: EditObjectsInfo called with NULL list.");
  switch (objtype)
    {
    case OBJ_THINGS:
      if (!thinginit)
        {
          for (i = 0; i < 9 ; i++)
            things[i] = (Int16 *) GetMemory(2 * SB_CELL_SIZE * sizeof(Int16));
          if (DoomVersion < 16)
            {
              for (i = MINDTHINGINFO0; i <= MAXDTHINGINFO0; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things[tclass][thinglen[tclass]++] = i;
              for (i = MINDTHINGINFO2; i <= MAXDTHINGINFO2; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things[tclass][thinglen[tclass]++] = i;
              for (i = MINDTHINGINFO3; i <= MAXDTHINGINFO3; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things[tclass][thinglen[tclass]++] = i;
            }
          else
            {
              for (i = MINHTHINGINFO0; i <= MAXHTHINGINFO0; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things [tclass] [thinglen [tclass]++] = i;
              for (i = MINHTHINGINFO1; i <= MAXHTHINGINFO1; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things [tclass] [thinglen [tclass]++] = i;
              for (i = MINHTHINGINFO2; i <= MAXHTHINGINFO2; i++)
                if ((tclass = GetThingClass(i)) != -1)
                  things [tclass] [thinglen [tclass]++] = i;
            }
          thinginit = TRUE;
        }
      type  = level->things[list->objnum].type;
      angle = level->things[list->objnum].angle;
      when  = level->things[list->objnum].when;
      xpos  = level->things[list->objnum].xpos;
      ypos  = level->things[list->objnum].ypos;
      i = when;

      GetEditTitle(title, 65, objtype, list);

      db_main = LoadDialogBox(-1, -1, 545, 420, &changes, 5,
       DBSC_TEXT,  -0x0102, 10, '\0', title, 0, RED,

       DBSC_TEXT,       14,  28, 'P', "Player starts:", 0, YELLOW,
       DBSC_SCROLLBOX,  10,  40, 'P', LT_THINGS, thinglen[TC_PLAYER], &type,
        0x01L, 5, 17, things[TC_PLAYER],

       DBSC_TEXT,      184,  28, 'E', "Enemies:", 0, YELLOW,
       DBSC_SCROLLBOX, 180,  40, 'E', LT_THINGS, thinglen[TC_ENEMY],  &type,
        0x01L, 5, 18, things[TC_ENEMY]);

      if (DoomVersion & 0x10)
        AppendDbscList(db_main, &changes, 2,
         DBSC_TEXT,      362,  28, 'u', "Sounds:", 0, YELLOW,
         DBSC_SCROLLBOX, 358,  40, 'u', LT_THINGS, thinglen[TC_SOUND], &type,
          0x01L, 5, 19, things[TC_SOUND]);
      else
        AppendDbscList(db_main, &changes, 2,
         DBSC_TEXT,      362,  28, 'C', "Corpses:", 0, YELLOW,
         DBSC_SCROLLBOX, 358,  40, 'C', LT_THINGS, thinglen[TC_CORPSE], &type,
          0x01L, 5, 19, things[TC_CORPSE]);

      AppendDbscList(db_main, &changes, 12,
       DBSC_TEXT,       14,  98, 'q', "Equipment:", 0, YELLOW,
       DBSC_SCROLLBOX,  10, 110, 'q', LT_THINGS, thinglen[TC_EQPMNT], &type,
        0x01L, 5, 17, things[TC_EQPMNT],

       DBSC_TEXT,      184,  98, 'I', "Items:", 0, YELLOW,
       DBSC_SCROLLBOX, 180, 110, 'I', LT_THINGS, thinglen[TC_ARTFCT], &type,
        0x01L, 5, 18, things[TC_ARTFCT],

       DBSC_TEXT,      362,  98, 'D', "Decorations:", 0, YELLOW,
       DBSC_SCROLLBOX, 358, 110, 'D', LT_THINGS, thinglen[TC_DECOR],  &type,
        0x01L, 5, 19, things[TC_DECOR],

       DBSC_TEXT,       14, 168, 'W', "Weapons:", 0, YELLOW,
       DBSC_SCROLLBOX,  10, 180, 'W', LT_THINGS, thinglen[TC_WEAPON], &type,
        0x01L, 5, 17, things[TC_WEAPON],

       DBSC_TEXT,      184, 168, 'L', "Light Sources:", 0, YELLOW,
       DBSC_SCROLLBOX, 180, 180, 'L', LT_THINGS, thinglen[TC_LIGHT],  &type,
        0x01L, 5, 18, things[TC_LIGHT],

       DBSC_TEXT,      362, 168, 'H', "Hanging Decor:", 0, YELLOW,
       DBSC_SCROLLBOX, 358, 180, 'H', LT_THINGS, thinglen[TC_HNGDEC], &type,
        0x01L, 5, 19, things[TC_HNGDEC]);

      AppendDbscList(db_main, &changes, 18,
       DBSC_BITMAP,   -0x0102, 240, '\0', BMP_THING, &type, mtex1,

       DBSC_TEXT,      19, 246, '\0', "Select Angle", 0, BLUE,

       DBSC_CHECKBOX,  20, 271, '7', &angle, 0x02L, SVAL, 135,
       DBSC_TEXT,      23, 259, '7', "7", 0, YELLOW,
       DBSC_CHECKBOX,  60, 271, '8', &angle, 0x02L, SVAL,  90,
       DBSC_TEXT,      63, 259, '8', "8", 0, YELLOW,
       DBSC_CHECKBOX, 100, 271, '9', &angle, 0x02L, SVAL,  45,
       DBSC_TEXT,     103, 259, '9', "9", 0, YELLOW,
       DBSC_CHECKBOX, 100, 311, '6', &angle, 0x02L, SVAL,   0,
       DBSC_TEXT,     103, 299, '6', "6", 0, YELLOW,
       DBSC_CHECKBOX, 100, 351, '3', &angle, 0x02L, SVAL, 315,
       DBSC_TEXT,     103, 339, '3', "3", 0, YELLOW,
       DBSC_CHECKBOX,  60, 351, '2', &angle, 0x02L, SVAL, 270,
       DBSC_TEXT,      63, 339, '2', "2", 0, YELLOW,
       DBSC_CHECKBOX,  20, 351, '1', &angle, 0x02L, SVAL, 225,
       DBSC_TEXT,      23, 339, '1', "1", 0, YELLOW,
       DBSC_CHECKBOX,  20, 311, '4', &angle, 0x02L, SVAL, 180,
       DBSC_TEXT,      23, 299, '4', "4", 0, YELLOW);

      AppendDbscList(db_main, &changes, 14,
       DBSC_TEXT,       428, 246, '\0', "Flags", 0, BLUE,
       DBSC_L_CHECKBOX, 428, 263,  's', &when, 0x04L, BIT, 0x01, "Easy",
       DBSC_L_CHECKBOX, 428, 285,  'M', &when, 0x04L, BIT, 0x02, "Medium",
       DBSC_L_CHECKBOX, 428, 307,  'r', &when, 0x04L, BIT, 0x04, "Hard",
       DBSC_L_CHECKBOX, 428, 329,  'f', &when, 0x04L, BIT, 0x08, "Deaf",
       DBSC_L_CHECKBOX, 428, 351,  'N', &when, 0x04L, BIT, 0x10, "Net",

       DBSC_OK,       -0x0210, 390, 'O',

       DBSC_TEXT,     -0x0510, 377, 'T', "Type:", 0, YELLOW,
       DBSC_INPUTBOX, -0x0510, 392, 'T', &type, 0x01L, 0, 32767,

       DBSC_TEXT,     -0x0810, 377, 'X', "X loc:", 0, YELLOW,
       DBSC_INPUTBOX, -0x0810, 392, 'X', &xpos, 0x08L, level->map_minX, level->map_maxX,
       DBSC_TEXT,     -0x0B10, 377, 'Y', "Y loc:", 0, YELLOW,
       DBSC_INPUTBOX, -0x0B10, 392, 'Y', &ypos, 0x10L, level->map_minY, level->map_maxY,

       DBSC_CANCEL,   -0x0E10, 390, 'a');


      if (ProcessDialogBox(db_main, &changes))
        {
          when ^= i;
          dx = xpos - level->things[list->objnum].xpos;
          dy = ypos - level->things[list->objnum].ypos;

          for (cur = list; cur; cur = cur->next)
            {
              if (changes & 0x01L)
                level->things[cur->objnum].type = type;
              if (changes & 0x02L)
                level->things[cur->objnum].angle = angle;
              if (changes & 0x04L)
                level->things[cur->objnum].when ^= when;
              if (changes & 0x08L)
                level->things[cur->objnum].ypos += dx;
              if (changes & 0x10L)
                level->things[cur->objnum].ypos += dy;
            }
          level->made_changes = TRUE;
        }
      break;

    case OBJ_VERTEXES:
      xpos = level->vertexes[list->objnum].x;
      ypos = level->vertexes[list->objnum].y;
      GetEditTitle(title, 25, objtype, list);

      if (DrawDialogBox(-1, -1, 220, 118, NULL, 7,
          DBSC_TEXT, -0x0102, 7, '\0', title, 0, RED,

          DBSC_TEXT,      12, 25, 'X', "X Location:", 0, YELLOW,
          DBSC_INPUTBOX, 108, 23, 'X', &xpos, MIN(level->map_minX, -10000),
                                              MAX(level->map_maxX,  10000),
          DBSC_TEXT,      12, 45, 'Y', "Y Location:", 0, YELLOW,
          DBSC_INPUTBOX, 108, 43, 'Y', &ypos, MIN(level->map_minY, -10000),
                                              MAX(level->map_maxY,  10000),

          DBSC_OK,     -0x0102,  67, 'O',
          DBSC_CANCEL, -0x0102,  92, 'C'))
        {
          dx = xpos - level->vertexes[list->objnum].x;
          dy = ypos - level->vertexes[list->objnum].y;

          for (cur = list; cur; cur = cur->next)
            {
              level->vertexes[cur->objnum].x += dx;
              level->vertexes[cur->objnum].y += dy;
            }

          level->made_changes = TRUE;
          level->made_map_changes = TRUE;
        }
      break;

    case OBJ_LINEDEFS:
      bkflags = flags = level->linedefs[list->objnum].flags;
      tag = level->linedefs[list->objnum].tag;
      type = level->linedefs[list->objnum].type;
      v1 = level->linedefs[list->objnum].start;
      v2 = level->linedefs[list->objnum].end;
      sidedef1 = level->linedefs[list->objnum].sidedef1;
      sidedef2 = level->linedefs[list->objnum].sidedef2;
      if (sidedef1 != -1)
        {
          strncpy(utex1, level->sidedefs[level->linedefs[list->objnum].sidedef1].tex1, 8);
          utex1[8] = '\0';
          strncpy(mtex1, level->sidedefs[level->linedefs[list->objnum].sidedef1].tex3, 8);
          mtex1[8] = '\0';
          strncpy(ltex1, level->sidedefs[level->linedefs[list->objnum].sidedef1].tex2, 8);
          ltex1[8] = '\0';
          xoff1 = level->sidedefs[level->linedefs[list->objnum].sidedef1].xoff;
          yoff1 = level->sidedefs[level->linedefs[list->objnum].sidedef1].yoff;
          sect1 = level->sidedefs[level->linedefs[list->objnum].sidedef1].sector;
        }
      if (sidedef2 != -1)
        {
          strncpy(utex2, level->sidedefs[level->linedefs[list->objnum].sidedef2].tex1, 8);
          utex2[8] = '\0';
          strncpy(mtex2, level->sidedefs[level->linedefs[list->objnum].sidedef2].tex3, 8);
          mtex2[8] = '\0';
          strncpy(ltex2, level->sidedefs[level->linedefs[list->objnum].sidedef2].tex2, 8);
          ltex2[8] = '\0';
          xoff2 = level->sidedefs[level->linedefs[list->objnum].sidedef2].xoff;
          yoff2 = level->sidedefs[level->linedefs[list->objnum].sidedef2].yoff;
          sect2 = level->sidedefs[level->linedefs[list->objnum].sidedef2].sector;
        }

      db_linetype = LoadDialogBox(-1, -1, 639, 420, &changes, 9,
        DBSC_TEXT,   -0x0102,  7, '\0', "Edit Trigger Effect", 0, RED,

        DBSC_TEXT,        13, 25,  'M', "Miscellaneous (??)", 0, YELLOW,
        DBSC_SCROLLBOX,   10, 37,  'M', LT_L_EFFECTS, 19, &type,
         0x40000L, 7, 35,
          0, /* Normal */  11, 52, 51, 124, /* Exits */
          97, 126, 39, 125, /* Teleporters */  7, 127, 8, 100, /* Stairs */
          87, 89, 48, /* Misc */  46, 24, 47, /* Impact */

        DBSC_TEXT,       328, 25,  'D', "Manual Door (DR)", 0, YELLOW,
        DBSC_SCROLLBOX,  325, 37,  'D', LT_L_EFFECTS, 10, &type,
         0x40000L, 7, 35,
          1, 117, 31, 118, 26, 32, 28, 33, 27, 34, /* Manual Doors */

        DBSC_TEXT,       12, 125,  'S', "Switch (S1)", 0, YELLOW,
        DBSC_SCROLLBOX,  10, 137,  'S', LT_L_EFFECTS, 22, &type,
         0x40000L, 7, 35,
          29, 111, 103, 112, 133, 135, 137, 50, 113, /* Doors */
          21, 122, /* Elevators */
          101, 18, 20, 131, 15, 14, 140, /* Raise Floor */
          102, 71, 23, /* Lower Floor */  41, /* Ceiling */

        DBSC_TEXT,       328, 125,  'B', "Button (SR)", 0, YELLOW,
        DBSC_SCROLLBOX,  325, 137,  'B', LT_L_EFFECTS, 23, &type,
         0x40000L, 7, 35,
          63, 114, 61, 115, 99, 134, 136, 42, 116, /* Doors */
          62, 123, /* Elevators */  138, 139, /* Lights */
          45, 60, 70, /* Lower Floor */
          64, 68, 69, 132, 66, 67, /* Raise Floor */  43 /* Ceiling */);

       AppendDbscList(db_linetype, &changes, 11,
        DBSC_TEXT,        13, 225,  'T', "Trigger (W1)", 0, YELLOW,
        DBSC_SCROLLBOX,   10, 237,  'T', LT_L_EFFECTS, 26, &type,
         0x40000L, 7, 35,
          4, 108, 2, 109, 3, 110, 16, /* Doors */ 10, 121, /* Elevators */
          12, 104, 13, 35, 17, /* Lights */
          19, 36, 37, 38, 40, /* Lower Floor */
          5, 130, 119, 22, 58, 59, 30, /* Raise Floor */

        DBSC_TEXT,       328, 225,  'R', "Retrigger (WR)", 0, YELLOW,
        DBSC_SCROLLBOX,  325, 237,  'R', LT_L_EFFECTS, 25, &type,
         0x40000L, 7, 35,
          90, 105, 86, 106, 75, 107, 76, /* Doors */ 88, 120, /* Elevators */
          80, 78, 81, 79, /* Lights */ 83, 98, 84, 82, 85, /* Lower Floor */
          91, 129, 128, 95, 92, 93, 96, /* Raise Floor */

        DBSC_TEXT,        13, 325,  'u', "Crushing (??)", 0, YELLOW,
        DBSC_SCROLLBOX,   10, 337,  'u', LT_L_EFFECTS, 14, &type,
         0x40000L, 7, 35,
          73, 74, 77, 72, 94, /* WR -- Retrigger */
          25, 57, 6, 44, 56, 141, /* W1 -- Trigger */
          49, 55, /* S1 -- Switch */  65, /* SR -- Button */

        DBSC_L_CHECKBOX, 335, 352, 'N', &type, 0x40000L, TVAL, 0, "No Effect",

        DBSC_TEXT,     443, 353,  'I', "Integer Value:", 0, YELLOW,
        DBSC_INPUTBOX, 563, 351,  'I', &type, 0x40000L, 0, 32767,

        DBSC_OK,     365, 380, 'O',
        DBSC_CANCEL, 500, 380, 'C');

      db_linedef = LoadDialogBox(-1, 43, 450, 130, &changes, 19,
        DBSC_TEXT,   -0x0102,  7, '\0', "Edit Linedef", 0, RED,

        DBSC_L_CHECKBOX,  10,  28, 'I', &flags, 0x01L, BIT, 0x001, "Impassible",
        DBSC_L_CHECKBOX,  10,  43, 'M', &flags, 0x01L, BIT, 0x002, "Mnstr Block",
        DBSC_L_CHECKBOX,  10,  58, 'w', &flags, 0x01L, BIT, 0x004, "Two-sided",
        DBSC_L_CHECKBOX,  10,  73, 'U', &flags, 0x01L, BIT, 0x008, "Upper Unpgd",
        DBSC_L_CHECKBOX,  10,  88, 'L', &flags, 0x01L, BIT, 0x010, "Lower Unpgd",
        DBSC_L_CHECKBOX, 130,  28, 'S', &flags, 0x01L, BIT, 0x020, "Secret",
        DBSC_L_CHECKBOX, 130,  43, 'n', &flags, 0x01L, BIT, 0x040, "Snd Block",
        DBSC_L_CHECKBOX, 130,  58, 'v', &flags, 0x01L, BIT, 0x080, "Invisible",
        DBSC_L_CHECKBOX, 130,  73, 'A', &flags, 0x01L, BIT, 0x100, "Automapped",

        DBSC_TEXT,      250,  28, '1', "Vertex 1:", 0, YELLOW,
        DBSC_INPUTBOX,  250,  40, '1', &v1, 0x04L, 0, level->num_vertexes - 1,

        DBSC_TEXT,      250,  58, '2', "Vertex 2:", 0, YELLOW,
        DBSC_INPUTBOX,  250,  70, '2', &v2, 0x08L, 0, level->num_vertexes - 1,

        DBSC_TEXT,      340,  28, 'T', "Trigger Tag:", 0, YELLOW,
        DBSC_INPUTBOX,  340,  40, 'T', &tag, 0x02L, -32767, 32767,

        DBSC_BUTTON,    326,  65, 'E', BUTTON_PP_DIALOG, "Trigger Effect",
         WHITE, &type, DB_ALL, db_linetype,

        DBSC_OK,     -0x0103, 105, 'O',
        DBSC_CANCEL, -0x0203, 105, 'C');

      db_sidedef1 = LoadDialogBox(-1, -1, 480, 480, &changes, 18,
        DBSC_TEXT, -0x0102,  7, '\0', "Edit First Sidedef", 0, RED,

        DBSC_TEXT,      15, 20,  'X', "X offset:", 0, YELLOW,
        DBSC_INPUTBOX,  95, 18,  'X', &xoff1, 0x20L, -256, 256,

        DBSC_TEXT,     170, 20,  'Y', "Y offset:", 0, YELLOW,
        DBSC_INPUTBOX, 250, 18,  'Y', &yoff1, 0x40L, -256, 256,

        DBSC_TEXT,     325, 20,  'S', "Sector:", 0, YELLOW,
        DBSC_INPUTBOX, 389, 18,  'S', &sect1, 0x80L, 0, level->num_sectors - 1,

        DBSC_TEXT,       12,  36, 'U', "Upper Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10,  48, 'U', LT_STR, num_wtexture, utex1,
         0x100L, 13, 8, wtexture,
        DBSC_BITMAP,    110,  48, '\0', BMP_WALL, &i, utex1,

        DBSC_TEXT,       12, 186, 'M', "Middle Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10, 198, 'M', LT_STR, num_wtexture, mtex1,
         0x200L, 13, 8, wtexture,
        DBSC_BITMAP,    110, 198, '\0', BMP_WALL, &i, mtex1,

        DBSC_TEXT,       12, 336, 'L', "Lower Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10, 348, 'L', LT_STR, num_wtexture, ltex1,
         0x400L, 13, 8, wtexture,
        DBSC_BITMAP,    110, 348, '\0', BMP_WALL, &i, ltex1,

        DBSC_OK,        380,  80,  'O',
        DBSC_CANCEL,    380, 130,  'C');

      db_sidedef2 = LoadDialogBox(-1, -1, 480, 480, &changes, 18,
        DBSC_TEXT, -0x0102, 7, '\0', "Edit Second Sidedef", 0, RED,

        DBSC_TEXT,      15, 20,  'X', "X offset:", 0, YELLOW,
        DBSC_INPUTBOX,  95, 18,  'X', &xoff2, 0x1000L, -256, 256,

        DBSC_TEXT,     170, 20,  'Y', "Y offset:", 0, YELLOW,
        DBSC_INPUTBOX, 250, 18,  'Y', &yoff2, 0x2000L, -256, 256,

        DBSC_TEXT,     325, 20,  'S', "Sector:", 0, YELLOW,
        DBSC_INPUTBOX, 389, 18,  'S', &sect2, 0x4000L, 0, level->num_sectors - 1,

        DBSC_TEXT,       12,  36, 'U', "Upper Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10,  48, 'U', LT_STR, num_wtexture, utex2,
         0x8000L, 13, 8, wtexture,
        DBSC_BITMAP,    110,  48, '\0', BMP_WALL, &i, utex2,

        DBSC_TEXT,       12, 186, 'M', "Middle Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10, 198, 'M', LT_STR, num_wtexture, mtex2,
         0x10000L, 13, 8, wtexture,
        DBSC_BITMAP,    110, 198, '\0', BMP_WALL, &i, mtex2,

        DBSC_TEXT,       12, 336, 'L', "Lower Texture", 0, YELLOW,
        DBSC_SCROLLBOX,  10, 348, 'L', LT_STR, num_wtexture, ltex2,
         0x20000L, 13, 8, wtexture,
        DBSC_BITMAP,    110, 348, '\0', BMP_WALL, &i, ltex2,

        DBSC_OK,        380,  80,  'O',
        DBSC_CANCEL,    380, 130,  'C');

      GetEditTitle(title, 57, objtype, list);

      if (DrawDialogBox(-1, -1, 480, 215, &changes, 17,
           DBSC_UPDATE, 0, 0, '\0', &sidedef1, DB_UPDATE, DbUpdateSidedef,
           DBSC_UPDATE, 0, 0, '\0', &sidedef2, DB_UPDATE, DbUpdateSidedef,
           DBSC_TEXT, -0x0102, 7, '\0', title, 0, RED,

           DBSC_TEXT, -0x0102, 30, '\0', "Linedef:", 0, BLUE,
           DBSC_BUTTON, -0x0102, 45, 'L', BUTTON_PP_DIALOG, "Edit Linedef",
            WHITE, NULL, DB_CUR, db_linedef,

           DBSC_TEXT,      -0x0207,  85, '\0', "First Sidedef:", 0, BLUE,
           DBSC_TEXT,      -0x0507,  85, '\0', "Second Sidedef:", 0, BLUE,

           DBSC_TEXT,      -0x0207, 100, '1', "Sidedef 1", 0, YELLOW,
           DBSC_INPUTBOX,  -0x0207, 112, '1', &sidedef1, 0x10L, -1, level->num_sidedefs,
           DBSC_TEXT,      -0x0507, 100, '2', "Sidedef 2", 0, YELLOW,
           DBSC_INPUTBOX,  -0x0507, 112, '2', &sidedef2, 0x800L, -1, level->num_sidedefs,

           DBSC_BUTTON,    -0x0207, 130,  'F', BUTTON_FUNCTION,
            kludge1,  GREEN, &sidedef1, DB_UPDATE,
            InsDelSidedef,
             level, &sidedef2, utex1, mtex1, ltex1, utex2, mtex2,
             ltex2, &xoff1, &yoff1, &flags, 0x10L, 0x700L, 0x38000L,
           DBSC_BUTTON,    -0x0507, 130,  'S', BUTTON_FUNCTION,
            kludge2, GREEN, &sidedef2, DB_UPDATE,
            InsDelSidedef,
             level, &sidedef1, utex2, mtex2, ltex2, utex1, mtex1,
             ltex1, &xoff2, &yoff2, &flags, 0x800L, 0x38000L, 0x700L,

           DBSC_BUTTON,    -0x0207, 155,  'E', BUTTON_PP_DIALOG,
            "Edit First Sidedef",  WHITE, &sidedef1, DB_ALL, db_sidedef1,
           DBSC_BUTTON,    -0x0507, 155,  'd', BUTTON_PP_DIALOG,
            "Edit Second Sidedef", WHITE, &sidedef2, DB_ALL, db_sidedef2,

           DBSC_OK,     -0x0103, 180, 'O',
           DBSC_CANCEL, -0x0203, 180, 'C'))
        {
          flags ^= bkflags;

          for (cur = list; cur; cur = cur->next)
            {
              if (changes & 0x01L && flags)
                level->linedefs[cur->objnum].flags ^= flags;
              if (changes & 0x02L)
                level->linedefs[cur->objnum].tag = tag;
              if (changes & 0x04L)
                level->linedefs[cur->objnum].start = v1;
              if (changes & 0x08L)
                level->linedefs[cur->objnum].end = v2;
              if (changes & 0x40000L)
                level->linedefs[cur->objnum].type = type;

              if (changes & 0x10L)
                { /* If the first sidedef has been changed */
                  if (sidedef1 == -1 && level->linedefs[cur->objnum].sidedef1 != -1)
                    {
                      if (sidedef2 > level->linedefs[cur->objnum].sidedef1)
                        sidedef2--;
                      sidedef1--;
                      DeleteSidedef(level, &(level->linedefs[cur->objnum].sidedef1));
                    }
                  else if (sidedef1 == level->num_sidedefs &&
                           level->linedefs[cur->objnum].sidedef1 == -1)
                    {
                      if (sidedef2 == level->num_sidedefs)
                        sidedef2++;
                      sidedef1++;
                      InsertSidedef(level, &(level->linedefs[cur->objnum].sidedef1),
                                    xoff1, yoff1,
                                    utex1, mtex1, ltex1);
                    }
                  else
                    level->linedefs[cur->objnum].sidedef1 = sidedef1;
                }

              if (changes & 0x800L)
                { /* If the second sidedef has been changed */
                  if (sidedef2 == -1 && level->linedefs[cur->objnum].sidedef2 != -1)
                    {
                      if (sidedef1 > level->linedefs[cur->objnum].sidedef2)
                        sidedef1--;
                      sidedef2--;
                      DeleteSidedef(level, &(level->linedefs[cur->objnum].sidedef2));
                    }
                  else if (sidedef2 == level->num_sidedefs &&
                           level->linedefs[cur->objnum].sidedef2 == -1)
                    {
                      if (sidedef1 == level->num_sidedefs)
                        sidedef1++;
                      sidedef2++;
                      InsertSidedef(level, &(level->linedefs[cur->objnum].sidedef2),
                                    xoff2, yoff2,
                                    utex2, mtex2, ltex2);
                    }
                  else
                    level->linedefs[cur->objnum].sidedef2 = sidedef2;
                }

              if (level->linedefs[cur->objnum].sidedef1 != -1)
                {
                  if (changes & 0x20L) /* xoff */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef1].xoff = xoff1;
                  if (changes & 0x40L) /* yoff */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef1].yoff = yoff1;
                  if (changes & 0x80L) /* sect */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef1].sector = sect1;
                  if (changes & 0x100L) /* utex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef1].tex1,
                            utex1, 8);
                  if (changes & 0x200L) /* mtex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef1].tex3,
                            mtex1, 8);
                  if (changes & 0x400L) /* ltex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef1].tex2,
                            ltex1, 8);
                }
              if (level->linedefs[cur->objnum].sidedef2 != -1)
                {
                  if (changes & 0x1000L) /* xoff */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef2].xoff = xoff2;
                  if (changes & 0x2000L) /* yoff */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef2].yoff = yoff2;
                  if (changes & 0x4000L) /* sect */
                    level->sidedefs[level->linedefs[cur->objnum].sidedef2].sector = sect2;
                  if (changes & 0x8000L) /* utex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef2].tex1,
                            utex2, 8);
                  if (changes & 0x10000L) /* mtex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef2].tex3,
                            mtex2, 8);
                  if (changes & 0x20000L) /* ltex */
                    strncpy(level->sidedefs[level->linedefs[cur->objnum].sidedef2].tex2,
                            ltex2, 8);
                }
            }
          level->made_changes = TRUE;
        }
      break;

    case OBJ_SECTORS:
      floorh = level->sectors[list->objnum].floorh;
      ceilh = level->sectors[list->objnum].ceilh;
      strncpy(ltex1, level->sectors[list->objnum].floort, 8);
      strncpy(utex1, level->sectors[list->objnum].ceilt, 8);
      light = level->sectors[list->objnum].light;
      tag = level->sectors[list->objnum].tag;
      type = level->sectors[list->objnum].type;

      GetEditTitle(title, 49, objtype, list);

      db_main = LoadDialogBox(-1, -1, 417, 344, &changes, 13,
       DBSC_TEXT, -0x0102, 7, '\0', title, 0, RED,

       DBSC_TEXT,          26,  25,  'F', "Floor Texture:", 0, YELLOW,
       DBSC_SCROLLBOX,     24,  37,  'F', LT_STR, num_ftexture, ltex1,
        0x01L, 11, 8, ftexture,
       DBSC_BITMAP,       124,  37, '\0', BMP_FLAT, &i, ltex1,

       DBSC_TEXT,         222,  25,  'C', "Ceiling Texture:", 0, YELLOW,
       DBSC_SCROLLBOX,    219,  37,  'C', LT_STR, num_ftexture, utex1,
        0x04L, 11, 8, ftexture,
       DBSC_BITMAP,       319,  37, '\0', BMP_FLAT, &i, utex1,

       DBSC_TEXT,         124, 116,  'r', "Floor Height:", 7, YELLOW,
       DBSC_INPUTBOX,     124, 138,  'r', &floorh, 0x02L, -16384, 16383,

       DBSC_TEXT,         319, 116,  'e', "Ceiling Height:", 7, YELLOW,
       DBSC_INPUTBOX,     319, 138,  'e', &ceilh, 0x08L, -16384, 16383,

       DBSC_TEXT,          15, 167,  'S', "Special Effect:", 0, YELLOW,
       DBSC_SCROLLBOX,     12, 179,  'S', LT_S_EFFECTS, 17, &type, 0x10L,
        6, 46,   0, 9, 7, 5, 16, 4, 11, 2, 3, 1, 17, 8, 13, 12, 6, 10, 14);

      AppendDbscList(db_main, &changes, 8,
       DBSC_TEXT,          36, 252,  'I', "Integer Effect Value:", 0, YELLOW,
       DBSC_INPUTBOX,     212, 250,  'I', &type, 0x10L, 0, 32767,

       DBSC_TEXT,         108, 270,  'L', "Light level:", 0, YELLOW,
       DBSC_INPUTBOX,     212, 268,  'L', &light,   0x20L, 0, 0xFF,

       DBSC_TEXT,         108, 288,  'T', "Trigger Tag:", 0, YELLOW,
       DBSC_INPUTBOX,     212, 286,  'T', &tag,     0x40L, 0, 32767,

       DBSC_OK,     -0x0103, 314, 'O',
       DBSC_CANCEL, -0x0203, 314, 'a');

      if (ProcessDialogBox(db_main, &changes))
        {
          for (cur = list; cur; cur = cur->next)
            {
              if (changes & 0x01L)
                strncpy(level->sectors[cur->objnum].floort, ltex1, 8);
              if (changes & 0x02L)
                level->sectors[cur->objnum].floorh = floorh;
              if (changes & 0x04L)
                strncpy(level->sectors[cur->objnum].ceilt, utex1, 8);
              if (changes & 0x08L)
                level->sectors[cur->objnum].ceilh = ceilh;
              if (changes & 0x10L)
                level->sectors[cur->objnum].type = type;
              if (changes & 0x20L)
                level->sectors[cur->objnum].light = light;
              if (changes & 0x40L)
                level->sectors[cur->objnum].tag = tag;
            }
          level->made_changes = TRUE;
        }
      break;
    }
}


/*
   Callback function that inserts and deletes a SideDef.
*/

void InsDelSidedef(va_list *args, DBSC *btn, Bool status)
{
  char     *tex1, *tex2, *tex3, *tex4, *tex5, *tex6;
  Int16    *sidedef, *osidedef, *xoff, *yoff, *flags;
  UInt32    chbit, chtex1, chtex2;
  LevelPtr  level;

  sidedef = (Int16 *)btn->i.button.var;
  level = va_arg(*args, LevelPtr);
  osidedef = va_arg(*args, Int16 *);
  tex1 = va_arg(*args, char *);
  tex2 = va_arg(*args, char *);
  tex3 = va_arg(*args, char *);
  tex4 = va_arg(*args, char *);
  tex5 = va_arg(*args, char *);
  tex6 = va_arg(*args, char *);
  xoff = va_arg(*args, Int16 *);
  yoff = va_arg(*args, Int16 *);
  flags = va_arg(*args, Int16 *);
  chbit = va_arg(*args, UInt32);
  chtex1 = va_arg(*args, UInt32);
  chtex2 = va_arg(*args, UInt32);

  if (status == INIT || status == UNDO)
    return;

  if (*sidedef == -1)
    { /* Do Insert */
      *xoff = 0;
      *yoff = 0;

      strcpy(tex1, "-");
      strcpy(tex3, "-");
      if (*osidedef != -1)
        {
          strcpy(tex2, "-");
          strcpy(tex4, "-");
          strcpy(tex5, "-");
          strcpy(tex6, "-");
          *flags |=  0x4;
          *flags &= ~0x1;
          *changes |= 0x1;
          *changes |= chtex1 | chtex2;
        }
      else
        {
          strcpy(tex2, Config.wallTexture);
          *changes |= chtex1;
        }

      *sidedef = level->num_sidedefs;

      strncpy(btn->i.button.name, "Delete", 6);
      btn->i.button.color = RED;
    }
  else
    { /* Do Delete */
      *changes |= 0x1;
      *flags |=  0x1;
      *flags &= ~0x4;

      *sidedef = -1;

      strncpy(btn->i.button.name, "Insert", 6);
      btn->i.button.color = GREEN;
    }
  *changes |= chbit;
}


/*
   Callback function to update the sidedef display in the linedef editing card.
*/

void DbUpdateSidedef(va_list *args, DBSC *btn, Bool status)
{
  Bool   match;
  Int16 *sidedef;
  DBSC  *ptr;

  sidedef = (Int16 *)btn->i.button.var; /* Sidedef Number */

  if (status == INIT || status == UNDO)
    return;

  for (ptr = dbcur->start; ptr; ptr = ptr->next)
    {
      match = FALSE;

      if (*sidedef != -1)
        {
          if (ptr->type == DBSC_BUTTON
              && ptr->i.button.type == BUTTON_FUNCTION
/*! The following line generates a warning: nonportable pointer comparison */
              && ptr->i.button.hookfunc == (void *) InsDelSidedef
              && sidedef == ptr->i.button.var)
            {
              strncpy(ptr->i.button.name, "Delete", 6);
              ptr->i.button.color = RED;
              match = TRUE;
            }
        }
      else
        {
          if (ptr->type == DBSC_BUTTON
              && ptr->i.button.type == BUTTON_FUNCTION
/*! The following line generates a warning: nonportable pointer comparison */
              && ptr->i.button.hookfunc == (void *) InsDelSidedef
              && sidedef == ptr->i.button.var)
            {
              strncpy(ptr->i.button.name, "Insert", 6);
              ptr->i.button.color = GREEN;
              match = TRUE;
            }
        }

      if (match == FALSE && GetVar(ptr) == sidedef && ptr->type == DBSC_BUTTON)
        ptr->active = (*sidedef != -1);
    }
}


/* end of file */
