home *** CD-ROM | disk | FTP | other *** search
/ MegaDoom Adventures / PMWMEGADOOM.iso / doom / creators / deu52gcc / src / editobj.c < prev    next >
C/C++ Source or Header  |  1994-05-21  |  82KB  |  2,674 lines

  1. /*
  2.    Doom Editor Utility, by Brendon Wyber and Raphaël Quinet.
  3.  
  4.    You are allowed to use any parts of this code in another program, as
  5.    long as you give credits to the authors in the documentation and in
  6.    the program itself.  Read the file README.1ST for more information.
  7.  
  8.    This program comes with absolutely no warranty.
  9.  
  10.    EDITOBJ.C - object editing routines.
  11. */
  12.  
  13. /* the includes */
  14. #include "deu.h"
  15. #include "levels.h"
  16.  
  17. /*
  18.    display the information about one object
  19. */
  20.  
  21. void DisplayObjectInfo( BCINT objtype, BCINT objnum) /* SWAP! */
  22. {
  23.    char texname[ 9];
  24.    BCINT  tag, n;
  25.    BCINT  sd1, sd2, s1, s2;
  26.    BCINT  x0, y0;
  27.  
  28.    ObjectsNeeded( objtype, 0);
  29.    switch (objtype)
  30.    {
  31.    case OBJ_THINGS:
  32.       x0 = 0;
  33.       y0 = ScrMaxY - 60;
  34.       if (InfoShown)
  35.      y0 -= 13;
  36.       DrawScreenBox3D( x0, y0, x0 + 260, y0 + 60);
  37.       if (objnum < 0)
  38.       {
  39.      DrawScreenText( x0 + 60, y0 + 20, "Use the cursor to");
  40.      DrawScreenText( x0 + 72, y0 + 30, "select a Thing  ");
  41.      break;
  42.       }
  43.       SetColor( YELLOW);
  44.       DrawScreenText( x0 + 5, y0 + 5, "Selected Thing (#%d)", objnum);
  45.       SetColor( BLACK);
  46.       DrawScreenText( -1, y0 + 20, "Coordinates:  (%d, %d)", Things[ objnum].xpos, Things[ objnum].ypos);
  47.       DrawScreenText( -1, -1, "Type:         %s", GetThingName( Things[ objnum].type));
  48.       DrawScreenText( -1, -1, "Angle:        %s", GetAngleName( Things[ objnum].angle));
  49.       DrawScreenText( -1, -1, "Appears when: %s", GetWhenName( Things[ objnum].when));
  50.       break;
  51.    case OBJ_LINEDEFS:
  52.       x0 = 0;
  53.       y0 = ScrMaxY - 80;
  54.       if (InfoShown)
  55.      y0 -= 13;
  56.       DrawScreenBox3D(   x0, y0, x0 + 218, y0 + 80);
  57.       if (objnum >= 0)
  58.       {
  59.      SetColor( YELLOW);
  60.      DrawScreenText( x0 + 5, y0 + 5, "Selected LineDef (#%d)", objnum);
  61.      SetColor( BLACK);
  62.       DrawScreenText( -1, y0 + 20, "Flags:%3d    %s", LineDefs[ objnum].flags, GetLineDefFlagsName( LineDefs[ objnum].flags));
  63.      DrawScreenText( -1, -1, "Type: %3d %s", LineDefs[ objnum].type, GetLineDefTypeName( LineDefs[ objnum].type));
  64.      sd1 = LineDefs[ objnum].sidedef1;
  65.      sd2 = LineDefs[ objnum].sidedef2;
  66.      tag = LineDefs[ objnum].tag;
  67.      ObjectsNeeded( OBJ_SIDEDEFS, OBJ_SECTORS, 0);
  68.       s1 = LineDefs[ objnum].start;
  69.       s2 = LineDefs[ objnum].end;
  70.         ObjectsNeeded( OBJ_VERTEXES, 0);
  71.       n = ComputeDist( Vertexes[ s2].x - Vertexes[ s1].x, Vertexes[ s2].y - Vertexes[ s1].y);
  72.       DrawScreenText( x0 + 160, y0 + 60, "Length:");
  73.       DrawScreenText( x0 + 170, y0 + 70, "%d", n);
  74.      if (tag > 0)
  75.      {
  76.         for (n = 0; n < NumSectors; n++)
  77.            if (Sectors[ n].tag == tag)
  78.           break;
  79.      }
  80.      else
  81.         n = NumSectors;
  82.      if (n < NumSectors)
  83.         DrawScreenText( x0 + 5, y0 + 40, "Sector tag:  %d (#%d)", tag, n);
  84.      else
  85.         DrawScreenText( x0 + 5, y0 + 40, "Sector tag:  %d (none)", tag);
  86.       DrawScreenText( -1, -1, "Vertexes:    (#%d, #%d)", s1, s2);
  87.      DrawScreenText( -1, -1, "1st SideDef: #%d", sd1);
  88.      DrawScreenText( -1, -1, "2nd SideDef: #%d", sd2);
  89.      if (sd1 >= 0)
  90.         s1 = SideDefs[ sd1].sector;
  91.      else
  92.         s1 = -1;
  93.      if (sd2 >= 0)
  94.         s2 = SideDefs[ sd2].sector;
  95.      else
  96.         s2 = -1;
  97.       }
  98.       else
  99.       {
  100.     SetColor( DARKGRAY);
  101.     DrawScreenText( x0 + 25, y0 + 35, "(No LineDef selected)");
  102.       }
  103.       x0 = 220;
  104.       y0 = ScrMaxY - 80;
  105.       if (InfoShown)
  106.      y0 -= 13;
  107.       DrawScreenBox3D( x0, y0, x0 + 218, y0 + 80);
  108.       if (objnum >= 0 && sd1 >= 0)
  109.       {
  110.      SetColor( YELLOW);
  111.      DrawScreenText( x0 + 5, y0 + 5, "First SideDef (#%d)", sd1);
  112.      SetColor( BLACK);
  113.      texname[ 8] = '\0';
  114.      strncpy( texname, SideDefs[ sd1].tex3, 8);
  115.      DrawScreenText( -1, y0 + 20, "Normal texture: %s", texname);
  116.      strncpy( texname, SideDefs[ sd1].tex1, 8);
  117.      if (s1 >= 0 && s2 >= 0 && Sectors[ s1].ceilh > Sectors[ s2].ceilh)
  118.      {
  119.         if (texname[ 0] == '-' && texname[ 1] == '\0')
  120.            SetColor( RED);
  121.      }
  122.      else
  123.         SetColor( DARKGRAY);
  124.      DrawScreenText( -1, -1, "Upper texture:  %s", texname);
  125.      SetColor( BLACK);
  126.      strncpy( texname, SideDefs[ sd1].tex2, 8);
  127.      if (s1 >= 0 && s2 >= 0 && Sectors[ s1].floorh < Sectors[ s2].floorh)
  128.      {
  129.         if (texname[ 0] == '-' && texname[ 1] == '\0')
  130.            SetColor( RED);
  131.      }
  132.      else
  133.         SetColor( DARKGRAY);
  134.      DrawScreenText( -1, -1, "Lower texture:  %s", texname);
  135.      SetColor( BLACK);
  136.      DrawScreenText( -1, -1, "Tex. X offset:  %d", SideDefs[ sd1].xoff);
  137.      DrawScreenText( -1, -1, "Tex. Y offset:  %d", SideDefs[ sd1].yoff);
  138.      DrawScreenText( -1, -1, "Sector:         #%d", s1);
  139.       }
  140.       else
  141.       {
  142.     SetColor( DARKGRAY);
  143.     DrawScreenText( x0 + 25, y0 + 35, "(No first SideDef)");
  144.       }
  145.       x0 = 440;
  146.       y0 = ScrMaxY - 80;
  147.       if (InfoShown)
  148.      y0 -= 13;
  149.       DrawScreenBox3D( x0, y0, x0 + 200, y0 + 80);
  150.       if (objnum >= 0 && sd2 >= 0)
  151.       {
  152.      SetColor( YELLOW);
  153.      DrawScreenText( x0 + 5, y0 + 5, "Second SideDef (#%d)", sd2);
  154.      SetColor( BLACK);
  155.      texname[ 8] = '\0';
  156.      strncpy( texname, SideDefs[ sd2].tex3, 8);
  157.      DrawScreenText( -1, y0 + 20, "Normal texture: %s", texname);
  158.      strncpy( texname, SideDefs[ sd2].tex1, 8);
  159.      if (s1 >= 0 && s2 >= 0 && Sectors[ s2].ceilh > Sectors[ s1].ceilh)
  160.      {
  161.         if (texname[ 0] == '-' && texname[ 1] == '\0')
  162.            SetColor( RED);
  163.      }
  164.      else
  165.         SetColor( DARKGRAY);
  166.      DrawScreenText( -1, -1, "Upper texture:  %s", texname);
  167.      SetColor( BLACK);
  168.      strncpy( texname, SideDefs[ sd2].tex2, 8);
  169.      if (s1 >= 0 && s2 >= 0 && Sectors[ s2].floorh < Sectors[ s1].floorh)
  170.      {
  171.         if (texname[ 0] == '-' && texname[ 1] == '\0')
  172.            SetColor( RED);
  173.      }
  174.      else
  175.         SetColor( DARKGRAY);
  176.      DrawScreenText( -1, -1, "Lower texture:  %s", texname);
  177.      SetColor( BLACK);
  178.      DrawScreenText( -1, -1, "Tex. X offset:  %d", SideDefs[ sd2].xoff);
  179.      DrawScreenText( -1, -1, "Tex. Y offset:  %d", SideDefs[ sd2].yoff);
  180.      DrawScreenText( -1, -1, "Sector:         #%d", s2);
  181.       }
  182.       else
  183.       {
  184.     SetColor( DARKGRAY);
  185.     DrawScreenText( x0 + 25, y0 + 35, "(No second SideDef)");
  186.       }
  187.       break;
  188.    case OBJ_VERTEXES:
  189.       x0 = 0;
  190.       y0 = ScrMaxY - 30;
  191.       if (InfoShown)
  192.      y0 -= 13;
  193.       DrawScreenBox3D( x0, y0, x0 + 220, y0 + 30);
  194.       if (objnum < 0)
  195.       {
  196.      SetColor( DARKGRAY);
  197.      DrawScreenText( x0 + 30, y0 + 12, "(No Vertex selected)");
  198.      break;
  199.       }
  200.       SetColor( YELLOW);
  201.       DrawScreenText( x0 + 5, y0 + 5, "Selected Vertex (#%d)", objnum);
  202.       SetColor( BLACK);
  203.       DrawScreenText( -1, y0 + 20, "Coordinates: (%d, %d)", Vertexes[ objnum].x, Vertexes[ objnum].y);
  204.       break;
  205.    case OBJ_SECTORS:
  206.       x0 = 0;
  207.       y0 = ScrMaxY - 90;
  208.       if (InfoShown)
  209.      y0 -= 13;
  210.       DrawScreenBox3D( x0, y0, x0 + 255, y0 + 90);
  211.       if (objnum < 0)
  212.       {
  213.     SetColor( DARKGRAY);
  214.     DrawScreenText( x0 + 48, y0 + 35, "(No Sector selected)");
  215.     break;
  216.       }
  217.       SetColor( YELLOW);
  218.       DrawScreenText( x0 + 5, y0 + 5, "Selected Sector (#%d)", objnum);
  219.       SetColor( BLACK);
  220.       DrawScreenText( -1, y0 + 20, "Floor height:    %d", Sectors[ objnum].floorh);
  221.       DrawScreenText( -1, -1, "Ceiling height:  %d", Sectors[ objnum].ceilh);
  222.       texname[ 8] = '\0';
  223.       strncpy( texname, Sectors[ objnum].floort, 8);
  224.       DrawScreenText( -1, -1, "Floor texture:   %s", texname);
  225.       strncpy( texname, Sectors[ objnum].ceilt, 8);
  226.       DrawScreenText( -1, -1, "Ceiling texture: %s", texname);
  227.       DrawScreenText( -1, -1, "Light level:     %d", Sectors[ objnum].light);
  228.       DrawScreenText( -1, -1, "Type: %3d        %s", Sectors[ objnum].special, GetSectorTypeName( Sectors[ objnum].special));
  229.       tag = Sectors[ objnum].tag;
  230.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  231.       if (tag == 0)
  232.      n = NumLineDefs;
  233.       else
  234.      for (n = 0; n < NumLineDefs; n++)
  235.         if (LineDefs[ n].tag == tag)
  236.            break;
  237.       if (n < NumLineDefs)
  238.      DrawScreenText( -1, -1, "LineDef tag:     %d (#%d)", tag, n);
  239.       else if (tag == 99 || tag == 999)
  240.      DrawScreenText( -1, -1, "LineDef tag:     %d (stairs?)", tag);
  241.       else if (tag == 666)
  242.      DrawScreenText( -1, -1, "LineDef tag:     %d (lower@end)", tag);
  243.       else
  244.      DrawScreenText( -1, -1, "LineDef tag:     %d (none)", tag);
  245.       break;
  246.    }
  247. }
  248.  
  249.  
  250.  
  251. /*
  252.    display and execute a "things" menu
  253. */
  254.  
  255. BCINT DisplayThingsMenu( BCINT x0, BCINT y0, char *menutitle, ...)
  256. {
  257.    va_list args;
  258.    BCINT     val, num;
  259.    BCINT     thingid[ 30];
  260.    char   *menustr[ 30];
  261.    BCINT     dummy[ 30];
  262.  
  263.    /* put the va_args in the menustr table */
  264.    num = 0;
  265.    va_start( args, menutitle);
  266.    while ((num < 30) && ((thingid[ num] = va_arg( args, BCINT)) >= 0))
  267.    {
  268.       menustr[ num] = GetThingName( thingid[ num]);
  269.       num++;
  270.    }
  271.    va_end( args);
  272.  
  273.    /* display the menu */
  274.    val = DisplayMenuArray( x0, y0, menutitle, num, NULL, menustr, dummy) - 1;
  275.  
  276.    /* return the thing id, if valid */
  277.    if (val < 0 || val >= num)
  278.      return -1;
  279.    return thingid[ val];
  280. }
  281.  
  282.  
  283.  
  284. /*
  285.    display and execute a "linedef type" menu
  286. */
  287.  
  288. BCINT DisplayLineDefTypeMenu( BCINT x0, BCINT y0, char *menutitle, ...)
  289. {
  290.    va_list args;
  291.    BCINT   val, num, n;
  292.    BCINT   typid[30];
  293.    char    *menustr[30];
  294.    BCINT   dummy[30];
  295.  
  296.    /* put the va_args in the menustr table */
  297.    val = num = 0;
  298.    va_start( args, menutitle);
  299.    while ((num < 30) && ((typid[ num] = va_arg( args, BCINT)) >= 0))
  300.    {
  301.       menustr[ num] = GetMemory( 80 * sizeof( char));
  302.       sprintf( menustr[ num], "%-79s", GetLineDefTypeLongName( typid[ num]));
  303.       if (strlen( GetLineDefTypeLongName( typid[ num])) > val)
  304.          val = strlen( GetLineDefTypeLongName( typid[ num]));
  305.       num++;
  306.    }
  307.    va_end( args);
  308.  
  309.    /* put the type numbers at the end of the lines */
  310.    for (n = 0; n < num; n++)
  311.       sprintf( menustr[ n] + val + 1, "[%3d]", typid[ n]);
  312.  
  313.    /* display the menu */
  314.    val = DisplayMenuArray( x0, y0, menutitle, num, NULL, menustr, dummy) - 1;
  315.    for(n = 0; n < num; n++)
  316.       FreeMemory( menustr[ n]);
  317.  
  318.    /* return the thing id, if valid */
  319.    if (val < 0 || val >= num)
  320.      return -1;
  321.    return typid[ val];
  322. }
  323.  
  324.  
  325.  
  326. /*
  327.    ask for an object number and check for maximum valid number
  328.    (this is just like InputIntegerValue, but with a different prompt)
  329. */
  330.  
  331. BCINT InputObjectNumber( BCINT x0, BCINT y0, BCINT objtype, BCINT curobj)
  332. {
  333.    BCINT val, key;
  334.    char prompt[ 80];
  335.  
  336.    if (UseMouse)
  337.       HideMousePointer();
  338.    sprintf( prompt, "Enter a %s number between 0 and %d:", GetObjectTypeName( objtype), GetMaxObjectNum( objtype));
  339.    if (x0 < 0)
  340.       x0 = (ScrMaxX - 25 - 8 * strlen( prompt)) / 2;
  341.    if (y0 < 0)
  342.       y0 = (ScrMaxY - 55) / 2;
  343.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * strlen( prompt), y0 + 55);
  344.    SetColor( WHITE);
  345.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  346.    val = curobj;
  347.    while (((key = InputInteger( x0 + 10, y0 + 28, &val, 0, GetMaxObjectNum( objtype))) & 0x00FF) != 0x000D && (key & 0x00FF) != 0x001B)
  348.       Beep();
  349.    if (UseMouse)
  350.       ShowMousePointer();
  351.    return val;
  352. }
  353.  
  354.  
  355.  
  356. /*
  357.    ask for an object number and display a warning message
  358. */
  359.  
  360. BCINT InputObjectXRef( BCINT x0, BCINT y0, BCINT objtype, Bool allownone, BCINT curobj)
  361. {
  362.    BCINT val, key;
  363.    char prompt[ 80];
  364.  
  365.    if (UseMouse)
  366.       HideMousePointer();
  367.    sprintf( prompt, "Enter a %s number between 0 and %d%c", GetObjectTypeName( objtype), GetMaxObjectNum( objtype), allownone ? ',' : ':');
  368.    val = strlen( prompt);
  369.    if (val < 40)
  370.       val = 40;
  371.    if (x0 < 0)
  372.       x0 = (ScrMaxX - 25 - 8 * val) / 2;
  373.    if (y0 < 0)
  374.       y0 = (ScrMaxY - (allownone ? 85 : 75)) / 2;
  375.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * val, y0 + (allownone ? 85 : 75));
  376.    SetColor( WHITE);
  377.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  378.    if (allownone)
  379.       DrawScreenText( x0 + 10, y0 + 18, "or -1 for none:");
  380.    SetColor( RED);
  381.    DrawScreenText( x0 + 10, y0 + (allownone ? 60 : 50), "Warning: modifying the cross-references");
  382.    DrawScreenText( x0 + 10, y0 + (allownone ? 70 : 60), "between some objects may crash the game.");
  383.    val = curobj;
  384.    while (((key = InputInteger( x0 + 10, y0 + (allownone ? 38 : 28), &val, allownone ? -1 : 0, GetMaxObjectNum( objtype))) & 0x00FF) != 0x000D && (key & 0x00FF) != 0x001B)
  385.       Beep();
  386.    if (UseMouse)
  387.       ShowMousePointer();
  388.    return val;
  389. }
  390.  
  391.  
  392.  
  393. /*
  394.    ask for two vertex numbers and check for maximum valid number
  395. */
  396.  
  397. Bool Input2VertexNumbers( BCINT x0, BCINT y0, char *prompt1, BCINT *v1, BCINT *v2)
  398. {
  399.    BCINT  key;
  400.    BCINT  maxlen, first;
  401.    Bool ok;
  402.    char prompt2[ 80];
  403.  
  404.    if (UseMouse)
  405.       HideMousePointer();
  406.    sprintf( prompt2, "Enter two numbers between 0 and %d:", NumVertexes - 1);
  407.    if (strlen( prompt1) > strlen( prompt2))
  408.       maxlen = strlen( prompt1);
  409.    else
  410.       maxlen = strlen( prompt2);
  411.    if (x0 < 0)
  412.       x0 = (ScrMaxX - 25 - 8 * maxlen) / 2;
  413.    if (y0 < 0)
  414.       y0 = (ScrMaxY - 75) / 2;
  415.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * maxlen, y0 + 75);
  416.    DrawScreenText( x0 + 10, y0 + 36, "From this Vertex");
  417.    DrawScreenText( x0 + 180, y0 + 36, "To this Vertex");
  418.    SetColor( WHITE);
  419.    DrawScreenText( x0 + 10, y0 + 8, prompt1);
  420.    DrawScreenText( x0 + 10, y0 + 18, prompt2);
  421.    first = TRUE;
  422.    key = 0;
  423.    for (;;)
  424.    {
  425.       ok = TRUE;
  426.       DrawScreenBox3D( x0 + 10, y0 + 48, x0 + 71, y0 + 61);
  427.       if (*v1 < 0 || *v1 >= NumVertexes)
  428.       {
  429.      SetColor( DARKGRAY);
  430.      ok = FALSE;
  431.       }
  432.       DrawScreenText( x0 + 14, y0 + 51, "%d", *v1);
  433.       DrawScreenBox3D( x0 + 180, y0 + 48, x0 + 241, y0 + 61);
  434.       if (*v2 < 0 || *v2 >= NumVertexes)
  435.       {
  436.      SetColor( DARKGRAY);
  437.      ok = FALSE;
  438.       }
  439.       DrawScreenText( x0 + 184, y0 + 51, "%d", *v2);
  440.       if (first)
  441.      key = InputInteger( x0 + 10, y0 + 48, v1, 0, NumVertexes - 1);
  442.       else
  443.      key = InputInteger( x0 + 180, y0 + 48, v2, 0, NumVertexes - 1);
  444.       if ((key & 0xFF00) == 0x4B00 || (key & 0xFF00) == 0x4D00 || (key & 0x00FF) == 0x0009 || (key & 0xFF00) == 0x0F00)
  445.      first = !first;
  446.       else if ((key & 0x00FF) == 0x001B)
  447.      break;
  448.       else if ((key & 0x00FF) == 0x000D)
  449.       {
  450.      if (first)
  451.         first = FALSE;
  452.      else if (ok)
  453.         break;
  454.      else
  455.         Beep();
  456.       }
  457.       else
  458.      Beep();
  459.    }
  460.    if (UseMouse)
  461.       ShowMousePointer();
  462.    return ((key & 0x00FF) == 0x000D);
  463. }
  464.  
  465.  
  466.  
  467. /*
  468. */
  469.  
  470. char *GetTaggedLineDefFlag( BCINT linedefnum, BCINT flagndx)
  471. {
  472.    static char ldstr[ 9][ 50];
  473.  
  474.    if ((LineDefs[ linedefnum].flags & (0x01 << (flagndx - 1))) != 0)
  475.       strcpy( ldstr[ flagndx - 1], "\04 ");
  476.    else
  477.       strcpy( ldstr[ flagndx - 1], "  ");
  478.    strcat( ldstr[ flagndx - 1], GetLineDefFlagsLongName( 0x01 << (flagndx - 1)));
  479.    return ldstr[ flagndx - 1];
  480. }
  481.  
  482.  
  483.  
  484. /*
  485.    edit an object or a group of objects
  486. */
  487.  
  488. void EditObjectsInfo( BCINT x0, BCINT y0, BCINT objtype, SelPtr obj) /* SWAP! */
  489. {
  490.    char  *menustr[ 30];
  491.    BCINT    dummy[ 30];
  492.    char   texname[ 9];
  493.    BCINT    n, val;
  494.    SelPtr cur, sdlist;
  495.  
  496.    ObjectsNeeded( objtype, 0);
  497.    if (obj == NULL)
  498.       return;
  499.    switch (objtype)
  500.    {
  501.    case OBJ_THINGS:
  502.       for (n = 0; n < 6; n++)
  503.      menustr[ n] = (char*)GetMemory( 60);
  504.       sprintf( menustr[ 5], "Edit Thing #%d", obj->objnum);
  505.       sprintf( menustr[ 0], "Change Type          (Current: %s)", GetThingName( Things[ obj->objnum].type));
  506.       sprintf( menustr[ 1], "Change Angle         (Current: %s)", GetAngleName( Things[ obj->objnum].angle));
  507.       sprintf( menustr[ 2], "Change When Appears  (Current: %s)", GetWhenName( Things[ obj->objnum].when));
  508.       sprintf( menustr[ 3], "Change X position    (Current: %d)", Things[ obj->objnum].xpos);
  509.       sprintf( menustr[ 4], "Change Y position    (Current: %d)", Things[ obj->objnum].ypos);
  510.       val = DisplayMenuArray( x0, y0, menustr[ 5], 5, NULL, menustr, dummy);
  511.       for (n = 0; n < 6; n++)
  512.      FreeMemory( menustr[ n]);
  513.       switch (val)
  514.       {
  515.       case 1:
  516.      switch (DisplayMenu( x0 + 42, y0 + 34, "Select Class",
  517.                   "Player",
  518.                   "Enemy",
  519.                   "Weapon",
  520.                   "Bonus",
  521.                   "Decoration",
  522.                   "Decoration (light sources)",
  523.                   "Decoration (dead bodies)",
  524.                   "Decoration (hanging bodies)",
  525.                   "Teleport landing",
  526.                   "(Enter a decimal value)",
  527.                      NULL))
  528.      {
  529.      case 1:
  530.         val = DisplayThingsMenu( x0 + 84, y0 + 68, "Select Start Position Type",
  531.                      THING_PLAYER1,
  532.                      THING_PLAYER2,
  533.                      THING_PLAYER3,
  534.                      THING_PLAYER4,
  535.                      THING_DEATHMATCH,
  536.                      -1);
  537.         break;
  538.  
  539.      case 2:
  540.         val = DisplayThingsMenu( x0 + 84, y0 + 78, "Select Enemy",
  541.                      THING_TROOPER,
  542.                      THING_SARGEANT,
  543.                      THING_IMP,
  544.                      THING_DEMON,
  545.                      THING_SPECTOR,
  546.                      THING_BARON,
  547.                      THING_LOSTSOUL,
  548.                      THING_CACODEMON,
  549.                      THING_CYBERDEMON,
  550.                      THING_SPIDERBOSS,
  551.                      -1);
  552.         break;
  553.  
  554.      case 3:
  555.         val = DisplayThingsMenu( x0 + 84, y0 + 88, "Select Weapon",
  556.                      THING_SHOTGUN,
  557.                      THING_CHAINGUN,
  558.                      THING_LAUNCHER,
  559.                      THING_PLASMAGUN,
  560.                      THING_CHAINSAW,
  561.                      THING_SHELLS,
  562.                      THING_AMMOCLIP,
  563.                      THING_ROCKET,
  564.                      THING_ENERGYCELL,
  565.                      THING_BFG9000,
  566.                      THING_SHELLBOX,
  567.                      THING_AMMOBOX,
  568.                      THING_ROCKETBOX,
  569.                      THING_ENERGYPACK,
  570.                      THING_BACKPACK,
  571.                      -1);
  572.            break;
  573.  
  574.      case 4:
  575.         val = DisplayThingsMenu( x0 + 84, y0 + 98, "Select Bonus",
  576.                      THING_REDCARD,
  577.                      THING_YELLOWCARD,
  578.                      THING_BLUECARD,
  579.                      THING_REDSKULLKEY,
  580.                      THING_YELLOWSKULLKEY,
  581.                      THING_BLUESKULLKEY,
  582.                      THING_ARMBONUS1,
  583.                      THING_GREENARMOR,
  584.                      THING_BLUEARMOR,
  585.                      THING_HLTBONUS1,
  586.                      THING_STIMPACK,
  587.                      THING_MEDKIT,
  588.                      THING_SOULSPHERE,
  589.                      THING_BLURSPHERE,
  590.                      THING_MAP,
  591.                      THING_RADSUIT,
  592.                      THING_LITEAMP,
  593.                      THING_BESERK,
  594.                      THING_INVULN,
  595.                      -1);
  596.         break;
  597.  
  598.      case 5:
  599.         val = DisplayThingsMenu( x0 + 84, y0 + 108, "Select Decoration",
  600.                      THING_BARREL,
  601.                      THING_TECHCOLUMN,
  602.                      THING_TGREENPILLAR,
  603.                      THING_TREDPILLAR,
  604.                      THING_SGREENPILLAR,
  605.                      THING_SREDPILLAR,
  606.                      THING_PILLARHEART,
  607.                      THING_PILLARSKULL,
  608.                      THING_EYEINSYMBOL,
  609.                      THING_BROWNSTUB,
  610.                      THING_GREYTREE,
  611.                      THING_BROWNTREE,
  612.                      -1);
  613.         break;
  614.  
  615.      case 6:
  616.         val = DisplayThingsMenu( x0 + 84, y0 + 118, "Select Decoration",
  617.                         THING_CANDLE,
  618.                      THING_LAMP,
  619.                      THING_CANDELABRA,
  620.                      THING_TBLUETORCH,
  621.                      THING_TGREENTORCH,
  622.                      THING_TREDTORCH,
  623.                      THING_SBLUETORCH,
  624.                      THING_SGREENTORCH,
  625.                      THING_SREDTORCH,
  626.                      -1);
  627.         break;
  628.  
  629.      case 7:
  630.         val = DisplayThingsMenu( x0 + 84, y0 + 128, "Select Decoration",
  631.                      THING_DEADPLAYER,
  632.                      THING_DEADTROOPER,
  633.                      THING_DEADSARGEANT,
  634.                      THING_DEADIMP,
  635.                      THING_DEADDEMON,
  636.                      THING_DEADCACODEMON,
  637.                      THING_BONES,
  638.                      THING_BONES2,
  639.                      THING_POOLOFBLOOD,
  640.                      THING_SKULLTOPPOLE,
  641.                      THING_HEADSKEWER,
  642.                      THING_PILEOFSKULLS,
  643.                      THING_IMPALEDBODY,
  644.                      THING_IMPALEDBODY2,
  645.                      THING_SKULLSINFLAMES,
  646.                      -1);
  647.         break;
  648.  
  649.      case 8:
  650.         val = DisplayThingsMenu( x0 + 84, y0 + 138, "Select Decoration",
  651.                      THING_HANGINGSWAYING,
  652.                      THING_HANGINGARMSOUT,
  653.                      THING_HANGINGONELEG,
  654.                      THING_HANGINGTORSO,
  655.                      THING_HANGINGLEG,
  656.                      THING_HANGINGSWAYING2,
  657.                      THING_HANGINGARMSOUT2,
  658.                      THING_HANGINGONELEG2,
  659.                      THING_HANGINGTORSO2,
  660.                      THING_HANGINGLEG2,
  661.                      -1);
  662.            break;
  663.  
  664.      case 9:
  665.         val = THING_TELEPORT;
  666.         break;
  667.  
  668.      case 10:
  669.         val = InputIntegerValue( x0 + 84, y0 + 158, 0, 9999, Things[ obj->objnum].type);
  670.         break;
  671.  
  672.      default:
  673.         Beep();
  674.         return;
  675.      }
  676.      if (val >= 0)
  677.      {
  678.         for (cur = obj; cur; cur = cur->next)
  679.            Things[ cur->objnum].type = val;
  680.         MadeChanges = TRUE;
  681.      }
  682.      break;
  683.  
  684.       case 2:
  685.      switch (DisplayMenu( x0 + 42, y0 + 44, "Select Angle",
  686.                   "North",
  687.                   "NorthEast",
  688.                   "East",
  689.                   "SouthEast",
  690.                   "South",
  691.                   "SouthWest",
  692.                   "West",
  693.                   "NorthWest",
  694.                   NULL))
  695.      {
  696.      case 1:
  697.         for (cur = obj; cur; cur = cur->next)
  698.            Things[ cur->objnum].angle = 90;
  699.         MadeChanges = TRUE;
  700.         break;
  701.      case 2:
  702.         for (cur = obj; cur; cur = cur->next)
  703.            Things[ cur->objnum].angle = 45;
  704.         MadeChanges = TRUE;
  705.         break;
  706.      case 3:
  707.            for (cur = obj; cur; cur = cur->next)
  708.            Things[ cur->objnum].angle = 0;
  709.         MadeChanges = TRUE;
  710.         break;
  711.      case 4:
  712.         for (cur = obj; cur; cur = cur->next)
  713.            Things[ cur->objnum].angle = 315;
  714.         MadeChanges = TRUE;
  715.         break;
  716.      case 5:
  717.         for (cur = obj; cur; cur = cur->next)
  718.            Things[ cur->objnum].angle = 270;
  719.         MadeChanges = TRUE;
  720.         break;
  721.      case 6:
  722.         for (cur = obj; cur; cur = cur->next)
  723.            Things[ cur->objnum].angle = 225;
  724.         MadeChanges = TRUE;
  725.         break;
  726.      case 7:
  727.         for (cur = obj; cur; cur = cur->next)
  728.            Things[ cur->objnum].angle = 180;
  729.         MadeChanges = TRUE;
  730.         break;
  731.      case 8:
  732.         for (cur = obj; cur; cur = cur->next)
  733.            Things[ cur->objnum].angle = 135;
  734.         MadeChanges = TRUE;
  735.         break;
  736.      }
  737.      break;
  738.  
  739.       case 3:
  740.      val = DisplayMenu( x0 + 42, y0 + 54, "Choose the difficulty level(s)",
  741.                 "D12          (Easy only)",
  742.                 "D3           (Medium only)",
  743.                 "D12, D3      (Easy and Medium)",
  744.                 "D45          (Hard only)",
  745.                 "D12, D45     (Easy and Hard)",
  746.                 "D3, D45      (Medium and Hard)",
  747.                 "D12, D3, D45 (Easy, Medium, Hard)",
  748.                 "Toggle \"Deaf/Ambush\" bit",
  749.                 "Toggle \"Multi-player only\" bit",
  750.                 "(Enter a decimal value)",
  751.                 NULL);
  752.         switch (val)
  753.      {
  754.      case 1:
  755.      case 2:
  756.      case 3:
  757.      case 4:
  758.      case 5:
  759.      case 6:
  760.      case 7:
  761.         for (cur = obj; cur; cur = cur->next)
  762.            Things[ cur->objnum].when = (Things[ cur->objnum].when & 0x18) | val;
  763.         MadeChanges = TRUE;
  764.         break;
  765.      case 8:
  766.         for (cur = obj; cur; cur = cur->next)
  767.            Things[ cur->objnum].when ^= 0x08;
  768.         MadeChanges = TRUE;
  769.         break;
  770.      case 9:
  771.         for (cur = obj; cur; cur = cur->next)
  772.            Things[ cur->objnum].when ^= 0x10;
  773.         MadeChanges = TRUE;
  774.         break;
  775.      case 10:
  776.         val = InputIntegerValue( x0 + 84, y0 + 158, 1, 31, Things[ obj->objnum].when);
  777.         if (val > 0)
  778.         {
  779.            for (cur = obj; cur; cur = cur->next)
  780.           Things[ cur->objnum].when = val;
  781.            MadeChanges = TRUE;
  782.         }
  783.         break;
  784.      }
  785.      break;
  786.  
  787.       case 4:
  788.      val = InputIntegerValue( x0 + 42, y0 + 64, MapMinX, MapMaxX, Things[ obj->objnum].xpos);
  789.      if (val >= MapMinX)
  790.      {
  791.         n = val - Things[ obj->objnum].xpos;
  792.         for (cur = obj; cur; cur = cur->next)
  793.            Things[ cur->objnum].xpos += n;
  794.         MadeChanges = TRUE;
  795.      }
  796.      break;
  797.  
  798.       case 5:
  799.      val = InputIntegerValue( x0 + 42, y0 + 74, MapMinY, MapMaxY, Things[ obj->objnum].ypos);
  800.      if (val >= MapMinY)
  801.      {
  802.         n = val - Things[ obj->objnum].ypos;
  803.         for (cur = obj; cur; cur = cur->next)
  804.            Things[ cur->objnum].ypos += n;
  805.         MadeChanges = TRUE;
  806.      }
  807.      break;
  808.       }
  809.       break;
  810.  
  811.    case OBJ_VERTEXES:
  812.       for (n = 0; n < 3; n++)
  813.      menustr[ n] = (char*)GetMemory( 60);
  814.       sprintf( menustr[ 2], "Edit Vertex #%d", obj->objnum);
  815.       sprintf( menustr[ 0], "Change X position (Current: %d)", Vertexes[ obj->objnum].x);
  816.       sprintf( menustr[ 1], "Change Y position (Current: %d)", Vertexes[ obj->objnum].y);
  817.       val = DisplayMenuArray( 0, 30, menustr[ 2], 2, NULL, menustr, dummy);
  818.       for (n = 0; n < 3; n++)
  819.      FreeMemory( menustr[ n]);
  820.       switch (val)
  821.       {
  822.       case 1:
  823.      val = InputIntegerValue( x0 + 42, y0 + 34, min( MapMinX, -10000), max( MapMaxX, 10000), Vertexes[ obj->objnum].x);
  824.      if (val >= min( MapMinX, -10000))
  825.      {
  826.         n = val - Vertexes[ obj->objnum].x;
  827.         for (cur = obj; cur; cur = cur->next)
  828.            Vertexes[ cur->objnum].x += n;
  829.         MadeChanges = TRUE;
  830.         MadeMapChanges = TRUE;
  831.      }
  832.      break;
  833.  
  834.       case 2:
  835.      val = InputIntegerValue( x0 + 42, y0 + 44, min( MapMinY, -10000), max( MapMaxY, 10000), Vertexes[ obj->objnum].y);
  836.      if (val >= min( MapMinY, -10000))
  837.      {
  838.         n = val - Vertexes[ obj->objnum].y;
  839.         for (cur = obj; cur; cur = cur->next)
  840.            Vertexes[ cur->objnum].y += n;
  841.         MadeChanges = TRUE;
  842.         MadeMapChanges = TRUE;
  843.      }
  844.      break;
  845.       }         
  846.       break;
  847.  
  848.    case OBJ_LINEDEFS:
  849.       switch (DisplayMenu( x0, y0, "Choose the object to edit:",
  850.                "Edit the LineDef",
  851.                (LineDefs[ obj->objnum].sidedef1 >= 0) ? "Edit the 1st SideDef" : "Add a 1st SideDef",
  852.                (LineDefs[ obj->objnum].sidedef2 >= 0) ? "Edit the 2nd SideDef" : "Add a 2nd SideDef",
  853.                NULL))
  854.       {
  855.       case 1:
  856.      for (n = 0; n < 8; n++)
  857.         menustr[ n] = (char*)GetMemory( 60);
  858.      sprintf( menustr[ 7], "Edit LineDef #%d", obj->objnum);
  859.      sprintf( menustr[ 0], "Change Flags            (Current: %d)", LineDefs[ obj->objnum].flags);
  860.      sprintf( menustr[ 1], "Change Type             (Current: %d)", LineDefs[ obj->objnum].type);
  861.      sprintf( menustr[ 2], "Change Sector tag       (Current: %d)", LineDefs[ obj->objnum].tag);
  862.      sprintf( menustr[ 3], "Change Starting Vertex  (Current: #%d)", LineDefs[ obj->objnum].start);
  863.      sprintf( menustr[ 4], "Change Ending Vertex    (Current: #%d)", LineDefs[ obj->objnum].end);
  864.      sprintf( menustr[ 5], "Change 1st SideDef ref. (Current: #%d)", LineDefs[ obj->objnum].sidedef1);
  865.      sprintf( menustr[ 6], "Change 2nd SideDef ref. (Current: #%d)", LineDefs[ obj->objnum].sidedef2);
  866.      val = DisplayMenuArray( x0 + 42, y0 + 34, menustr[ 7], 7, NULL, menustr, dummy);
  867.      for (n = 0; n < 8; n++)
  868.         FreeMemory( menustr[ n]);
  869.      switch (val)
  870.      {
  871.      case 1:
  872.         val = DisplayMenu( x0 + 84, y0 + 68, "Toggle the flags:",
  873.                    GetTaggedLineDefFlag( obj->objnum, 1),
  874.                    GetTaggedLineDefFlag( obj->objnum, 2),
  875.                    GetTaggedLineDefFlag( obj->objnum, 3),
  876.                    GetTaggedLineDefFlag( obj->objnum, 4),
  877.                    GetTaggedLineDefFlag( obj->objnum, 5),
  878.                    GetTaggedLineDefFlag( obj->objnum, 6),
  879.                    GetTaggedLineDefFlag( obj->objnum, 7),
  880.                    GetTaggedLineDefFlag( obj->objnum, 8),
  881.                    GetTaggedLineDefFlag( obj->objnum, 9),
  882.                    "(Enter a decimal value)",
  883.                    NULL);
  884.         if (val >= 1 && val <= 9)
  885.         {
  886.            for (cur = obj; cur; cur = cur->next)
  887.           LineDefs[ cur->objnum].flags ^= 0x01 << (val - 1);
  888.            MadeChanges = TRUE;
  889.         }
  890.         else if (val == 10)
  891.         {                                           
  892.            val = InputIntegerValue( x0 + 126, y0 + 182, 0, 511, LineDefs[ obj->objnum].flags);
  893.            if (val >= 0)
  894.            {
  895.           for (cur = obj; cur; cur = cur->next)
  896.              LineDefs[ cur->objnum].flags = val;
  897.           MadeChanges = TRUE;
  898.            }
  899.         }
  900.         break;
  901.      case 2:
  902.         switch (DisplayMenu( x0 + 84, y0 + 78, "Choose a LineDef type:",
  903.                  "Normal",
  904.                  "Doors...",
  905.                  "Ceilings...",
  906.                  "Floors (raise)...",
  907.                                  "Floors (lower)...",
  908.                  "Lifts & Moving things...",
  909.                  "Special...",
  910.                  "(Enter a decimal value)",
  911.                  NULL))
  912.         {
  913.         case 1:
  914.            val = 0;
  915.            break;
  916.         case 2:
  917.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 122, NULL, /* Doors */
  918.                          1, 26, 27, 28, 63, 29, 90, 4, 31, 32, 34, 33, 61, 103, 50, 86, 2, 46, 42, 75, 3, 76, 16,
  919.                          -1);
  920.            break;
  921.         case 3:
  922.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 132, NULL, /* Ceilings */
  923.                          43, 41, 72, 44, 40,
  924.                          -1);
  925.            break;
  926.         case 4:
  927.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 142, NULL, /* Floors (raise) */
  928.                          69, 18, 20, 22, 95, 47, 5, 14, 30, 93, 59, 66, 67, 15, 92, 58, 96, 64, 101, 91, 24, 65, 94, 56,
  929.                          -1);
  930.            break;
  931.         case 5:
  932.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 142, NULL, /* Floors (lower) */
  933.                          45, 60, 102, 82, 83, 19, 38, 70, 71, 98, 36, 23, 84, 68, 37, 9, 21,
  934.                          -1);
  935.            break;
  936.         case 6:
  937.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 152, NULL, /* Lifts & Moving things */
  938.                          62, 88, 10, 77, 6, 73, 74, 57, 87, 53, 89, 54, 7, 8,
  939.                          -1);
  940.            break;
  941.         case 7:
  942.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 162, NULL, /* Special */
  943.                          48, 11, 52, 51, 97, 39, 81, 13, 79, 35, 80, 12, 104, 17,
  944.                          -1);
  945.            break;
  946.         case 8:
  947.            val = InputIntegerValue( x0 + 126, y0 + 172, 0, 255, LineDefs[ obj->objnum].type);
  948.            break;
  949.         default:
  950.            val = -1;
  951.         }
  952.         if (val >= 0)
  953.         {
  954.            for (cur = obj; cur; cur = cur->next)
  955.           LineDefs[ cur->objnum].type = val;
  956.            MadeChanges = TRUE;
  957.         }
  958.         break;
  959.      case 3:
  960.         val = InputIntegerValue( x0 + 84, y0 + 88, 0, 255, LineDefs[ obj->objnum].tag);
  961.         if (val >= 0)
  962.         {
  963.            for (cur = obj; cur; cur = cur->next)
  964.           LineDefs[ cur->objnum].tag = val;
  965.            MadeChanges = TRUE;
  966.         }
  967.         break;
  968.      case 4:
  969.         val = InputObjectXRef( x0 + 84, y0 + 98, OBJ_VERTEXES, FALSE, LineDefs[ obj->objnum].start);
  970.         if (val >= 0)
  971.         {
  972.            for (cur = obj; cur; cur = cur->next)
  973.           LineDefs[ cur->objnum].start = val;
  974.            MadeChanges = TRUE;
  975.            MadeMapChanges = TRUE;
  976.         }
  977.         break;
  978.      case 5:
  979.         val = InputObjectXRef( x0 + 84, y0 + 108, OBJ_VERTEXES, FALSE, LineDefs[ obj->objnum].end);
  980.         if (val >= 0)
  981.         {
  982.            for (cur = obj; cur; cur = cur->next)
  983.           LineDefs[ cur->objnum].end = val;
  984.            MadeChanges = TRUE;
  985.            MadeMapChanges = TRUE;
  986.         }
  987.         break;
  988.      case 6:
  989.         val = InputObjectXRef( x0 + 84, y0 + 118, OBJ_SIDEDEFS, TRUE, LineDefs[ obj->objnum].sidedef1);
  990.         if (val >= -1)
  991.         {
  992.            for (cur = obj; cur; cur = cur->next)
  993.           LineDefs[ cur->objnum].sidedef1 = val;
  994.            MadeChanges = TRUE;
  995.            MadeMapChanges = TRUE;
  996.         }
  997.         break;
  998.      case 7:
  999.         val = InputObjectXRef( x0 + 84, y0 + 128, OBJ_SIDEDEFS, TRUE, LineDefs[ obj->objnum].sidedef2);
  1000.         if (val >= -1)
  1001.         {
  1002.            for (cur = obj; cur; cur = cur->next)
  1003.           LineDefs[ cur->objnum].sidedef2 = val;
  1004.            MadeChanges = TRUE;
  1005.            MadeMapChanges = TRUE;
  1006.         }
  1007.         break;
  1008.      }
  1009.      break;
  1010.  
  1011.       /* edit or add the first SideDef */
  1012.       case 2:
  1013.      ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  1014.      if (LineDefs[ obj->objnum].sidedef1 >= 0)
  1015.      {
  1016.         /* build a new selection list with the first SideDefs */
  1017.         objtype = OBJ_SIDEDEFS;
  1018.         sdlist = NULL;
  1019.         for (cur = obj; cur; cur = cur->next)
  1020.            if (LineDefs[ cur->objnum].sidedef1 >= 0)
  1021.           SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  1022.      }
  1023.      else
  1024.      {
  1025.         /* add a new first SideDef */
  1026.         for (cur = obj; cur; cur = cur->next)
  1027.            if (LineDefs[ cur->objnum].sidedef1 == -1)
  1028.            {
  1029.           InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1030.           LineDefs[ cur->objnum].sidedef1 = NumSideDefs - 1;
  1031.            }
  1032.         break;
  1033.      }
  1034.      /* no break here */
  1035.  
  1036.       /* edit or add the second SideDef */
  1037.       case 3:
  1038.      if (objtype != OBJ_SIDEDEFS)
  1039.      {
  1040.         if (LineDefs[ obj->objnum].sidedef2 >= 0)
  1041.         {
  1042.            /* build a new selection list with the second (or first) SideDefs */
  1043.            objtype = OBJ_SIDEDEFS;
  1044.            sdlist = NULL;
  1045.            for (cur = obj; cur; cur = cur->next)
  1046.           if (LineDefs[ cur->objnum].sidedef2 >= 0)
  1047.              SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef2);
  1048.           else if (LineDefs[ cur->objnum].sidedef1 >= 0)
  1049.              SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  1050.         }
  1051.         else
  1052.         {
  1053.            /* add a new second (or first) SideDef */
  1054.            for (cur = obj; cur; cur = cur->next)
  1055.           if (LineDefs[ cur->objnum].sidedef1 == -1)
  1056.           {
  1057.              InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1058.              ObjectsNeeded( OBJ_LINEDEFS, 0);
  1059.              LineDefs[ cur->objnum].sidedef1 = NumSideDefs - 1;
  1060.           }
  1061.           else if (LineDefs[ cur->objnum].sidedef2 == -1)
  1062.           {
  1063.              n = LineDefs[ cur->objnum].sidedef1;
  1064.              InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1065.              strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
  1066.              strncpy( SideDefs[ n].tex3, "-", 8);
  1067.              ObjectsNeeded( OBJ_LINEDEFS, 0);
  1068.              LineDefs[ cur->objnum].sidedef2 = NumSideDefs - 1;
  1069.              LineDefs[ cur->objnum].flags = 4;
  1070.           }
  1071.            break;
  1072.         }
  1073.      }
  1074.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1075.      for (n = 0; n < 7; n++)
  1076.         menustr[ n] = (char*)GetMemory( 60);
  1077.      sprintf( menustr[ 6], "Edit SideDef #%d", sdlist->objnum);
  1078.      texname[ 8] = '\0';
  1079.      strncpy( texname, SideDefs[ sdlist->objnum].tex3, 8);
  1080.      sprintf( menustr[ 0], "Change Normal Texture   (Current: %s)", texname);
  1081.      strncpy( texname, SideDefs[ sdlist->objnum].tex1, 8);
  1082.      sprintf( menustr[ 1], "Change Upper texture    (Current: %s)", texname);
  1083.      strncpy( texname, SideDefs[ sdlist->objnum].tex2, 8);
  1084.      sprintf( menustr[ 2], "Change Lower texture    (Current: %s)", texname);
  1085.      sprintf( menustr[ 3], "Change Texture X offset (Current: %d)", SideDefs[ sdlist->objnum].xoff);
  1086.      sprintf( menustr[ 4], "Change Texture Y offset (Current: %d)", SideDefs[ sdlist->objnum].yoff);
  1087.      sprintf( menustr[ 5], "Change Sector ref.      (Current: #%d)", SideDefs[ sdlist->objnum].sector);
  1088.      val = DisplayMenuArray( x0 + 42, y0 + 54, menustr[ 6], 6, NULL, menustr, dummy);
  1089.      for (n = 0; n < 7; n++)
  1090.         FreeMemory( menustr[ n]);
  1091.      switch (val)
  1092.      {
  1093.      case 1:
  1094.         strncpy( texname, SideDefs[ sdlist->objnum].tex3, 8);
  1095.         ObjectsNeeded( 0);
  1096.         ChooseWallTexture( x0 + 84, y0 + 88, "Choose a wall texture", NumWTexture, WTexture, texname);
  1097.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1098.         if (strlen(texname) > 0)
  1099.         {
  1100.            for (cur = sdlist; cur; cur = cur->next)
  1101.           if (cur->objnum >= 0)
  1102.              strncpy( SideDefs[ cur->objnum].tex3, texname, 8);
  1103.            MadeChanges = TRUE;
  1104.         }
  1105.         break;
  1106.      case 2:
  1107.         strncpy( texname, SideDefs[ sdlist->objnum].tex1, 8);
  1108.         ObjectsNeeded( 0);
  1109.         ChooseWallTexture( x0 + 84, y0 + 98, "Choose a wall texture", NumWTexture, WTexture, texname);
  1110.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1111.         if (strlen(texname) > 0)
  1112.         {
  1113.            for (cur = sdlist; cur; cur = cur->next)
  1114.           if (cur->objnum >= 0)
  1115.              strncpy( SideDefs[ cur->objnum].tex1, texname, 8);
  1116.            MadeChanges = TRUE;
  1117.         }
  1118.         break;
  1119.      case 3:
  1120.         strncpy( texname, SideDefs[ sdlist->objnum].tex2, 8);
  1121.         ObjectsNeeded( 0);
  1122.         ChooseWallTexture( x0 + 84, y0 + 108, "Choose a wall texture", NumWTexture, WTexture, texname);
  1123.         ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1124.         if (strlen(texname) > 0)
  1125.         {
  1126.            for (cur = sdlist; cur; cur = cur->next)
  1127.           if (cur->objnum >= 0)
  1128.              strncpy( SideDefs[ cur->objnum].tex2, texname, 8);
  1129.            MadeChanges = TRUE;
  1130.         }
  1131.         break;
  1132.      case 4:
  1133.         val = InputIntegerValue( x0 + 84, y0 + 118, -255, 255, SideDefs[ sdlist->objnum].xoff);
  1134.         if (val >= -255)
  1135.         {
  1136.            for (cur = sdlist; cur; cur = cur->next)
  1137.           if (cur->objnum >= 0)
  1138.              SideDefs[ cur->objnum].xoff = val;
  1139.            MadeChanges = TRUE;
  1140.         }
  1141.         break;
  1142.      case 5:
  1143.         val = InputIntegerValue( x0 + 84, y0 + 128, -255, 255, SideDefs[ sdlist->objnum].yoff);
  1144.         if (val >= -255)
  1145.         {
  1146.            for (cur = sdlist; cur; cur = cur->next)
  1147.           if (cur->objnum >= 0)
  1148.              SideDefs[ cur->objnum].yoff = val;
  1149.            MadeChanges = TRUE;
  1150.         }
  1151.         break;
  1152.      case 6:
  1153.         val = InputObjectXRef( x0 + 84, y0 + 138, OBJ_SECTORS, FALSE, SideDefs[ sdlist->objnum].sector);
  1154.         if (val >= 0)
  1155.         {
  1156.            for (cur = sdlist; cur; cur = cur->next)
  1157.           if (cur->objnum >= 0)
  1158.              SideDefs[ cur->objnum].sector = val;
  1159.            MadeChanges = TRUE;
  1160.         }
  1161.         break;
  1162.      }
  1163.      ForgetSelection( &sdlist);
  1164.      break;
  1165.  
  1166.       }
  1167.       break;
  1168.  
  1169.    case OBJ_SECTORS:
  1170.       for (n = 0; n < 8; n++)
  1171.      menustr[ n] = (char*)GetMemory( 60);
  1172.       sprintf( menustr[ 7], "Edit Sector #%d", obj->objnum);
  1173.       sprintf( menustr[ 0], "Change Floor height     (Current: %d)", Sectors[ obj->objnum].floorh);
  1174.       sprintf( menustr[ 1], "Change Ceiling height   (Current: %d)", Sectors[ obj->objnum].ceilh);
  1175.       texname[ 8] = '\0';
  1176.       strncpy( texname, Sectors[ obj->objnum].floort, 8);
  1177.       sprintf( menustr[ 2], "Change Floor texture    (Current: %s)", texname);
  1178.       strncpy( texname, Sectors[ obj->objnum].ceilt, 8);
  1179.       sprintf( menustr[ 3], "Change Ceiling texture  (Current: %s)", texname);
  1180.       sprintf( menustr[ 4], "Change Light level      (Current: %d)", Sectors[ obj->objnum].light);
  1181.       sprintf( menustr[ 5], "Change Type             (Current: %d)", Sectors[ obj->objnum].special);
  1182.       sprintf( menustr[ 6], "Change LineDef tag      (Current: %d)", Sectors[ obj->objnum].tag);
  1183.       val = DisplayMenuArray( x0, y0, menustr[ 7], 7, NULL, menustr, dummy);
  1184.       for (n = 0; n < 8; n++)
  1185.      FreeMemory( menustr[ n]);
  1186.       switch (val)
  1187.       {
  1188.       case 1:
  1189.      val = InputIntegerValue( x0 + 42, y0 + 34, -16384, 16383, Sectors[ obj->objnum].floorh);
  1190.      if (val >= -16384)
  1191.      {
  1192.         for (cur = obj; cur; cur = cur->next)
  1193.            Sectors[ cur->objnum].floorh = val;
  1194.         MadeChanges = TRUE;
  1195.      }
  1196.      break;
  1197.       case 2:
  1198.      val = InputIntegerValue( x0 + 42, y0 + 44, -16384, 16383, Sectors[ obj->objnum].ceilh);
  1199.      if (val >= -16384)
  1200.      {
  1201.         for (cur = obj; cur; cur = cur->next)
  1202.            Sectors[ cur->objnum].ceilh = val;
  1203.         MadeChanges = TRUE;
  1204.      }
  1205.      break;
  1206.       case 3:
  1207.      strncpy( texname, Sectors[ obj->objnum].floort, 8);
  1208.      ObjectsNeeded( 0);
  1209.      ChooseFloorTexture( x0 + 42, y0 + 54, "Choose a floor texture", NumFTexture, FTexture, texname);
  1210.      ObjectsNeeded( OBJ_SECTORS, 0);
  1211.      if (strlen(texname) > 0)
  1212.      {
  1213.         for (cur = obj; cur; cur = cur->next)
  1214.            strncpy( Sectors[ cur->objnum].floort, texname, 8);
  1215.         MadeChanges = TRUE;
  1216.      }
  1217.      break;
  1218.       case 4:
  1219.      strncpy( texname, Sectors[ obj->objnum].ceilt, 8);
  1220.      ObjectsNeeded( 0);
  1221.      ChooseFloorTexture( x0 + 42, y0 + 64, "Choose a ceiling texture", NumFTexture, FTexture, texname);
  1222.      ObjectsNeeded( OBJ_SECTORS, 0);
  1223.      if (strlen(texname) > 0)
  1224.      {
  1225.         for (cur = obj; cur; cur = cur->next)
  1226.            strncpy( Sectors[ cur->objnum].ceilt, texname, 8);
  1227.         MadeChanges = TRUE;
  1228.      }
  1229.      break;
  1230.       case 5:
  1231.      val = InputIntegerValue( x0 + 42, y0 + 74, 0, 255, Sectors[ obj->objnum].light);
  1232.      if (val >= 0)
  1233.      {
  1234.         for (cur = obj; cur; cur = cur->next)
  1235.            Sectors[ cur->objnum].light = val;
  1236.         MadeChanges = TRUE;
  1237.      }
  1238.      break;
  1239.       case 6:
  1240.      val = DisplayMenu( x0 + 42, y0 + 84, "Choose a special behaviour",
  1241.                 GetSectorTypeLongName( 0),
  1242.                 GetSectorTypeLongName( 1),
  1243.                 GetSectorTypeLongName( 2),
  1244.                 GetSectorTypeLongName( 3),
  1245.                 GetSectorTypeLongName( 4),
  1246.                 GetSectorTypeLongName( 5),
  1247.                 GetSectorTypeLongName( 7),
  1248.                 GetSectorTypeLongName( 8),
  1249.                 GetSectorTypeLongName( 9),
  1250.                 GetSectorTypeLongName( 10),
  1251.                 GetSectorTypeLongName( 11),
  1252.                 GetSectorTypeLongName( 12),
  1253.                 GetSectorTypeLongName( 13),
  1254.                 GetSectorTypeLongName( 14),
  1255.                 GetSectorTypeLongName( 16),
  1256.                 "(Enter a decimal value)",
  1257.                 NULL);
  1258.      switch (val)
  1259.      {
  1260.      case 1:
  1261.      case 2:
  1262.      case 3:
  1263.      case 4:
  1264.      case 5:
  1265.      case 6:
  1266.         for (cur = obj; cur; cur = cur->next)
  1267.            Sectors[ cur->objnum].special = val - 1;
  1268.         MadeChanges = TRUE;
  1269.         break;
  1270.      case 7:
  1271.      case 8:
  1272.      case 9:
  1273.      case 10:
  1274.      case 11:
  1275.      case 12:
  1276.      case 13:
  1277.      case 14:
  1278.         for (cur = obj; cur; cur = cur->next)
  1279.            Sectors[ cur->objnum].special = val;
  1280.         MadeChanges = TRUE;
  1281.         break;
  1282.      case 15:
  1283.         for (cur = obj; cur; cur = cur->next)
  1284.            Sectors[ cur->objnum].special = 16;
  1285.         MadeChanges = TRUE;
  1286.         break;
  1287.      case 16:
  1288.         val = InputIntegerValue( x0 + 84, y0 + 208, 0, 255, Sectors[ obj->objnum].special);
  1289.         if (val >= 0)
  1290.         {
  1291.            for (cur = obj; cur; cur = cur->next)
  1292.           Sectors[ cur->objnum].special = val;
  1293.            MadeChanges = TRUE;
  1294.         }
  1295.         break;
  1296.      }
  1297.      break;
  1298.       case 7:
  1299.      val = InputIntegerValue( x0 + 42, y0 + 94, 0, 999, Sectors[ obj->objnum].tag);
  1300.      if (val >= 0)
  1301.      {
  1302.         for (cur = obj; cur; cur = cur->next)
  1303.            Sectors[ cur->objnum].tag = val;
  1304.         MadeChanges = TRUE;
  1305.      }
  1306.      break;
  1307.       }
  1308.       break;
  1309.    }
  1310. }
  1311.  
  1312.  
  1313.  
  1314. /*
  1315.    Yuck!  Dirty piece of code...
  1316. */
  1317.  
  1318. Bool Input2Numbers( BCINT x0, BCINT y0, char *name1, char *name2, BCINT v1max, BCINT v2max, BCINT *v1, BCINT *v2)
  1319. {
  1320.    BCINT  key;
  1321.    BCINT  maxlen, first;
  1322.    Bool ok;
  1323.    char prompt[ 80];
  1324.  
  1325.    if (UseMouse)
  1326.       HideMousePointer();
  1327.    sprintf( prompt, "Give the %s and %s for the object:", name1, name2);
  1328.    maxlen = strlen( prompt);
  1329.    if (x0 < 0)
  1330.       x0 = (ScrMaxX - 25 - 8 * maxlen) / 2;
  1331.    if (y0 < 0)
  1332.       y0 = (ScrMaxY - 75) / 2;
  1333.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * maxlen, y0 + 75);
  1334.    DrawScreenText( x0 + 10, y0 + 26, name1);
  1335.    DrawScreenText( x0 + 180, y0 + 26, name2);
  1336.    DrawScreenText( x0 + 10, y0 + 58, "(0-%d)", v1max);
  1337.    DrawScreenText( x0 + 180, y0 + 58, "(0-%d)", v2max);
  1338.    SetColor( WHITE);
  1339.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  1340.    first = TRUE;
  1341.    key = 0;
  1342.    for (;;)
  1343.    {
  1344.       ok = TRUE;
  1345.       DrawScreenBox3D( x0 + 10, y0 + 38, x0 + 71, y0 + 51);
  1346.       if (*v1 < 0 || *v1 > v1max)
  1347.       {
  1348.      SetColor( DARKGRAY);
  1349.      ok = FALSE;
  1350.       }
  1351.       DrawScreenText( x0 + 14, y0 + 41, "%d", *v1);
  1352.       DrawScreenBox3D( x0 + 180, y0 + 38, x0 + 241, y0 + 51);
  1353.       if (*v2 < 0 || *v2 > v2max)
  1354.       {
  1355.      SetColor( DARKGRAY);
  1356.      ok = FALSE;
  1357.       }
  1358.       DrawScreenText( x0 + 184, y0 + 41, "%d", *v2);
  1359.       if (first)
  1360.      key = InputInteger( x0 + 10, y0 + 38, v1, 0, v1max);
  1361.       else
  1362.      key = InputInteger( x0 + 180, y0 + 38, v2, 0, v2max);
  1363.       if ((key & 0xFF00) == 0x4B00 || (key & 0xFF00) == 0x4D00 || (key & 0x00FF) == 0x0009 || (key & 0xFF00) == 0x0F00)
  1364.      first = !first;
  1365.       else if ((key & 0x00FF) == 0x001B)
  1366.      break;
  1367.       else if ((key & 0x00FF) == 0x000D)
  1368.       {
  1369.      if (first)
  1370.         first = FALSE;
  1371.      else if (ok)
  1372.         break;
  1373.      else
  1374.         Beep();
  1375.       }
  1376.       else
  1377.      Beep();
  1378.    }
  1379.    if (UseMouse)
  1380.       ShowMousePointer();
  1381.    return ((key & 0x00FF) == 0x000D);
  1382. }
  1383.  
  1384.  
  1385.  
  1386. /*
  1387.    display number of objects, etc.
  1388. */
  1389.  
  1390. void Statistics( BCINT x0, BCINT y0)
  1391. {
  1392.    if (x0 < 0)
  1393.       x0 = (ScrMaxX - 270) / 2;
  1394.    if (y0 < 0)
  1395.       y0 = (ScrMaxY - 100) / 2;
  1396.    if (UseMouse)
  1397.       HideMousePointer();
  1398.    DrawScreenBox3D( x0, y0, x0 + 270, y0 + 100);
  1399.    SetColor( WHITE);
  1400.    DrawScreenText( x0 + 10, y0 + 5, "Statistics");
  1401.    if (Things == NULL)
  1402.       SetColor( DARKGRAY);
  1403.    else
  1404.       SetColor( BLACK);
  1405.    DrawScreenText( -1, y0 + 25, "Number of Things:   %4d (%lu K)",
  1406.            NumThings, ((unsigned long) NumThings * sizeof( struct Thing) + 512L) / 1024L);
  1407.    if (Vertexes == NULL)
  1408.       SetColor( DARKGRAY);
  1409.    else
  1410.       SetColor( BLACK);
  1411.    DrawScreenText( -1, -1, "Number of Vertices: %4d (%lu K)",
  1412.            NumVertexes, ((unsigned long) NumVertexes * sizeof( struct Vertex) + 512L) / 1024L);
  1413.    if (LineDefs == NULL)
  1414.       SetColor( DARKGRAY);
  1415.    else
  1416.       SetColor( BLACK);
  1417.    DrawScreenText( -1, -1, "Number of LineDefs: %4d (%lu K)",
  1418.            NumLineDefs, ((unsigned long) NumLineDefs * sizeof( struct LineDef) + 512L) / 1024L);
  1419.    if (SideDefs == NULL)
  1420.       SetColor( DARKGRAY);
  1421.    else
  1422.       SetColor( BLACK);
  1423.    DrawScreenText( -1, -1, "Number of SideDefs: %4d (%lu K)",
  1424.            NumSideDefs, ((unsigned long) NumSideDefs * sizeof( struct SideDef) + 512L) / 1024L);
  1425.    if (Sectors == NULL)
  1426.       SetColor( DARKGRAY);
  1427.    else
  1428.       SetColor( BLACK);
  1429.    DrawScreenText( -1, -1, "Number of Sectors:  %4d (%lu K)",
  1430.            NumSectors, ((unsigned long) NumSectors * sizeof( struct Sector) + 512L) / 1024L);
  1431.    SetColor( YELLOW);
  1432.    DrawScreenText( x0 + 10, y0 + 85, "Press any key to continue...");
  1433.    bioskey( 0);
  1434.    if (UseMouse)
  1435.       ShowMousePointer();
  1436. }
  1437.  
  1438.  
  1439.  
  1440. /*
  1441.    display a message while the user is waiting...
  1442. */
  1443.  
  1444. void CheckingObjects( BCINT x0, BCINT y0)
  1445. {
  1446.    if (UseMouse)
  1447.       HideMousePointer();
  1448.    if (x0 < 0)
  1449.       x0 = (ScrMaxX - 172) / 2;
  1450.    if (y0 < 0)
  1451.       y0 = (ScrMaxY - 30) / 2;
  1452.    DrawScreenBox3D( x0, y0, x0 + 172, y0 + 30);
  1453.    DrawScreenText( x0 + 10, y0 + 5, "Checking objects...");
  1454.    DrawScreenText( x0 + 10, y0 + 15, "   Please wait");
  1455.    if (UseMouse)
  1456.       ShowMousePointer();
  1457. }
  1458.  
  1459.  
  1460. /*
  1461.    display a message, then ask if the check should continue (prompt2 may be NULL)
  1462. */
  1463.  
  1464. Bool CheckFailed( BCINT x0, BCINT y0, char *prompt1, char *prompt2, Bool fatal)
  1465. {
  1466.    BCINT key;
  1467.    BCINT maxlen;
  1468.  
  1469.    if (UseMouse)
  1470.       HideMousePointer();
  1471.    if (fatal == TRUE)
  1472.       maxlen = 44;
  1473.    else
  1474.       maxlen = 27;
  1475.    if (strlen( prompt1) > maxlen)
  1476.       maxlen = strlen( prompt1);
  1477.    if (prompt2 != NULL && strlen( prompt2) > maxlen)
  1478.       maxlen = strlen( prompt2);
  1479.    if (x0 < 0)
  1480.       x0 = (ScrMaxX - 22 - 8 * maxlen) / 2;
  1481.    if (y0 < 0)
  1482.       y0 = (ScrMaxY - (prompt2 ? 73 : 63)) / 2;
  1483.    DrawScreenBox3D( x0, y0, x0 + 22 + 8 * maxlen, y0 + (prompt2 ? 73 : 63));
  1484.    SetColor( RED);
  1485.    DrawScreenText( x0 + 10, y0 + 8, "Verification failed:");
  1486.    Beep();
  1487.    SetColor( WHITE);
  1488.    DrawScreenText( x0 + 10, y0 + 18, prompt1);
  1489.    LogMessage( "\t%s\n", prompt1);
  1490.    if (prompt2 != NULL)
  1491.    {
  1492.       DrawScreenText( x0 + 10, y0 + 28, prompt2);
  1493.       LogMessage( "\t%s\n", prompt2);
  1494.    }
  1495.    if (fatal == TRUE)
  1496.    {
  1497.       DrawScreenText( x0 + 10, y0 + (prompt2 ? 38 : 28), "DOOM will crash if you play with this level.");
  1498.       SetColor( YELLOW);
  1499.       DrawScreenText( x0 + 10, y0 + (prompt2 ? 58 : 48), "Press any key to see the object");
  1500.       LogMessage( "\n");
  1501.    }
  1502.    else
  1503.    {
  1504.       SetColor( YELLOW);
  1505.       DrawScreenText( x0 + 10, y0 + (prompt2 ? 48 : 38), "Press Esc to see the object,");
  1506.       DrawScreenText( x0 + 10, y0 + (prompt2 ? 58 : 48), "or any other key to continue");
  1507.    }
  1508.    key = bioskey( 0);
  1509.    if ((key & 0x00FF) != 0x001B)
  1510.    {
  1511.       DrawScreenBox3D( x0, y0, x0 + 22 + 8 * maxlen, y0 + (prompt2 ? 73 : 63));
  1512.       DrawScreenText( x0 + 10 + 4 * (maxlen - 26), y0 + 28, "Verifying other objects...");
  1513.    }
  1514.    if (UseMouse)
  1515.       ShowMousePointer();
  1516.  
  1517.    return ((key & 0x00FF) == 0x001B);
  1518. }
  1519.  
  1520.  
  1521.  
  1522. /*
  1523.    check if all sectors are closed
  1524. */
  1525.  
  1526. void CheckSectors( void) /* SWAP! */
  1527. {
  1528.    BCINT      s, n, sd;
  1529.    char huge *ends;
  1530.    char       msg1[ 80], msg2[80];
  1531.  
  1532.    CheckingObjects( -1, -1);
  1533.    LogMessage( "\nVerifying Sectors...\n");
  1534.    ObjectsNeeded( OBJ_LINEDEFS, OBJ_SIDEDEFS, 0);
  1535.    ends = GetFarMemory( NumVertexes * sizeof( char));
  1536.    for (s = 0; s < NumSectors; s++)
  1537.    {
  1538.       /* clear the "ends" array */
  1539.       for (n = 0; n < NumVertexes; n++)
  1540.      ends[ n] = 0;
  1541.       /* for each SideDef bound to the Sector, store a "1" in the "ends" */
  1542.       /* array for its starting Vertex, and a "2" for its ending Vertex  */
  1543.       for (n = 0; n < NumLineDefs; n++)
  1544.       {
  1545.      sd = LineDefs[ n].sidedef1;
  1546.      if (sd >= 0 && SideDefs[ sd].sector == s)
  1547.      {
  1548.         ends[ LineDefs[ n].start] |= 1;
  1549.         ends[ LineDefs[ n].end] |= 2;
  1550.      }
  1551.      sd = LineDefs[ n].sidedef2;
  1552.      if (sd >= 0 && SideDefs[ sd].sector == s)
  1553.      {
  1554.         ends[ LineDefs[ n].end] |= 1;
  1555.         ends[ LineDefs[ n].start] |= 2;
  1556.      }
  1557.       }
  1558.       /* every entry in the "ends" array should be "0" or "3" */
  1559.       for (n = 0; n < NumVertexes; n++)
  1560.       {
  1561.      if (ends[ n] == 1)
  1562.      {
  1563.         sprintf( msg1, "Sector #%d is not closed!", s);
  1564.         sprintf( msg2, "There is no SideDef ending at Vertex #%d", n);
  1565.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1566.         {
  1567.            GoToObject( OBJ_VERTEXES, n);
  1568.            return;
  1569.         }
  1570.      }
  1571.      if (ends[ n] == 2)
  1572.      {
  1573.         sprintf( msg1, "Sector #%d is not closed!", s);
  1574.         sprintf( msg2, "There is no SideDef starting at Vertex #%d", n);
  1575.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1576.         {
  1577.            GoToObject( OBJ_VERTEXES, n);
  1578.            return;
  1579.         }
  1580.      }
  1581.       }
  1582.    }
  1583.    FreeFarMemory( ends);
  1584.  
  1585.    /*
  1586.       Note from RQ:
  1587.      This is a very simple idea, but it works!  The first test (above)
  1588.      checks that all Sectors are closed.  But if a closed set of LineDefs
  1589.      is moved out of a Sector and has all its "external" SideDefs pointing
  1590.      to that Sector instead of the new one, then we need a second test.
  1591.      That's why I check if the SideDefs facing each other are bound to
  1592.      the same Sector.
  1593.  
  1594.       Other note from RQ:
  1595.      Nowadays, what makes the power of a good editor is its automatic tests.
  1596.      So, if you are writing another Doom editor, you will probably want
  1597.      to do the same kind of tests in your program.  Fine, but if you use
  1598.      these ideas, don't forget to credit DEU...  Just a reminder... :-)
  1599.    */
  1600.  
  1601.    /* now check if all SideDefs are facing a SideDef with the same Sector number */
  1602.    for (n = 0; n < NumLineDefs; n++)
  1603.    {
  1604.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1605.       sd = LineDefs[ n].sidedef1;
  1606.       if (sd >= 0)
  1607.       {
  1608.      s = GetOppositeSector( n, TRUE);
  1609.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1610.      if (s < 0 || SideDefs[ sd].sector != s)
  1611.      {
  1612.         if (s < 0)
  1613.         {
  1614.            sprintf( msg1, "Sector #%d is not closed!", SideDefs[ sd].sector);
  1615.            sprintf( msg2, "Check LineDef #%d (first SideDef: #%d)", n, sd);
  1616.         }
  1617.         else
  1618.         {
  1619.            sprintf( msg1, "Sectors #%d and #%d are not closed!", SideDefs[ sd].sector, s);
  1620.            sprintf( msg2, "Check LineDef #%d (first SideDef: #%d) and the one facing it", n, sd);
  1621.         }
  1622.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1623.         {
  1624.            GoToObject( OBJ_LINEDEFS, n);
  1625.            return;
  1626.         }
  1627.      }
  1628.       }
  1629.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1630.       sd = LineDefs[ n].sidedef2;
  1631.       if (sd >= 0)
  1632.       {
  1633.      s = GetOppositeSector( n, FALSE);
  1634.      ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1635.      if (s < 0 || SideDefs[ sd].sector != s)
  1636.      {
  1637.         if (s < 0)
  1638.         {
  1639.            sprintf( msg1, "Sector #%d is not closed!", SideDefs[ sd].sector);
  1640.            sprintf( msg2, "Check LineDef #%d (second SideDef: #%d)", n, sd);
  1641.         }
  1642.         else
  1643.         {
  1644.            sprintf( msg1, "Sectors #%d and #%d are not closed!", SideDefs[ sd].sector, s);
  1645.            sprintf( msg2, "Check LineDef #%d (second SideDef: #%d) and the one facing it", n, sd);
  1646.         }
  1647.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1648.         {
  1649.            GoToObject( OBJ_LINEDEFS, n);
  1650.            return;
  1651.         }
  1652.      }
  1653.       }
  1654.    }
  1655. }
  1656.  
  1657.  
  1658.  
  1659. /*
  1660.    check cross-references and delete unused objects
  1661. */      
  1662.  
  1663. void CheckCrossReferences( void) /* SWAP! */
  1664. {
  1665.    char   msg[ 80];
  1666.    BCINT    n, m;
  1667.    SelPtr cur;
  1668.  
  1669.    CheckingObjects( -1, -1);
  1670.    LogMessage( "\nVerifying cross-references...\n");
  1671.    ObjectsNeeded( OBJ_LINEDEFS, 0);
  1672.    for (n = 0; n < NumLineDefs; n++)
  1673.    {
  1674.       /* check for missing first SideDefs */
  1675.       if (LineDefs[ n].sidedef1 < 0)
  1676.       {
  1677.      sprintf( msg, "ERROR: LineDef #%d has no first SideDef!", n);
  1678.      CheckFailed( -1, -1, msg, NULL, TRUE);
  1679.      GoToObject( OBJ_LINEDEFS, n);
  1680.      return;
  1681.       }
  1682.       /* check for SideDefs used twice in the same LineDef */
  1683.       if (LineDefs[ n].sidedef1 == LineDefs[ n].sidedef2)
  1684.       {
  1685.      sprintf( msg, "ERROR: LineDef #%d uses the same SideDef twice (#%d)", n, LineDefs[ n].sidedef1);
  1686.      CheckFailed( -1, -1, msg, NULL, TRUE);
  1687.      GoToObject( OBJ_LINEDEFS, n);
  1688.      return;
  1689.       }
  1690.       /* check for Vertices used twice in the same LineDef */
  1691.       if (LineDefs[ n].start == LineDefs[ n].end)
  1692.       {
  1693.      sprintf( msg, "ERROR: LineDef #%d uses the same Vertex twice (#%d)", n, LineDefs[ n].start);
  1694.      CheckFailed( -1, -1, msg, NULL, TRUE);
  1695.      GoToObject( OBJ_LINEDEFS, n);
  1696.      return;
  1697.       }
  1698.    }
  1699.  
  1700.    /* check if there aren't two LineDefs between the same Vertices */
  1701.    cur = NULL;
  1702.    for (n = NumLineDefs - 1; n >= 1; n--)
  1703.    {
  1704.       for (m = n - 1; m >= 0; m--)
  1705.      if ((LineDefs[ n].start == LineDefs[ m].start && LineDefs[ n].end == LineDefs[ m].end)
  1706.       || (LineDefs[ n].start == LineDefs[ m].end && LineDefs[ n].end == LineDefs[ m].start))
  1707.      {
  1708.         SelectObject( &cur, n);
  1709.         break;
  1710.      }
  1711.    }
  1712.    if (cur && (Expert || Confirm(-1, -1, "There are multiple LineDefs between the same Vertices", "Do you want to delete the redundant LineDefs?")))
  1713.       DeleteObjects( OBJ_LINEDEFS, &cur);
  1714.    else
  1715.       ForgetSelection( &cur);
  1716.  
  1717.    CheckingObjects( -1, -1);
  1718.    /* check for invalid flags in the LineDefs */
  1719.    for (n = 0; n < NumLineDefs; n++)
  1720.       if ((LineDefs[ n].flags & 0x01) == 0 && LineDefs[ n].sidedef2 < 0)
  1721.      SelectObject( &cur, n);
  1722.    if (cur && (Expert || Confirm(-1, -1, "Some LineDefs have only one side but their Im bit is not set", "Do you want to set the 'Impassible' flag?")))
  1723.    {
  1724.       while (cur)
  1725.       {
  1726.      LineDefs[ cur->objnum].flags |= 0x01;
  1727.      UnSelectObject( &cur, cur->objnum);
  1728.       }
  1729.    }
  1730.    else
  1731.       ForgetSelection( &cur);
  1732.  
  1733.    CheckingObjects( -1, -1);
  1734.    for (n = 0; n < NumLineDefs; n++)
  1735.       if ((LineDefs[ n].flags & 0x04) != 0 && LineDefs[ n].sidedef2 < 0)
  1736.      SelectObject( &cur, n);
  1737.    if (cur && (Expert || Confirm(-1, -1, "Some LineDefs have only one side but their 2S bit is set", "Do you want to clear the 'two-sided' flag?")))
  1738.    {
  1739.       while (cur)
  1740.       {
  1741.      LineDefs[ cur->objnum].flags &= ~0x04;
  1742.      UnSelectObject( &cur, cur->objnum);
  1743.       }
  1744.    }
  1745.    else
  1746.       ForgetSelection( &cur);
  1747.  
  1748.    CheckingObjects( -1, -1);
  1749.    for (n = 0; n < NumLineDefs; n++)
  1750.       if ((LineDefs[ n].flags & 0x04) == 0 && LineDefs[ n].sidedef2 >= 0)
  1751.      SelectObject( &cur, n);
  1752.    if (cur && (Expert || Confirm(-1, -1, "Some LineDefs have two sides but their 2S bit is not set", "Do you want to set the 'two-sided' flag?")))
  1753.    {
  1754.       while (cur)
  1755.       {
  1756.      LineDefs[ cur->objnum].flags |= 0x04;
  1757.      UnSelectObject( &cur, cur->objnum);
  1758.       }
  1759.    }
  1760.    else
  1761.       ForgetSelection( &cur);
  1762.  
  1763.    CheckingObjects( -1, -1);
  1764.    /* select all Vertices */
  1765.    for (n = 0; n < NumVertexes; n++)
  1766.       SelectObject( &cur, n);
  1767.    /* unselect Vertices used in a LineDef */
  1768.    for (n = 0; n < NumLineDefs; n++)
  1769.    {
  1770.       m = LineDefs[ n].start;
  1771.       if (cur && m >= 0)
  1772.      UnSelectObject( &cur, m);
  1773.       m = LineDefs[ n].end;
  1774.       if (cur && m >= 0)
  1775.      UnSelectObject( &cur, m);
  1776.       continue;
  1777.    }
  1778.    /* check if there are any Vertices left */
  1779.    if (cur && (Expert || Confirm(-1, -1, "Some Vertices are not bound to any LineDef", "Do you want to delete these unused Vertices?")))
  1780.    {
  1781.       DeleteObjects( OBJ_VERTEXES, &cur);
  1782.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1783.    }
  1784.    else
  1785.       ForgetSelection( &cur);
  1786.    
  1787.    CheckingObjects( -1, -1);
  1788.    /* select all SideDefs */
  1789.    for (n = 0; n < NumSideDefs; n++)
  1790.       SelectObject( &cur, n);
  1791.    /* unselect SideDefs bound to a LineDef */
  1792.    for (n = 0; n < NumLineDefs; n++)
  1793.    {
  1794.       m = LineDefs[ n].sidedef1;
  1795.       if (cur && m >= 0)
  1796.      UnSelectObject( &cur, m);
  1797.       m = LineDefs[ n].sidedef2;
  1798.       if (cur && m >= 0)
  1799.      UnSelectObject( &cur, m);
  1800.       continue;
  1801.    }
  1802.    /* check if there are any SideDefs left */
  1803.    if (cur && (Expert || Confirm(-1, -1, "Some SideDefs are not bound to any LineDef", "Do you want to delete these unused SideDefs?")))
  1804.       DeleteObjects( OBJ_SIDEDEFS, &cur);
  1805.    else
  1806.       ForgetSelection( &cur);
  1807.  
  1808.    CheckingObjects( -1, -1);
  1809.    /* select all Sectors */
  1810.    for (n = 0; n < NumSectors; n++)
  1811.       SelectObject( &cur, n);
  1812.    /* unselect Sectors bound to a SideDef */
  1813.    for (n = 0; n < NumLineDefs; n++)
  1814.    {
  1815.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1816.       m = LineDefs[ n].sidedef1;
  1817.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1818.       if (cur && m >= 0 && SideDefs[ m].sector >= 0)
  1819.      UnSelectObject( &cur, SideDefs[ m].sector);
  1820.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1821.       m = LineDefs[ n].sidedef2;
  1822.       ObjectsNeeded( OBJ_SIDEDEFS, 0);
  1823.       if (cur && m >= 0 && SideDefs[ m].sector >= 0)
  1824.      UnSelectObject( &cur, SideDefs[ m].sector);
  1825.       continue;
  1826.    }
  1827.    /* check if there are any Sectors left */
  1828.    if (cur && (Expert || Confirm(-1, -1, "Some Sectors are not bound to any SideDef", "Do you want to delete these unused Sectors?")))
  1829.       DeleteObjects( OBJ_SECTORS, &cur);
  1830.    else
  1831.       ForgetSelection( &cur);
  1832. }
  1833.  
  1834.  
  1835.  
  1836. /*
  1837.    check for missing textures
  1838. */
  1839.  
  1840. void CheckTextures( void) /* SWAP! */
  1841. {
  1842.    BCINT  n;
  1843.    BCINT  sd1, sd2;
  1844.    BCINT  s1, s2;
  1845.    char msg1[ 80], msg2[ 80];
  1846.  
  1847.    CheckingObjects( -1, -1);
  1848.    LogMessage( "\nVerifying textures...\n");
  1849.    ObjectsNeeded( OBJ_SECTORS, 0);
  1850.    for (n = 0; n < NumSectors; n++)
  1851.    {
  1852.       if (Sectors[ n].ceilt[ 0] == '-' && Sectors[ n].ceilt == '\0')
  1853.       {
  1854.      sprintf( msg1, "Error: Sector #%d has no ceiling texture", n);
  1855.      sprintf( msg2, "You probaly used a brain-damaged editor to do that...");
  1856.      CheckFailed( -1, -1, msg1, msg2, TRUE);
  1857.      GoToObject( OBJ_SECTORS, n);
  1858.      return;
  1859.       }
  1860.       if (Sectors[ n].floort[ 0] == '-' && Sectors[ n].floort == '\0')
  1861.       {
  1862.      sprintf( msg1, "Error: Sector #%d has no floor texture", n);
  1863.      sprintf( msg2, "You probaly used a brain-damaged editor to do that...");
  1864.      CheckFailed( -1, -1, msg1, msg2, TRUE);
  1865.      GoToObject( OBJ_SECTORS, n);
  1866.      return;
  1867.       }
  1868.       if (Sectors[ n].ceilh < Sectors[ n].floorh)
  1869.       {
  1870.      sprintf( msg1, "Error: Sector #%d has its ceiling lower than its floor", n);
  1871.      sprintf( msg2, "The textures will never be displayed if you cannot go there");
  1872.      CheckFailed( -1, -1, msg1, msg2, TRUE);
  1873.      GoToObject( OBJ_SECTORS, n);
  1874.      return;
  1875.       }
  1876.       if (Sectors[ n].ceilh - Sectors[ n].floorh > 1023)
  1877.       {
  1878.      sprintf( msg1, "Error: Sector #%d has its ceiling too high", n);
  1879.      sprintf( msg2, "The maximum difference allowed is 1023 (ceiling - floor)");
  1880.      CheckFailed( -1, -1, msg1, msg2, TRUE);
  1881.      GoToObject( OBJ_SECTORS, n);
  1882.      return;
  1883.       }
  1884.    }
  1885.    for (n = 0; n < NumLineDefs; n++)
  1886.    {
  1887.       ObjectsNeeded( OBJ_LINEDEFS, 0);
  1888.       sd1 = LineDefs[ n].sidedef1;
  1889.       sd2 = LineDefs[ n].sidedef2;
  1890.       ObjectsNeeded( OBJ_SIDEDEFS, OBJ_SECTORS, 0);
  1891.       if (sd1 >= 0)
  1892.      s1 = SideDefs[ sd1].sector;
  1893.       else
  1894.      s1 = -1;
  1895.       if (sd2 >= 0)
  1896.      s2 = SideDefs[ sd2].sector;
  1897.       else
  1898.      s2 = -1;
  1899.       if (s1 >= 0 && s2 < 0)
  1900.       {
  1901.      if (SideDefs[ sd1].tex3[ 0] == '-' && SideDefs[ sd1].tex3[ 1] == '\0')
  1902.      {
  1903.          sprintf( msg1, "Error in one-sided Linedef #%d: SideDef #%d has no normal texture", n, sd1);
  1904.          sprintf( msg2, "Do you want to set the texture to \"%s\" and continue?", DefaultWallTexture);
  1905.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1906.             {
  1907.                GoToObject( OBJ_LINEDEFS, n);
  1908.            return;
  1909.             }
  1910.          strncpy( SideDefs[ sd1].tex3, DefaultWallTexture, 8);
  1911.             CheckingObjects( -1, -1);
  1912.      }
  1913.       }
  1914.       if (s1 >= 0 && s2 >= 0 && Sectors[ s1].ceilh > Sectors[ s2].ceilh)
  1915.       {
  1916.      if (SideDefs[ sd1].tex1[ 0] == '-' && SideDefs[ sd1].tex1[ 1] == '\0'
  1917.          && (strncmp( Sectors[ s1].ceilt, "F_SKY1", 8) || strncmp( Sectors[ s2].ceilt, "F_SKY1", 8)))
  1918.      {
  1919.          sprintf( msg1, "Error in first SideDef of Linedef #%d: SideDef #%d has no upper texture", n, sd1);
  1920.          sprintf( msg2, "Do you want to set the texture to \"%s\" and continue?", DefaultUpperTexture);
  1921.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1922.         {
  1923.            GoToObject( OBJ_LINEDEFS, n);
  1924.            return;
  1925.         }
  1926.             strncpy( SideDefs[ sd1].tex1, DefaultUpperTexture, 8);
  1927.             CheckingObjects( -1, -1);
  1928.      }
  1929.       }
  1930.       if (s1 >= 0 && s2 >= 0 && Sectors[ s1].floorh < Sectors[ s2].floorh)
  1931.       {
  1932.      if (SideDefs[ sd1].tex2[ 0] == '-' && SideDefs[ sd1].tex2[ 1] == '\0')
  1933.      {
  1934.          sprintf( msg1, "Error in first SideDef of Linedef #%d: SideDef #%d has no lower texture", n, sd1);
  1935.          sprintf( msg2, "Do you want to set the texture to \"%s\" and continue?", DefaultLowerTexture);
  1936.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1937.         {
  1938.            GoToObject( OBJ_LINEDEFS, n);
  1939.            return;
  1940.         }
  1941.             strncpy( SideDefs[ sd1].tex2, DefaultLowerTexture, 8);
  1942.             CheckingObjects( -1, -1);
  1943.      }
  1944.       }
  1945.       if (s1 >= 0 && s2 >= 0 && Sectors[ s2].ceilh > Sectors[ s1].ceilh)
  1946.       {
  1947.      if (SideDefs[ sd2].tex1[ 0] == '-' && SideDefs[ sd2].tex1[ 1] == '\0'
  1948.          && (strncmp( Sectors[ s1].ceilt, "F_SKY1", 8) || strncmp( Sectors[ s2].ceilt, "F_SKY1", 8)))
  1949.      {
  1950.          sprintf( msg1, "Error in second SideDef of Linedef #%d: SideDef #%d has no upper texture", n, sd2);
  1951.          sprintf( msg2, "Do you want to set the texture to \"%s\" and continue?", DefaultUpperTexture);
  1952.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1953.         {
  1954.            GoToObject( OBJ_LINEDEFS, n);
  1955.            return;
  1956.         }
  1957.             strncpy( SideDefs[ sd2].tex1, DefaultUpperTexture, 8);
  1958.             CheckingObjects( -1, -1);
  1959.      }
  1960.       }
  1961.       if (s1 >= 0 && s2 >= 0 && Sectors[ s2].floorh < Sectors[ s1].floorh)
  1962.       {
  1963.      if (SideDefs[ sd2].tex2[ 0] == '-' && SideDefs[ sd2].tex2[ 1] == '\0')
  1964.      {
  1965.          sprintf( msg1, "Error in second SideDef of Linedef #%d: SideDef #%d has no lower texture", n, sd2);
  1966.          sprintf( msg2, "Do you want to set the texture to \"%s\" and continue?", DefaultLowerTexture);
  1967.         if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  1968.         {
  1969.            GoToObject( OBJ_LINEDEFS, n);
  1970.            return;
  1971.         }
  1972.             strncpy( SideDefs[ sd2].tex2, DefaultUpperTexture, 8);
  1973.             CheckingObjects( -1, -1);
  1974.      }
  1975.       }
  1976.    }
  1977. }
  1978.  
  1979.  
  1980.  
  1981. /*
  1982.    check if a texture name matches one of the elements of a list
  1983. */
  1984.  
  1985. Bool IsTextureNameInList( char *name, char **list, BCINT numelems)
  1986. {
  1987.    BCINT n;
  1988.  
  1989.    for (n = 0; n < numelems; n++)
  1990.       if (! strnicmp( name, list[ n], 8))
  1991.      return TRUE;
  1992.    return FALSE;
  1993. }
  1994.  
  1995.  
  1996.  
  1997. /*
  1998.    check for invalid texture names
  1999. */
  2000.  
  2001. void CheckTextureNames( void) /* SWAP! */
  2002. {
  2003.    BCINT  n;
  2004.    char msg1[ 80], msg2[ 80];
  2005.  
  2006.    LogMessage( "\nVerifying texture names...\n");
  2007.    if (FindMasterDir( MasterDir, "F2_START") == NULL)
  2008.       NumThings--;
  2009.    ObjectsNeeded( OBJ_SECTORS, 0);
  2010.    for (n = 0; n < NumSectors; n++)
  2011.    {
  2012.       if (! IsTextureNameInList( Sectors[ n].ceilt, FTexture, NumFTexture))
  2013.       {
  2014.      sprintf( msg1, "Invalid ceiling texture in Sector #%d", n);
  2015.      sprintf( msg2, "The name \"%s\" is not a floor/ceiling texture", Sectors[ n].ceilt);
  2016.      if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  2017.      {
  2018.         GoToObject( OBJ_SECTORS, n);
  2019.         return;
  2020.      }                           
  2021.          CheckingObjects( -1, -1);
  2022.       }
  2023.       if (! IsTextureNameInList( Sectors[ n].floort, FTexture, NumFTexture))
  2024.       {
  2025.      sprintf( msg1, "Invalid floor texture in Sector #%d", n);
  2026.      sprintf( msg2, "The name \"%s\" is not a floor/ceiling texture", Sectors[ n].floort);
  2027.      if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  2028.      {
  2029.         GoToObject( OBJ_SECTORS, n);
  2030.         return;
  2031.      }                        
  2032.          CheckingObjects( -1, -1);
  2033.       }
  2034.    }
  2035.    ObjectsNeeded( OBJ_SIDEDEFS, 0);
  2036.    for (n = 0; n < NumSideDefs; n++)
  2037.    {
  2038.       if (! IsTextureNameInList( SideDefs[ n].tex1, WTexture, NumWTexture))
  2039.       {
  2040.      sprintf( msg1, "Invalid upper texture in SideDef #%d", n);
  2041.      sprintf( msg2, "The name \"%s\" is not a wall texture", SideDefs[ n].tex1);
  2042.      if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  2043.      {
  2044.         GoToObject( OBJ_SIDEDEFS, n);
  2045.         return;               
  2046.      }
  2047.          CheckingObjects( -1, -1);
  2048.       }
  2049.       if (! IsTextureNameInList( SideDefs[ n].tex2, WTexture, NumWTexture))
  2050.       {
  2051.      sprintf( msg1, "Invalid lower texture in SideDef #%d", n);
  2052.      sprintf( msg2, "The name \"%s\" is not a wall texture", SideDefs[ n].tex2);
  2053.      if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  2054.      {
  2055.         GoToObject( OBJ_SIDEDEFS, n);
  2056.         return;
  2057.      }                        
  2058.          CheckingObjects( -1, -1);
  2059.       }
  2060.       if (! IsTextureNameInList( SideDefs[ n].tex3, WTexture, NumWTexture))
  2061.       {
  2062.      sprintf( msg1, "Invalid normal texture in SideDef #%d", n);
  2063.      sprintf( msg2, "The name \"%s\" is not a wall texture", SideDefs[ n].tex3);
  2064.      if (CheckFailed( -1, -1, msg1, msg2, FALSE))
  2065.      {
  2066.         GoToObject( OBJ_SIDEDEFS, n);
  2067.         return;
  2068.      }
  2069.          CheckingObjects( -1, -1);
  2070.       }
  2071.    }
  2072. }
  2073.  
  2074.  
  2075.  
  2076. /*
  2077.    check the level consistency
  2078. */                                
  2079.  
  2080. void CheckLevel( BCINT x0, BCINT y0) /* SWAP! */
  2081. {
  2082.    char *line5 = NULL;
  2083.  
  2084.    if (Registered)
  2085.    {
  2086.       if (FindMasterDir( MasterDir, "TEXTURE2") == NULL)
  2087.      NumVertexes--;
  2088.       else
  2089.      line5 = "Check texture names";
  2090.    }
  2091.    switch (DisplayMenu( x0, y0, ((x0 == -1) ? "Check level consistency" : NULL),
  2092.             "Number of objects",
  2093.             "Check if all Sectors are closed",
  2094.             "Check all cross-references",
  2095.             "Check for missing textures",
  2096.             line5,
  2097.             NULL))
  2098.    {
  2099.    case 1:
  2100.       Statistics( -1, -1);
  2101.       break;
  2102.    case 2:
  2103.       CheckSectors();
  2104.       break;
  2105.    case 3:
  2106.       CheckCrossReferences();
  2107.       break;
  2108.    case 4:
  2109.       CheckTextures();
  2110.       break;
  2111.    case 5:
  2112.       CheckTextureNames();
  2113.       break;
  2114.    }
  2115. }
  2116.  
  2117.  
  2118.  
  2119. /*
  2120.    check for players starting points
  2121. */
  2122.  
  2123. Bool CheckStartingPos() /* SWAP! */
  2124. {
  2125.    char msg1[ 80], msg2[80];
  2126.    Bool p1 = FALSE;
  2127.    Bool p2 = FALSE;
  2128.    Bool p3 = FALSE;
  2129.    Bool p4 = FALSE;
  2130.    BCINT  dm = 0;
  2131.    BCINT  t;
  2132.  
  2133.    ObjectsNeeded( OBJ_THINGS, 0);
  2134.    for (t = 0; t < NumThings; t++)
  2135.    {
  2136.       if (Things[ t].type == THING_PLAYER1)
  2137.      p1 = TRUE;
  2138.       if (Things[ t].type == THING_PLAYER2)
  2139.      p2 = TRUE;
  2140.       if (Things[ t].type == THING_PLAYER3)
  2141.      p3 = TRUE;
  2142.       if (Things[ t].type == THING_PLAYER4)
  2143.      p4 = TRUE;
  2144.       if (Things[ t].type == THING_DEATHMATCH)
  2145.      dm++;
  2146.    }
  2147.    if (p1 == FALSE)
  2148.    {
  2149.       Beep();
  2150.       sprintf( msg1, "Warning: there is no player 1 starting point!  DOOM will crash if");
  2151.       sprintf( msg2, "you play with this level.  Do you really want to save it?");
  2152.       return Confirm( -1, -1, msg1, msg2);
  2153.    }
  2154.    if (Expert)
  2155.       return TRUE;
  2156.    if (p2 == FALSE || p3 == FALSE || p4 == FALSE)
  2157.    {
  2158.       if (p4 == FALSE)
  2159.     t = 4;
  2160.       if (p3 == FALSE)
  2161.     t = 3;
  2162.       if (p2 == FALSE)
  2163.     t = 2;
  2164.       sprintf( msg1, "Warning: there is no player %d starting point.  You will not be able to", t);
  2165.       sprintf( msg2, "use this level for multi-player games.  Press Y to return to the editor.");
  2166.       return !Confirm( -1, -1, msg1, msg2);
  2167.    }
  2168.    if (dm < 4)
  2169.    {
  2170.       if (dm == 0)
  2171.      sprintf( msg1, "Warning: there are no DeathMatch starting points.  You need at least four");
  2172.       else if (dm == 1)
  2173.      sprintf( msg1, "Warning: there is only one DeathMatch starting point.  You need at least four");
  2174.       else
  2175.      sprintf( msg1, "Warning: there are only %d DeathMatch starting points.  You need at least four", dm);
  2176.       sprintf( msg2, "starting points to play DeathMatch games.  Press Y to return to the editor.");
  2177.       return !Confirm( -1, -1, msg1, msg2);
  2178.    }
  2179.    return TRUE;
  2180. }
  2181.  
  2182.  
  2183.  
  2184. /*
  2185.    insert a standard object at given position
  2186. */
  2187.  
  2188. void InsertStandardObject( BCINT x0, BCINT y0, BCINT xpos, BCINT ypos) /* SWAP! */
  2189. {
  2190.    BCINT sector;
  2191.    BCINT choice, n;
  2192.    BCINT a, b;
  2193.  
  2194.    /* show where the object will be inserted */
  2195.    if (UseMouse)
  2196.       HideMousePointer();
  2197.    DrawPointer( TRUE);
  2198.    if (UseMouse)
  2199.       ShowMousePointer();
  2200.    /* are we inside a Sector? */
  2201.    sector = GetCurObject( OBJ_SECTORS, xpos, ypos, xpos, ypos);
  2202.    if (sector >= 0)
  2203.       choice = DisplayMenu( x0, y0, ((x0 == -1) ? "Insert a pre-defined object (inside a Sector)" : NULL),
  2204.                 "Rectangle",
  2205.                 "Polygon (N sides)",
  2206.                 "Stairs",
  2207.                 "Hidden stairs",
  2208.                 NULL);
  2209.    else
  2210.       choice = DisplayMenu( x0, y0, ((x0 == -1) ? "Insert a pre-defined object (outside)" : NULL),
  2211.                 "Rectangle",
  2212.                 "Polygon (N sides)",
  2213.                 NULL);
  2214.    /* !!!! Should also check for overlapping objects (sectors) !!!! */
  2215.    switch (choice)
  2216.    {
  2217.    case 1:
  2218.       a = 256;
  2219.       b = 128;
  2220.       if (Input2Numbers( -1, -1, "Width", "Height", 2000, 2000, &a, &b))
  2221.       {
  2222.      if (a < 8)
  2223.         a = 8;
  2224.      if (b < 8)
  2225.         b = 8;
  2226.      xpos = xpos - a / 2;
  2227.      ypos = ypos - b / 2;
  2228.      InsertObject( OBJ_VERTEXES, -1, xpos, ypos);
  2229.      InsertObject( OBJ_VERTEXES, -1, xpos + a, ypos);
  2230.      InsertObject( OBJ_VERTEXES, -1, xpos + a, ypos + b);
  2231.      InsertObject( OBJ_VERTEXES, -1, xpos, ypos + b);
  2232.      if (sector < 0)
  2233.         InsertObject( OBJ_SECTORS, -1, 0, 0);
  2234.      for (n = 0; n < 4; n++)
  2235.      {
  2236.         InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  2237.         LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs;
  2238.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  2239.         if (sector >= 0)
  2240.            SideDefs[ NumSideDefs - 1].sector = sector;
  2241.      }
  2242.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  2243.      if (sector >= 0)
  2244.      {
  2245.         LineDefs[ NumLineDefs - 4].start = NumVertexes - 4;
  2246.         LineDefs[ NumLineDefs - 4].end = NumVertexes - 3;
  2247.         LineDefs[ NumLineDefs - 3].start = NumVertexes - 3;
  2248.         LineDefs[ NumLineDefs - 3].end = NumVertexes - 2;
  2249.         LineDefs[ NumLineDefs - 2].start = NumVertexes - 2;
  2250.         LineDefs[ NumLineDefs - 2].end = NumVertexes - 1;
  2251.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  2252.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 4;
  2253.      }
  2254.      else
  2255.      {
  2256.         LineDefs[ NumLineDefs - 4].start = NumVertexes - 1;
  2257.         LineDefs[ NumLineDefs - 4].end = NumVertexes - 2;
  2258.         LineDefs[ NumLineDefs - 3].start = NumVertexes - 2;
  2259.         LineDefs[ NumLineDefs - 3].end = NumVertexes - 3;
  2260.         LineDefs[ NumLineDefs - 2].start = NumVertexes - 3;
  2261.         LineDefs[ NumLineDefs - 2].end = NumVertexes - 4;
  2262.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 4;
  2263.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 1;
  2264.      }
  2265.       }
  2266.       break;
  2267.    case 2:
  2268.       a = 8;
  2269.       b = 128;
  2270.       if (Input2Numbers( -1, -1, "Number of sides", "Radius", 32, 2000, &a, &b))
  2271.       {
  2272.      if (a < 3)
  2273.         a = 3;
  2274.      if (b < 8)
  2275.         b = 8;
  2276.      InsertPolygonVertices( xpos, ypos, a, b);
  2277.      if (sector < 0)
  2278.         InsertObject( OBJ_SECTORS, -1, 0, 0);
  2279.      for (n = 0; n < a; n++)
  2280.      {
  2281.         InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  2282.         LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs;
  2283.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  2284.         if (sector >= 0)
  2285.            SideDefs[ NumSideDefs - 1].sector = sector;
  2286.      }
  2287.      ObjectsNeeded( OBJ_LINEDEFS, 0);
  2288.      if (sector >= 0)
  2289.      {
  2290.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  2291.         LineDefs[ NumLineDefs - 1].end = NumVertexes - a;
  2292.         for (n = 2; n <= a; n++)
  2293.         {
  2294.            LineDefs[ NumLineDefs - n].start = NumVertexes - n;
  2295.            LineDefs[ NumLineDefs - n].end = NumVertexes - n + 1;
  2296.         }
  2297.      }
  2298.      else
  2299.      {
  2300.         LineDefs[ NumLineDefs - 1].start = NumVertexes - a;
  2301.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 1;
  2302.         for (n = 2; n <= a; n++)
  2303.         {
  2304.            LineDefs[ NumLineDefs - n].start = NumVertexes - n + 1;
  2305.            LineDefs[ NumLineDefs - n].end = NumVertexes - n;
  2306.         }
  2307.      }
  2308.       }
  2309.       break;
  2310.    case 3:
  2311. /*
  2312.       a = 6;
  2313.       b = 16;
  2314.       if (Input2Numbers( -1, -1, "Number of steps", "Step height", 32, 48, &a, &b))
  2315.       {
  2316.      if (a < 2)
  2317.         a = 2;
  2318.      ObjectsNeeded( OBJ_SECTORS, 0);
  2319.      n = Sectors[ sector].ceilh;
  2320.      h = Sectors[ sector].floorh;
  2321.      if (a * b < n - h)
  2322.      {
  2323.         Beep();
  2324.         Notify( -1, -1, "The stairs are too high for this Sector", NULL);
  2325.         return;
  2326.      }
  2327.      xpos = xpos - 32;
  2328.      ypos = ypos - 32 * a;
  2329.      for (n = 0; n < a; n++)
  2330.      {
  2331.         InsertObject( OBJ_VERTEXES, -1, xpos, ypos);
  2332.         InsertObject( OBJ_VERTEXES, -1, xpos + 64, ypos);
  2333.         InsertObject( OBJ_VERTEXES, -1, xpos + 64, ypos + 64);
  2334.         InsertObject( OBJ_VERTEXES, -1, xpos, ypos + 64);
  2335.         ypos += 64;
  2336.         InsertObject( OBJ_SECTORS, sector, 0, 0);
  2337.         h += b;
  2338.         Sectors[ NumSectors - 1].floorh = h;
  2339.  
  2340.         InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  2341.         LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs;
  2342.         LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs + 1;
  2343.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  2344.         SideDefs[ NumSideDefs - 1].sector = sector;
  2345.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  2346.  
  2347.         ObjectsNeeded( OBJ_LINEDEFS, 0);
  2348.         LineDefs[ NumLineDefs - 4].start = NumVertexes - 4;
  2349.         LineDefs[ NumLineDefs - 4].end = NumVertexes - 3;
  2350.         LineDefs[ NumLineDefs - 3].start = NumVertexes - 3;
  2351.         LineDefs[ NumLineDefs - 3].end = NumVertexes - 2;
  2352.         LineDefs[ NumLineDefs - 2].start = NumVertexes - 2;
  2353.         LineDefs[ NumLineDefs - 2].end = NumVertexes - 1;
  2354.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  2355.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 4;
  2356.     }
  2357.       }
  2358.       break;
  2359. */
  2360.    case 4:
  2361.      NotImplemented();
  2362.      break;
  2363.    }
  2364. }
  2365.  
  2366.  
  2367.  
  2368. /*
  2369.    menu of miscellaneous operations
  2370. */
  2371.  
  2372. void MiscOperations( BCINT x0, BCINT y0, BCINT objtype, SelPtr *list) /* SWAP! */
  2373. {
  2374.    char   msg[ 80];
  2375.    BCINT    val;
  2376.    BCINT    angle, scale;
  2377.  
  2378.    sprintf( msg, "Rotate and scale %s", GetEditModeName( objtype));
  2379.    if (objtype == OBJ_VERTEXES)
  2380.    {
  2381.       val = DisplayMenu( x0, y0, ((x0 == -1) ? "Misc. Operations" : NULL),
  2382.              "Find first free tag number",
  2383.              msg,
  2384.              "Delete Vertex and join LineDefs",
  2385.              "Merge several Vertices into one",
  2386.              "Add a LineDef and split Sector",
  2387.              NULL);
  2388.    }
  2389.    else if (objtype == OBJ_LINEDEFS)
  2390.    {
  2391.       val = DisplayMenu( x0, y0, ((x0 == -1) ? "Misc. Operations" : NULL),
  2392.              "Find first free tag number",
  2393.              msg,
  2394.              "Split LineDef (add new Vertex)",
  2395.              "Split LineDefs and Sector",
  2396.           "Delete LineDefs and join Sectors",
  2397.              "Flip LineDef",
  2398.              "Swap SideDefs",
  2399.              "Align textures (Y offset)",
  2400.                          "Align textures (X offset)",
  2401.              NULL);
  2402.    }
  2403.    else if (objtype == OBJ_SECTORS)
  2404.    {
  2405.       val = DisplayMenu( x0, y0, ((x0 == -1) ? "Misc. Operations" : NULL),
  2406.              "Find first free tag number",
  2407.              msg,
  2408.              "Make door from Sector",
  2409.              "Make lift from Sector",
  2410.           "Distribute Sector floor heights",
  2411.              "Distribute Sector ceiling heights",
  2412.              NULL);
  2413.    }                                                         
  2414.    else
  2415.    {
  2416.       val = DisplayMenu( x0, y0, ((x0 == -1) ? "Misc. Operations" : NULL),
  2417.              "Find first free tag number",
  2418.              msg,
  2419.              NULL);
  2420.    }
  2421.    if (val > 1 && *list == NULL)
  2422.    {
  2423.       Beep();
  2424.       sprintf( msg, "You must select at least one %s", GetObjectTypeName( objtype));
  2425.       Notify( -1, -1, msg, NULL);
  2426.       return;
  2427.    }
  2428.    switch (val)
  2429.    {
  2430.    case 1:
  2431.       sprintf( msg, "First free tag number: %d", FindFreeTag());
  2432.       Notify( -1, -1, msg, NULL);
  2433.       break;
  2434.    case 2:
  2435.       if ((objtype == OBJ_THINGS || objtype == OBJ_VERTEXES) && (*list)->next == NULL)
  2436.       {
  2437.      Beep();
  2438.      sprintf( msg, "You must select more than one %s", GetObjectTypeName( objtype));
  2439.      Notify( -1, -1, msg, NULL);
  2440.      return;
  2441.       }
  2442.       angle = 0;
  2443.       scale = 100;
  2444.       if (Input2Numbers( -1, -1, "rotation angle (°)", "scale (%)", 360, 1000, &angle, &scale))
  2445.      RotateAndScaleObjects( objtype, *list, (double) angle * 0.0174533, (double) scale * 0.01);
  2446.       break;
  2447.    case 3:
  2448.       if (objtype == OBJ_VERTEXES)
  2449.       {
  2450.      DeleteVerticesJoinLineDefs( *list);
  2451.      ForgetSelection( list);
  2452.       }
  2453.       else if (objtype == OBJ_LINEDEFS)
  2454.       {
  2455.      SplitLineDefs( *list);
  2456.       }
  2457.       else if (objtype == OBJ_SECTORS)
  2458.       {
  2459.      if ((*list)->next != NULL)
  2460.      {
  2461.         Beep();
  2462.         Notify( -1, -1, "You must select exactly one Sector", NULL);
  2463.      }
  2464.      else
  2465.      {
  2466.         MakeDoorFromSector( (*list)->objnum);
  2467.      }
  2468.       }
  2469.       break;
  2470.    case 4:
  2471.       if (objtype == OBJ_VERTEXES)
  2472.       {
  2473.      MergeVertices( list);
  2474.       }
  2475.       else if (objtype == OBJ_LINEDEFS)
  2476.       {
  2477.      if ((*list)->next == NULL || (*list)->next->next != NULL)
  2478.      {
  2479.         Beep();
  2480.         Notify( -1, -1, "You must select exactly two LineDefs", NULL);
  2481.      }
  2482.      else
  2483.      {
  2484.         SplitLineDefsAndSector( (*list)->objnum, (*list)->next->objnum);
  2485.         ForgetSelection( list);
  2486.      }
  2487.       }
  2488.       else if (objtype == OBJ_SECTORS)
  2489.       {
  2490.      if ((*list)->next != NULL)
  2491.      {
  2492.         Beep();
  2493.         Notify( -1, -1, "You must select exactly one Sector", NULL);
  2494.      }
  2495.      else
  2496.      {
  2497.         MakeLiftFromSector( (*list)->objnum);
  2498.      }
  2499.       }
  2500.       break;
  2501.    case 5:
  2502.       if (objtype == OBJ_VERTEXES)
  2503.       {
  2504.      if ((*list)->next == NULL || (*list)->next->next != NULL)
  2505.      {
  2506.         Beep();
  2507.         Notify( -1, -1, "You must select exactly two Vertices", NULL);
  2508.      }
  2509.      else
  2510.      {
  2511.         SplitSector( (*list)->objnum, (*list)->next->objnum);
  2512.         ForgetSelection( list);
  2513.      }
  2514.       }
  2515.       else if (objtype == OBJ_LINEDEFS)
  2516.       {
  2517.          DeleteLineDefsJoinSectors( list);
  2518.       }
  2519.       else if (objtype == OBJ_SECTORS)
  2520.       {
  2521.            if ((*list)->next == NULL || (*list)->next->next == NULL)
  2522.            {
  2523.               Beep();
  2524.               Notify( -1, -1, "You must select three or more Sectors", NULL);
  2525.            }
  2526.            else
  2527.            {
  2528.               DistributeSectorFloors( *list);
  2529.            }
  2530.       }
  2531.       break;
  2532.    case 6:
  2533.       if (objtype == OBJ_LINEDEFS)
  2534.       {
  2535.          FlipLineDefs( *list, TRUE);
  2536.       }
  2537.       else if (objtype == OBJ_SECTORS)
  2538.       {
  2539.             if ((*list)->next == NULL || (*list)->next->next == NULL)
  2540.             {
  2541.                Beep();
  2542.                Notify( -1, -1, "You must select three or more Sectors", NULL);
  2543.             }
  2544.             else
  2545.             {
  2546.                DistributeSectorCeilings( *list);
  2547.             }
  2548.       }
  2549.       break;
  2550.    case 7:
  2551.       if (objtype == OBJ_LINEDEFS)
  2552.       {
  2553.          if (Expert || Confirm( -1, -1, "Warning: the Sector references are also swapped", "You may get strange results if you don't know what you are doing..."))
  2554.              FlipLineDefs( *list, FALSE);
  2555.        }
  2556.        break;
  2557.     case 8:
  2558.        if (objtype == OBJ_LINEDEFS)
  2559.        {
  2560.            SelPtr sdlist, cur;
  2561.  
  2562.            /* select all SideDefs */
  2563.            ObjectsNeeded( OBJ_LINEDEFS);
  2564.            sdlist = NULL;
  2565.            for (cur = *list; cur; cur = cur->next)
  2566.            {
  2567.               if (LineDefs[ cur->objnum].sidedef1 >= 0)
  2568.                  SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  2569.               if (LineDefs[ cur->objnum].sidedef2 >= 0)
  2570.                  SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef2);
  2571.           }
  2572.          /* align the textures along the Y axis (height) */
  2573.          AlignTexturesY( &sdlist);
  2574.        }
  2575.     case 9:
  2576.        if (objtype == OBJ_LINEDEFS)
  2577.        {
  2578.       SelPtr sdlist, cur;
  2579.  
  2580.       /* select all SideDefs */
  2581.       ObjectsNeeded( OBJ_LINEDEFS,0);
  2582.       sdlist = NULL;
  2583.       for (cur = *list; cur; cur = cur->next)
  2584.       {
  2585.          if (LineDefs[ cur->objnum].sidedef1 >= 0)
  2586.             SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  2587.          if (LineDefs[ cur->objnum].sidedef2 >= 0)
  2588.             SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef2);
  2589.       }
  2590.       /* align the textures along the X axis (width) */
  2591.       AlignTexturesX( &sdlist);
  2592.        }
  2593.        break;
  2594.    }
  2595. }
  2596.  
  2597.  
  2598.  
  2599. /*
  2600.    display a "Preferences" menu (change default textures, etc.)
  2601. */
  2602.  
  2603. void Preferences( BCINT x0, BCINT y0)
  2604. {
  2605.    char   *menustr[ 30];
  2606.    BCINT     dummy[ 30];
  2607.    BCINT     n, val;
  2608.    char    texname[ 9];
  2609.  
  2610.    if (x0 < 0)
  2611.       x0 = (ScrMaxX - 50 * 8 - 19) / 2;
  2612.    if (y0 < 0)
  2613.       y0 = (ScrMaxY - 5 * 10 - 28) / 2;
  2614.    for (n = 0; n < 8; n++)
  2615.       menustr[ n] = (char*)GetMemory( 80);
  2616.    sprintf( menustr[ 7], "Preferences");
  2617.    sprintf( menustr[ 1], "Change default \"upper\" texture (Current: %s)", DefaultUpperTexture);
  2618.    sprintf( menustr[ 2], "Change default \"lower\" texture (Current: %s)", DefaultLowerTexture);
  2619.    sprintf( menustr[ 3], "Change default floor texture   (Current: %s)", DefaultFloorTexture);
  2620.    sprintf( menustr[ 4], "Change default ceiling texture (Current: %s)", DefaultCeilingTexture);
  2621.    sprintf( menustr[ 5], "Change default floor height    (Current: %d)", DefaultFloorHeight);
  2622.    sprintf( menustr[ 6], "Change default ceiling height  (Current: %d)", DefaultCeilingHeight);
  2623.    val = DisplayMenuArray( x0, y0, menustr[ 7], 7, NULL, menustr, dummy);
  2624.    for (n = 0; n < 8; n++)
  2625.       FreeMemory( menustr[ n]);
  2626.    switch (val)
  2627.    {
  2628.    case 1:
  2629.       strcpy( texname, DefaultWallTexture);
  2630.       ChooseWallTexture( x0 + 42, y0 + 34, "Choose a wall texture", NumWTexture, WTexture, texname);
  2631.       if (strlen( texname) > 0)
  2632.      strcpy( DefaultWallTexture, texname);
  2633.       break;
  2634.    case 2:
  2635.       strcpy( texname, DefaultUpperTexture);
  2636.       ChooseWallTexture( x0 + 42, y0 + 34, "Choose a wall texture", NumWTexture, WTexture, texname);
  2637.       if (strlen( texname) > 0)
  2638.      strcpy( DefaultUpperTexture, texname);
  2639.       break;
  2640.    case 3:
  2641.       strcpy( texname, DefaultLowerTexture);
  2642.       ChooseWallTexture( x0 + 42, y0 + 34, "Choose a wall texture", NumWTexture, WTexture, texname);
  2643.       if (strlen( texname) > 0)
  2644.      strcpy( DefaultLowerTexture, texname);
  2645.       break;
  2646.    case 4:
  2647.       strcpy( texname, DefaultFloorTexture);
  2648.       ChooseFloorTexture( x0 + 42, y0 + 44, "Choose a floor texture", NumFTexture, FTexture, texname);
  2649.       if (strlen( texname) > 0)
  2650.      strcpy( DefaultFloorTexture, texname);
  2651.       break;
  2652.    case 5:
  2653.       strcpy( texname, DefaultCeilingTexture);
  2654.       ChooseFloorTexture( x0 + 42, y0 + 54, "Choose a ceiling texture", NumFTexture, FTexture, texname);
  2655.       if (strlen( texname) > 0)
  2656.      strcpy( DefaultCeilingTexture, texname);
  2657.       break;
  2658.    case 6:
  2659.       val = InputIntegerValue( x0 + 42, y0 + 64, -512, 511, DefaultFloorHeight);
  2660.       if (val >= -512)
  2661.      DefaultFloorHeight = val;
  2662.       break;
  2663.    case 7:
  2664.       val = InputIntegerValue( x0 + 42, y0 + 74, -512, 511, DefaultCeilingHeight);
  2665.       if (val >= -512)
  2666.      DefaultCeilingHeight = val;
  2667.       break;
  2668.    }               
  2669. }
  2670.  
  2671.  
  2672.  
  2673. /* end of file */
  2674.