@@ -404,7 +404,7 @@ void Console::Update()
404404 Rect r = CellRect (cursorX, cursorY);
405405 if (cursorDrawn)
406406 DrawCell (cursorX, cursorY, true );
407- else
407+ else if (cursorRequestedHidden == false )
408408 InvertRect (&r);
409409 cursorDrawn = !cursorDrawn;
410410 }
@@ -546,8 +546,18 @@ char Console::WaitNextChar()
546546// Map a letter to a function
547547void Console::InitEscapeSequenceMap ()
548548{
549- escapeSequenceMap.insert ({' H' , [&](std::string args) { Console::SetCursorPosition (args); } });
549+ escapeSequenceMap.insert ({' A' , [&](std::string args) { MoveCursorUp (args); } });
550+ escapeSequenceMap.insert ({' B' , [&](std::string args) { MoveCursorDown (args); } });
551+ escapeSequenceMap.insert ({' C' , [&](std::string args) { MoveCursorForward (args); } });
552+ escapeSequenceMap.insert ({' D' , [&](std::string args) { MoveCursorBack (args); } });
553+ escapeSequenceMap.insert ({' E' , [&](std::string args) { MoveCursorNextLine (args); } });
554+ escapeSequenceMap.insert ({' F' , [&](std::string args) { MoveCursorPreviousLine (args); } });
555+ escapeSequenceMap.insert ({' G' , [&](std::string args) { MoveCursorHorizonalAbsolute (args); } });
556+ escapeSequenceMap.insert ({' H' , [&](std::string args) { SetCursorPosition (args); } });
550557 escapeSequenceMap.insert ({' J' , [&](std::string args) { EraseInDisplay (args); } });
558+ escapeSequenceMap.insert ({' K' , [&](std::string args) { EraseInLine (args); } });
559+ escapeSequenceMap.insert ({' h' , [&](std::string args) { ShowCursor (args); } });
560+ escapeSequenceMap.insert ({' l' , [&](std::string args) { HideCursor (args); } });
551561 escapeSequenceMap.insert ({' m' , [&](std::string args) { SetDisplayAttributes (args); } });
552562}
553563
@@ -590,8 +600,8 @@ void Console::SetCursorPosition(std::string args)
590600 // -> (1,1)
591601
592602 auto numberVector = parseArguments (args);
593- cursorX = numberVector.at (1 );
594- cursorY = numberVector.at (0 );
603+ SetCursorX ( numberVector.at (1 ) );
604+ SetCursorY ( numberVector.at (0 ) );
595605 Update ();
596606}
597607
@@ -667,7 +677,7 @@ void Console::ClearWindow()
667677// Clears the window of text from the current cursor position to the bottom of the window
668678void Console::ClearFromCursorToEndOfWindow ()
669679{
670- int newPosition = cursorY * cols + cursorX ;
680+ int newPosition = GetCursorY () * cols + GetCursorX () - 1 ;
671681
672682 // Fill the buffer with blank spaces
673683 std::fill (chars.begin () + newPosition, chars.end (), AttributedChar (' ' , currentAttr));
@@ -682,7 +692,7 @@ void Console::ClearFromCursorToEndOfWindow()
682692// Clears the window from the top to the current cursor position
683693void Console::ClearFromTopOfWindowToCursor ()
684694{
685- int newPosition = cursorY * cols + cursorX ;
695+ int newPosition = GetCursorY () * cols + GetCursorX () ;
686696
687697 // Fill the buffer with blank spaces
688698 std::fill (chars.begin (), chars.begin () + newPosition, AttributedChar (' ' , currentAttr));
@@ -710,3 +720,247 @@ void Console::HandleControlSequence(char c)
710720 argument = argument + c;
711721 }
712722}
723+
724+ // Bound to ANSI escape code A
725+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
726+ // Section: Some ANSI control sequences
727+ // Name: Cursor Up
728+ void Console::MoveCursorUp (std::string args)
729+ {
730+ auto numberVector = parseArguments (args);
731+ int lines;
732+ if (numberVector.size () == 0 )
733+ {
734+ lines = 1 ;
735+ }
736+ else
737+ {
738+ lines = numberVector.at (0 );
739+ }
740+ SetCursorY (GetCursorY () - lines);
741+ Update ();
742+ }
743+
744+ // Bound to ANSI escape code B
745+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
746+ // Section: Some ANSI control sequences
747+ // Name: Cursor Down
748+ void Console::MoveCursorDown (std::string args)
749+ {
750+ auto numberVector = parseArguments (args);
751+ int lines;
752+ if (numberVector.size () == 0 )
753+ {
754+ lines = 1 ;
755+ }
756+ else
757+ {
758+ lines = numberVector.at (0 );
759+ }
760+ SetCursorY (GetCursorY () + lines);
761+ Update ();
762+ }
763+
764+ // Bound to ANSI escape code C
765+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
766+ // Section: Some ANSI control sequences
767+ // Name: Cursor Forward
768+ void Console::MoveCursorForward (std::string args)
769+ {
770+ auto numberVector = parseArguments (args);
771+ int columns;
772+ if (numberVector.size () == 0 )
773+ {
774+ columns = 1 ;
775+ }
776+ else
777+ {
778+ columns = numberVector.at (0 );
779+ }
780+ SetCursorX (GetCursorX () + columns);
781+ Update ();
782+ }
783+
784+ // Bound to ANSI escape code D
785+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
786+ // Section: Some ANSI control sequences
787+ // Name: Cursor Back
788+ void Console::MoveCursorBack (std::string args)
789+ {
790+ auto numberVector = parseArguments (args);
791+ int columns;
792+ if (numberVector.size () == 0 )
793+ {
794+ columns = 1 ;
795+ }
796+ else
797+ {
798+ columns = numberVector.at (0 );
799+ }
800+ SetCursorX (GetCursorX () - columns);
801+ Update ();
802+ }
803+
804+ // Bound to ANSI escape code E
805+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
806+ // Section: Some ANSI control sequences
807+ // Name: Cursor Next Line
808+ void Console::MoveCursorNextLine (std::string args)
809+ {
810+ auto numberVector = parseArguments (args);
811+ int lines;
812+ if (numberVector.size () == 0 )
813+ {
814+ lines = 1 ;
815+ }
816+ else
817+ {
818+ lines = numberVector.at (0 );
819+ }
820+ SetCursorX (1 );
821+ SetCursorY (GetCursorY () + lines);
822+ Update ();
823+ }
824+
825+ // Bound to ANSI escape code F
826+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
827+ // Section: Some ANSI control sequences
828+ // Name: Cursor Previous Line
829+ void Console::MoveCursorPreviousLine (std::string args)
830+ {
831+ auto numberVector = parseArguments (args);
832+ int lines;
833+ if (numberVector.size () == 0 )
834+ {
835+ lines = 1 ;
836+ }
837+ else
838+ {
839+ lines = numberVector.at (0 );
840+ }
841+ SetCursorX (1 );
842+ SetCursorY (GetCursorY () - lines);
843+ Update ();
844+ }
845+
846+ // Bound to ANSI escape code G
847+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
848+ // Section: Some ANSI control sequences
849+ // Name: Cursor Horizontal Absolute
850+ void Console::MoveCursorHorizonalAbsolute (std::string args)
851+ {
852+ auto numberVector = parseArguments (args);
853+ auto newPosition = numberVector.at (0 );
854+ SetCursorX (newPosition);
855+ Update ();
856+ }
857+
858+ // Bound to ANSI escape code K
859+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
860+ // Section: Some ANSI control sequences
861+ // Name: Erase in Line
862+ void Console::EraseInLine (std::string args)
863+ {
864+ auto numberVector = parseArguments (args);
865+ int argument = numberVector.at (0 );
866+ switch (argument)
867+ {
868+ case 0 :
869+ ClearFromCursorToEndOfLine ();
870+ break ;
871+ case 1 :
872+ ClearFromBeginningOfLineToCursor ();
873+ break ;
874+ case 2 :
875+ ClearEntireLine ();
876+ break ;
877+ }
878+ }
879+
880+ // Erases from the current cursor position to the end of the line
881+ void Console::ClearFromCursorToEndOfLine ()
882+ {
883+ int currentPosition = (GetCursorY () - 1 ) * cols + GetCursorX () - 1 ;
884+ int endOfLinePosition = GetCursorY () * cols;
885+
886+ // Fill part of the buffer with blank spaces
887+ std::fill (chars.begin () + currentPosition, chars.begin () + endOfLinePosition, AttributedChar (' ' , currentAttr));
888+ std::fill (onscreen.begin () + currentPosition, onscreen.begin () + endOfLinePosition, AttributedChar (' ' , currentAttr));
889+
890+ Update ();
891+ Draw (bounds);
892+ }
893+
894+ // Erases from the beginning of the line to the cursor's position
895+ void Console::ClearFromBeginningOfLineToCursor ()
896+ {
897+ int currentPosition = (GetCursorY () - 1 ) * cols + GetCursorX ();
898+ int beginningOfLinePosition = (GetCursorY () - 1 ) * cols;
899+
900+ // Fill part of the buffer with blank spaces
901+ std::fill (chars.begin () + beginningOfLinePosition, chars.begin () + currentPosition, AttributedChar (' ' , currentAttr));
902+ std::fill (onscreen.begin () + beginningOfLinePosition, onscreen.begin () + currentPosition, AttributedChar (' ' , currentAttr));
903+
904+ Update ();
905+ Draw (bounds);
906+ }
907+
908+ // Erases the entire line the cursor is on
909+ void Console::ClearEntireLine ()
910+ {
911+ int beginningOfLinePosition = (GetCursorY () - 1 ) * cols;
912+ int endOfLinePosition = GetCursorY () * cols;
913+
914+ // Fill part of the buffer with blank spaces
915+ std::fill (chars.begin () + beginningOfLinePosition, chars.begin () + endOfLinePosition, AttributedChar (' ' , currentAttr));
916+ std::fill (onscreen.begin () + beginningOfLinePosition, onscreen.begin () + endOfLinePosition, AttributedChar (' ' , currentAttr));
917+
918+ Update ();
919+ Draw (bounds);
920+ }
921+
922+ // Bound to ANSI escape code h
923+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
924+ // Section: Some popular private sequences
925+ // Description: Sets a variable to indicate the cursor should be shown
926+ void Console::ShowCursor (std::string args)
927+ {
928+ cursorRequestedHidden = false ;
929+ }
930+
931+ // Bound to ANSI escape code l
932+ // Page: https://en.wikipedia.org/wiki/ANSI_escape_code
933+ // Section: Some popular private sequences
934+ // Description: Sets a variable to indicate the cursor should be hidden
935+ void Console::HideCursor (std::string args)
936+ {
937+ cursorRequestedHidden = true ;
938+ }
939+
940+ /*
941+ These setter and getter functions fix a problem where ANSI escape codes expect
942+ an origin of (1,1) while the Console class expects an origin of (0,0).
943+ Only functions that work with ANSI escape codes should use these functions.
944+ */
945+
946+ void Console::SetCursorX (int newX)
947+ {
948+ cursorX = newX - 1 ;
949+ cursorX = cursorX < 0 ? 0 : cursorX; // Terminal.app does this so we will too
950+ }
951+
952+ int Console::GetCursorX ()
953+ {
954+ return cursorX + 1 ;
955+ }
956+
957+ void Console::SetCursorY (int newY)
958+ {
959+ cursorY = newY - 1 ;
960+ cursorY = cursorY < 0 ? 0 : cursorY; // Terminal.app does this so we will too
961+ }
962+
963+ int Console::GetCursorY ()
964+ {
965+ return cursorY + 1 ;
966+ }
0 commit comments