sources/interface.cpp

changeset 72
1b9c53e0c846
parent 71
4f7c2c944637
child 73
07dda51a7a8e
equal deleted inserted replaced
71:4f7c2c944637 72:1b9c53e0c846
35 #include "network/ipaddress.h" 35 #include "network/ipaddress.h"
36 #include "coloredline.h" 36 #include "coloredline.h"
37 37
38 static const int g_pageSize = 10; 38 static const int g_pageSize = 10;
39 39
40 enum InputState 40 // -------------------------------------------------------------------------------------------------
41 { 41 //
42 INPUTSTATE_NORMAL, 42 int Interface::color_pair (Color fg, Color bg)
43 INPUTSTATE_ADDRESS,
44 INPUTSTATE_PASSWORD,
45 INPUTSTATE_CONFIRM_DISCONNECTION,
46 };
47
48 static StringList InputHistory;
49 static int InputCursor = 0;
50 static int CursorPosition = 0;
51 static int InputPanning = 0;
52 static bool NeedRefresh = false;
53 static bool NeedStatusBarRender = false;
54 static bool NeedInputRender = false;
55 static bool NeedOutputRender = false;
56 static bool NeedNicklistRender = false;
57 static struct { char ch; int x; } CursorCharacter;
58 static Vector<ColoredLine> OutputLines;
59 static int OutputScroll = 0;
60 static String Title;
61 static InputState CurrentInputState = INPUTSTATE_NORMAL;
62 static Function<void (void)> DisconnectConfirmFunction = nullptr;
63 static IPAddress CurrentAddress;
64 static String StatusBarText;
65 static StringList PlayerNames;
66 static String PasteBuffer;
67
68 // -------------------------------------------------------------------------------------------------
69 //
70 static FUNCTION
71 interface_color_pair (Color fg, Color bg) -> int
72 { 43 {
73 return COLOR_PAIR ((int (fg) * NUM_COLORS) + int (bg)); 44 return COLOR_PAIR ((int (fg) * NUM_COLORS) + int (bg));
74 } 45 }
75 46
76 // ------------------------------------------------------------------------------------------------- 47 // -------------------------------------------------------------------------------------------------
77 // 48 //
78 static FUNCTION 49 const String& Interface::current_input()
79 current_input() -> const String&
80 { 50 {
81 return InputHistory[InputCursor]; 51 return InputHistory[InputCursor];
82 } 52 }
83 53
84 // ------------------------------------------------------------------------------------------------- 54 // -------------------------------------------------------------------------------------------------
85 // 55 //
86 // Makes current_input() the lastmost input (so that we won't modify history) 56 // Makes current_input() the lastmost input (so that we won't modify history)
87 // 57 //
88 static FUNCTION 58 void Interface::detach_input()
89 detach_input() -> void
90 { 59 {
91 if (InputCursor > 0) 60 if (InputCursor > 0)
92 { 61 {
93 InputHistory[0] = current_input(); 62 InputHistory[0] = current_input();
94 InputCursor = 0; 63 InputCursor = 0;
96 } 65 }
97 66
98 // ------------------------------------------------------------------------------------------------- 67 // -------------------------------------------------------------------------------------------------
99 // A version of current_input() that allows changing the contents of it. 68 // A version of current_input() that allows changing the contents of it.
100 // 69 //
101 static FUNCTION 70 String& Interface::mutable_current_input()
102 mutable_current_input() -> String&
103 { 71 {
104 detach_input(); 72 detach_input();
105 return InputHistory[InputCursor]; 73 return InputHistory[InputCursor];
106 } 74 }
107 75
108 // ------------------------------------------------------------------------------------------------- 76 // -------------------------------------------------------------------------------------------------
109 // 77 //
110 static FUNCTION 78 void Interface::move_input_cursor (int delta)
111 move_input_cursor (int delta) -> void
112 { 79 {
113 // No input history when inputting addresses or passwords 80 // No input history when inputting addresses or passwords
114 if (CurrentInputState != INPUTSTATE_NORMAL) 81 if (CurrentInputState != INPUTSTATE_NORMAL)
115 { 82 {
116 InputCursor = 0; 83 InputCursor = 0;
127 } 94 }
128 } 95 }
129 96
130 // ------------------------------------------------------------------------------------------------- 97 // -------------------------------------------------------------------------------------------------
131 // 98 //
132 static FUNCTION 99 String Interface::prompt_string()
133 interface_prompt_string() -> String
134 { 100 {
135 String prompt; 101 String prompt;
136 102
137 switch (CurrentInputState) 103 switch (CurrentInputState)
138 { 104 {
145 return prompt; 111 return prompt;
146 } 112 }
147 113
148 // ------------------------------------------------------------------------------------------------- 114 // -------------------------------------------------------------------------------------------------
149 // 115 //
150 static FUNCTION 116 void Interface::set_input_state (InputState newstate)
151 set_input_state (InputState newstate) -> void
152 { 117 {
153 // Clear the input row (unless going to or from confirm state) 118 // Clear the input row (unless going to or from confirm state)
154 if (newstate != INPUTSTATE_CONFIRM_DISCONNECTION 119 if (newstate != INPUTSTATE_CONFIRM_DISCONNECTION
155 and CurrentInputState != INPUTSTATE_CONFIRM_DISCONNECTION) 120 and CurrentInputState != INPUTSTATE_CONFIRM_DISCONNECTION)
156 { 121 {
173 NeedInputRender = true; 138 NeedInputRender = true;
174 } 139 }
175 140
176 // ------------------------------------------------------------------------------------------------- 141 // -------------------------------------------------------------------------------------------------
177 // 142 //
178 FUNCTION 143 Interface::Interface() :
179 Interface::initialize() -> void 144 Session (this)
180 { 145 {
181 ::initscr(); 146 ::initscr();
182 ::start_color(); 147 ::start_color();
183 ::raw(); 148 ::raw();
184 ::keypad (stdscr, true); 149 ::keypad (stdscr, true);
205 NeedRefresh = false; 170 NeedRefresh = false;
206 } 171 }
207 172
208 // ------------------------------------------------------------------------------------------------- 173 // -------------------------------------------------------------------------------------------------
209 // 174 //
210 static FUNCTION 175 void Interface::render_titlebar()
211 interface_render_titlebar() -> void
212 { 176 {
213 if (Title.length() <= COLS) 177 if (Title.length() <= COLS)
214 { 178 {
215 int pair = interface_color_pair (WHITE, BLUE); 179 int pair = color_pair (WHITE, BLUE);
216 int startx = (COLS - Title.length()) / 2; 180 int startx = (COLS - Title.length()) / 2;
217 int endx = startx + Title.length(); 181 int endx = startx + Title.length();
218 attron (pair); 182 attron (pair);
219 mvprintw (0, startx, "%s", Title.chars()); 183 mvprintw (0, startx, "%s", Title.chars());
220 mvhline (0, 0, ' ', startx); 184 mvhline (0, 0, ' ', startx);
225 NeedRefresh = true; 189 NeedRefresh = true;
226 } 190 }
227 191
228 // ------------------------------------------------------------------------------------------------- 192 // -------------------------------------------------------------------------------------------------
229 // 193 //
230 FUNCTION 194 void Interface::set_title (const String& title)
231 Interface::set_title (const String& title) -> void
232 { 195 {
233 Title = title; 196 Title = title;
234 interface_render_titlebar(); 197 render_titlebar();
235 } 198 }
236 199
237 // ------------------------------------------------------------------------------------------------- 200 // -------------------------------------------------------------------------------------------------
238 // 201 //
239 static FUNCTION 202 void Interface::safe_disconnect (Function<void()> afterwards)
240 safe_disconnect (Function<void()> afterwards) -> void 203 {
241 { 204 if (Session.is_active())
242 if (RCONSession::get_session()->is_active())
243 { 205 {
244 DisconnectConfirmFunction = afterwards; 206 DisconnectConfirmFunction = afterwards;
245 set_input_state (INPUTSTATE_CONFIRM_DISCONNECTION); 207 set_input_state (INPUTSTATE_CONFIRM_DISCONNECTION);
246 } 208 }
247 else 209 else
248 afterwards(); 210 afterwards();
249 } 211 }
250 212
251 // ------------------------------------------------------------------------------------------------- 213 // -------------------------------------------------------------------------------------------------
252 // 214 //
253 static FUNCTION 215 int Interface::nicklist_width()
254 interface_nicklist_width() -> int
255 { 216 {
256 // Allocate at least 12 characters, at most 24 characters, for the nicklist. If we cannot 217 // Allocate at least 12 characters, at most 24 characters, for the nicklist. If we cannot
257 // afford that (o_O) then we probably shouldn't draw the nicklist at all I think. 218 // afford that (o_O) then we probably shouldn't draw the nicklist at all I think.
258 int nicklistWidth = COLS / 4; 219 int nicklistWidth = COLS / 4;
259 220
265 226
266 // ------------------------------------------------------------------------------------------------- 227 // -------------------------------------------------------------------------------------------------
267 // Renders the given colored line onto the screen. Will wrap if allowWrap is true. Returns the 228 // Renders the given colored line onto the screen. Will wrap if allowWrap is true. Returns the
268 // 'y' value for the next line. 229 // 'y' value for the next line.
269 // 230 //
270 static FUNCTION 231 int Interface::render_colorline (int y, int x0, int width, const ColoredLine& line, bool allowWrap)
271 interface_render_colorline (int y, int x0, int width,
272 const ColoredLine& line, bool allowWrap) -> int
273 { 232 {
274 int x = x0; 233 int x = x0;
275 234
276 for (int byte : line.data()) 235 for (int byte : line.data())
277 { 236 {
297 case RLINE_ON_YELLOW: 256 case RLINE_ON_YELLOW:
298 case RLINE_ON_BLUE: 257 case RLINE_ON_BLUE:
299 case RLINE_ON_MAGENTA: 258 case RLINE_ON_MAGENTA:
300 case RLINE_ON_CYAN: 259 case RLINE_ON_CYAN:
301 case RLINE_ON_WHITE: 260 case RLINE_ON_WHITE:
302 attron (interface_color_pair (Color (byte - RLINE_ON_BLACK), DEFAULT)); 261 attron (color_pair (Color (byte - RLINE_ON_BLACK), DEFAULT));
303 break; 262 break;
304 263
305 case RLINE_OFF_BLACK: 264 case RLINE_OFF_BLACK:
306 case RLINE_OFF_RED: 265 case RLINE_OFF_RED:
307 case RLINE_OFF_GREEN: 266 case RLINE_OFF_GREEN:
308 case RLINE_OFF_YELLOW: 267 case RLINE_OFF_YELLOW:
309 case RLINE_OFF_BLUE: 268 case RLINE_OFF_BLUE:
310 case RLINE_OFF_MAGENTA: 269 case RLINE_OFF_MAGENTA:
311 case RLINE_OFF_CYAN: 270 case RLINE_OFF_CYAN:
312 case RLINE_OFF_WHITE: 271 case RLINE_OFF_WHITE:
313 attroff (interface_color_pair (Color (byte - RLINE_OFF_BLACK), DEFAULT)); 272 attroff (color_pair (Color (byte - RLINE_OFF_BLACK), DEFAULT));
314 break; 273 break;
315 274
316 case RLINE_ON_BOLD: 275 case RLINE_ON_BOLD:
317 attron (A_BOLD); 276 attron (A_BOLD);
318 break; 277 break;
326 return y + 1; 285 return y + 1;
327 } 286 }
328 287
329 // ------------------------------------------------------------------------------------------------- 288 // -------------------------------------------------------------------------------------------------
330 // 289 //
331 static FUNCTION 290 void Interface::render_output()
332 interface_render_output() -> void
333 { 291 {
334 if (OutputLines.size() == 1) 292 if (OutputLines.size() == 1)
335 return; 293 return;
336 294
337 OutputScroll = clamp (OutputScroll, 0, OutputLines.size() - 1); 295 OutputScroll = clamp (OutputScroll, 0, OutputLines.size() - 1);
338 296
339 int height = LINES - 3; 297 int height = LINES - 3;
340 int width = COLS - interface_nicklist_width(); 298 int width = COLS - nicklist_width();
341 int printOffset = 0; 299 int printOffset = 0;
342 int end = OutputLines.size() - 1 - OutputScroll; 300 int end = OutputLines.size() - 1 - OutputScroll;
343 int start = end; 301 int start = end;
344 int usedHeight = 0; 302 int usedHeight = 0;
345 int y = 1; 303 int y = 1;
395 353
396 // Print the lines 354 // Print the lines
397 y += printOffset; 355 y += printOffset;
398 356
399 for (int i = start; i < end; ++i) 357 for (int i = start; i < end; ++i)
400 y = interface_render_colorline (y, 0, width, OutputLines[i], true); 358 y = render_colorline (y, 0, width, OutputLines[i], true);
401 359
402 NeedOutputRender = false; 360 NeedOutputRender = false;
403 NeedRefresh = true; 361 NeedRefresh = true;
404 } 362 }
405 363
406 // ------------------------------------------------------------------------------------------------- 364 // -------------------------------------------------------------------------------------------------
407 // 365 //
408 static FUNCTION 366 void Interface::render_nicklist()
409 interface_render_nicklist() -> void 367 {
410 { 368 int width = nicklist_width();
411 int width = interface_nicklist_width();
412 int height = LINES- 3; 369 int height = LINES- 3;
413 int y = 1; 370 int y = 1;
414 int x = COLS - width; 371 int x = COLS - width;
415 372
416 if (width == 0) 373 if (width == 0)
440 NeedRefresh = true; 397 NeedRefresh = true;
441 } 398 }
442 399
443 // ------------------------------------------------------------------------------------------------- 400 // -------------------------------------------------------------------------------------------------
444 // 401 //
445 static FUNCTION 402 void Interface::render_input()
446 interface_render_input() -> void 403 {
447 { 404 int promptColor = color_pair (WHITE, BLUE);
448 int promptColor = interface_color_pair (WHITE, BLUE);
449 405
450 // If we're asking the user if they want to disconnect, we don't render any input strings, 406 // If we're asking the user if they want to disconnect, we don't render any input strings,
451 // just the confirmation message. 407 // just the confirmation message.
452 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION) 408 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION)
453 { 409 {
457 attroff (promptColor); 413 attroff (promptColor);
458 NeedRefresh = true; 414 NeedRefresh = true;
459 return; 415 return;
460 } 416 }
461 417
462 String prompt = interface_prompt_string(); 418 String prompt = prompt_string();
463 int displayLength = COLS - prompt.length() - 2; 419 int displayLength = COLS - prompt.length() - 2;
464 String displayString = current_input(); 420 String displayString = current_input();
465 int y = LINES - 2; 421 int y = LINES - 2;
466 422
467 // If we're inputting a password, replace it with asterisks 423 // If we're inputting a password, replace it with asterisks
502 NeedInputRender = false; 458 NeedInputRender = false;
503 } 459 }
504 460
505 // ------------------------------------------------------------------------------------------------- 461 // -------------------------------------------------------------------------------------------------
506 // 462 //
507 static FUNCTION 463 void Interface::render_statusbar()
508 interface_render_statusbar() -> void 464 {
509 { 465 int color = color_pair (WHITE, BLUE);
510 int color = interface_color_pair (WHITE, BLUE);
511 int y = LINES - 1; 466 int y = LINES - 1;
512 attron (color); 467 attron (color);
513 mvhline (y, 0, ' ', COLS); 468 mvhline (y, 0, ' ', COLS);
514 mvprintw (y, 0, "%s", StatusBarText.chars()); 469 mvprintw (y, 0, "%s", StatusBarText.chars());
515 attroff (color); 470 attroff (color);
517 NeedStatusBarRender = false; 472 NeedStatusBarRender = false;
518 } 473 }
519 474
520 // ------------------------------------------------------------------------------------------------- 475 // -------------------------------------------------------------------------------------------------
521 // 476 //
522 FUNCTION 477 void Interface::update_statusbar()
523 Interface::update_statusbar() -> void
524 { 478 {
525 String text; 479 String text;
526 RCONSession* session = RCONSession::get_session(); 480
527 481 switch (Session.state())
528 switch (session->state())
529 { 482 {
530 case RCON_DISCONNECTED: 483 case RCON_DISCONNECTED:
531 text = "Disconnected."; 484 text = "Disconnected.";
532 break; 485 break;
533 486
534 case RCON_CONNECTING: 487 case RCON_CONNECTING:
535 case RCON_AUTHENTICATING: 488 case RCON_AUTHENTICATING:
536 text = "Connecting to " + session->address().to_string (IP_WITH_PORT) + "..."; 489 text = "Connecting to " + Session.address().to_string (IP_WITH_PORT) + "...";
537 break; 490 break;
538 491
539 case RCON_CONNECTED: 492 case RCON_CONNECTED:
540 { 493 {
541 String adminText = (session->num_admins() == 0) ? "No other admins" 494 String adminText;
542 : format ("%1 other admin%s1", session->num_admins()); 495
543 text = format ("%1 | %2 | %3", session->address().to_string (IP_WITH_PORT), 496 if (Session.num_admins() == 0)
544 session->level(), adminText); 497 adminText = "No other admins";
498 else
499 adminText = format ("%1 other admin%s1", Session.num_admins());
500
501 text = format ("%1 | %2 | %3", Session.address().to_string (IP_WITH_PORT),
502 Session.level(), adminText);
545 } 503 }
546 break; 504 break;
547 } 505 }
548 506
549 if (not text.is_empty()) 507 if (not text.is_empty())
558 } 516 }
559 } 517 }
560 518
561 // ------------------------------------------------------------------------------------------------- 519 // -------------------------------------------------------------------------------------------------
562 // 520 //
563 FUNCTION 521 void Interface::render_full()
564 Interface::render_full() -> void
565 { 522 {
566 update_statusbar(); 523 update_statusbar();
567 interface_render_titlebar(); 524 render_titlebar();
568 interface_render_output(); 525 render_output();
569 interface_render_statusbar(); 526 render_statusbar();
570 interface_render_input(); 527 render_input();
571 interface_render_nicklist(); 528 render_nicklist();
572 } 529 }
573 530
574 // ------------------------------------------------------------------------------------------------- 531 // -------------------------------------------------------------------------------------------------
575 // 532 //
576 static FUNCTION 533 void Interface::position_cursor()
577 interface_position_cursor() -> void
578 { 534 {
579 // This is only relevant if the input string is being drawn 535 // This is only relevant if the input string is being drawn
580 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION) 536 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION)
581 return; 537 return;
582 538
583 int y = LINES - 2; 539 int y = LINES - 2;
584 540
585 if (CursorCharacter.ch != '\0') 541 if (CursorCharacter.ch != '\0')
586 mvprintw (y, CursorCharacter.x, "%c", CursorCharacter.ch); 542 mvprintw (y, CursorCharacter.x, "%c", CursorCharacter.ch);
587 else 543 else
588 mvprintw (y, interface_prompt_string().length(), " "); 544 mvprintw (y, prompt_string().length(), " ");
589 } 545 }
590 546
591 // ------------------------------------------------------------------------------------------------- 547 // -------------------------------------------------------------------------------------------------
592 // 548 //
593 static FUNCTION 549 int Interface::find_previous_word()
594 interface_find_previous_word() -> int
595 { 550 {
596 const String& input = current_input(); 551 const String& input = current_input();
597 int pos = CursorPosition; 552 int pos = CursorPosition;
598 553
599 // Move past whitespace 554 // Move past whitespace
607 return pos; 562 return pos;
608 } 563 }
609 564
610 // ------------------------------------------------------------------------------------------------- 565 // -------------------------------------------------------------------------------------------------
611 // 566 //
612 static FUNCTION 567 int Interface::find_next_word()
613 interface_find_next_word() -> int
614 { 568 {
615 const String& input = current_input(); 569 const String& input = current_input();
616 int pos = CursorPosition; 570 int pos = CursorPosition;
617 571
618 // Move past current whitespace 572 // Move past current whitespace
626 return pos; 580 return pos;
627 } 581 }
628 582
629 // ------------------------------------------------------------------------------------------------- 583 // -------------------------------------------------------------------------------------------------
630 // 584 //
631 static FUNCTION 585 void Interface::yank (int a, int b)
632 yank (int a, int b) -> void
633 { 586 {
634 if (a >= b) 587 if (a >= b)
635 return; 588 return;
636 589
637 if (CursorPosition > a and CursorPosition <= b) 590 if (CursorPosition > a and CursorPosition <= b)
643 NeedInputRender = true; 596 NeedInputRender = true;
644 } 597 }
645 598
646 // ------------------------------------------------------------------------------------------------- 599 // -------------------------------------------------------------------------------------------------
647 // 600 //
648 FUNCTION 601 void Interface::handle_input()
649 Interface::handle_input() -> void
650 { 602 {
651 int ch = ::getch(); 603 int ch = ::getch();
652 604
653 if (ch == KEY_RESIZE) 605 if (ch == KEY_RESIZE)
654 { 606 {
659 611
660 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION) 612 if (CurrentInputState == INPUTSTATE_CONFIRM_DISCONNECTION)
661 { 613 {
662 if (ch == 'y' or ch == 'Y') 614 if (ch == 'y' or ch == 'Y')
663 { 615 {
664 RCONSession::get_session()->disconnect(); 616 Session.disconnect();
665 DisconnectConfirmFunction(); 617 DisconnectConfirmFunction();
666 } 618 }
667 else if (ch == 'n' or ch == 'N') 619 else if (ch == 'n' or ch == 'N')
668 set_input_state (INPUTSTATE_NORMAL); 620 set_input_state (INPUTSTATE_NORMAL);
669 621
682 { 634 {
683 case INPUTSTATE_CONFIRM_DISCONNECTION: 635 case INPUTSTATE_CONFIRM_DISCONNECTION:
684 break; 636 break;
685 637
686 case INPUTSTATE_NORMAL: 638 case INPUTSTATE_NORMAL:
687 safe_disconnect ([]() 639 safe_disconnect ([&]()
688 { 640 {
689 RCONSession* session = RCONSession::get_session(); 641 if (Session.is_active())
690
691 if (session->is_active())
692 { 642 {
693 session->disconnect(); 643 Session.disconnect();
694 set_input_state (INPUTSTATE_NORMAL); 644 set_input_state (INPUTSTATE_NORMAL);
695 } 645 }
696 else 646 else
697 { 647 {
698 endwin(); 648 endwin();
789 case 'K' - 'A' + 1: // readline ^K - delete from cursor to end 739 case 'K' - 'A' + 1: // readline ^K - delete from cursor to end
790 yank (CursorPosition, mutable_current_input().length()); 740 yank (CursorPosition, mutable_current_input().length());
791 break; 741 break;
792 742
793 case 'W' - 'A' + 1: // readline ^W - delete from previous word bounary to current 743 case 'W' - 'A' + 1: // readline ^W - delete from previous word bounary to current
794 yank (interface_find_previous_word(), CursorPosition); 744 yank (find_previous_word(), CursorPosition);
795 break; 745 break;
796 746
797 case 'Y' - 'A' + 1: // readline ^Y - paste previously deleted text 747 case 'Y' - 'A' + 1: // readline ^Y - paste previously deleted text
798 if (not PasteBuffer.is_empty()) 748 if (not PasteBuffer.is_empty())
799 { 749 {
806 case '\t': 756 case '\t':
807 { 757 {
808 int space = current_input().find (" "); 758 int space = current_input().find (" ");
809 759
810 if (CurrentInputState == INPUTSTATE_NORMAL 760 if (CurrentInputState == INPUTSTATE_NORMAL
811 and InputCursor > 0 761 and CursorPosition > 0
812 and (space == -1 or space >= InputCursor)) 762 and (space == -1 or space >= CursorPosition))
813 { 763 {
814 String start = current_input().mid (0, InputCursor); 764 String start = current_input().mid (0, CursorPosition);
815 RCONSession::get_session()->request_tab_complete (start); 765 Session.request_tab_complete (start);
816 } 766 }
817 } 767 }
818 break; 768 break;
819 769
820 case '\n': 770 case '\n':
842 break; 792 break;
843 793
844 case INPUTSTATE_PASSWORD: 794 case INPUTSTATE_PASSWORD:
845 if (CurrentInputState == INPUTSTATE_PASSWORD and not current_input().is_empty()) 795 if (CurrentInputState == INPUTSTATE_PASSWORD and not current_input().is_empty())
846 { 796 {
847 RCONSession* session = RCONSession::get_session(); 797 Session.disconnect();
848 session->disconnect(); 798 Session.set_password (current_input());
849 session->set_password (current_input()); 799 Session.connect (CurrentAddress);
850 session->connect (CurrentAddress);
851 set_input_state (INPUTSTATE_NORMAL); 800 set_input_state (INPUTSTATE_NORMAL);
852 } 801 }
853 break; 802 break;
854 803
855 case INPUTSTATE_NORMAL: 804 case INPUTSTATE_NORMAL:
856 if (RCONSession::get_session()->send_command (current_input())) 805 if (Session.send_command (current_input()))
857 { 806 {
858 InputHistory.insert (0, ""); 807 InputHistory.insert (0, "");
859 NeedInputRender = true; 808 NeedInputRender = true;
860 } 809 }
861 break; 810 break;
862 } 811 }
863 break; 812 break;
864 813
865 case 'N' - 'A' + 1: // ^N 814 case 'N' - 'A' + 1: // ^N
866 if (CurrentInputState == INPUTSTATE_NORMAL) 815 if (CurrentInputState == INPUTSTATE_NORMAL)
867 safe_disconnect ([]() {set_input_state (INPUTSTATE_ADDRESS);}); 816 safe_disconnect ([&]() {set_input_state (INPUTSTATE_ADDRESS);});
868 break; 817 break;
869 818
870 case '\e': // Escape 819 case '\e': // Escape
871 // We may have an alt key coming 820 // We may have an alt key coming
872 ch = ::getch(); 821 ch = ::getch();
876 switch (ch) 825 switch (ch)
877 { 826 {
878 case 'b': 827 case 'b':
879 case 'B': 828 case 'B':
880 // readline alt-b - move one word to the left 829 // readline alt-b - move one word to the left
881 CursorPosition = interface_find_previous_word(); 830 CursorPosition = find_previous_word();
882 NeedInputRender = true; 831 NeedInputRender = true;
883 break; 832 break;
884 833
885 case 'f': 834 case 'f':
886 case 'F': 835 case 'F':
887 // readline alt-f - move one word to the right 836 // readline alt-f - move one word to the right
888 CursorPosition = interface_find_next_word(); 837 CursorPosition = find_next_word();
889 NeedInputRender = true; 838 NeedInputRender = true;
890 break; 839 break;
891 840
892 case 'd': 841 case 'd':
893 case 'D': 842 case 'D':
894 // readline alt-d - delete from here till next word boundary 843 // readline alt-d - delete from here till next word boundary
895 yank (CursorPosition, interface_find_next_word()); 844 yank (CursorPosition, find_next_word());
896 break; 845 break;
897 } 846 }
898 } 847 }
899 else 848 else
900 { 849 {
910 render(); 859 render();
911 } 860 }
912 861
913 // ------------------------------------------------------------------------------------------------- 862 // -------------------------------------------------------------------------------------------------
914 // 863 //
915 FUNCTION 864 void Interface::render()
916 Interface::render() -> void 865 {
917 { 866 if (NeedStatusBarRender) render_statusbar();
918 if (NeedStatusBarRender) interface_render_statusbar(); 867 if (NeedInputRender) render_input();
919 if (NeedInputRender) interface_render_input(); 868 if (NeedOutputRender) render_output();
920 if (NeedOutputRender) interface_render_output(); 869 if (NeedNicklistRender) render_nicklist();
921 if (NeedNicklistRender) interface_render_nicklist();
922 870
923 if (NeedRefresh) 871 if (NeedRefresh)
924 { 872 {
925 interface_position_cursor(); 873 position_cursor();
926 refresh(); 874 refresh();
927 NeedRefresh = false; 875 NeedRefresh = false;
928 } 876 }
929 } 877 }
930 878
931 // ------------------------------------------------------------------------------------------------- 879 // -------------------------------------------------------------------------------------------------
932 // 880 //
933 FUNCTION print_to_console (String a) -> void 881 void Interface::print_to_console (String a)
934 { 882 {
935 // Zandronum is retarded and SOMETIMES sends color codes as "\\c" and sometimes as "\x1C". 883 // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C".
936 // Let's correct that on our end and HOPE this won't cause conflicts. 884 // Let's correct that on our end and hope this won't cause conflicts.
937 a.replace ("\\c", "\x1C"); 885 a.replace ("\\c", "\x1C");
938 886
939 for (char ch : a) 887 for (char ch : a)
940 { 888 {
941 if (ch == '\n') 889 if (ch == '\n')
962 NeedOutputRender = true; 910 NeedOutputRender = true;
963 } 911 }
964 912
965 // ------------------------------------------------------------------------------------------------- 913 // -------------------------------------------------------------------------------------------------
966 // 914 //
967 FUNCTION 915 void Interface::connect (String address, String password)
968 Interface::connect (String address, String password) -> void
969 { 916 {
970 try 917 try
971 { 918 {
972 CurrentAddress = IPAddress::from_string (address); 919 CurrentAddress = IPAddress::from_string (address);
973 } 920 }
978 } 925 }
979 926
980 if (CurrentAddress.port == 0) 927 if (CurrentAddress.port == 0)
981 CurrentAddress.port = 10666; 928 CurrentAddress.port = 10666;
982 929
983 RCONSession* session = RCONSession::get_session(); 930 Session.disconnect();
984 session->disconnect(); 931 Session.set_password (password);
985 session->set_password (password); 932 Session.connect (CurrentAddress);
986 session->connect (CurrentAddress); 933 }
987 } 934
988 935 // -------------------------------------------------------------------------------------------------
989 // ------------------------------------------------------------------------------------------------- 936 //
990 // 937 void Interface::set_player_names (const StringList& names)
991 FUNCTION
992 Interface::set_player_names (const StringList& names) -> void
993 { 938 {
994 PlayerNames = names; 939 PlayerNames = names;
995 NeedNicklistRender = true; 940 NeedNicklistRender = true;
996 } 941 }
997 942
998 // ------------------------------------------------------------------------------------------------- 943 // -------------------------------------------------------------------------------------------------
999 // 944 //
1000 FUNCTION 945 void Interface::tab_complete (const String& part, String complete)
1001 Interface::tab_complete (const String& part, String complete) -> void
1002 { 946 {
1003 String& input = mutable_current_input(); 947 String& input = mutable_current_input();
1004 948
1005 if (input.starts_with (part)) 949 if (input.starts_with (part))
1006 { 950 {
1007 if (input[part.length()] != ' ') 951 if (input[part.length()] != ' ')
1008 complete += ' '; 952 complete += ' ';
1009 953
1010 input.replace (0, part.length(), complete); 954 input.replace (0, part.length(), complete);
1011 InputCursor = complete.length(); 955 CursorPosition = complete.length();
1012 NeedInputRender = true; 956 NeedInputRender = true;
1013 } 957 }
1014 } 958 }

mercurial