From 242a70e6103e6f444661a049dab608e3aa48a5c6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Oct 2020 23:16:08 +0200 Subject: [PATCH] - split the command line buffer off from c_console.cpp and reactivated the check for CONBACK. --- source/common/console/c_commandbuffer.h | 373 ++++++++++++++++++++++++ source/core/console/c_console.cpp | 370 +---------------------- source/core/gi.h | 1 + source/core/menu/razemenu.cpp | 1 + 4 files changed, 390 insertions(+), 355 deletions(-) create mode 100644 source/common/console/c_commandbuffer.h diff --git a/source/common/console/c_commandbuffer.h b/source/common/console/c_commandbuffer.h new file mode 100644 index 000000000..a1fddd9aa --- /dev/null +++ b/source/common/console/c_commandbuffer.h @@ -0,0 +1,373 @@ +/* +** c_commandbuffer.cpp +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** Copyright 2010-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +// for inclusion in c_console.cpp. + +struct FCommandBuffer +{ +private: + std::u32string Text; + unsigned CursorPos = 0; + unsigned StartPos = 0; // First character to display + unsigned CursorPosCells = 0; + unsigned StartPosCells = 0; + + std::u32string YankBuffer; // Deleted text buffer + +public: + bool AppendToYankBuffer = false; // Append consecutive deletes to buffer + int ConCols; + + FCommandBuffer() = default; + + FCommandBuffer(const FCommandBuffer &o) + { + Text = o.Text; + CursorPos = o.CursorPos; + StartPos = o.StartPos; + } + + FString GetText() const + { + FString build; + for (auto chr : Text) build.AppendCharacter(chr); + return build; + } + + size_t TextLength() const + { + return Text.length(); + } + + void Draw(int x, int y, int scale, bool cursor) + { + if (scale == 1) + { + DrawChar(twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', TAG_DONE); + DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, + &Text[StartPos], TAG_DONE); + + if (cursor) + { + DrawChar(twod, CurrentConsoleFont, CR_YELLOW, + x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), + y, '\xb', TAG_DONE); + } + } + else + { + DrawChar(twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', + DTA_VirtualWidth, twod->GetWidth() / scale, + DTA_VirtualHeight, twod->GetHeight() / scale, + DTA_KeepRatio, true, TAG_DONE); + + DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, + &Text[StartPos], + DTA_VirtualWidth, twod->GetWidth() / scale, + DTA_VirtualHeight, twod->GetHeight() / scale, + DTA_KeepRatio, true, TAG_DONE); + + if (cursor) + { + DrawChar(twod, CurrentConsoleFont, CR_YELLOW, + x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), + y, '\xb', + DTA_VirtualWidth, twod->GetWidth() / scale, + DTA_VirtualHeight, twod->GetHeight() / scale, + DTA_KeepRatio, true, TAG_DONE); + } + } + } + + unsigned CalcCellSize(unsigned length) + { + unsigned cellcount = 0; + for (unsigned i = 0; i < length; i++) + { + int w; + NewConsoleFont->GetChar(Text[i], CR_UNTRANSLATED, &w); + cellcount += w / 9; + } + return cellcount; + + } + + unsigned CharsForCells(unsigned cellin, bool *overflow) + { + unsigned chars = 0; + int cells = cellin; + while (cells > 0) + { + int w; + NewConsoleFont->GetChar(Text[chars++], CR_UNTRANSLATED, &w); + cells -= w / 9; + } + *overflow = (cells < 0); + return chars; + } + + + void MakeStartPosGood() + { + // Make sure both values point to something valid. + if (CursorPos > Text.length()) CursorPos = (unsigned)Text.length(); + if (StartPos > Text.length()) StartPos = (unsigned)Text.length(); + + CursorPosCells = CalcCellSize(CursorPos); + StartPosCells = CalcCellSize(StartPos); + unsigned LengthCells = CalcCellSize((unsigned)Text.length()); + + int n = StartPosCells; + unsigned cols = ConCols / active_con_scale(twod); + + if (StartPosCells >= LengthCells) + { // Start of visible line is beyond end of line + n = CursorPosCells - cols + 2; + } + if ((CursorPosCells - StartPosCells) >= cols - 2) + { // The cursor is beyond the visible part of the line + n = CursorPosCells - cols + 2; + } + if (StartPosCells > CursorPosCells) + { // The cursor is in front of the visible part of the line + n = CursorPosCells; + } + StartPosCells = std::max(0, n); + bool overflow; + StartPos = CharsForCells(StartPosCells, &overflow); + if (overflow) + { + // We ended up in the middle of a double cell character, so set the start to the following character. + StartPosCells++; + StartPos = CharsForCells(StartPosCells, &overflow); + } + } + + void CursorStart() + { + CursorPos = 0; + StartPos = 0; + CursorPosCells = 0; + StartPosCells = 0; + } + + void CursorEnd() + { + CursorPos = (unsigned)Text.length(); + MakeStartPosGood(); + } + +private: + void MoveCursorLeft() + { + CursorPos--; + } + + void MoveCursorRight() + { + CursorPos++; + } + +public: + void CursorLeft() + { + if (CursorPos > 0) + { + MoveCursorLeft(); + MakeStartPosGood(); + } + } + + void CursorRight() + { + if (CursorPos < Text.length()) + { + MoveCursorRight(); + MakeStartPosGood(); + } + } + + void CursorWordLeft() + { + if (CursorPos > 0) + { + do MoveCursorLeft(); + while (CursorPos > 0 && Text[CursorPos - 1] != ' '); + MakeStartPosGood(); + } + } + + void CursorWordRight() + { + if (CursorPos < Text.length()) + { + do MoveCursorRight(); + while (CursorPos < Text.length() && Text[CursorPos] != ' '); + MakeStartPosGood(); + } + } + + void DeleteLeft() + { + if (CursorPos > 0) + { + MoveCursorLeft(); + Text.erase(CursorPos, 1); + MakeStartPosGood(); + } + } + + void DeleteRight() + { + if (CursorPos < Text.length()) + { + Text.erase(CursorPos, 1); + MakeStartPosGood(); + } + } + + void DeleteWordLeft() + { + if (CursorPos > 0) + { + auto now = CursorPos; + + CursorWordLeft(); + + if (AppendToYankBuffer) { + YankBuffer = Text.substr(CursorPos, now - CursorPos) + YankBuffer; + } else { + YankBuffer = Text.substr(CursorPos, now - CursorPos); + } + Text.erase(CursorPos, now - CursorPos); + MakeStartPosGood(); + } + } + + void DeleteLineLeft() + { + if (CursorPos > 0) + { + if (AppendToYankBuffer) { + YankBuffer = Text.substr(0, CursorPos) + YankBuffer; + } else { + YankBuffer = Text.substr(0, CursorPos); + } + Text.erase(0, CursorPos); + CursorStart(); + } + } + + void DeleteLineRight() + { + if (CursorPos < Text.length()) + { + if (AppendToYankBuffer) { + YankBuffer += Text.substr(CursorPos, Text.length() - CursorPos); + } else { + YankBuffer = Text.substr(CursorPos, Text.length() - CursorPos); + } + Text.resize(CursorPos); + CursorEnd(); + } + } + + void AddChar(int character) + { + if (Text.length() == 0) + { + Text += character; + } + else + { + Text.insert(CursorPos, 1, character); + } + CursorPos++; + MakeStartPosGood(); + } + + void AddString(FString clip) + { + if (clip.IsNotEmpty()) + { + // Only paste the first line. + long brk = clip.IndexOfAny("\r\n\b"); + std::u32string build; + if (brk >= 0) + { + clip.Truncate(brk); + } + auto strp = (const uint8_t*)clip.GetChars(); + while (auto chr = GetCharFromString(strp)) build += chr; + + if (Text.length() == 0) + { + Text = build; + } + else + { + Text.insert(CursorPos, build); + } + CursorPos += (unsigned)build.length(); + MakeStartPosGood(); + } + } + + void SetString(const FString &str) + { + Text.clear(); + auto strp = (const uint8_t*)str.GetChars(); + while (auto chr = GetCharFromString(strp)) Text += chr; + + CursorEnd(); + MakeStartPosGood(); + } + + void AddYankBuffer() + { + if (YankBuffer.length() > 0) + { + if (Text.length() == 0) + { + Text = YankBuffer; + } + else + { + Text.insert(CursorPos, YankBuffer); + } + CursorPos += (unsigned)YankBuffer.length(); + MakeStartPosGood(); + } + } +}; diff --git a/source/core/console/c_console.cpp b/source/core/console/c_console.cpp index 9a22a59d2..314199365 100644 --- a/source/core/console/c_console.cpp +++ b/source/core/console/c_console.cpp @@ -68,6 +68,9 @@ #include "menustate.h" #include "i_interface.h" #include "vm.h" +#include "gi.h" +#include "texturemanager.h" +#include "c_commandbuffer.h" #define LEFTMARGIN 8 #define RIGHTMARGIN 8 @@ -92,7 +95,7 @@ static bool TabbedList; // True if tab list was shown CVAR(Bool, con_notablist, false, CVAR_ARCHIVE) -static FGameTexture *conback; +static FTextureID conback; static uint32_t conshade; static bool conline; @@ -101,7 +104,6 @@ extern bool advancedemo; extern FBaseCVar *CVars; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; -unsigned ConCols; int ConWidth; bool vidactive = false; bool cursoron = false; @@ -177,342 +179,6 @@ struct History FString String; }; -struct FCommandBuffer -{ -private: - std::u32string Text; - unsigned CursorPos = 0; - unsigned StartPos = 0; // First character to display - unsigned CursorPosCells = 0; - unsigned StartPosCells = 0; - - std::u32string YankBuffer; // Deleted text buffer - -public: - bool AppendToYankBuffer = false; // Append consecutive deletes to buffer - - FCommandBuffer() = default; - - FCommandBuffer(const FCommandBuffer &o) - { - Text = o.Text; - CursorPos = o.CursorPos; - StartPos = o.StartPos; - } - - FString GetText() const - { - FString build; - for (auto chr : Text) build.AppendCharacter(chr); - return build; - } - - size_t TextLength() const - { - return Text.length(); - } - - void Draw(int x, int y, int scale, bool cursor) - { - if (scale == 1) - { - DrawChar(twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', TAG_DONE); - DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, - &Text[StartPos], TAG_DONE); - - if (cursor) - { - DrawChar(twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), - y, '\xb', TAG_DONE); - } - } - else - { - DrawChar(twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', - DTA_VirtualWidth, twod->GetWidth() / scale, - DTA_VirtualHeight, twod->GetHeight() / scale, - DTA_KeepRatio, true, TAG_DONE); - - DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, - &Text[StartPos], - DTA_VirtualWidth, twod->GetWidth() / scale, - DTA_VirtualHeight, twod->GetHeight() / scale, - DTA_KeepRatio, true, TAG_DONE); - - if (cursor) - { - DrawChar(twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), - y, '\xb', - DTA_VirtualWidth, twod->GetWidth() / scale, - DTA_VirtualHeight, twod->GetHeight() / scale, - DTA_KeepRatio, true, TAG_DONE); - } - } - } - - unsigned CalcCellSize(unsigned length) - { - unsigned cellcount = 0; - for (unsigned i = 0; i < length; i++) - { - int w; - NewConsoleFont->GetChar(Text[i], CR_UNTRANSLATED, &w); - cellcount += w / 9; - } - return cellcount; - - } - - unsigned CharsForCells(unsigned cellin, bool *overflow) - { - unsigned chars = 0; - int cells = cellin; - while (cells > 0) - { - int w; - NewConsoleFont->GetChar(Text[chars++], CR_UNTRANSLATED, &w); - cells -= w / 9; - } - *overflow = (cells < 0); - return chars; - } - - - void MakeStartPosGood() - { - // Make sure both values point to something valid. - if (CursorPos > Text.length()) CursorPos = (unsigned)Text.length(); - if (StartPos > Text.length()) StartPos = (unsigned)Text.length(); - - CursorPosCells = CalcCellSize(CursorPos); - StartPosCells = CalcCellSize(StartPos); - unsigned LengthCells = CalcCellSize((unsigned)Text.length()); - - int n = StartPosCells; - unsigned cols = ConCols / active_con_scale(twod); - - if (StartPosCells >= LengthCells) - { // Start of visible line is beyond end of line - n = CursorPosCells - cols + 2; - } - if ((CursorPosCells - StartPosCells) >= cols - 2) - { // The cursor is beyond the visible part of the line - n = CursorPosCells - cols + 2; - } - if (StartPosCells > CursorPosCells) - { // The cursor is in front of the visible part of the line - n = CursorPosCells; - } - StartPosCells = std::max(0, n); - bool overflow; - StartPos = CharsForCells(StartPosCells, &overflow); - if (overflow) - { - // We ended up in the middle of a double cell character, so set the start to the following character. - StartPosCells++; - StartPos = CharsForCells(StartPosCells, &overflow); - } - } - - void CursorStart() - { - CursorPos = 0; - StartPos = 0; - CursorPosCells = 0; - StartPosCells = 0; - } - - void CursorEnd() - { - CursorPos = (unsigned)Text.length(); - MakeStartPosGood(); - } - -private: - void MoveCursorLeft() - { - CursorPos--; - } - - void MoveCursorRight() - { - CursorPos++; - } - -public: - void CursorLeft() - { - if (CursorPos > 0) - { - MoveCursorLeft(); - MakeStartPosGood(); - } - } - - void CursorRight() - { - if (CursorPos < Text.length()) - { - MoveCursorRight(); - MakeStartPosGood(); - } - } - - void CursorWordLeft() - { - if (CursorPos > 0) - { - do MoveCursorLeft(); - while (CursorPos > 0 && Text[CursorPos - 1] != ' '); - MakeStartPosGood(); - } - } - - void CursorWordRight() - { - if (CursorPos < Text.length()) - { - do MoveCursorRight(); - while (CursorPos < Text.length() && Text[CursorPos] != ' '); - MakeStartPosGood(); - } - } - - void DeleteLeft() - { - if (CursorPos > 0) - { - MoveCursorLeft(); - Text.erase(CursorPos, 1); - MakeStartPosGood(); - } - } - - void DeleteRight() - { - if (CursorPos < Text.length()) - { - Text.erase(CursorPos, 1); - MakeStartPosGood(); - } - } - - void DeleteWordLeft() - { - if (CursorPos > 0) - { - auto now = CursorPos; - - CursorWordLeft(); - - if (AppendToYankBuffer) { - YankBuffer = Text.substr(CursorPos, now - CursorPos) + YankBuffer; - } else { - YankBuffer = Text.substr(CursorPos, now - CursorPos); - } - Text.erase(CursorPos, now - CursorPos); - MakeStartPosGood(); - } - } - - void DeleteLineLeft() - { - if (CursorPos > 0) - { - if (AppendToYankBuffer) { - YankBuffer = Text.substr(0, CursorPos) + YankBuffer; - } else { - YankBuffer = Text.substr(0, CursorPos); - } - Text.erase(0, CursorPos); - CursorStart(); - } - } - - void DeleteLineRight() - { - if (CursorPos < Text.length()) - { - if (AppendToYankBuffer) { - YankBuffer += Text.substr(CursorPos, Text.length() - CursorPos); - } else { - YankBuffer = Text.substr(CursorPos, Text.length() - CursorPos); - } - Text.resize(CursorPos); - CursorEnd(); - } - } - - void AddChar(int character) - { - if (Text.length() == 0) - { - Text += character; - } - else - { - Text.insert(CursorPos, 1, character); - } - CursorPos++; - MakeStartPosGood(); - } - - void AddString(FString clip) - { - if (clip.IsNotEmpty()) - { - // Only paste the first line. - long brk = clip.IndexOfAny("\r\n\b"); - std::u32string build; - if (brk >= 0) - { - clip.Truncate(brk); - } - auto strp = (const uint8_t*)clip.GetChars(); - while (auto chr = GetCharFromString(strp)) build += chr; - - if (Text.length() == 0) - { - Text = build; - } - else - { - Text.insert(CursorPos, build); - } - CursorPos += (unsigned)build.length(); - MakeStartPosGood(); - } - } - - void SetString(const FString &str) - { - Text.clear(); - auto strp = (const uint8_t*)str.GetChars(); - while (auto chr = GetCharFromString(strp)) Text += chr; - - CursorEnd(); - MakeStartPosGood(); - } - - void AddYankBuffer() - { - if (YankBuffer.length() > 0) - { - if (Text.length() == 0) - { - Text = YankBuffer; - } - else - { - Text.insert(CursorPos, YankBuffer); - } - CursorPos += (unsigned)YankBuffer.length(); - MakeStartPosGood(); - } - } -}; static FCommandBuffer CmdLine; #define MAXHISTSIZE 50 @@ -601,7 +267,6 @@ CUSTOM_CVAR (Int, msgmidcolor2, CR_BROWN, CVAR_ARCHIVE) void C_InitConback() { -#if 0 conback = TexMan.CheckForTexture ("CONBACK", ETextureType::MiscPatch); if (!conback.isValid()) @@ -615,10 +280,6 @@ void C_InitConback() conshade = 0; conline = false; } -#else - conshade = MAKEARGB(175, 0, 0, 0); - conline = true; -#endif } void C_InitConsole (int width, int height, bool ingame) @@ -636,7 +297,7 @@ void C_InitConsole (int width, int height, bool ingame) cwidth = cheight = 8; } ConWidth = (width - LEFTMARGIN - RIGHTMARGIN); - ConCols = ConWidth / cwidth; + CmdLine.ConCols = ConWidth / cwidth; if (conbuffer == NULL) conbuffer = new FConsoleBuffer; } @@ -923,7 +584,7 @@ int PrintString (int iprintlevel, const char *outline) conbuffer->AddText(printlevel, outline); if (!(iprintlevel & PRINT_NONOTIFY)) { - if (vidactive && ((iprintlevel & PRINT_NOTIFY) || con_notify_advanced)) + if (screen && vidactive && ((iprintlevel & PRINT_NOTIFY) || con_notify_advanced)) { NotifyStrings.AddString(printlevel, outline); } @@ -1260,15 +921,15 @@ void C_DrawConsole () visheight = ConBottom; - if (conback) + if (conback.isValid()) { - DrawTexture (twod, conback, 0, visheight - screen->GetHeight(), - DTA_DestWidth, screen->GetWidth(), - DTA_DestHeight, screen->GetHeight(), - DTA_ColorOverlay, conshade, - DTA_Alpha, (/*gamestate != GS_FULLCONSOLE*/true) ? (double)con_alpha : 1., - DTA_Masked, false, - TAG_DONE); + DrawTexture (twod, TexMan.GetGameTexture(conback), 0, visheight - screen->GetHeight(), + DTA_DestWidth, twod->GetWidth(), + DTA_DestHeight, twod->GetHeight(), + DTA_ColorOverlay, conshade, + DTA_Alpha, (gamestate != GS_FULLCONSOLE) ? (double)con_alpha : 1., + DTA_Masked, false, + TAG_DONE); } else { @@ -1699,7 +1360,6 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) } else if (gamestate == GS_FULLCONSOLE) { - gamestate = GS_MENUSCREEN; C_DoCommand ("menu_main"); } else @@ -2138,7 +1798,7 @@ static bool C_TabCompleteList () Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; - if (x > ConCols / active_con_scale(twod) - maxwidth) + if (x > CmdLine.ConCols / active_con_scale(twod) - maxwidth) { x = 0; Printf ("\n"); diff --git a/source/core/gi.h b/source/core/gi.h index 4a8c2622f..865cd0e4b 100644 --- a/source/core/gi.h +++ b/source/core/gi.h @@ -45,6 +45,7 @@ struct gameinfo_t int gametype; FName mSliderColor; FString mBackButton; + FString TitlePage; }; diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 6f01f0a06..f0fbfa8a9 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -638,6 +638,7 @@ CCMD(reset2saved) CCMD(menu_main) { + if (gamestate == GS_FULLCONSOLE) gamestate = GS_MENUSCREEN; M_StartControlPanel(true); M_SetMenu(NAME_Mainmenu, -1); }