view src/objinfo.cc @ 25:8eaf72e2041b

Reindent the source using GNU indent and "indent -i4 -bli0 -npcs -nprs -npsl". Fix the problems introduced afterwards.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 24 Sep 2011 14:16:04 +0300
parents f1fb248bf997
children a68786b9c74b
line wrap: on
line source

/*
 *	objinfo.cc
 *	AYM 1998-09-20
 */


/*
This file is part of Yadex.

Yadex incorporates code from DEU 5.21 that was put in the public domain in
1994 by Raphaël Quinet and Brendon Wyber.

The rest of Yadex is Copyright © 1997-2003 André Majorel and others.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307, USA.
*/


#include "yadex.h"
#include <vector>
#include <algorithm>
#include <X11/Xlib.h>
#include "disppic.h"
#include "flats.h"		// DisplayFloorTexture()
#include "game.h"		// THINGDEF_SPECTRAL
#include "gamesky.h"		// is_sky()
#include "gfx.h"
#include "img.h"
#include "imgspect.h"
#include "l_super.h"
#include "levels.h"
#include "objid.h"
#include "objinfo.h"
#include "pic2img.h"
#include "sticker.h"
#include "things.h"
#include "wadres.h"


static const int sprite_width = 90;
static const int sprite_height = 90;


/*
 *	Extraf - one item in the list of EDGE extrafloors
 */
class Extraf
{
    public: Extraf(obj_no_t sector, wad_name_t & tex, wad_z_t height)
    {
	this->sector = sector;
	memcpy(this->tex, &tex, sizeof this->tex);
	this->height = height;
    }

    bool operator<(const Extraf & other) const
    {
	if (height < other.height)
	    return true;
	else if (height == other.height && sector < other.sector)
	    return true;
	return false;
    }

    wad_z_t height;		// To sort by increasing floor height
    obj_no_t sector;		// Sector# (for heights, flats and light level)
    wad_tex_name_t tex;		// Texture (middle tex of first sidedef)
};


static void get_extrafloors(std::vector < Extraf > &list, wad_tag_t tag);


objinfo_c::objinfo_c()
{
    for (size_t n = 0; n < MAX_BOXES; n++)
	box_disp[n] = false;
    obj_no = OBJ_NO_NONE;
    obj_no_disp = OBJ_NO_NONE;
    prev_sector = OBJ_NO_NONE;
    out_y1 = 0;
}


void objinfo_c::draw()
{
    int n;
    int sd1 = OBJ_NO_NONE;
    int sd2 = OBJ_NO_NONE;
    int s1 = OBJ_NO_NONE;
    int s2 = OBJ_NO_NONE;
    int x0, y0;			// Outer top left corner
    int ix0, iy0;		// Inner top left corner
    int width;
    int height;

    // Am I already drawn ?
    if (!is_obj(obj_no) || obj_no == obj_no_disp && obj_type == obj_type_disp)
	return;

    // Does the box need to be redrawn ?
    if (obj_type != obj_type_disp)
	box_disp[0] = false;

    // The caller should have called set_y1() before !
    if (!out_y1)
	return;

    switch (obj_type)
    {
    case OBJ_THINGS:
	{
	    const int columns = 27;
	    width = 2 * BOX_BORDER + 3 * WIDE_HSPACING + columns * FONTW
		+ 2 * HOLLOW_BORDER + sprite_width;
	    height = 2 * BOX_BORDER + 2 * WIDE_VSPACING
		+ y_max((int) (6.5 * FONTH), sprite_height);
	    x0 = 0;
	    y0 = out_y1 - height + 1;
	    ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	    iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
	    int ix1 = x0 + width - 1 - BOX_BORDER - WIDE_HSPACING;
	    int iy1 = y0 + height - 1 - BOX_BORDER - WIDE_VSPACING;
	    if (box_disp[0])
	    {
		push_colour(WINBG);
		DrawScreenBox(ix0, iy0, ix0 + columns * FONTW - 1, iy1);
		pop_colour();
	    }
	    else
		DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	    if (obj_no < 0)
	    {
		const char *message = "(no thing selected)";
		set_colour(WINFG_DIM);
		DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			       y0 + (height - FONTH) / 2, message);
		break;
	    }
	    set_colour(WINTITLE);
	    DrawScreenText(ix0, iy0, "Thing #%d", obj_no);
	    const bool invalid_type = !is_thing_type(Things[obj_no].type);
	    set_colour(WINFG);
	    DrawScreenText(-1, iy0 + (int) (1.5 * FONTH), 0);
	    DrawScreenText(-1, -1, "\1Coords:\2 (%d, %d)",
			   Things[obj_no].xpos, Things[obj_no].ypos);
	    DrawScreenString(-1, -1, "\1Type:   ");
	    if (invalid_type)
		push_colour(CLR_ERROR);
	    DrawScreenText(-2, -2, "%d", Things[obj_no].type);
	    if (invalid_type)
		pop_colour();
	    DrawScreenString(-1, -1, "\1Desc:   ");
	    if (invalid_type)
		push_colour(CLR_ERROR);
	    DrawScreenText(-2, -2, "%.19s",
			   get_thing_name(Things[obj_no].type));
	    if (invalid_type)
		pop_colour();
	    DrawScreenText(-1, -1, "\1Angle:\2  %s",
			   GetAngleName(Things[obj_no].angle));
	    DrawScreenText(-1, -1, "\1Flags:\2  %s",
			   GetWhenName(Things[obj_no].when));

	    // Show the corresponding sprite
	    {
		int sx1 = ix1 + 1 - HOLLOW_BORDER;
		int sy1 = iy1 + 1 - HOLLOW_BORDER;
		int sx0 = sx1 + 1 - sprite_width;
		int sy0 = sy1 + 1 - sprite_height;
		draw_box_border(sx0 - HOLLOW_BORDER, sy0 - HOLLOW_BORDER,
				sprite_width + 2 * HOLLOW_BORDER,
				sprite_height + 2 * HOLLOW_BORDER,
				HOLLOW_BORDER, 0);
		const char *sprite_root =
		    get_thing_sprite(Things[obj_no].type);
		char flags = get_thing_flags(Things[obj_no].type);
		if (sprite_root == NULL)
		{
		    push_colour(WINBG);
		    DrawScreenBox(sx0, sy0, sx1, sy1);
		    pop_colour();
		    set_colour(WINFG_DIM);
		    DrawScreenText(sx0 + (sprite_width - 2 * FONTW) / 2,
				   sy0 + sprite_height / 2 + 1 - FONTH, "no");
		    DrawScreenText(sx0 + (sprite_width - 6 * FONTW) / 2,
				   sy0 + sprite_height / 2 + 1, "sprite");
		}
		else
		{
		    Lump_loc loc;
		    Img img(sprite_width, sprite_height, false);
		    Sticker sticker;
		    wad_res.sprites.loc_by_root(sprite_root, loc);
		    if (loc.wad == 0
			|| LoadPicture(img, sprite_root, loc, INT_MIN,
				       INT_MIN))
		    {
			push_colour(WINBG);
			DrawScreenBox(sx0, sy0, sx1, sy1);
			pop_colour();
			set_colour(CLR_ERROR);
			DrawScreenString(sx0 +
					 (sprite_width -
					  strlen(sprite_root) * FONTW) / 2,
					 sy0 + sprite_height / 2 + 1 -
					 3 * FONTH / 2, sprite_root);
			DrawScreenText(sx0 + (sprite_width - 3 * FONTW) / 2,
				       sy0 + sprite_height / 2 + 1 -
				       FONTH / 2, "not");
			DrawScreenText(sx0 + (sprite_width - 5 * FONTW) / 2,
				       sy0 + sprite_height / 2 + 1 +
				       FONTH / 2, "found");
		    }
		    else
		    {
			if (flags & THINGDEF_SPECTRAL)
			    spectrify_img(img);
			sticker.load(img, true);
			sticker.draw(drw, 't', sx0, sy0);
		    }
		}
	    }
	}
	break;

    case OBJ_LINEDEFS:
	// Linedef
	width = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 29 * FONTW;
	height = 2 * BOX_BORDER + 2 * WIDE_VSPACING + (int) (8.5 * FONTH);
	x0 = 0;
	y0 = out_y1 - height + 1;
	ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
	// Ignore box_disp -- always redraw the whole box
	DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	if (obj_no >= 0)
	{
	    set_colour(WINTITLE);
	    DrawScreenText(ix0, iy0, "Linedef #%d", obj_no);
	    set_colour(WINFG);
	    DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
			   "\1Flags:\2    %.19s",
			   GetLineDefFlagsName(LineDefs[obj_no].flags));
	    DrawScreenText(-1, -1, "\1Type:\2 %3d %.19s",
			   LineDefs[obj_no].type,
			   GetLineDefTypeName(LineDefs[obj_no].type));
	    {
		int tag = LineDefs[obj_no].tag;
		int first_sector = NumSectors;
		int second_sector = NumSectors;
		if (tag != 0)
		{
		    for (int n = 0; n < NumSectors; n++)
			if (Sectors[n].tag == tag)
			{
			    if (first_sector >= NumSectors)
				first_sector = n;
			    else
			    {
				second_sector = n;
				break;
			    }
			}
		}
		if (first_sector < NumSectors && second_sector < NumSectors)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (#%d+)", tag,
				   first_sector);
		else if (first_sector < NumSectors)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (#%d)", tag,
				   first_sector);
		else
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (none)", tag);
	    }
	    s1 = LineDefs[obj_no].start;
	    s2 = LineDefs[obj_no].end;
	    DrawScreenText(-1, -1, "\1Vertices:\2 (#%d, #%d)", s1, s2);
	    n = ComputeDist(Vertices[s2].x - Vertices[s1].x,
			    Vertices[s2].y - Vertices[s1].y);
	    DrawScreenText(-1, -1, "\1Length:\2   %d", n);
	    sd1 = LineDefs[obj_no].sidedef1;
	    sd2 = LineDefs[obj_no].sidedef2;
	    DrawScreenText(-1, -1, "\1" "1st sd:\2   #%d", sd1);
	    DrawScreenText(-1, -1, "\1" "2nd sd:\2   #%d", sd2);
	    if (sd1 >= 0)
		s1 = SideDefs[sd1].sector;
	    else
		s1 = -1;
	    if (sd2 >= 0)
		s2 = SideDefs[sd2].sector;
	    else
		s2 = -1;
	}
	else
	{
	    const char *message = "(no linedef selected)";
	    set_colour(WINFG_DIM);
	    DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			   y0 + (height - FONTH) / 2, message);
	}

	// 1st sidedef
	x0 += width;
	width = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 16 * FONTW;
	ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	y0 = out_y1 - height + 1;
	// Ignore box_disp -- always redraw the whole box
	DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	if (obj_no >= 0 && sd1 >= 0)
	{
	    set_colour(WINTITLE);
	    DrawScreenText(ix0, iy0, "Sidedef1 #%d", sd1);

	    if (s1 >= 0 && s2 >= 0 && Sectors[s1].ceilh > Sectors[s2].ceilh
		&& !(is_sky(Sectors[s1].ceilt) && is_sky(Sectors[s2].ceilt)))
	    {
		if (SideDefs[sd1].tex1[0] == '-'
		    && SideDefs[sd1].tex1[1] == '\0')
		    set_colour(CLR_ERROR);
		else
		    set_colour(WINFG);
	    }
	    else
		set_colour(WINFG_DIM);
	    DrawScreenText(-1, iy0 + (int) (1.5 * FONTH), "\1Upper:\2  %.*s",
			   WAD_TEX_NAME, SideDefs[sd1].tex1);

	    if (sd2 < 0
		&& SideDefs[sd1].tex3[0] == '-'
		&& SideDefs[sd1].tex3[1] == '\0')
		set_colour(CLR_ERROR);
	    else
		set_colour(WINFG);
	    DrawScreenText(-1, -1,
			   "\1Middle:\2 %.*s", WAD_TEX_NAME,
			   SideDefs[sd1].tex3);

	    if (s1 >= 0 && s2 >= 0 && Sectors[s1].floorh < Sectors[s2].floorh
		&& !(is_sky(Sectors[s1].floort)
		     && is_sky(Sectors[s2].floort)))
	    {
		if (SideDefs[sd1].tex2[0] == '-'
		    && SideDefs[sd1].tex2[1] == '\0')
		    set_colour(CLR_ERROR);
		else
		    set_colour(WINFG);
	    }
	    else
		set_colour(WINFG_DIM);
	    DrawScreenText(-1, -1, "\1Lower:\2  %.*s",
			   WAD_TEX_NAME, SideDefs[sd1].tex2);

	    set_colour(WINFG);
	    DrawScreenText(-1, -1, "\1X-ofs:\2  %d", SideDefs[sd1].xoff);
	    DrawScreenText(-1, -1, "\1Y-ofs:\2  %d", SideDefs[sd1].yoff);
	    DrawScreenText(-1, -1, "\1Sector:\2 #%d", s1);
	}
	else
	{
	    const char *message = "(no 1st sidedef)";
	    set_colour(CLR_ERROR);
	    DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			   y0 + (height - FONTH) / 2, message);
	}

	// 2nd sidedef
	x0 += width;
	ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	y0 = out_y1 - height + 1;
	// Ignore box_disp -- always redraw the whole box
	DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	if (obj_no >= 0 && sd2 >= 0)
	{
	    set_colour(WINTITLE);
	    DrawScreenText(ix0, iy0, "Sidedef2 #%d", sd2);
	    set_colour(WINFG);
	    const char *tex_name;

	    tex_name = SideDefs[sd2].tex1;	// Upper texture
	    if (s1 >= 0 && s2 >= 0 && Sectors[s2].ceilh > Sectors[s1].ceilh
		&& !(is_sky(Sectors[s1].ceilt) && is_sky(Sectors[s2].ceilt)))
	    {
		if (tex_name[0] == '-' && tex_name[1] == '\0')
		    set_colour(CLR_ERROR);
		else
		    set_colour(WINFG);
	    }
	    else
		set_colour(WINFG_DIM);
	    DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
			   "\1Upper:\2  %.*s", WAD_TEX_NAME, tex_name);

	    tex_name = SideDefs[sd2].tex3;	// Middle texture
	    set_colour(WINFG);
	    DrawScreenText(-1, -1,
			   "\1Middle:\2 %.*s", WAD_TEX_NAME, tex_name);

	    tex_name = SideDefs[sd2].tex2;	// Lower texture
	    if (s1 >= 0 && s2 >= 0 && Sectors[s2].floorh < Sectors[s1].floorh
		&& !(is_sky(Sectors[s1].floort)
		     && is_sky(Sectors[s2].floort)))
	    {
		if (tex_name[0] == '-' && tex_name[1] == '\0')
		    set_colour(CLR_ERROR);
		else
		    set_colour(WINFG);
	    }
	    else
		set_colour(WINFG_DIM);
	    DrawScreenText(-1, -1, "\1Lower:\2  %.*s", WAD_TEX_NAME,
			   tex_name);

	    set_colour(WINFG);
	    DrawScreenText(-1, -1, "\1X-ofs:\2  %d", SideDefs[sd2].xoff);
	    DrawScreenText(-1, -1, "\1Y-ofs:\2  %d", SideDefs[sd2].yoff);
	    DrawScreenText(-1, -1, "\1Sector:\2 #%d", s2);
	}
	else
	{
	    const char *message = "(no 2nd sidedef)";
	    // If the "2" flag is set, there must be a second sidedef
	    if (LineDefs[obj_no].flags & 0x04)	// FIXME hard-coded
		set_colour(CLR_ERROR);
	    else
		set_colour(WINFG_DIM);
	    DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			   y0 + (height - FONTH) / 2, message);
	}

	// Superimposed linedefs
	{
	    Superimposed_ld super;
	    super.set(obj_no);
	    obj_no_t l = super.get();
	    int iy1;

	    if (l != -1 || box_disp[3])
	    {
		x0 += width;
		width = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 12 * FONTW;
		ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
		iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
		iy1 = y0 + height - 1 - BOX_BORDER - WIDE_VSPACING;
		DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	    }
	    if (l != -1)
	    {
		box_disp[3] = true;
		set_colour(WINTITLE);
		DrawScreenString(ix0, iy0, "Superimposed");
		set_colour(WINFG);
		iy0 += int (1.5 * FONTH);
		while (l != -1)
		{
		    if (iy0 + FONTH - 1 <= iy1)
			DrawScreenText(ix0, iy0, "#%d", l);
		    /* Too many linedefs, replace the last one by "(more)".
		       Not elegant, but it makes the code simpler. */
		    else
		    {
			iy0 -= FONTH;
			set_colour(WINBG);
			DrawScreenBox(ix0, iy0, ix0 + 12 * FONTW - 1,
				      iy0 + FONTH - 1);
			set_colour(WINFG);
			DrawScreenString(ix0, iy0, "(more)");
			break;
		    }
		    iy0 += FONTH;
		    l = super.get();
		}
	    }
	}
	break;

    case OBJ_VERTICES:
	width = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 29 * FONTW;
	height = 2 * BOX_BORDER + 2 * WIDE_VSPACING + (int) (2.5 * FONTH);
	x0 = 0;
	y0 = out_y1 - height + 1;
	ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
	// Ignore box_disp -- always redraw the whole box
	DrawScreenBox3D(x0, y0, x0 + width - 1, y0 + height - 1);
	if (obj_no < 0)
	{
	    const char *message = "(no vertex selected)";
	    set_colour(WINFG_DIM);
	    DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			   y0 + (height - FONTH) / 2, message);
	    break;
	}
	set_colour(WINTITLE);
	DrawScreenText(ix0, iy0, "Vertex #%d", obj_no);
	set_colour(WINFG);
	DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
		       "\1Coordinates:\2 (%d, %d)", Vertices[obj_no].x,
		       Vertices[obj_no].y);
	break;

    case OBJ_SECTORS:
	{
	    int x1, y1;
	    int ix1, iy1;
	    const int columns = 24;
	    width = BOX_BORDER
		+ WIDE_HSPACING
		+ columns * FONTW
		+ WIDE_HSPACING
		+ HOLLOW_BORDER
		+ DOOM_FLAT_WIDTH
		+ HOLLOW_BORDER + WIDE_HSPACING + BOX_BORDER;
	    height = 2 * BOX_BORDER
		+ 2 * WIDE_VSPACING
		+ y_max((unsigned) (9.5 * FONTH),
			WIDE_HSPACING + 4 * HOLLOW_BORDER +
			2 * DOOM_FLAT_HEIGHT);
	    x0 = 0;
	    y0 = out_y1 - height + 1;
	    x1 = x0 + width - 1;
	    y1 = y0 + height - 1;
	    ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
	    iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
	    ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
	    iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
	    if (box_disp[0])
	    {
		push_colour(WINBG);
		DrawScreenBox(ix0, iy0, ix0 + columns * FONTW - 1, iy1);
		pop_colour();
	    }
	    else
		DrawScreenBox3D(x0, y0, x1, y1);
	    if (obj_no < 0)
	    {
		const char *const message = "(no sector selected)";
		set_colour(WINFG_DIM);
		DrawScreenText(x0 + (width - FONTW * strlen(message)) / 2,
			       y0 + (height - FONTH) / 2, message);
		break;
	    }
	    set_colour(WINTITLE);
	    DrawScreenText(ix0, iy0, "Sector #%d", obj_no);
	    set_colour(WINFG);
	    const struct Sector *sec = Sectors + obj_no;
	    if (prev_sector >= 0 && prev_sector != obj_no)
	    {
		DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
			       "\1Floor:\2    %d (%+d)",
			       sec->floorh, sec->floorh - prev_floorh);
		DrawScreenText(-1, -1, "\1Ceiling:\2  %d (%+d)",
			       sec->ceilh, sec->ceilh - prev_ceilh);
	    }
	    else
	    {
		DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
			       "\1Floor:\2    %d", sec->floorh);
		DrawScreenText(-1, -1, "\1Ceiling:\2  %d", sec->ceilh);
	    }
	    DrawScreenText(-1, -1, "\1Headroom:\2 %d",
			   sec->ceilh - sec->floorh);
	    DrawScreenText(-1, -1, "\1Floor:\2    %.*s", WAD_FLAT_NAME,
			   sec->floort);
	    DrawScreenText(-1, -1, "\1Ceiling:\2  %.*s", WAD_FLAT_NAME,
			   sec->ceilt);
	    DrawScreenText(-1, -1, "\1Light:\2    %d", sec->light);
	    DrawScreenText(-1, -1, "\1Type:\2 %3d %.14s",
			   sec->special, GetSectorTypeName(sec->special));
	    {
		int tag = sec->tag;
		int first_ld = NumLineDefs;
		int second_ld = NumLineDefs;

		if (tag != 0)
		{
		    for (n = 0; n < NumLineDefs; n++)
			if (LineDefs[n].tag == tag)
			{
			    if (first_ld >= NumLineDefs)
				first_ld = n;
			    else
			    {
				second_ld = n;
				break;
			    }
			}
		}
		if (first_ld < NumLineDefs && second_ld < NumLineDefs)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (#%d+)", tag,
				   first_ld);
		else if (first_ld < NumLineDefs)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (#%d)", tag,
				   first_ld);
		else if (tag == 99 || tag == 999)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (stairs?)", tag);
		else if (tag == 666)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (lower@end)",
				   tag);
		else if (tag == 667)
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (raise@end)",
				   tag);
		else
		    DrawScreenText(-1, -1, "\1Tag:\2      %d (none)", tag);
	    }
	    {
		hookfunc_comm_t block;

		// Display the floor texture in the bottom right corner
		block.x1 = ix1;
		block.x0 =
		    block.x1 - (DOOM_FLAT_WIDTH + 2 * HOLLOW_BORDER - 1);
		block.y1 = iy1;
		block.y0 =
		    block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
		block.name = sec->floort;
		display_flat_depressed(&block);

		// Display the ceiling texture above the floor texture
		block.y1 = block.y0 - (WIDE_VSPACING + 1);
		block.y0 =
		    block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
		block.name = sec->ceilt;
		display_flat_depressed(&block);
	    }

	    // Show all EDGE extrafloors for this sector
	    {
		x0 += width;
		const int columns2 = 16;
		const int width2 = BOX_BORDER
		    + WIDE_HSPACING
		    + columns2 * FONTW
		    + WIDE_HSPACING
		    + HOLLOW_BORDER
		    + DOOM_FLAT_WIDTH
		    + HOLLOW_BORDER + WIDE_HSPACING + BOX_BORDER;
		std::vector < Extraf > v;
		get_extrafloors(v, sec->tag);
		size_t e;
		for (e = 0; e < v.size() && e + 1 < MAX_BOXES;
		     e++, x0 += width2)
		{
		    const Extraf & i = v[e];
		    obj_no_t dsecno = i.sector;
		    bool thick = (*i.tex != '\0');
		    const struct Sector *dsec = Sectors + dsecno;
		    x1 = x0 + width2 - 1;
		    y1 = y0 + height - 1;
		    ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
		    iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
		    ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
		    iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
		    if (box_disp[e + 1])	// FIXME
		    {
			push_colour(WINBG);
			DrawScreenBox(ix0, iy0, ix0 + columns2 * FONTW - 1,
				      iy1);
			pop_colour();
		    }
		    else
		    {
			DrawScreenBox3D(x0, y0, x1, y1);
			box_disp[e + 1] = true;
		    }
		    if (!is_sector(dsecno))	// Can't happen
			continue;
		    set_colour(WINTITLE);
		    if (thick)
			DrawScreenText(ix0, iy0, "Thick #%d", dsecno);
		    else
			DrawScreenText(ix0, iy0, "Thin #%d", dsecno);
		    set_colour(WINFG);
		    if (thick)
		    {
			DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
				       "\1Bottom:\2 %d", dsec->floorh);
			DrawScreenText(-1, -1, "\1Top:\2    %d", dsec->ceilh);
			DrawScreenText(-1, -1, "\1Thick:\2  %d",
				       dsec->ceilh - dsec->floorh);
			DrawScreenText(-1, -1, "\1Bottom:\2 %.*s",
				       WAD_FLAT_NAME, dsec->floort);
			DrawScreenText(-1, -1, "\1Top:\2    %.*s",
				       WAD_FLAT_NAME, dsec->ceilt);
		    }
		    else
		    {
			DrawScreenText(-1, iy0 + (int) (1.5 * FONTH),
				       "\1Height:\2 %d", dsec->floorh);
			DrawScreenText(-1, -1, "\1Flat:\2   %.*s",
				       WAD_FLAT_NAME, dsec->floort);
		    }
		    DrawScreenText(-1, -1, "\1Shadow:\2 %d", dsec->light);
		    DrawScreenText(-1, -1, "\1Type:\2   %d", dsec->special);
		    if (thick)
			DrawScreenText(-1, -1, "\1Side:\2   %.*s",
				       WAD_TEX_NAME, i.tex);
		    {
			hookfunc_comm_t block;

			// Display the top texture in the bottom right corner
			block.x1 = ix1;
			block.x0 =
			    block.x1 - (DOOM_FLAT_WIDTH + 2 * HOLLOW_BORDER -
					1);
			block.y1 = iy1;
			block.y0 =
			    block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER -
					1);
			block.name = dsec->floort;
			display_flat_depressed(&block);

			// Display the bottom texture above the floor texture
			block.y1 = block.y0 - (WIDE_VSPACING + 1);
			block.y0 =
			    block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER -
					1);
			if (thick)
			{
			    block.name = dsec->ceilt;
			    display_flat_depressed(&block);
			}
			else
			{
			    push_colour(WINBG);
			    DrawScreenBoxwh(block.x0, block.y0,
					    DOOM_FLAT_WIDTH +
					    2 * HOLLOW_BORDER,
					    DOOM_FLAT_HEIGHT +
					    2 * HOLLOW_BORDER);
			    pop_colour();
			}
		    }
		}
		// Clear out remaining boxes
		for (; e + 1 < MAX_BOXES && box_disp[e + 1];
		     e++, x0 += width2)
		{
		    x1 = x0 + width2 - 1;
		    y1 = y0 + height - 1;
		    ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
		    iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
		    ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
		    iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
		    push_colour(WINBG);
		    DrawScreenBox(ix0, iy0, ix1, iy1);
		    pop_colour();
		}
	    }
	    break;
	}
    }

    if (obj_type == OBJ_SECTORS)
    {
	if (obj_no != prev_sector)
	    prev_sector = obj_no;
	if (obj_no >= 0)
	{
	    prev_floorh = Sectors[obj_no].floorh;
	    prev_ceilh = Sectors[obj_no].ceilh;
	}
    }
    box_disp[0] = true;
    obj_no_disp = obj_no;
    obj_type_disp = obj_type;
}


/*
 *	get_extrafloors - get list of EDGE extrafloors for tag
 *
 *	Put in <v> a list of the extrafloors for tag <tag>,
 *	sorted by floor height major, sector number minor. The
 *	previous content of <v> is lost. Each Extraf object in
 *	<v> is set up in the following way :
 *
 *	- <sector> is set to the number of the dummy sector,
 *
 *	- <tex> is set to the side texture of the extrafloor, or
 *	  "" if it's a thin extrafloor,
 *
 *	- <height> is the to the floor height of the dummy
 *	  sector.
 */
static void get_extrafloors(std::vector < Extraf > &v, wad_tag_t tag)
{
    v.clear();
    for (obj_no_t l = 0; l < NumLineDefs; l++)
    {
	if (LineDefs[l].tag == tag && LineDefs[l].type >= 400 && LineDefs[l].type <= 407)	// FIXME
	{
	    obj_no_t sd = LineDefs[l].sidedef1;
	    if (!is_sidedef(sd) || !is_sector(SideDefs[sd].sector))	// Paranoia
		continue;
	    wad_tex_name_t tex;
	    if (LineDefs[l].type == 400)
		memcpy(tex, SideDefs[sd].tex3, sizeof tex);
	    else if (LineDefs[l].type == 401)	// side_upper
		memcpy(tex, SideDefs[sd].tex1, sizeof tex);
	    else if (LineDefs[l].type == 402)	// side_lower
		memcpy(tex, SideDefs[sd].tex2, sizeof tex);
	    else
		memset(tex, '\0', sizeof tex);
	    v.push_back(Extraf(SideDefs[sd].sector,
			       tex, Sectors[SideDefs[sd].sector].floorh));
	}
    }
    sort(v.begin(), v.end());
}