sources/interface.cpp

changeset 47
35b968619b0c
parent 46
19be47c9bab7
child 48
02009f1ec2b7
equal deleted inserted replaced
46:19be47c9bab7 47:35b968619b0c
50 static int g_pan = 0; 50 static int g_pan = 0;
51 static bool g_needRefresh = false; 51 static bool g_needRefresh = false;
52 static bool g_needStatusBarRender = false; 52 static bool g_needStatusBarRender = false;
53 static bool g_needInputRender = false; 53 static bool g_needInputRender = false;
54 static bool g_needOutputRender = false; 54 static bool g_needOutputRender = false;
55 static bool g_needNicklistRender = false;
55 static struct { char ch; int x; } g_cursorChar; 56 static struct { char ch; int x; } g_cursorChar;
56 static Vector<ColoredLine> g_output;; 57 static Vector<ColoredLine> g_output;;
57 static int g_outputScroll = 0; 58 static int g_outputScroll = 0;
58 static String g_title; 59 static String g_title;
59 static InputState g_inputState = INPUTSTATE_NORMAL; 60 static InputState g_inputState = INPUTSTATE_NORMAL;
60 static Function<void (void)> g_disconnectConfirmFunction = nullptr; 61 static Function<void (void)> g_disconnectConfirmFunction = nullptr;
61 static IPAddress g_address; 62 static IPAddress g_address;
62 static String g_statusBarText; 63 static String g_statusBarText;
64 static StringList g_playerNames;
63 65
64 // ------------------------------------------------------------------------------------------------- 66 // -------------------------------------------------------------------------------------------------
65 // 67 //
66 static FUNCTION 68 static FUNCTION
67 interface_color_pair (Color fg, Color bg) -> int 69 interface_color_pair (Color fg, Color bg) -> int
245 } 247 }
246 248
247 // ------------------------------------------------------------------------------------------------- 249 // -------------------------------------------------------------------------------------------------
248 // 250 //
249 static FUNCTION 251 static FUNCTION
252 inteface_nicklist_width() -> int
253 {
254 // Allocate at least 12 characters, at most 24 characters, for the nicklist. If we cannot
255 // afford that (o_O) then we probably shouldn't draw the nicklist at all I think.
256 int nicklistWidth = COLS / 4;
257
258 if (nicklistWidth < 12)
259 return 0;
260
261 return min (nicklistWidth, 24);
262 }
263
264 // -------------------------------------------------------------------------------------------------
265 // Renders the given colored line onto the screen. Will wrap if allowWrap is true. Returns the
266 // 'y' value for the next line.
267 //
268 static FUNCTION
269 interface_render_colorline (int y, int x0, int width,
270 const ColoredLine& line, bool allowWrap) -> int
271 {
272 int x = x0;
273
274 for (int byte : line.data())
275 {
276 if (x == x0 + width)
277 {
278 if (not allowWrap)
279 return y;
280
281 x = x0;
282 ++y;
283 }
284
285 if (isprint (byte))
286 {
287 mvaddch (y, x, char (byte));
288 ++x;
289 }
290 else switch (byte)
291 {
292 case RLINE_ON_BLACK:
293 case RLINE_ON_GREEN:
294 case RLINE_ON_YELLOW:
295 case RLINE_ON_BLUE:
296 case RLINE_ON_MAGENTA:
297 case RLINE_ON_CYAN:
298 case RLINE_ON_WHITE:
299 attron (interface_color_pair (Color (byte - RLINE_ON_BLACK), DEFAULT));
300 break;
301
302 case RLINE_OFF_BLACK:
303 case RLINE_OFF_GREEN:
304 case RLINE_OFF_YELLOW:
305 case RLINE_OFF_BLUE:
306 case RLINE_OFF_MAGENTA:
307 case RLINE_OFF_CYAN:
308 case RLINE_OFF_WHITE:
309 attroff (interface_color_pair (Color (byte - RLINE_OFF_BLACK), DEFAULT));
310 break;
311
312 case RLINE_ON_BOLD:
313 attron (A_BOLD);
314 break;
315
316 case RLINE_OFF_BOLD:
317 attroff (A_BOLD);
318 break;
319 }
320 }
321
322 return y + 1;
323 }
324
325 // -------------------------------------------------------------------------------------------------
326 //
327 static FUNCTION
250 interface_render_output() -> void 328 interface_render_output() -> void
251 { 329 {
252 if (g_output.size() == 1) 330 if (g_output.size() == 1)
253 return; 331 return;
254 332
255 g_outputScroll = clamp (g_outputScroll, 0, g_output.size() - 1); 333 g_outputScroll = clamp (g_outputScroll, 0, g_output.size() - 1);
256 334
257 int height = LINES - 3; 335 int height = LINES - 3;
336 int width = COLS - inteface_nicklist_width();
258 int printOffset = 0; 337 int printOffset = 0;
259 int end = g_output.size() - 1 - g_outputScroll; 338 int end = g_output.size() - 1 - g_outputScroll;
260 int start = end; 339 int start = end;
261 int usedHeight = 0; 340 int usedHeight = 0;
262 int y = 1; 341 int y = 1;
263 bool tightFit = false; 342 bool tightFit = false;
264 343
265 // Where to start? 344 // Where to start?
266 while (start > 0) 345 while (start > 0)
267 { 346 {
268 int rows = g_output[start - 1].rows (COLS); 347 int rows = g_output[start - 1].rows (width);
269 348
270 if (usedHeight + rows > height) 349 if (usedHeight + rows > height)
271 { 350 {
272 // This line won't fit anymore. 351 // This line won't fit anymore.
273 tightFit = true; 352 tightFit = true;
281 // See if there's any more rows to use (end may be too small) 360 // See if there's any more rows to use (end may be too small)
282 if (not tightFit) 361 if (not tightFit)
283 { 362 {
284 while (end < g_output.size()) 363 while (end < g_output.size())
285 { 364 {
286 int rows = g_output[end].rows (COLS); 365 int rows = g_output[end].rows (width);
287 366
288 if (usedHeight + rows > height) 367 if (usedHeight + rows > height)
289 { 368 {
290 tightFit = true; 369 tightFit = true;
291 break; 370 break;
306 385
307 assert (start <= end and start - end <= height); 386 assert (start <= end and start - end <= height);
308 387
309 // Clear the display 388 // Clear the display
310 for (int i = y; i < y + height; ++i) 389 for (int i = y; i < y + height; ++i)
311 mvhline (i, 0, ' ', COLS); 390 mvhline (i, 0, ' ', width);
312 391
313 // Print the lines 392 // Print the lines
314 y += printOffset; 393 y += printOffset;
315 394
316 for (int i = start; i < end; ++i) 395 for (int i = start; i < end; ++i)
317 { 396 y = interface_render_colorline (y, 0, width, g_output[i], true);
318 int x = 0; 397
319 398 g_needOutputRender = false;
320 for (int byte : g_output[i].data()) 399 g_needRefresh = true;
321 { 400 }
322 if (x == COLS) 401
402 // -------------------------------------------------------------------------------------------------
403 //
404 static FUNCTION
405 interface_render_nicklist() -> void
406 {
407 int width = inteface_nicklist_width();
408 int height = LINES- 3;
409 int y = 1;
410 int x = COLS - width;
411
412 if (width == 0)
413 return;
414
415 for (int i = 0; i < height; ++i)
416 {
417 mvhline (y, x, ' ', width);
418
419 if (i < g_playerNames.size())
420 {
421 String displaynick = g_playerNames[i];
422
423 if (displaynick.length() > width)
323 { 424 {
324 x = 0; 425 displaynick = displaynick.mid (0, width - 3);
325 ++y; 426 displaynick += "...";
326 } 427 }
327 428
328 if (isprint (byte)) 429 mvprintw (y, x, "%s", displaynick.chars());
329 mvaddch (y, x++, char (byte)); 430 }
330 else switch (byte) 431
331 { 432 y++;
332 case RLINE_ON_BLACK: 433 }
333 case RLINE_ON_GREEN: 434
334 case RLINE_ON_YELLOW: 435 g_needNicklistRender = false;
335 case RLINE_ON_BLUE:
336 case RLINE_ON_MAGENTA:
337 case RLINE_ON_CYAN:
338 case RLINE_ON_WHITE:
339 attron (interface_color_pair (Color (byte - RLINE_ON_BLACK), DEFAULT));
340 break;
341
342 case RLINE_OFF_BLACK:
343 case RLINE_OFF_GREEN:
344 case RLINE_OFF_YELLOW:
345 case RLINE_OFF_BLUE:
346 case RLINE_OFF_MAGENTA:
347 case RLINE_OFF_CYAN:
348 case RLINE_OFF_WHITE:
349 attroff (interface_color_pair (Color (byte - RLINE_OFF_BLACK), DEFAULT));
350 break;
351
352 case RLINE_ON_BOLD:
353 attron (A_BOLD);
354 break;
355
356 case RLINE_OFF_BOLD:
357 attroff (A_BOLD);
358 break;
359 }
360 }
361
362 ++y;
363 }
364
365 g_needOutputRender = false;
366 g_needRefresh = true; 436 g_needRefresh = true;
367 } 437 }
368 438
369 // ------------------------------------------------------------------------------------------------- 439 // -------------------------------------------------------------------------------------------------
370 // 440 //
492 update_statusbar(); 562 update_statusbar();
493 interface_render_titlebar(); 563 interface_render_titlebar();
494 interface_render_output(); 564 interface_render_output();
495 interface_render_statusbar(); 565 interface_render_statusbar();
496 interface_render_input(); 566 interface_render_input();
567 interface_render_nicklist();
497 } 568 }
498 569
499 // ------------------------------------------------------------------------------------------------- 570 // -------------------------------------------------------------------------------------------------
500 // 571 //
501 static FUNCTION 572 static FUNCTION
814 Interface::render() -> void 885 Interface::render() -> void
815 { 886 {
816 if (g_needStatusBarRender) interface_render_statusbar(); 887 if (g_needStatusBarRender) interface_render_statusbar();
817 if (g_needInputRender) interface_render_input(); 888 if (g_needInputRender) interface_render_input();
818 if (g_needOutputRender) interface_render_output(); 889 if (g_needOutputRender) interface_render_output();
890 if (g_needNicklistRender) interface_render_nicklist();
819 891
820 if (g_needRefresh) 892 if (g_needRefresh)
821 { 893 {
822 interface_position_cursor(); 894 interface_position_cursor();
823 refresh(); 895 refresh();
868 940
869 RCONSession* session = RCONSession::new_session(); 941 RCONSession* session = RCONSession::new_session();
870 session->set_password (password); 942 session->set_password (password);
871 session->connect (g_address); 943 session->connect (g_address);
872 } 944 }
945
946 // -------------------------------------------------------------------------------------------------
947 //
948 FUNCTION
949 Interface::set_player_names (const StringList& names) -> void
950 {
951 g_playerNames = names;
952 g_needNicklistRender = true;
953 }

mercurial