1 //------------------------------------------------------------------------
2 //  Information Bar (bottom of window)
3 //------------------------------------------------------------------------
4 //
5 //  Eureka DOOM Editor
6 //
7 //  Copyright (C) 2007-2019 Andrew Apted
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; either version 2
12 //  of the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //------------------------------------------------------------------------
20 
21 #include "main.h"
22 #include "ui_window.h"
23 
24 #include "e_main.h"
25 #include "e_linedef.h"
26 #include "m_config.h"
27 #include "m_game.h"
28 #include "r_grid.h"
29 #include "r_render.h"
30 
31 
32 #define SNAP_COLOR  (gui_scheme == 2 ? fl_rgb_color(255,96,0) : fl_rgb_color(255, 96, 0))
33 #define FREE_COLOR  (gui_scheme == 2 ? fl_rgb_color(0,192,0) : fl_rgb_color(128, 255, 128))
34 
35 #define RATIO_COLOR  FL_YELLOW
36 
37 
38 const char *UI_InfoBar::scale_options_str =
39 	"  6%| 12%| 25%| 33%| 50%|100%|200%|400%|800%";
40 
41 const double UI_InfoBar::scale_amounts[9] =
42 {
43 	0.0625, 0.125, 0.25, 0.33333, 0.5, 1.0, 2.0, 4.0, 8.0
44 };
45 
46 const char *UI_InfoBar::grid_options_str =
47 	"1024|512|256|192|128| 64| 32| 16|  8|  4|  2|OFF";
48 
49 const int UI_InfoBar::grid_amounts[12] =
50 {
51 	1024, 512, 256, 192, 128, 64, 32, 16, 8, 4, 2,
52 	-1 /* OFF */
53 };
54 
55 
56 //
57 // UI_InfoBar Constructor
58 //
UI_InfoBar(int X,int Y,int W,int H,const char * label)59 UI_InfoBar::UI_InfoBar(int X, int Y, int W, int H, const char *label) :
60     Fl_Group(X, Y, W, H, label)
61 {
62 	box(FL_FLAT_BOX);
63 
64 
65 	// Fitts' law : keep buttons flush with bottom of window
66 	Y += 4;
67 	H -= 4;
68 
69 
70 	Fl_Box *mode_lab = new Fl_Box(FL_NO_BOX, X, Y, 56, H, "Mode:");
71 	mode_lab->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
72 	mode_lab->labelsize(16);
73 
74 	mode = new Fl_Menu_Button(X+58, Y, 96, H, "Things");
75 	mode->align(FL_ALIGN_INSIDE);
76 	mode->add("Things|Linedefs|Sectors|Vertices");
77 	mode->callback(mode_callback, this);
78 	mode->labelsize(16);
79 
80 	X = mode->x() + mode->w() + 10;
81 
82 
83 	Fl_Box *scale_lab = new Fl_Box(FL_NO_BOX, X, Y, 58, H, "Scale:");
84 	scale_lab->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
85 	scale_lab->labelsize(16);
86 
87 	scale = new Fl_Menu_Button(X+60+26, Y, 78, H, "100%");
88 	scale->align(FL_ALIGN_INSIDE);
89 	scale->add(scale_options_str);
90 	scale->callback(scale_callback, this);
91 	scale->labelsize(16);
92 
93 	Fl_Button *sc_minus, *sc_plus;
94 
95 	sc_minus = new Fl_Button(X+60, Y+1, 24, H-2, "-");
96 	sc_minus->callback(sc_minus_callback, this);
97 	sc_minus->labelfont(FL_HELVETICA_BOLD);
98 	sc_minus->labelsize(16);
99 
100 	sc_plus = new Fl_Button(X+60+26+80, Y+1, 24, H-2, "+");
101 	sc_plus->callback(sc_plus_callback, this);
102 	sc_plus->labelfont(FL_HELVETICA_BOLD);
103 	sc_plus->labelsize(16);
104 
105 	X = sc_plus->x() + sc_plus->w() + 12;
106 
107 
108 	Fl_Box *gs_lab = new Fl_Box(FL_NO_BOX, X, Y, 42, H, "Grid:");
109 	gs_lab->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
110 	gs_lab->labelsize(16);
111 
112 	grid_size = new Fl_Menu_Button(X+44, Y, 72, H, "OFF");
113 
114 	grid_size->align(FL_ALIGN_INSIDE);
115 	grid_size->add(grid_options_str);
116 	grid_size->callback(grid_callback, this);
117 	grid_size->labelsize(16);
118 
119 	X = grid_size->x() + grid_size->w() + 12;
120 
121 
122 	grid_snap = new Fl_Toggle_Button(X+4, Y, 72, H);
123 	grid_snap->value(grid.snap ? 1 : 0);
124 	grid_snap->color(FREE_COLOR);
125 	grid_snap->selection_color(SNAP_COLOR);
126 	grid_snap->callback(snap_callback, this);
127 	grid_snap->labelsize(16);
128 
129 	UpdateSnapText();
130 
131 	X = grid_snap->x() + grid_snap->w() + 12;
132 
133 
134 	Fl_Box *ratio_lab = new Fl_Box(FL_NO_BOX, X, Y, 52, H, "Ratio:");
135 	ratio_lab->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
136 	ratio_lab->labelsize(16);
137 
138 	ratio_lock = new Fl_Menu_Button(X+54, Y, 106, H, "UNLOCK");
139 	ratio_lock->align(FL_ALIGN_INSIDE);
140 	ratio_lock->add("UNLOCK|1:1|2:1|4:1|8:1|5:4|7:4|User Value");
141 	ratio_lock->callback(ratio_callback, this);
142 	ratio_lock->labelsize(16);
143 
144 	X = ratio_lock->x() + ratio_lock->w() + 12;
145 
146 
147 	Fl_Box *rend_lab = new Fl_Box(FL_FLAT_BOX, X, Y, 56, H, "Rend:");
148 	rend_lab->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
149 	rend_lab->labelsize(16);
150 
151 	sec_rend = new Fl_Menu_Button(X+58, Y, 96, H, "PLAIN");
152 	sec_rend->align(FL_ALIGN_INSIDE);
153 	sec_rend->add("PLAIN|Floor|Ceiling|Lighting|Floor Bright|Ceil Bright|Sound|3D VIEW");
154 	sec_rend->callback(rend_callback, this);
155 	sec_rend->labelsize(16);
156 
157 	X = sec_rend->x() + rend_lab->w() + 10;
158 
159 
160 	resizable(NULL);
161 
162 	end();
163 }
164 
165 //
166 // UI_InfoBar Destructor
167 //
~UI_InfoBar()168 UI_InfoBar::~UI_InfoBar()
169 { }
170 
171 
handle(int event)172 int UI_InfoBar::handle(int event)
173 {
174 	return Fl_Group::handle(event);
175 }
176 
177 
mode_callback(Fl_Widget * w,void * data)178 void UI_InfoBar::mode_callback(Fl_Widget *w, void *data)
179 {
180 	Fl_Menu_Button *mode = (Fl_Menu_Button *)w;
181 
182 	static const char *mode_keys = "tlsvr";
183 
184 	Editor_ChangeMode(mode_keys[mode->value()]);
185 }
186 
187 
rend_callback(Fl_Widget * w,void * data)188 void UI_InfoBar::rend_callback(Fl_Widget *w, void *data)
189 {
190 	Fl_Menu_Button *sec_rend = (Fl_Menu_Button *)w;
191 
192 	// last option is 3D mode
193 	if (sec_rend->value() > SREND_SoundProp)
194 	{
195 		Render3D_Enable(true);
196 		return;
197 	}
198 
199 	switch (sec_rend->value())
200 	{
201 	case 1: edit.sector_render_mode = SREND_Floor; break;
202 	case 2: edit.sector_render_mode = SREND_Ceiling; break;
203 	case 3: edit.sector_render_mode = SREND_Lighting; break;
204 	case 4: edit.sector_render_mode = SREND_FloorBright; break;
205 	case 5: edit.sector_render_mode = SREND_CeilBright; break;
206 	case 6: edit.sector_render_mode = SREND_SoundProp; break;
207 	default: edit.sector_render_mode = SREND_Nothing; break;
208 	}
209 
210 	if (edit.render3d)
211 		Render3D_Enable(false);
212 
213 	// need sectors mode for sound propagation display
214 	if (edit.sector_render_mode == SREND_SoundProp && edit.mode != OBJ_SECTORS)
215 		Editor_ChangeMode('s');
216 
217 	RedrawMap();
218 }
219 
220 
scale_callback(Fl_Widget * w,void * data)221 void UI_InfoBar::scale_callback(Fl_Widget *w, void *data)
222 {
223 	Fl_Menu_Button *scale = (Fl_Menu_Button *)w;
224 
225 	double new_scale = scale_amounts[scale->value()];
226 
227 	grid.NearestScale(new_scale);
228 }
229 
230 
sc_minus_callback(Fl_Widget * w,void * data)231 void UI_InfoBar::sc_minus_callback(Fl_Widget *w, void *data)
232 {
233 	ExecuteCommand("Zoom", "-1", "/center");
234 }
235 
sc_plus_callback(Fl_Widget * w,void * data)236 void UI_InfoBar::sc_plus_callback(Fl_Widget *w, void *data)
237 {
238 	ExecuteCommand("Zoom", "+1", "/center");
239 }
240 
241 
grid_callback(Fl_Widget * w,void * data)242 void UI_InfoBar::grid_callback(Fl_Widget *w, void *data)
243 {
244 	Fl_Menu_Button *gsize = (Fl_Menu_Button *)w;
245 
246 	int new_step = grid_amounts[gsize->value()];
247 
248 	if (new_step < 0)
249 		grid.SetShown(false);
250 	else
251 		grid.ForceStep(new_step);
252 }
253 
254 
snap_callback(Fl_Widget * w,void * data)255 void UI_InfoBar::snap_callback(Fl_Widget *w, void *data)
256 {
257 	Fl_Toggle_Button *grid_snap = (Fl_Toggle_Button *)w;
258 
259 	// update editor state
260 	grid.SetSnap(grid_snap->value() ? true : false);
261 }
262 
263 
ratio_callback(Fl_Widget * w,void * data)264 void UI_InfoBar::ratio_callback(Fl_Widget *w, void *data)
265 {
266 	Fl_Menu_Button *ratio_lock = (Fl_Menu_Button *)w;
267 
268 	grid.ratio = ratio_lock->value();
269 	main_win->info_bar->UpdateRatio();
270 }
271 
272 
273 //------------------------------------------------------------------------
274 
NewEditMode(obj_type_e new_mode)275 void UI_InfoBar::NewEditMode(obj_type_e new_mode)
276 {
277 	switch (new_mode)
278 	{
279 		case OBJ_THINGS:   mode->value(0); break;
280 		case OBJ_LINEDEFS: mode->value(1); break;
281 		case OBJ_SECTORS:  mode->value(2); break;
282 		case OBJ_VERTICES: mode->value(3); break;
283 
284 		default: break;
285 	}
286 
287 	UpdateModeColor();
288 }
289 
290 
SetMouse(double mx,double my)291 void UI_InfoBar::SetMouse(double mx, double my)
292 {
293 	// TODO this method should go away
294 
295 	main_win->status_bar->redraw();
296 }
297 
298 
SetScale(double new_scale)299 void UI_InfoBar::SetScale(double new_scale)
300 {
301 	double perc = new_scale * 100.0;
302 
303 	char buffer[64];
304 
305 	if (perc < 10.0)
306 		snprintf(buffer, sizeof(buffer), "%1.1f%%", perc);
307 	else
308 		snprintf(buffer, sizeof(buffer), "%3d%%", (int)perc);
309 
310 	scale->copy_label(buffer);
311 }
312 
SetGrid(int new_step)313 void UI_InfoBar::SetGrid(int new_step)
314 {
315 	if (new_step < 0)
316 	{
317 		grid_size->label("OFF");
318 	}
319 	else
320 	{
321 		char buffer[64];
322 		snprintf(buffer, sizeof(buffer), "%d", new_step);
323 		grid_size->copy_label(buffer);
324 	}
325 }
326 
327 
UpdateSnap()328 void UI_InfoBar::UpdateSnap()
329 {
330    grid_snap->value(grid.snap ? 1 : 0);
331 
332    UpdateSnapText();
333 }
334 
335 
UpdateSecRend()336 void UI_InfoBar::UpdateSecRend()
337 {
338 	if (edit.render3d)
339 	{
340 		sec_rend->label("3D VIEW");
341 		return;
342 	}
343 
344 	switch (edit.sector_render_mode)
345 	{
346 	case SREND_Floor:       sec_rend->label("Floor");   break;
347 	case SREND_Ceiling:     sec_rend->label("Ceiling"); break;
348 	case SREND_Lighting:    sec_rend->label("Lighting"); break;
349 	case SREND_FloorBright: sec_rend->label("Floor Brt"); break;
350 	case SREND_CeilBright:  sec_rend->label("Ceil Brt"); break;
351 	case SREND_SoundProp:   sec_rend->label("Sound");    break;
352 	default:                sec_rend->label("PLAIN");    break;
353 	}
354 }
355 
356 
UpdateRatio()357 void UI_InfoBar::UpdateRatio()
358 {
359 	if (grid.ratio == 0)
360 		ratio_lock->color(FL_BACKGROUND_COLOR);
361 	else
362 		ratio_lock->color(RATIO_COLOR);
363 
364 	if (grid.ratio == 7)
365 	{
366 		char buffer[256];
367 		snprintf(buffer, sizeof(buffer), "Usr %d:%d", grid_ratio_high, grid_ratio_low);
368 
369 		// drop the "Usr" part when overly long
370 		if (strlen(buffer) > 9)
371 			ratio_lock->copy_label(buffer+4);
372 		else
373 			ratio_lock->copy_label(buffer);
374 	}
375 	else
376 	{
377 		ratio_lock->copy_label(ratio_lock->text(grid.ratio));
378 	}
379 }
380 
381 
UpdateModeColor()382 void UI_InfoBar::UpdateModeColor()
383 {
384 	switch (mode->value())
385 	{
386 		case 0: mode->label("Things");   mode->color(THING_MODE_COL);  break;
387 		case 1: mode->label("Linedefs"); mode->color(LINE_MODE_COL);   break;
388 		case 2: mode->label("Sectors");  mode->color(SECTOR_MODE_COL); break;
389 		case 3: mode->label("Vertices"); mode->color(VERTEX_MODE_COL); break;
390 	}
391 }
392 
393 
UpdateSnapText()394 void UI_InfoBar::UpdateSnapText()
395 {
396 	if (grid_snap->value())
397 	{
398 		grid_snap->label("SNAP");
399 	}
400 	else
401 	{
402 		grid_snap->label("Free");
403 	}
404 
405 	grid_snap->redraw();
406 }
407 
408 
409 //------------------------------------------------------------------------
410 
411 
412 #define INFO_TEXT_COL	fl_rgb_color(192, 192, 192)
413 #define INFO_DIM_COL	fl_rgb_color(128, 128, 128)
414 
415 
UI_StatusBar(int X,int Y,int W,int H,const char * label)416 UI_StatusBar::UI_StatusBar(int X, int Y, int W, int H, const char *label) :
417     Fl_Widget(X, Y, W, H, label),
418 	status()
419 {
420 	box(FL_NO_BOX);
421 }
422 
~UI_StatusBar()423 UI_StatusBar::~UI_StatusBar()
424 { }
425 
426 
handle(int event)427 int UI_StatusBar::handle(int event)
428 {
429 	// this never handles any events
430 	return 0;
431 }
432 
draw()433 void UI_StatusBar::draw()
434 {
435 	fl_color(fl_rgb_color(64, 64, 64));
436 	fl_rectf(x(), y(), w(), h());
437 
438 	fl_color(fl_rgb_color(96, 96, 96));
439 	fl_rectf(x(), y() + h() - 1, w(), 1);
440 
441 	fl_push_clip(x(), y(), w(), h());
442 
443 	fl_font(FL_COURIER, 16);
444 
445 	int cx = x() + 10;
446 	int cy = y() + 20;
447 
448 	if (edit.render3d)
449 	{
450 		IB_Number(cx, cy, "x", I_ROUND(r_view.x), 5);
451 		IB_Number(cx, cy, "y", I_ROUND(r_view.y), 5);
452 		IB_Number(cx, cy, "z", I_ROUND(r_view.z) - Misc_info.view_height, 4);
453 
454 		// use less space when an action is occurring
455 		if (edit.action == ACT_NOTHING)
456 		{
457 			int ang = I_ROUND(r_view.angle * 180 / M_PI);
458 			if (ang < 0) ang += 360;
459 
460 			IB_Number(cx, cy, "ang", ang, 3);
461 			cx += 2;
462 
463 			IB_Flag(cx, cy, r_view.gravity, "GRAV", "grav");
464 #if 0
465 			IB_Number(cx, cy, "gamma", usegamma, 1);
466 #endif
467 		}
468 
469 		cx += 4;
470 	}
471 	else  // 2D view
472 	{
473 		float mx = grid.SnapX(edit.map_x);
474 		float my = grid.SnapX(edit.map_y);
475 
476 		mx = CLAMP(-32767, mx, 32767);
477 		my = CLAMP(-32767, my, 32767);
478 
479 		IB_Coord(cx, cy, "x", mx);
480 		IB_Coord(cx, cy, "y", my);
481 		cx += 10;
482 #if 0
483 		IB_Number(cx, cy, "gamma", usegamma, 1);
484 		cx += 10;
485 #endif
486 	}
487 
488 	/* status message */
489 
490 	IB_Flag(cx, cy, true, "|", "|");
491 
492 	fl_color(INFO_TEXT_COL);
493 
494 	switch (edit.action)
495 	{
496 	case ACT_DRAG:
497 		IB_ShowDrag(cx, cy);
498 		break;
499 
500 	case ACT_TRANSFORM:
501 		IB_ShowTransform(cx, cy);
502 		break;
503 
504 	case ACT_ADJUST_OFS:
505 		IB_ShowOffsets(cx, cy);
506 		break;
507 
508 	case ACT_DRAW_LINE:
509 		IB_ShowDrawLine(cx, cy);
510 		break;
511 
512 	default:
513 		fl_draw(status.c_str(), cx, cy);
514 		break;
515 	}
516 
517 	fl_pop_clip();
518 }
519 
520 
IB_ShowDrag(int cx,int cy)521 void UI_StatusBar::IB_ShowDrag(int cx, int cy)
522 {
523 	if (edit.render3d && edit.mode == OBJ_SECTORS)
524 	{
525 		IB_Number(cx, cy, "raise delta", I_ROUND(edit.drag_sector_dz), 4);
526 		return;
527 	}
528 	if (edit.render3d && edit.mode == OBJ_THINGS && edit.drag_thing_up_down)
529 	{
530 		double dz = edit.drag_cur_z - edit.drag_start_z;
531 		IB_Number(cx, cy, "raise delta", I_ROUND(dz), 4);
532 		return;
533 	}
534 
535 	double dx, dy;
536 
537 	if (edit.render3d)
538 	{
539 		dx = edit.drag_cur_x - edit.drag_start_x;
540 		dy = edit.drag_cur_y - edit.drag_start_y;
541 	}
542 	else
543 	{
544 		main_win->canvas->DragDelta(&dx, &dy);
545 	}
546 
547 	IB_Coord(cx, cy, "dragging delta x", dx);
548 	IB_Coord(cx, cy,                "y", dy);
549 }
550 
551 
IB_ShowTransform(int cx,int cy)552 void UI_StatusBar::IB_ShowTransform(int cx, int cy)
553 {
554 	int rot_degrees;
555 
556 	switch (edit.trans_mode)
557 	{
558 	case TRANS_K_Scale:
559 		IB_Coord(cx, cy, "scale by", edit.trans_param.scale_x);
560 		break;
561 
562 	case TRANS_K_Stretch:
563 		IB_Coord(cx, cy, "stretch x", edit.trans_param.scale_x);
564 		IB_Coord(cx, cy,         "y", edit.trans_param.scale_y);
565 		break;
566 
567 	case TRANS_K_Rotate:
568 	case TRANS_K_RotScale:
569 		rot_degrees = edit.trans_param.rotate * 90 / 16384;
570 		IB_Number(cx, cy, "rotate by", rot_degrees, 3);
571 		break;
572 
573 	case TRANS_K_Skew:
574 		IB_Coord(cx, cy, "skew x", edit.trans_param.skew_x);
575 		IB_Coord(cx, cy,      "y", edit.trans_param.skew_y);
576 		break;
577 	}
578 
579 	if (edit.trans_mode == TRANS_K_RotScale)
580 		IB_Coord(cx, cy, "scale", edit.trans_param.scale_x);
581 }
582 
583 
IB_ShowOffsets(int cx,int cy)584 void UI_StatusBar::IB_ShowOffsets(int cx, int cy)
585 {
586 	int dx = I_ROUND(edit.adjust_dx);
587 	int dy = I_ROUND(edit.adjust_dy);
588 
589 	Objid hl = edit.highlight;
590 
591 	if (! edit.Selected->empty())
592 	{
593 		if (edit.Selected->count_obj() == 1)
594 		{
595 			int first = edit.Selected->find_first();
596 			int parts = edit.Selected->get_ext(first);
597 
598 			hl = Objid(edit.mode, first, parts);
599 		}
600 		else
601 		{
602 			hl.clear();
603 		}
604 	}
605 
606 	if (hl.valid() && hl.parts >= 2)
607 	{
608 		const LineDef *L = LineDefs[edit.highlight.num];
609 
610 		int x_offset = 0;
611 		int y_offset = 0;
612 
613 		const SideDef *SD = NULL;
614 
615 		if (hl.parts & PART_LF_ALL)
616 			SD = L->Left();
617 		else
618 			SD = L->Right();
619 
620 		if (SD != NULL)
621 		{
622 			x_offset = SD->x_offset;
623 			y_offset = SD->y_offset;
624 
625 			IB_Number(cx, cy, "new ofs x", x_offset + dx, 4);
626 			IB_Number(cx, cy,         "y", y_offset + dy, 4);
627 		}
628 	}
629 
630 	IB_Number(cx, cy, "delta x", dx, 4);
631 	IB_Number(cx, cy,       "y", dy, 4);
632 }
633 
634 
IB_ShowDrawLine(int cx,int cy)635 void UI_StatusBar::IB_ShowDrawLine(int cx, int cy)
636 {
637 	if (! edit.draw_from.valid())
638 		return;
639 
640 	const Vertex *V = Vertices[edit.draw_from.num];
641 
642 	double dx = edit.draw_to_x - V->x();
643 	double dy = edit.draw_to_y - V->y();
644 
645 	// show a ratio value
646 	fixcoord_t fdx = TO_COORD(dx);
647 	fixcoord_t fdy = TO_COORD(dy);
648 
649 	std::string ratio_name = LD_RatioName(fdx, fdy, false);
650 
651 	int old_cx = cx;
652 	IB_String(cx, cy, ratio_name.c_str());
653 
654 	cx = MAX(cx+12, old_cx + 170);
655 
656 	IB_Coord(cx, cy, "delta x", dx);
657 	IB_Coord(cx, cy,       "y", dy);
658 }
659 
660 
IB_Number(int & cx,int & cy,const char * label,int value,int size)661 void UI_StatusBar::IB_Number(int& cx, int& cy, const char *label, int value, int size)
662 {
663 	char buffer[256];
664 
665 	// negative size means we require a sign
666 	if (size < 0)
667 		snprintf(buffer, sizeof(buffer), "%s:%-+*d ", label, -size + 1, value);
668 	else
669 		snprintf(buffer, sizeof(buffer), "%s:%-*d ", label, size, value);
670 
671 	fl_color(INFO_TEXT_COL);
672 	fl_draw(buffer, cx, cy);
673 
674 	cx = cx + fl_width(buffer);
675 }
676 
677 
IB_Coord(int & cx,int & cy,const char * label,float value)678 void UI_StatusBar::IB_Coord(int& cx, int& cy, const char *label, float value)
679 {
680 	char buffer[256];
681 	snprintf(buffer, sizeof(buffer), "%s:%-8.2f ", label, value);
682 
683 	fl_color(INFO_TEXT_COL);
684 	fl_draw(buffer, cx, cy);
685 
686 	cx = cx + fl_width(buffer);
687 }
688 
689 
IB_String(int & cx,int & cy,const char * str)690 void UI_StatusBar::IB_String(int& cx, int& cy, const char *str)
691 {
692 	fl_draw(str, cx, cy);
693 
694 	cx = cx + fl_width(str);
695 }
696 
697 
IB_Flag(int & cx,int & cy,bool value,const char * label_on,const char * label_off)698 void UI_StatusBar::IB_Flag(int& cx, int& cy, bool value, const char *label_on, const char *label_off)
699 {
700 	const char *label = value ? label_on : label_off;
701 
702 	fl_color(value ? INFO_TEXT_COL : INFO_DIM_COL);
703 
704 	fl_draw(label, cx, cy);
705 
706 	cx = cx + fl_width(label) + 20;
707 }
708 
709 
SetStatus(const char * str)710 void UI_StatusBar::SetStatus(const char *str)
711 {
712 	if (status == str)
713 		return;
714 
715 	status = str;
716 
717 	redraw();
718 }
719 
720 
Status_Set(const char * fmt,...)721 void Status_Set(const char *fmt, ...)
722 {
723 	if (! main_win)
724 		return;
725 
726 	va_list arg_ptr;
727 
728 	static char buffer[MSG_BUF_LEN];
729 
730 	va_start(arg_ptr, fmt);
731 	vsnprintf(buffer, MSG_BUF_LEN-1, fmt, arg_ptr);
732 	va_end(arg_ptr);
733 
734 	buffer[MSG_BUF_LEN-1] = 0;
735 
736 	main_win->status_bar->SetStatus(buffer);
737 }
738 
739 
Status_Clear()740 void Status_Clear()
741 {
742 	if (! main_win)
743 		return;
744 
745 	main_win->status_bar->SetStatus("");
746 }
747 
748 //--- editor settings ---
749 // vi:ts=4:sw=4:noexpandtab
750