sources/interface.cpp

branch
protocol5
changeset 84
3bd32eec3d57
parent 80
f992b027374b
parent 83
08bfc3d9d2ae
child 103
b78c0ca832a9
equal deleted inserted replaced
80:f992b027374b 84:3bd32eec3d57
39 39
40 // ------------------------------------------------------------------------------------------------- 40 // -------------------------------------------------------------------------------------------------
41 // 41 //
42 int Interface::color_pair (Color fg, Color bg) 42 int Interface::color_pair (Color fg, Color bg)
43 { 43 {
44 return COLOR_PAIR ((int (fg) * NUM_COLORS) + int (bg)); 44 return COLOR_PAIR (1 + (int (fg) * NUM_COLORS) + int (bg));
45 } 45 }
46 46
47 // ------------------------------------------------------------------------------------------------- 47 // -------------------------------------------------------------------------------------------------
48 // 48 //
49 const String& Interface::current_input() 49 const String& Interface::current_input()
141 // ------------------------------------------------------------------------------------------------- 141 // -------------------------------------------------------------------------------------------------
142 // 142 //
143 Interface::Interface() : 143 Interface::Interface() :
144 Session (this) 144 Session (this)
145 { 145 {
146 ::initscr(); 146 #ifdef XCURSES
147 ::start_color(); 147 ::Xinitscr(argc, argv);
148 ::raw(); 148 #else
149 ::initscr();
150 #endif
151
152 ::cbreak();
149 ::keypad (stdscr, true); 153 ::keypad (stdscr, true);
150 ::noecho(); 154 ::noecho();
151 ::refresh(); 155 ::refresh();
152 ::timeout (0); 156 ::timeout (0);
153 ::use_default_colors();
154 InputHistory.clear(); 157 InputHistory.clear();
155 InputHistory << ""; 158 InputHistory << "";
156 OutputLines.clear(); 159 OutputLines.clear();
157 OutputLines << ColoredLine(); 160 OutputLines << ColoredLine();
158 161 Title.sprintf (APPNAME " %s (%d)", full_version_string(), changeset_date_string());
159 for (int i = 0; i < NUM_COLORS; ++i) 162
160 for (int j = 0; j < NUM_COLORS; ++j) 163 if (::has_colors())
161 { 164 {
162 init_pair ((i * NUM_COLORS + j), 165 ::start_color();
163 (i == DEFAULT) ? -1 : i, 166 ::use_default_colors();
164 (j == DEFAULT) ? -1 : j); 167
168 int defaultFg = (use_default_colors() == OK) ? -1 : COLOR_WHITE;
169 int defaultBg = (use_default_colors() == OK) ? -1 : COLOR_BLACK;
170
171 // Initialize color pairs
172 for (int i = 0; i < NUM_COLORS; ++i)
173 for (int j = 0; j < NUM_COLORS; ++j)
174 {
175 int pairnum = 1 + (i * NUM_COLORS + j);
176 int fg = (i == DEFAULT) ? defaultFg : i;
177 int bg = (j == DEFAULT) ? defaultBg : j;
178
179 if (::init_pair (pairnum, fg, bg) == ERR)
180 print ("Unable to initialize color pair %d (%d, %d)\n", pairnum, fg, bg);
181 }
182 }
183 else
184 {
185 print ("This terminal does not appear to support colors.\n");
165 } 186 }
166 187
167 render_full(); 188 render_full();
168 refresh(); 189 refresh();
169 NeedRefresh = false; 190 NeedRefresh = false;
171 192
172 // ------------------------------------------------------------------------------------------------- 193 // -------------------------------------------------------------------------------------------------
173 // 194 //
174 void Interface::render_titlebar() 195 void Interface::render_titlebar()
175 { 196 {
176 String message = Title; 197 if (Title.length() <= COLS)
177
178 if (Title.is_empty())
179 message = format (APPNAME " %1 (%2)", full_version_string(), changeset_date_string());
180
181 if (message.length() <= COLS)
182 { 198 {
183 int pair = color_pair (WHITE, BLUE); 199 int pair = color_pair (WHITE, BLUE);
184 int startx = (COLS - message.length()) / 2; 200 int startx = (COLS - Title.length()) / 2;
185 int endx = startx + message.length(); 201 int endx = startx + Title.length();
186 attron (pair); 202 attron (pair);
187 mvprintw (0, startx, "%s", message.chars()); 203 mvprintw (0, startx, "%s", Title.chars());
188 mvhline (0, 0, ' ', startx); 204 mvhline (0, 0, ' ', startx);
189 mvhline (0, endx, ' ', COLS - endx); 205 mvhline (0, endx, ' ', COLS - endx);
190 attroff (pair); 206 attroff (pair);
191 } 207 }
192 208
380 for (int i = 0; i < height; ++i) 396 for (int i = 0; i < height; ++i)
381 { 397 {
382 mvhline (y, x, ' ', width); 398 mvhline (y, x, ' ', width);
383 399
384 if (i < PlayerNames.size()) 400 if (i < PlayerNames.size())
385 render_colorline (y, x, width, PlayerNames[i], false); 401 {
402 String displaynick = PlayerNames[i];
403
404 if (displaynick.length() > width)
405 {
406 displaynick = displaynick.mid (0, width - 3);
407 displaynick += "...";
408 }
409
410 mvprintw (y, x, "%s", displaynick.chars());
411 }
386 412
387 y++; 413 y++;
388 } 414 }
389 415
390 NeedNicklistRender = false; 416 NeedNicklistRender = false;
486 case RCON_CONNECTED: 512 case RCON_CONNECTED:
487 { 513 {
488 String adminText; 514 String adminText;
489 515
490 if (Session.num_admins() == 0) 516 if (Session.num_admins() == 0)
517 {
491 adminText = "No other admins"; 518 adminText = "No other admins";
519 }
492 else 520 else
493 adminText = format ("%1 other admin%s1", Session.num_admins()); 521 {
494 522 adminText.sprintf ("%d other admin%s", Session.num_admins(),
495 text = format ("%1 | %2 | %3", Session.address().to_string (IP_WITH_PORT), 523 Session.num_admins() != 1 ? "s" : "");
496 Session.level(), adminText); 524 }
525
526 text.sprintf ("%s | %s | %s", Session.address().to_string (IP_WITH_PORT).chars(),
527 Session.level().chars(), adminText.chars());
497 } 528 }
498 break; 529 break;
499 } 530 }
500 531
501 if (not text.is_empty()) 532 if (not text.is_empty())
502 text += " | "; 533 text += " | ";
503 534
504 text += "^N to connect, ^Q to quit"; 535 text += "Ctrl+N to connect, Ctrl+Q to quit";
505 536
506 if (text != StatusBarText) 537 if (text != StatusBarText)
507 { 538 {
508 StatusBarText = text; 539 StatusBarText = text;
509 NeedStatusBarRender = true; 540 NeedStatusBarRender = true;
593 // ------------------------------------------------------------------------------------------------- 624 // -------------------------------------------------------------------------------------------------
594 // 625 //
595 void Interface::handle_input() 626 void Interface::handle_input()
596 { 627 {
597 int ch = ::getch(); 628 int ch = ::getch();
629
630 if (ch < 0)
631 return;
598 632
599 if (ch == KEY_RESIZE) 633 if (ch == KEY_RESIZE)
600 { 634 {
601 ::clear(); 635 ::clear();
602 render_full(); 636 render_full();
694 NeedInputRender = true; 728 NeedInputRender = true;
695 } 729 }
696 break; 730 break;
697 731
698 case KEY_BACKSPACE: 732 case KEY_BACKSPACE:
733 case '\b':
699 if (CursorPosition > 0) 734 if (CursorPosition > 0)
700 { 735 {
701 mutable_current_input().remove_at (--CursorPosition); 736 mutable_current_input().remove_at (--CursorPosition);
702 NeedInputRender = true; 737 NeedInputRender = true;
703 } 738 }
773 { 808 {
774 CurrentAddress = IPAddress::from_string (current_input()); 809 CurrentAddress = IPAddress::from_string (current_input());
775 } 810 }
776 catch (std::exception& e) 811 catch (std::exception& e)
777 { 812 {
778 print ("%1\n", e.what()); 813 print ("%s\n", e.what());
779 return; 814 return;
780 } 815 }
781 816
782 if (CurrentAddress.port == 0) 817 if (CurrentAddress.port == 0)
783 CurrentAddress.port = 10666; 818 CurrentAddress.port = 10666;
870 } 905 }
871 } 906 }
872 907
873 // ------------------------------------------------------------------------------------------------- 908 // -------------------------------------------------------------------------------------------------
874 // 909 //
910 void Interface::vprint (const char* fmtstr, va_list args)
911 {
912 String message;
913 message.vsprintf (fmtstr, args);
914 print_to_console (message);
915 }
916
917 // -------------------------------------------------------------------------------------------------
918 //
919 void __cdecl Interface::print (const char* fmtstr, ...)
920 {
921 va_list args;
922 va_start (args, fmtstr);
923 vprint (fmtstr, args);
924 va_end (args);
925 }
926
927 // -------------------------------------------------------------------------------------------------
928 //
929 void __cdecl Interface::print_warning (const char* fmtstr, ...)
930 {
931 va_list args;
932 va_start (args, fmtstr);
933 print_to_console (TEXTCOLOR_BrightYellow "-!- ");
934 vprint (fmtstr, args);
935 print_to_console (TEXTCOLOR_Reset);
936 va_end (args);
937 }
938
939 // -------------------------------------------------------------------------------------------------
940 //
941 void __cdecl Interface::print_error (const char* fmtstr, ...)
942 {
943 va_list args;
944 va_start (args, fmtstr);
945 print_to_console (TEXTCOLOR_BrightRed "!!! ");
946 vprint (fmtstr, args);
947 print_to_console (TEXTCOLOR_Reset);
948 va_end (args);
949 }
950
951 // -------------------------------------------------------------------------------------------------
952 //
875 void Interface::print_to_console (String a) 953 void Interface::print_to_console (String a)
876 { 954 {
877 // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C". 955 // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C".
878 // Let's correct that on our end and hope this won't cause conflicts. 956 // Let's correct that on our end and hope this won't cause conflicts.
879 a.replace ("\\c", "\x1C"); 957 a.replace ("\\c", "\x1C");
912 { 990 {
913 CurrentAddress = IPAddress::from_string (address); 991 CurrentAddress = IPAddress::from_string (address);
914 } 992 }
915 catch (std::exception& e) 993 catch (std::exception& e)
916 { 994 {
917 print ("%1\n", e.what()); 995 print ("%s\n", e.what());
918 return; 996 return;
919 } 997 }
920 998
921 if (CurrentAddress.port == 0) 999 if (CurrentAddress.port == 0)
922 CurrentAddress.port = 10666; 1000 CurrentAddress.port = 10666;
928 1006
929 // ------------------------------------------------------------------------------------------------- 1007 // -------------------------------------------------------------------------------------------------
930 // 1008 //
931 void Interface::set_player_names (const StringList& names) 1009 void Interface::set_player_names (const StringList& names)
932 { 1010 {
933 PlayerNames.clear(); 1011 PlayerNames = names;
934
935 for (const String& name : names)
936 {
937 ColoredLine coloredname;
938 coloredname.add_string (name);
939 coloredname.finalize();
940 PlayerNames.append (coloredname);
941 }
942
943 NeedNicklistRender = true; 1012 NeedNicklistRender = true;
944 } 1013 }
945 1014
946 // ------------------------------------------------------------------------------------------------- 1015 // -------------------------------------------------------------------------------------------------
947 // 1016 //
957 input.replace (0, part.length(), complete); 1026 input.replace (0, part.length(), complete);
958 CursorPosition = complete.length(); 1027 CursorPosition = complete.length();
959 NeedInputRender = true; 1028 NeedInputRender = true;
960 } 1029 }
961 } 1030 }
962
963 // -------------------------------------------------------------------------------------------------
964 //
965 void Interface::disconnected()
966 {
967 Title = "";
968 update_statusbar();
969 render_titlebar();
970 }

mercurial