sources/interface.cpp

changeset 182
20ca0a6be175
parent 181
e254398fcc7c
child 183
9b6a0daedfc0
equal deleted inserted replaced
181:e254398fcc7c 182:20ca0a6be175
201 201
202 // ------------------------------------------------------------------------------------------------- 202 // -------------------------------------------------------------------------------------------------
203 // 203 //
204 void Interface::renderTitlebar() 204 void Interface::renderTitlebar()
205 { 205 {
206 if (m_title.length() <= COLS) 206 if (static_cast<signed>(m_title.length()) <= COLS)
207 { 207 {
208 chtype pair = getColorPair(WHITE, BLUE); 208 chtype pair = getColorPair(WHITE, BLUE);
209 int startx =(COLS - m_title.length()) / 2; 209 int startx =(COLS - m_title.length()) / 2;
210 int endx = startx + m_title.length(); 210 int endx = startx + m_title.length();
211 attron(pair); 211 attron(pair);
212 mvprintw(0, startx, "%s", m_title.chars()); 212 mvprintw(0, startx, "%s", m_title.data());
213 mvhline(0, 0, ' ', startx); 213 mvhline(0, 0, ' ', startx);
214 mvhline(0, endx, ' ', COLS - endx); 214 mvhline(0, endx, ' ', COLS - endx);
215 attroff(pair); 215 attroff(pair);
216 } 216 }
217 217
428 for (char &ch : displayString) 428 for (char &ch : displayString)
429 ch = '*'; 429 ch = '*';
430 } 430 }
431 431
432 // Ensure the cursor is within bounds 432 // Ensure the cursor is within bounds
433 m_cursorPosition = clamp(m_cursorPosition, 0, displayString.length()); 433 m_cursorPosition = clamp(m_cursorPosition, 0, static_cast<signed>(displayString.length()));
434 434
435 // Ensure that the cursor is always in view, adjust panning if this is not the case 435 // Ensure that the cursor is always in view, adjust panning if this is not the case
436 if (m_cursorPosition > m_inputPanning + displayLength) 436 if (m_cursorPosition > m_inputPanning + displayLength)
437 m_inputPanning = m_cursorPosition - displayLength; // cursor went too far right 437 m_inputPanning = m_cursorPosition - displayLength; // cursor went too far right
438 else if (m_cursorPosition < m_inputPanning) 438 else if (m_cursorPosition < m_inputPanning)
443 int end = min<int>(displayString.length(), start + displayLength); 443 int end = min<int>(displayString.length(), start + displayLength);
444 assert(m_cursorPosition >= start and m_cursorPosition <= end); 444 assert(m_cursorPosition >= start and m_cursorPosition <= end);
445 445
446 // Render the input string 446 // Render the input string
447 mvhline(LINES - 2, 0, ' ', COLS); 447 mvhline(LINES - 2, 0, ' ', COLS);
448 mvprintw(y, prompt.length() + 1, "%s", displayString.mid(start, end).chars()); 448 mvprintw(y, prompt.length() + 1, "%s", mid(displayString, start, end).data());
449 449
450 // Render the prompt 450 // Render the prompt
451 attron(promptColor); 451 attron(promptColor);
452 mvprintw(y, 0, "%s", prompt.chars()); 452 mvprintw(y, 0, "%s", prompt.data());
453 attroff(promptColor); 453 attroff(promptColor);
454 454
455 // Store in memory where the cursor is now(so that we can re-draw it to position the terminal 455 // Store in memory where the cursor is now(so that we can re-draw it to position the terminal
456 // cursor). 456 // cursor).
457 m_cursorCharacter.ch = m_cursorPosition != 0 ? displayString[m_cursorPosition - 1] : '\0'; 457 m_cursorCharacter.ch = m_cursorPosition != 0 ? displayString[m_cursorPosition - 1] : '\0';
466 { 466 {
467 chtype color = getColorPair(WHITE, BLUE); 467 chtype color = getColorPair(WHITE, BLUE);
468 int y = LINES - 1; 468 int y = LINES - 1;
469 attron(color); 469 attron(color);
470 mvhline(y, 0, ' ', COLS); 470 mvhline(y, 0, ' ', COLS);
471 mvprintw(y, 0, "%s", m_statusBarText.chars()); 471 mvprintw(y, 0, "%s", m_statusBarText.data());
472 attroff(color); 472 attroff(color);
473 m_needRefresh = true; 473 m_needRefresh = true;
474 m_needStatusBarRender = false; 474 m_needStatusBarRender = false;
475 } 475 }
476 476
499 { 499 {
500 adminText = "No other admins"; 500 adminText = "No other admins";
501 } 501 }
502 else 502 else
503 { 503 {
504 adminText.sprintf("%d other admin%s", m_session.getAdminCount(), 504 adminText = zfc::sprintf("%d other admin%s", m_session.getAdminCount(),
505 m_session.getAdminCount() != 1 ? "s" : ""); 505 m_session.getAdminCount() != 1 ? "s" : "");
506 } 506 }
507 507
508 text.sprintf("%s | %s | %s", 508 text = zfc::sprintf("%s | %s | %s",
509 m_session.address().to_string(IPAddress::WITH_PORT).chars(), 509 m_session.address().to_string(IPAddress::WITH_PORT).data(),
510 m_session.getLevel().chars(), 510 m_session.getLevel().data(),
511 adminText.chars()); 511 adminText.data());
512 } 512 }
513 break; 513 break;
514 } 514 }
515 515
516 if (not text.isEmpty()) 516 if (not text.empty())
517 text += " | "; 517 text += " | ";
518 518
519 text += "Ctrl+N to connect, Ctrl+Q to "; 519 text += "Ctrl+N to connect, Ctrl+Q to ";
520 text +=(m_session.getState() == RCON_DISCONNECTED) ? "quit" : "disconnect"; 520 text +=(m_session.getState() == RCON_DISCONNECTED) ? "quit" : "disconnect";
521 521
578 { 578 {
579 const String& input = getCurrentInput(); 579 const String& input = getCurrentInput();
580 int pos = m_cursorPosition; 580 int pos = m_cursorPosition;
581 581
582 // Move past current whitespace 582 // Move past current whitespace
583 while (pos < input.length() and isspace(input[pos])) 583 while (pos < static_cast<signed>(input.length()) and isspace(input[pos]))
584 pos++; 584 pos++;
585 585
586 // Move past the word 586 // Move past the word
587 while (input[pos] != '\0' and not isspace(input[pos])) 587 while (input[pos] != '\0' and not isspace(input[pos]))
588 pos++; 588 pos++;
599 599
600 if (m_cursorPosition > a and m_cursorPosition <= b) 600 if (m_cursorPosition > a and m_cursorPosition <= b)
601 m_cursorPosition = a; 601 m_cursorPosition = a;
602 602
603 String& input = getEditableInput(); 603 String& input = getEditableInput();
604 m_pasteBuffer = input.mid(a, b); 604 m_pasteBuffer = mid(input, a, b);
605 input.remove(a, b - a); 605 input = remove_range(input, a, b - a);
606 m_needInputRender = true; 606 m_needInputRender = true;
607 } 607 }
608 608
609 // ------------------------------------------------------------------------------------------------- 609 // -------------------------------------------------------------------------------------------------
610 // 610 //
635 return; 635 return;
636 } 636 }
637 637
638 if (ch >= 0x20 and ch <= 0x7E) 638 if (ch >= 0x20 and ch <= 0x7E)
639 { 639 {
640 getEditableInput().insert(m_cursorPosition++, char(ch)); 640 std::string& input = getEditableInput();
641 input.insert(input.begin() + m_cursorPosition, char(ch));
642 m_cursorPosition += 1;
641 m_needInputRender = true; 643 m_needInputRender = true;
642 } 644 }
643 else switch (ch) 645 else switch (ch)
644 { 646 {
645 case 'Q' - 'A' + 1: // ^Q 647 case 'Q' - 'A' + 1: // ^Q
681 } 683 }
682 break; 684 break;
683 685
684 case KEY_RIGHT: 686 case KEY_RIGHT:
685 case 'F' - 'A' + 1: // readline ^F 687 case 'F' - 'A' + 1: // readline ^F
686 if (m_cursorPosition < getCurrentInput().length()) 688 if (m_cursorPosition < static_cast<int>(getCurrentInput().length()))
687 { 689 {
688 m_cursorPosition++; 690 m_cursorPosition++;
689 m_needInputRender = true; 691 m_needInputRender = true;
690 } 692 }
691 break; 693 break;
704 } 706 }
705 break; 707 break;
706 708
707 case KEY_END: 709 case KEY_END:
708 case 'E' - 'A' + 1: // readline ^E 710 case 'E' - 'A' + 1: // readline ^E
709 if (m_cursorPosition != getCurrentInput().length()) 711 if (m_cursorPosition != static_cast<signed>(getCurrentInput().length()))
710 { 712 {
711 m_cursorPosition = getCurrentInput().length(); 713 m_cursorPosition = getCurrentInput().length();
712 m_needInputRender = true; 714 m_needInputRender = true;
713 } 715 }
714 break; 716 break;
715 717
716 case KEY_BACKSPACE: 718 case KEY_BACKSPACE:
717 case '\b': 719 case '\b':
718 if (m_cursorPosition > 0) 720 if (m_cursorPosition > 0)
719 { 721 {
720 getEditableInput().removeAt(--m_cursorPosition); 722 String& input = getEditableInput();
723 input.erase(input.begin() + m_cursorPosition);
724 m_cursorPosition -= 1;
721 m_needInputRender = true; 725 m_needInputRender = true;
722 } 726 }
723 break; 727 break;
724 728
725 case KEY_DC: 729 case KEY_DC:
726 case 'D' - 'A' + 1: // readline ^D 730 case 'D' - 'A' + 1: // readline ^D
727 if (m_cursorPosition < getCurrentInput().length()) 731 if (m_cursorPosition < static_cast<signed>(getCurrentInput().length()))
728 { 732 {
729 getEditableInput().removeAt(m_cursorPosition); 733 String& input = getEditableInput();
734 input.erase(input.begin() + m_cursorPosition);
730 m_needInputRender = true; 735 m_needInputRender = true;
731 } 736 }
732 break; 737 break;
733 738
734 case KEY_PPAGE: 739 case KEY_PPAGE:
756 case 'W' - 'A' + 1: // readline ^W - delete from previous word bounary to current 761 case 'W' - 'A' + 1: // readline ^W - delete from previous word bounary to current
757 yank(findPreviousWord(), m_cursorPosition); 762 yank(findPreviousWord(), m_cursorPosition);
758 break; 763 break;
759 764
760 case 'Y' - 'A' + 1: // readline ^Y - paste previously deleted text 765 case 'Y' - 'A' + 1: // readline ^Y - paste previously deleted text
761 if (not m_pasteBuffer.isEmpty()) 766 if (not m_pasteBuffer.empty())
762 { 767 {
763 getEditableInput().insert(m_cursorPosition, m_pasteBuffer); 768 getEditableInput().insert(m_cursorPosition, m_pasteBuffer);
764 m_cursorPosition += m_pasteBuffer.length(); 769 m_cursorPosition += m_pasteBuffer.length();
765 m_needInputRender = true; 770 m_needInputRender = true;
766 } 771 }
772 777
773 if (m_inputState == INPUTSTATE_NORMAL 778 if (m_inputState == INPUTSTATE_NORMAL
774 and m_cursorPosition > 0 779 and m_cursorPosition > 0
775 and(space == -1 or space >= m_cursorPosition)) 780 and(space == -1 or space >= m_cursorPosition))
776 { 781 {
777 String start = getCurrentInput().mid(0, m_cursorPosition); 782 String start = mid(getCurrentInput(), 0, m_cursorPosition);
778 m_session.requestTabCompletion(start); 783 m_session.requestTabCompletion(start);
779 } 784 }
780 } 785 }
781 break; 786 break;
782 787
804 809
805 setInputState(INPUTSTATE_PASSWORD); 810 setInputState(INPUTSTATE_PASSWORD);
806 break; 811 break;
807 812
808 case INPUTSTATE_PASSWORD: 813 case INPUTSTATE_PASSWORD:
809 if (m_inputState == INPUTSTATE_PASSWORD and not getCurrentInput().isEmpty()) 814 if (m_inputState == INPUTSTATE_PASSWORD and not getCurrentInput().empty())
810 { 815 {
811 m_session.disconnect(); 816 m_session.disconnect();
812 m_session.setPassword(getCurrentInput()); 817 m_session.setPassword(getCurrentInput());
813 m_session.connect(m_remoteAddress); 818 m_session.connect(m_remoteAddress);
814 setInputState(INPUTSTATE_NORMAL); 819 setInputState(INPUTSTATE_NORMAL);
902 // ------------------------------------------------------------------------------------------------- 907 // -------------------------------------------------------------------------------------------------
903 // 908 //
904 void Interface::vprint(const char* fmtstr, va_list args) 909 void Interface::vprint(const char* fmtstr, va_list args)
905 { 910 {
906 String message; 911 String message;
907 message.vsprintf(fmtstr, args); 912 message = vsprintf(fmtstr, args);
908 printToConsole(message); 913 printToConsole(message);
909 } 914 }
910 915
911 // ------------------------------------------------------------------------------------------------- 916 // -------------------------------------------------------------------------------------------------
912 // 917 //
955 // 960 //
956 void Interface::printToConsole(String message) 961 void Interface::printToConsole(String message)
957 { 962 {
958 // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C". 963 // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C".
959 // Let's correct that on our end and hope this won't cause conflicts. 964 // Let's correct that on our end and hope this won't cause conflicts.
960 message.replace("\\c", "\x1C"); 965 replace_all(message, "\\c", "\x1C");
961 966
962 for (char ch : message) 967 for (char ch : message)
963 { 968 {
964 if (ch == '\n') 969 if (ch == '\n')
965 { 970 {
1032 // 1037 //
1033 void Interface::tabComplete(const String& part, String complete) 1038 void Interface::tabComplete(const String& part, String complete)
1034 { 1039 {
1035 String& input = getEditableInput(); 1040 String& input = getEditableInput();
1036 1041
1037 if (input.startsWith(part)) 1042 if (starts_with(input, part))
1038 { 1043 {
1039 if (input[part.length()] != ' ') 1044 if (input[part.length()] != ' ')
1040 complete += ' '; 1045 complete += ' ';
1041 1046
1042 input.replace(0, part.length(), complete); 1047 input.replace(0, part.length(), complete);
1050 void Interface::handleCommand(const String& input) 1055 void Interface::handleCommand(const String& input)
1051 { 1056 {
1052 if (input[0] != '/') 1057 if (input[0] != '/')
1053 return; 1058 return;
1054 1059
1055 StringList args = input.right(input.length() - 1).split(" "); 1060 StringList args = split(right(input, input.length() - 1), " ");
1056 String command = args[0].toLowerCase(); 1061 String command = to_lowercase(args[0]);
1057 args.erase(args.begin()); 1062 args.erase(args.begin());
1058 1063
1059 if (command == "connect") 1064 if (command == "connect")
1060 { 1065 {
1061 if (args.size() != 2) 1066 if (args.size() != 2)
1093 m_session.disconnect(); 1098 m_session.disconnect();
1094 endwin(); 1099 endwin();
1095 throw Exitception(); 1100 throw Exitception();
1096 } 1101 }
1097 else 1102 else
1098 printError("Unknown command: %s\n", command.chars()); 1103 printError("Unknown command: %s\n", command.data());
1099 } 1104 }
1100 1105
1101 // ------------------------------------------------------------------------------------------------- 1106 // -------------------------------------------------------------------------------------------------
1102 // 1107 //
1103 void Interface::disconnected() 1108 void Interface::disconnected()
1104 { 1109 {
1105 print("Disconnected from %s\n", m_session.address().to_string(IPAddress::WITH_PORT).chars()); 1110 print("Disconnected from %s\n", m_session.address().to_string(IPAddress::WITH_PORT).data());
1106 resetTitle(); 1111 resetTitle();
1107 renderFull(); 1112 renderFull();
1108 } 1113 }
1109 1114
1110 // ------------------------------------------------------------------------------------------------- 1115 // -------------------------------------------------------------------------------------------------
1111 // 1116 //
1112 void Interface::resetTitle() 1117 void Interface::resetTitle()
1113 { 1118 {
1114 m_title.sprintf("%s %s (%s)", application_name(), full_version_string(), changeset_date_string()); 1119 m_title = sprintf("%s %s (%s)", application_name(), full_version_string(), changeset_date_string());
1115 } 1120 }
1116 1121
1117 // ------------------------------------------------------------------------------------------------- 1122 // -------------------------------------------------------------------------------------------------
1118 // 1123 //
1119 void Interface::flushInput() 1124 void Interface::flushInput()

mercurial