1 /*
2  *	objinfo.cc
3  *	AYM 1998-09-20
4  */
5 
6 
7 /*
8 This file is part of Yadex.
9 
10 Yadex incorporates code from DEU 5.21 that was put in the public domain in
11 1994 by Rapha�l Quinet and Brendon Wyber.
12 
13 The rest of Yadex is Copyright � 1997-2003 Andr� Majorel and others.
14 
15 This program is free software; you can redistribute it and/or modify it under
16 the terms of the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any later
18 version.
19 
20 This program is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23 
24 You should have received a copy of the GNU General Public License along with
25 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 Place, Suite 330, Boston, MA 02111-1307, USA.
27 */
28 
29 
30 #include "yadex.h"
31 #include <vector>
32 #include <algorithm>
33 #include <X11/Xlib.h>
34 #include "disppic.h"
35 #include "flats.h"	// DisplayFloorTexture()
36 #include "game.h"	// THINGDEF_SPECTRAL
37 #include "gamesky.h"	// is_sky()
38 #include "gfx.h"
39 #include "img.h"
40 #include "imgspect.h"
41 #include "l_super.h"
42 #include "levels.h"
43 #include "objid.h"
44 #include "objinfo.h"
45 #include "pic2img.h"
46 #include "sticker.h"
47 #include "things.h"
48 #include "wadres.h"
49 
50 
51 static const int sprite_width  = 90;
52 static const int sprite_height = 90;
53 
54 
55 /*
56  *	Extraf - one item in the list of EDGE extrafloors
57  */
58 class Extraf
59 {
60   public :
Extraf(obj_no_t sector,wad_name_t & tex,wad_z_t height)61     Extraf (obj_no_t sector, wad_name_t& tex, wad_z_t height)
62     {
63       this->sector = sector;
64       memcpy (this->tex, &tex, sizeof this->tex);
65       this->height = height;
66     }
67 
operator <(const Extraf & other) const68     bool operator< (const Extraf& other) const
69     {
70       if (height < other.height)
71 	return true;
72       else if (height == other.height && sector < other.sector)
73 	return true;
74       return false;
75     }
76 
77     wad_z_t height;	// To sort by increasing floor height
78     obj_no_t sector;	// Sector# (for heights, flats and light level)
79     wad_tex_name_t tex;	// Texture (middle tex of first sidedef)
80 };
81 
82 
83 static void get_extrafloors (std::vector<Extraf>& list, wad_tag_t tag);
84 
85 
objinfo_c()86 objinfo_c::objinfo_c ()
87 {
88   for (size_t n = 0; n < MAX_BOXES; n++)
89     box_disp[n] = false;
90   obj_no      = OBJ_NO_NONE;
91   obj_no_disp = OBJ_NO_NONE;
92   prev_sector = OBJ_NO_NONE;
93   out_y1      = 0;
94 }
95 
96 
draw()97 void objinfo_c::draw ()
98 {
99   int  n;
100   int  sd1 = OBJ_NO_NONE;
101   int  sd2 = OBJ_NO_NONE;
102   int  s1 = OBJ_NO_NONE;
103   int  s2 = OBJ_NO_NONE;
104   int  x0, y0;		// Outer top left corner
105   int  ix0, iy0;		// Inner top left corner
106   int  width;
107   int  height;
108 
109   // Am I already drawn ?
110   if (! is_obj (obj_no) || obj_no == obj_no_disp && obj_type == obj_type_disp)
111     return;
112 
113   // Does the box need to be redrawn ?
114   if (obj_type != obj_type_disp)
115     box_disp[0] = false;
116 
117   // The caller should have called set_y1() before !
118   if (! out_y1)
119     return;
120 
121   ObjectsNeeded (obj_type, 0);
122   switch (obj_type)
123   {
124     case OBJ_THINGS:
125     {
126       const int columns = 27;
127       width  = 2 * BOX_BORDER + 3 * WIDE_HSPACING + columns * FONTW
128 	     + 2 * HOLLOW_BORDER + sprite_width;
129       height = 2 * BOX_BORDER + 2 * WIDE_VSPACING
130 	     + y_max ((int) (6.5 * FONTH), sprite_height);
131       x0 = 0;
132       y0 = out_y1 - height + 1;
133       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
134       iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
135       int ix1 = x0 + width - 1 - BOX_BORDER - WIDE_HSPACING;
136       int iy1 = y0 + height - 1 - BOX_BORDER - WIDE_VSPACING;
137       if (box_disp[0])
138       {
139 	push_colour (WINBG);
140 	DrawScreenBox (ix0, iy0, ix0 + columns * FONTW - 1, iy1);
141 	pop_colour ();
142       }
143       else
144 	DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
145       if (obj_no < 0)
146       {
147 	const char *message = "(no thing selected)";
148 	set_colour (WINFG_DIM);
149 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
150 	   y0 + (height - FONTH) / 2, message);
151 	break;
152       }
153       set_colour (WINTITLE);
154       DrawScreenText (ix0, iy0, "Thing #%d", obj_no);
155       const bool invalid_type = ! is_thing_type (Things[obj_no].type);
156       set_colour (WINFG);
157       DrawScreenText (-1, iy0 + (int) (1.5 * FONTH), 0);
158       DrawScreenText (-1, -1, "\1Coords:\2 (%d, %d)",
159 	Things[obj_no].xpos, Things[obj_no].ypos);
160       DrawScreenString (-1, -1, "\1Type:   ");
161       if (invalid_type)
162 	push_colour (CLR_ERROR);
163       DrawScreenText (-2, -2, "%d", Things[obj_no].type);
164       if (invalid_type)
165 	pop_colour ();
166       DrawScreenString (-1, -1, "\1Desc:   ");
167       if (invalid_type)
168 	push_colour (CLR_ERROR);
169       DrawScreenText (-2, -2, "%.19s", get_thing_name (Things[obj_no].type));
170       if (invalid_type)
171 	pop_colour ();
172       DrawScreenText (-1, -1, "\1Angle:\2  %s",
173 	GetAngleName (Things[obj_no].angle));
174       DrawScreenText (-1, -1, "\1Flags:\2  %s",
175 	GetWhenName (Things[obj_no].when));
176 
177       // Show the corresponding sprite
178       {
179 	int sx1 = ix1 + 1 - HOLLOW_BORDER;
180 	int sy1 = iy1 + 1 - HOLLOW_BORDER;
181 	int sx0 = sx1 + 1 - sprite_width;
182 	int sy0 = sy1 + 1 - sprite_height;
183 	draw_box_border (sx0 - HOLLOW_BORDER, sy0 - HOLLOW_BORDER,
184 			 sprite_width + 2 * HOLLOW_BORDER,
185 			 sprite_height + 2 * HOLLOW_BORDER,
186 			 HOLLOW_BORDER, 0);
187 	const char *sprite_root = get_thing_sprite (Things[obj_no].type);
188 	char        flags       = get_thing_flags  (Things[obj_no].type);
189 	if (sprite_root == NULL)
190 	{
191 	  push_colour (WINBG);
192 	  DrawScreenBox (sx0, sy0, sx1, sy1);
193 	  pop_colour ();
194 	  set_colour (WINFG_DIM);
195 	  DrawScreenText (
196 	     sx0 + (sprite_width - 2 * FONTW) / 2,
197 	     sy0 + sprite_height / 2 + 1 - FONTH, "no");
198 	  DrawScreenText (
199 	     sx0 + (sprite_width - 6 * FONTW) / 2,
200 	     sy0 + sprite_height / 2 + 1, "sprite");
201 	}
202 	else
203 	{
204 	  Lump_loc loc;
205 	  Img img (sprite_width, sprite_height, false);
206 	  Sticker sticker;
207 	  wad_res.sprites.loc_by_root (sprite_root, loc);
208 	  if (loc.wad == 0
209 	    || LoadPicture (img, sprite_root, loc, INT_MIN, INT_MIN))
210 	  {
211 	    push_colour (WINBG);
212 	    DrawScreenBox (sx0, sy0, sx1, sy1);
213 	    pop_colour ();
214 	    set_colour (CLR_ERROR);
215 	    DrawScreenString (
216 	      sx0 + (sprite_width - strlen (sprite_root) * FONTW) / 2,
217 	      sy0 + sprite_height / 2 + 1 - 3 * FONTH / 2, sprite_root);
218 	    DrawScreenText (
219 	      sx0 + (sprite_width - 3 * FONTW) / 2,
220 	      sy0 + sprite_height / 2 + 1 - FONTH / 2, "not");
221 	    DrawScreenText (
222 	      sx0 + (sprite_width - 5 * FONTW) / 2,
223 	      sy0 + sprite_height / 2 + 1 + FONTH / 2, "found");
224 	  }
225 	  else
226 	  {
227 	    if (flags & THINGDEF_SPECTRAL)
228 	      spectrify_img (img);
229 	    sticker.load (img, true);
230 	    sticker.draw (drw, 't', sx0, sy0);
231 	  }
232 	}
233       }
234     }
235     break;
236 
237     case OBJ_LINEDEFS:
238       // Linedef
239       width  = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 29 * FONTW;
240       height = 2 * BOX_BORDER + 2 * WIDE_VSPACING + (int) (8.5 * FONTH);
241       x0 = 0;
242       y0 = out_y1 - height + 1;
243       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
244       iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
245       // Ignore box_disp -- always redraw the whole box
246       DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
247       if (obj_no >= 0)
248       {
249 	set_colour (WINTITLE);
250 	DrawScreenText (ix0, iy0, "Linedef #%d", obj_no);
251 	set_colour (WINFG);
252 	DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
253 			"\1Flags:\2    %.19s",
254 			GetLineDefFlagsName (LineDefs[obj_no].flags));
255 	DrawScreenText (-1, -1, "\1Type:\2 %3d %.19s",
256 			LineDefs[obj_no].type,
257 			GetLineDefTypeName (LineDefs[obj_no].type));
258 	ObjectsNeeded (OBJ_SIDEDEFS, OBJ_SECTORS, 0);
259 	{
260 	  int tag           = LineDefs[obj_no].tag;
261 	  int first_sector  = NumSectors;
262 	  int second_sector = NumSectors;
263 	  if (tag != 0)
264 	  {
265 	    for (int n = 0; n < NumSectors; n++)
266 	      if (Sectors[n].tag == tag)
267 	      {
268 		if (first_sector >= NumSectors)
269 		  first_sector = n;
270 		else
271 		{
272 		  second_sector = n;
273 		  break;
274 		}
275 	      }
276 	  }
277 	  if (first_sector < NumSectors && second_sector < NumSectors)
278 	    DrawScreenText (-1, -1, "\1Tag:\2      %d (#%d+)", tag, first_sector);
279 	  else if (first_sector < NumSectors)
280 	    DrawScreenText (-1, -1, "\1Tag:\2      %d (#%d)", tag, first_sector);
281 	  else
282 	    DrawScreenText (-1, -1, "\1Tag:\2      %d (none)", tag);
283 	}
284 	s1 = LineDefs[obj_no].start;
285 	s2 = LineDefs[obj_no].end;
286 	DrawScreenText (-1, -1, "\1Vertices:\2 (#%d, #%d)", s1, s2);
287 	ObjectsNeeded (OBJ_VERTICES, 0);
288 	n = ComputeDist (Vertices[s2].x - Vertices[s1].x,
289 			 Vertices[s2].y - Vertices[s1].y);
290 	DrawScreenText (-1, -1, "\1Length:\2   %d", n);
291 	sd1 = LineDefs[obj_no].sidedef1;
292 	sd2 = LineDefs[obj_no].sidedef2;
293 	DrawScreenText (-1, -1, "\1" "1st sd:\2   #%d", sd1);
294 	DrawScreenText (-1, -1, "\1" "2nd sd:\2   #%d", sd2);
295 	if (sd1 >= 0)
296 	  s1 = SideDefs[sd1].sector;
297 	else
298 	  s1 = -1;
299 	if (sd2 >= 0)
300 	  s2 = SideDefs[sd2].sector;
301 	else
302 	  s2 = -1;
303       }
304       else
305       {
306 	const char *message = "(no linedef selected)";
307 	set_colour (WINFG_DIM);
308 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
309 	  y0 + (height - FONTH) / 2, message);
310       }
311 
312       // 1st sidedef
313       x0 += width;
314       width  = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 16 * FONTW;
315       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
316       y0 = out_y1 - height + 1;
317       // Ignore box_disp -- always redraw the whole box
318       DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
319       if (obj_no >= 0 && sd1 >= 0)
320       {
321 	set_colour (WINTITLE);
322 	DrawScreenText (ix0, iy0, "Sidedef1 #%d", sd1);
323 
324 	if (s1 >= 0 && s2 >= 0 && Sectors[s1].ceilh > Sectors[s2].ceilh
325 	  && ! (is_sky (Sectors[s1].ceilt) && is_sky (Sectors[s2].ceilt)))
326 	{
327 	  if (SideDefs[sd1].tex1[0] == '-' && SideDefs[sd1].tex1[1] == '\0')
328 	    set_colour (CLR_ERROR);
329 	  else
330 	    set_colour (WINFG);
331 	}
332 	else
333 	  set_colour (WINFG_DIM);
334 	DrawScreenText (-1, iy0 + (int) (1.5 * FONTH), "\1Upper:\2  %.*s",
335 	    WAD_TEX_NAME, SideDefs[sd1].tex1);
336 
337 	if (sd2 < 0
338 	  && SideDefs[sd1].tex3[0] == '-' && SideDefs[sd1].tex3[1] == '\0')
339 	  set_colour (CLR_ERROR);
340 	else
341 	  set_colour (WINFG);
342 	DrawScreenText (-1, -1,
343 	  "\1Middle:\2 %.*s", WAD_TEX_NAME, SideDefs[sd1].tex3);
344 
345 	if (s1 >= 0 && s2 >= 0 && Sectors[s1].floorh < Sectors[s2].floorh
346 	  && ! (is_sky (Sectors[s1].floort) && is_sky (Sectors[s2].floort)))
347 	{
348 	  if (SideDefs[sd1].tex2[0] == '-' && SideDefs[sd1].tex2[1] == '\0')
349 	    set_colour (CLR_ERROR);
350 	  else
351 	    set_colour (WINFG);
352 	}
353 	else
354 	  set_colour (WINFG_DIM);
355 	DrawScreenText (-1, -1, "\1Lower:\2  %.*s",
356 	  WAD_TEX_NAME, SideDefs[sd1].tex2);
357 
358 	set_colour (WINFG);
359 	DrawScreenText (-1, -1, "\1X-ofs:\2  %d", SideDefs[sd1].xoff);
360 	DrawScreenText (-1, -1, "\1Y-ofs:\2  %d", SideDefs[sd1].yoff);
361 	DrawScreenText (-1, -1, "\1Sector:\2 #%d", s1);
362       }
363       else
364       {
365 	const char *message = "(no 1st sidedef)";
366 	set_colour (CLR_ERROR);
367 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
368 	  y0 + (height - FONTH) / 2, message);
369       }
370 
371       // 2nd sidedef
372       x0 += width;
373       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
374       y0 = out_y1 - height + 1;
375       // Ignore box_disp -- always redraw the whole box
376       DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
377       if (obj_no >= 0 && sd2 >= 0)
378       {
379 	set_colour (WINTITLE);
380 	DrawScreenText (ix0, iy0, "Sidedef2 #%d", sd2);
381 	set_colour (WINFG);
382 	const char *tex_name;
383 
384 	tex_name = SideDefs[sd2].tex1;  // Upper texture
385 	if (s1 >= 0 && s2 >= 0 && Sectors[s2].ceilh > Sectors[s1].ceilh
386 	  && ! (is_sky (Sectors[s1].ceilt) && is_sky (Sectors[s2].ceilt)))
387 	{
388 	  if (tex_name[0] == '-' && tex_name[1] == '\0')
389 	    set_colour (CLR_ERROR);
390 	  else
391 	    set_colour (WINFG);
392 	}
393 	else
394 	  set_colour (WINFG_DIM);
395 	DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
396 	  "\1Upper:\2  %.*s", WAD_TEX_NAME, tex_name);
397 
398 	tex_name = SideDefs[sd2].tex3;  // Middle texture
399 	set_colour (WINFG);
400 	DrawScreenText (-1, -1,
401 	  "\1Middle:\2 %.*s", WAD_TEX_NAME, tex_name);
402 
403 	tex_name = SideDefs[sd2].tex2;  // Lower texture
404 	if (s1 >= 0 && s2 >= 0 && Sectors[s2].floorh < Sectors[s1].floorh
405 	  && ! (is_sky (Sectors[s1].floort) && is_sky (Sectors[s2].floort)))
406 	{
407 	  if (tex_name[0] == '-' && tex_name[1] == '\0')
408 	    set_colour (CLR_ERROR);
409 	  else
410 	    set_colour (WINFG);
411 	}
412 	else
413 	  set_colour (WINFG_DIM);
414 	DrawScreenText (-1, -1, "\1Lower:\2  %.*s", WAD_TEX_NAME, tex_name);
415 
416 	set_colour (WINFG);
417 	DrawScreenText (-1, -1, "\1X-ofs:\2  %d", SideDefs[sd2].xoff);
418 	DrawScreenText (-1, -1, "\1Y-ofs:\2  %d", SideDefs[sd2].yoff);
419 	DrawScreenText (-1, -1, "\1Sector:\2 #%d", s2);
420       }
421       else
422       {
423 	const char *message = "(no 2nd sidedef)";
424 	// If the "2" flag is set, there must be a second sidedef
425 	if (LineDefs[obj_no].flags & 0x04)  // FIXME hard-coded
426 	  set_colour (CLR_ERROR);
427 	else
428 	  set_colour (WINFG_DIM);
429 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
430 	  y0 + (height - FONTH) / 2, message);
431       }
432 
433       // Superimposed linedefs
434       {
435 	Superimposed_ld super;
436 	super.set (obj_no);
437 	obj_no_t l = super.get ();
438 	int iy1;
439 
440 	if (l != -1 || box_disp[3])
441 	{
442 	  x0 += width;
443 	  width  = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 12 * FONTW;
444 	  ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
445 	  iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
446 	  iy1 = y0 + height - 1 - BOX_BORDER - WIDE_VSPACING;
447 	  DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
448 	}
449 	if (l != -1)
450 	{
451 	  box_disp[3] = true;
452 	  set_colour (WINTITLE);
453 	  DrawScreenString (ix0, iy0, "Superimposed");
454 	  set_colour (WINFG);
455 	  iy0 += int (1.5 * FONTH);
456 	  while (l != -1)
457 	  {
458 	    if (iy0 + FONTH - 1 <= iy1)
459 	      DrawScreenText (ix0, iy0, "#%d", l);
460 	    /* Too many linedefs, replace the last one by "(more)".
461 	       Not elegant, but it makes the code simpler. */
462 	    else
463 	    {
464 	      iy0 -= FONTH;
465 	      set_colour (WINBG);
466 	      DrawScreenBox (ix0, iy0, ix0 + 12 * FONTW - 1, iy0 + FONTH - 1);
467 	      set_colour (WINFG);
468 	      DrawScreenString (ix0, iy0, "(more)");
469 	      break;
470 	    }
471 	    iy0 += FONTH;
472 	    l = super.get ();
473 	  }
474 	}
475       }
476       break;
477 
478     case OBJ_VERTICES:
479       width  = 2 * BOX_BORDER + 2 * WIDE_HSPACING + 29 * FONTW;
480       height = 2 * BOX_BORDER + 2 * WIDE_VSPACING + (int) (2.5 * FONTH);
481       x0 = 0;
482       y0 = out_y1 - height + 1;
483       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
484       iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
485       // Ignore box_disp -- always redraw the whole box
486       DrawScreenBox3D (x0, y0, x0 + width - 1, y0 + height - 1);
487       if (obj_no < 0)
488       {
489 	const char *message = "(no vertex selected)";
490 	set_colour (WINFG_DIM);
491 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
492 	  y0 + (height - FONTH) / 2, message);
493 	break;
494       }
495       set_colour (WINTITLE);
496       DrawScreenText (ix0, iy0, "Vertex #%d", obj_no);
497       set_colour (WINFG);
498       DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
499 	"\1Coordinates:\2 (%d, %d)", Vertices[obj_no].x, Vertices[obj_no].y);
500       break;
501 
502     case OBJ_SECTORS:
503     {
504       int x1, y1;
505       int ix1, iy1;
506       const int columns = 24;
507       width  = BOX_BORDER
508 	     + WIDE_HSPACING
509 	     + columns * FONTW
510 	     + WIDE_HSPACING
511 	     + HOLLOW_BORDER
512 	     + DOOM_FLAT_WIDTH
513 	     + HOLLOW_BORDER
514 	     + WIDE_HSPACING
515 	     + BOX_BORDER;
516       height = 2 * BOX_BORDER
517 	     + 2 * WIDE_VSPACING
518 	     + y_max ((unsigned) (9.5 * FONTH),
519 		    WIDE_HSPACING + 4 * HOLLOW_BORDER + 2 * DOOM_FLAT_HEIGHT);
520       x0 = 0;
521       y0 = out_y1 - height + 1;
522       x1 = x0 + width - 1;
523       y1 = y0 + height - 1;
524       ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
525       iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
526       ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
527       iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
528       if (box_disp[0])
529       {
530 	push_colour (WINBG);
531 	DrawScreenBox (ix0, iy0, ix0 + columns * FONTW - 1, iy1);
532 	pop_colour ();
533       }
534       else
535 	DrawScreenBox3D (x0, y0, x1, y1);
536       if (obj_no < 0)
537       {
538 	const char *const message = "(no sector selected)";
539 	set_colour (WINFG_DIM);
540 	DrawScreenText (x0 + (width - FONTW * strlen (message)) / 2,
541 	  y0 + (height - FONTH) / 2, message);
542 	break;
543       }
544       set_colour (WINTITLE);
545       DrawScreenText (ix0, iy0, "Sector #%d", obj_no);
546       set_colour (WINFG);
547       const struct Sector *sec = Sectors + obj_no;
548       if (prev_sector >= 0 && prev_sector != obj_no)
549       {
550 	DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
551 	  "\1Floor:\2    %d (%+d)",
552 	  sec->floorh, sec->floorh - prev_floorh);
553 	DrawScreenText (-1, -1, "\1Ceiling:\2  %d (%+d)",
554 	  sec->ceilh, sec->ceilh - prev_ceilh);
555       }
556       else
557       {
558 	DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
559 	  "\1Floor:\2    %d",   sec->floorh);
560         DrawScreenText (-1, -1, "\1Ceiling:\2  %d",  sec->ceilh);
561       }
562       DrawScreenText (-1, -1, "\1Headroom:\2 %d",   sec->ceilh - sec->floorh);
563       DrawScreenText (-1, -1, "\1Floor:\2    %.*s", WAD_FLAT_NAME, sec->floort);
564       DrawScreenText (-1, -1, "\1Ceiling:\2  %.*s", WAD_FLAT_NAME, sec->ceilt);
565       DrawScreenText (-1, -1, "\1Light:\2    %d",   sec->light);
566       DrawScreenText (-1, -1, "\1Type:\2 %3d %.14s",
567 	sec->special, GetSectorTypeName (sec->special));
568       {
569 	int tag       = sec->tag;
570 	int first_ld  = NumLineDefs;
571 	int second_ld = NumLineDefs;
572 
573 	ObjectsNeeded (OBJ_LINEDEFS, 0);
574 	if (tag != 0)
575 	{
576 	  for (n = 0; n < NumLineDefs; n++)
577 	    if (LineDefs[n].tag == tag)
578 	    {
579 	      if (first_ld >= NumLineDefs)
580 		first_ld = n;
581 	      else
582 	      {
583 		second_ld = n;
584 		break;
585 	      }
586 	    }
587 	}
588 	if (first_ld < NumLineDefs && second_ld < NumLineDefs)
589 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (#%d+)", tag, first_ld);
590 	else if (first_ld < NumLineDefs)
591 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (#%d)", tag, first_ld);
592 	else if (tag == 99 || tag == 999)
593 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (stairs?)", tag);
594 	else if (tag == 666)
595 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (lower@end)", tag);
596 	else if (tag == 667)
597 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (raise@end)", tag);
598 	else
599 	   DrawScreenText (-1, -1, "\1Tag:\2      %d (none)", tag);
600       }
601       {
602 	hookfunc_comm_t block;
603 
604 	// Display the floor texture in the bottom right corner
605 	block.x1 = ix1;
606 	block.x0 = block.x1 - (DOOM_FLAT_WIDTH + 2 * HOLLOW_BORDER - 1);
607 	block.y1 = iy1;
608 	block.y0 = block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
609 	block.name = sec->floort;
610 	display_flat_depressed (&block);
611 
612 	// Display the ceiling texture above the floor texture
613 	block.y1 = block.y0 - (WIDE_VSPACING + 1);
614 	block.y0 = block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
615 	block.name = sec->ceilt;
616 	display_flat_depressed (&block);
617       }
618 
619       // Show all EDGE extrafloors for this sector
620       {
621 	x0 += width;
622 	const int columns2 = 16;
623 	const int width2   = BOX_BORDER
624 			   + WIDE_HSPACING
625 			   + columns2 * FONTW
626 			   + WIDE_HSPACING
627 			   + HOLLOW_BORDER
628 			   + DOOM_FLAT_WIDTH
629 			   + HOLLOW_BORDER
630 			   + WIDE_HSPACING
631 			   + BOX_BORDER;
632 	std::vector<Extraf> v;
633 	get_extrafloors (v, sec->tag);
634 	size_t e;
635 	for (e = 0; e < v.size () && e + 1 < MAX_BOXES; e++, x0 += width2)
636 	{
637 	  const Extraf& i = v[e];
638 	  obj_no_t dsecno = i.sector;
639 	  bool thick = (*i.tex != '\0');
640 	  const struct Sector *dsec = Sectors + dsecno;
641 	  x1 = x0 + width2 - 1;
642 	  y1 = y0 + height - 1;
643 	  ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
644 	  iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
645 	  ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
646 	  iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
647 	  if (box_disp[e + 1])  // FIXME
648 	  {
649 	    push_colour (WINBG);
650 	    DrawScreenBox (ix0, iy0, ix0 + columns2 * FONTW - 1, iy1);
651 	    pop_colour ();
652 	  }
653 	  else
654 	  {
655 	    DrawScreenBox3D (x0, y0, x1, y1);
656 	    box_disp[e + 1] = true;
657 	  }
658 	  if (! is_sector (dsecno))  // Can't happen
659 	    continue;
660 	  set_colour (WINTITLE);
661 	  if (thick)
662 	    DrawScreenText (ix0, iy0, "Thick #%d", dsecno);
663 	  else
664 	    DrawScreenText (ix0, iy0, "Thin #%d", dsecno);
665 	  set_colour (WINFG);
666 	  if (thick)
667 	  {
668 	    DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
669 				    "\1Bottom:\2 %d",   dsec->floorh);
670 	    DrawScreenText (-1, -1, "\1Top:\2    %d",   dsec->ceilh);
671 	    DrawScreenText (-1, -1, "\1Thick:\2  %d",   dsec->ceilh - dsec->floorh);
672 	    DrawScreenText (-1, -1, "\1Bottom:\2 %.*s", WAD_FLAT_NAME,dsec->floort);
673 	    DrawScreenText (-1, -1, "\1Top:\2    %.*s", WAD_FLAT_NAME, dsec->ceilt);
674 	  }
675 	  else
676 	  {
677 	    DrawScreenText (-1, iy0 + (int) (1.5 * FONTH),
678 				    "\1Height:\2 %d",   dsec->floorh);
679 	    DrawScreenText (-1, -1, "\1Flat:\2   %.*s", WAD_FLAT_NAME,dsec->floort);
680 	  }
681 	  DrawScreenText (-1, -1, "\1Shadow:\2 %d",   dsec->light);
682 	  DrawScreenText (-1, -1, "\1Type:\2   %d",   dsec->special);
683 	  ObjectsNeeded (OBJ_LINEDEFS, 0);
684 	  if (thick)
685 	    DrawScreenText (-1, -1, "\1Side:\2   %.*s", WAD_TEX_NAME, i.tex);
686 	  {
687 	    hookfunc_comm_t block;
688 
689 	    // Display the top texture in the bottom right corner
690 	    block.x1 = ix1;
691 	    block.x0 = block.x1 - (DOOM_FLAT_WIDTH + 2 * HOLLOW_BORDER - 1);
692 	    block.y1 = iy1;
693 	    block.y0 = block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
694 	    block.name = dsec->floort;
695 	    display_flat_depressed (&block);
696 
697 	    // Display the bottom texture above the floor texture
698 	    block.y1 = block.y0 - (WIDE_VSPACING + 1);
699 	    block.y0 = block.y1 - (DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER - 1);
700 	    if (thick)
701 	    {
702 	      block.name = dsec->ceilt;
703 	      display_flat_depressed (&block);
704 	    }
705 	    else
706 	    {
707 	      push_colour (WINBG);
708 	      DrawScreenBoxwh (block.x0, block.y0, DOOM_FLAT_WIDTH
709 	        + 2 * HOLLOW_BORDER, DOOM_FLAT_HEIGHT + 2 * HOLLOW_BORDER);
710 	      pop_colour ();
711 	    }
712 	  }
713 	}
714 	// Clear out remaining boxes
715 	for (; e + 1 < MAX_BOXES && box_disp[e + 1]; e++, x0 += width2)
716 	{
717 	  x1 = x0 + width2 - 1;
718 	  y1 = y0 + height - 1;
719 	  ix0 = x0 + BOX_BORDER + WIDE_HSPACING;
720 	  iy0 = y0 + BOX_BORDER + WIDE_VSPACING;
721 	  ix1 = x1 - BOX_BORDER - WIDE_HSPACING;
722 	  iy1 = y1 - BOX_BORDER - WIDE_VSPACING;
723 	  push_colour (WINBG);
724 	  DrawScreenBox (ix0, iy0, ix1, iy1);
725 	  pop_colour ();
726 	}
727       }
728       break;
729     }
730   }
731 
732   if (obj_type == OBJ_SECTORS)
733   {
734     if (obj_no != prev_sector)
735       prev_sector = obj_no;
736     if (obj_no >= 0)
737     {
738       prev_floorh = Sectors[obj_no].floorh;
739       prev_ceilh  = Sectors[obj_no].ceilh;
740     }
741   }
742   box_disp[0] = true;
743   obj_no_disp = obj_no;
744   obj_type_disp = obj_type;
745 }
746 
747 
748 /*
749  *	get_extrafloors - get list of EDGE extrafloors for tag
750  *
751  *	Put in <v> a list of the extrafloors for tag <tag>,
752  *	sorted by floor height major, sector number minor. The
753  *	previous content of <v> is lost. Each Extraf object in
754  *	<v> is set up in the following way :
755  *
756  *	- <sector> is set to the number of the dummy sector,
757  *
758  *	- <tex> is set to the side texture of the extrafloor, or
759  *	  "" if it's a thin extrafloor,
760  *
761  *	- <height> is the to the floor height of the dummy
762  *	  sector.
763  */
get_extrafloors(std::vector<Extraf> & v,wad_tag_t tag)764 static void get_extrafloors (std::vector<Extraf>& v, wad_tag_t tag)
765 {
766   v.clear ();
767   for (obj_no_t l = 0; l < NumLineDefs; l++)
768   {
769     if (LineDefs[l].tag == tag
770       && LineDefs[l].type >= 400 && LineDefs[l].type <= 407)  // FIXME
771     {
772       obj_no_t sd = LineDefs[l].sidedef1;
773       if (! is_sidedef (sd) || ! is_sector (SideDefs[sd].sector))  // Paranoia
774 	continue;
775       wad_tex_name_t tex;
776       if (LineDefs[l].type == 400)
777 	memcpy (tex, SideDefs[sd].tex3, sizeof tex);
778       else if (LineDefs[l].type == 401)		// side_upper
779 	memcpy (tex, SideDefs[sd].tex1, sizeof tex);
780       else if (LineDefs[l].type == 402)		// side_lower
781 	memcpy (tex, SideDefs[sd].tex2, sizeof tex);
782       else
783 	memset (tex, '\0', sizeof tex);
784       v.push_back (Extraf (SideDefs[sd].sector,
785 			   tex,
786 			   Sectors[SideDefs[sd].sector].floorh));
787     }
788   }
789   sort (v.begin (), v.end ());
790 }
791 
792 
793