Fix console input not scrolling when you hit the side of the screen

- Also changed the console input buffer into a struct instead of a
  frankenstein buffer.
This commit is contained in:
Marisa Heit 2016-11-11 22:31:49 -06:00
parent fd31c84745
commit 3926ca13b0
4 changed files with 340 additions and 289 deletions

View file

@ -100,7 +100,7 @@ extern bool advancedemo;
extern FBaseCVar *CVars; extern FBaseCVar *CVars;
extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE];
int ConCols, PhysRows; unsigned ConCols, PhysRows;
int ConWidth; int ConWidth;
bool vidactive = false; bool vidactive = false;
bool cursoron = false; bool cursoron = false;
@ -112,7 +112,6 @@ constate_e ConsoleState = c_up;
static int TopLine, InsertLine; static int TopLine, InsertLine;
static void ClearConsole (); static void ClearConsole ();
static void C_PasteText(FString clip, BYTE *buffer, int len);
struct GameAtExit struct GameAtExit
{ {
@ -139,24 +138,6 @@ static bool ConsoleDrawing;
static char *work = NULL; static char *work = NULL;
static int worklen = 0; static int worklen = 0;
struct History
{
struct History *Older;
struct History *Newer;
char String[1];
};
// CmdLine[0] = # of chars on command line
// CmdLine[1] = cursor position
// CmdLine[2+] = command line (max 255 chars + NULL)
// CmdLine[259]= offset from beginning of cmdline to display
static BYTE CmdLine[260];
#define MAXHISTSIZE 50
static struct History *HistHead = NULL, *HistTail = NULL, *HistPos = NULL;
static int HistSize;
CVAR(Float, con_notifytime, 3.f, CVAR_ARCHIVE) CVAR(Float, con_notifytime, 3.f, CVAR_ARCHIVE)
CVAR(Bool, con_centernotify, false, CVAR_ARCHIVE) CVAR(Bool, con_centernotify, false, CVAR_ARCHIVE)
CUSTOM_CVAR(Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions? CUSTOM_CVAR(Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions?
@ -172,10 +153,16 @@ CUSTOM_CVAR(Int, con_scale, 0, CVAR_ARCHIVE)
int active_con_scale() int active_con_scale()
{ {
if (con_scale == 0) int scale = con_scale;
return uiscale; if (scale == 0)
else {
return con_scale; scale = uiscale;
if (scale == 0)
{
scale = CleanXfac;
}
}
return scale;
} }
int active_con_scaletext() int active_con_scaletext()
@ -199,6 +186,194 @@ CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE)
// Command to run when Ctrl-D is pressed at start of line // Command to run when Ctrl-D is pressed at start of line
CVAR(String, con_ctrl_d, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(String, con_ctrl_d, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
struct History
{
struct History *Older;
struct History *Newer;
FString String;
};
struct FCommandBuffer
{
FString Text; // The actual command line text
unsigned CursorPos;
unsigned StartPos; // First character to display
FCommandBuffer()
{
CursorPos = StartPos = 0;
}
FCommandBuffer(const FCommandBuffer &o)
{
Text = o.Text;
CursorPos = o.CursorPos;
StartPos = o.StartPos;
}
void Draw(int x, int y, int scale, bool cursor)
{
if (scale == 1)
{
screen->DrawChar(ConFont, CR_ORANGE, x, y, '\x1c', TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, x + ConFont->GetCharWidth(0x1c), y,
&Text[StartPos], TAG_DONE);
if (cursor)
{
screen->DrawChar(ConFont, CR_YELLOW,
x + ConFont->GetCharWidth(0x1c) + (CursorPos - StartPos) * ConFont->GetCharWidth(0xb),
y, '\xb', TAG_DONE);
}
}
else
{
screen->DrawChar(ConFont, CR_ORANGE, x, y, '\x1c',
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
DTA_KeepRatio, true, TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, x + ConFont->GetCharWidth(0x1c), y,
&Text[StartPos],
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
DTA_KeepRatio, true, TAG_DONE);
if (cursor)
{
screen->DrawChar(ConFont, CR_YELLOW,
x + ConFont->GetCharWidth(0x1c) + (CursorPos - StartPos) * ConFont->GetCharWidth(0xb),
y, '\xb',
DTA_VirtualWidth, screen->GetWidth() / scale,
DTA_VirtualHeight, screen->GetHeight() / scale,
DTA_KeepRatio, true, TAG_DONE);
}
}
}
void MakeStartPosGood()
{
int n = StartPos;
unsigned cols = ConCols / active_con_scale();
if (StartPos >= Text.Len())
{ // Start of visible line is beyond end of line
n = CursorPos - cols + 2;
}
if ((CursorPos - StartPos) >= cols - 2)
{ // The cursor is beyond the visible part of the line
n = CursorPos - cols + 2;
}
if (StartPos > CursorPos)
{ // The cursor is in front of the visible part of the line
n = CursorPos;
}
StartPos = MAX(0, n);
}
void CursorStart()
{
CursorPos = 0;
StartPos = 0;
}
void CursorEnd()
{
CursorPos = Text.Len();
StartPos = 0;
MakeStartPosGood();
}
void CursorLeft()
{
if (CursorPos > 0)
{
CursorPos--;
MakeStartPosGood();
}
}
void CursorRight()
{
if (CursorPos < Text.Len())
{
CursorPos++;
MakeStartPosGood();
}
}
void DeleteLeft()
{
if (CursorPos > 0)
{
Text.Remove(CursorPos - 1, 1);
CursorPos--;
MakeStartPosGood();
}
}
void DeleteRight()
{
if (CursorPos < Text.Len())
{
Text.Remove(CursorPos, 1);
MakeStartPosGood();
}
}
void AddChar(int character)
{
///FIXME: Not Unicode-aware
if (CursorPos == Text.Len())
{
Text += char(character);
}
else
{
char foo = char(character);
Text.Insert(CursorPos, &foo, 1);
}
CursorPos++;
MakeStartPosGood();
}
void AddString(FString clip)
{
if (clip.IsNotEmpty())
{
// Only paste the first line.
long brk = clip.IndexOfAny("\r\n\b");
if (brk >= 0)
{
clip.Truncate(brk);
}
if (Text.IsEmpty())
{
Text = clip;
}
else
{
Text.Insert(CursorPos, clip);
}
CursorPos += clip.Len();
MakeStartPosGood();
}
}
void SetString(FString str)
{
Text = str;
CursorPos = Text.Len();
MakeStartPosGood();
}
};
static FCommandBuffer CmdLine;
#define MAXHISTSIZE 50
static struct History *HistHead = NULL, *HistTail = NULL, *HistPos = NULL;
static int HistSize;
#define NUMNOTIFIES 4 #define NUMNOTIFIES 4
#define NOTIFYFADETIME 6 #define NOTIFYFADETIME 6
@ -860,8 +1035,6 @@ void C_DrawConsole (bool hw2d)
int lines, left, offset; int lines, left, offset;
int textScale = active_con_scale(); int textScale = active_con_scale();
if (textScale == 0)
textScale = CleanXfac;
left = LEFTMARGIN; left = LEFTMARGIN;
lines = (ConBottom/textScale-ConFont->GetHeight()*2)/ConFont->GetHeight(); lines = (ConBottom/textScale-ConFont->GetHeight()*2)/ConFont->GetHeight();
@ -1037,44 +1210,8 @@ void C_DrawConsole (bool hw2d)
{ {
// Make a copy of the command line, in case an input event is handled // Make a copy of the command line, in case an input event is handled
// while we draw the console and it changes. // while we draw the console and it changes.
CmdLine[2+CmdLine[0]] = 0; FCommandBuffer command(CmdLine);
FString command((char *)&CmdLine[2+CmdLine[259]]); command.Draw(left, bottomline, textScale, cursoron);
int cursorpos = CmdLine[1] - CmdLine[259];
if (textScale == 1)
{
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c', TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
command, TAG_DONE);
if (cursoron)
{
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
bottomline, '\xb', TAG_DONE);
}
}
else
{
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c',
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
command,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
if (cursoron)
{
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
bottomline, '\xb',
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
}
}
} }
if (RowAdjust && ConBottom >= ConFont->GetHeight()*7/2) if (RowAdjust && ConBottom >= ConFont->GetHeight()*7/2)
{ {
@ -1146,35 +1283,8 @@ void C_HideConsole ()
} }
} }
static void makestartposgood () static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
{ {
int n;
int pos = CmdLine[259];
int curs = CmdLine[1];
int len = CmdLine[0];
n = pos;
if (pos >= len)
{ // Start of visible line is beyond end of line
n = curs - ConCols + 2;
}
if ((curs - pos) >= ConCols - 2)
{ // The cursor is beyond the visible part of the line
n = curs - ConCols + 2;
}
if (pos > curs)
{ // The cursor is in front of the visible part of the line
n = curs;
}
if (n < 0)
n = 0;
CmdLine[259] = n;
}
static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
{
int i;
int data1 = ev->data1; int data1 = ev->data1;
switch (ev->subtype) switch (ev->subtype)
@ -1184,29 +1294,8 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
case EV_GUI_Char: case EV_GUI_Char:
// Add keypress to command line // Add keypress to command line
if (buffer[0] < len) buffer.AddChar(ev->data1);
{
if (buffer[1] == buffer[0])
{
buffer[buffer[0] + 2] = BYTE(ev->data1);
}
else
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 1];
c = (char *)&buffer[buffer[1] + 2];
for (; e >= c; e--)
*(e + 1) = *e;
*c = char(ev->data1);
}
buffer[0]++;
buffer[1]++;
makestartposgood ();
HistPos = NULL; HistPos = NULL;
}
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
break; break;
@ -1289,7 +1378,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
} }
else else
{ // Move cursor to start of line { // Move cursor to start of line
buffer[1] = buffer[len+4] = 0; buffer.CursorStart();
} }
break; break;
@ -1300,66 +1389,30 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
} }
else else
{ // Move cursor to end of line { // Move cursor to end of line
buffer[1] = buffer[0]; buffer.CursorEnd();
makestartposgood ();
} }
break; break;
case GK_LEFT: case GK_LEFT:
// Move cursor left one character // Move cursor left one character
if (buffer[1]) buffer.CursorLeft();
{
buffer[1]--;
makestartposgood ();
}
break; break;
case GK_RIGHT: case GK_RIGHT:
// Move cursor right one character // Move cursor right one character
if (buffer[1] < buffer[0]) buffer.CursorRight();
{
buffer[1]++;
makestartposgood ();
}
break; break;
case '\b': case '\b':
// Erase character to left of cursor // Erase character to left of cursor
if (buffer[0] && buffer[1]) buffer.DeleteLeft();
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 2];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
buffer[1]--;
if (buffer[len+4])
buffer[len+4]--;
makestartposgood ();
}
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
break; break;
case GK_DEL: case GK_DEL:
// Erase character under cursor // Erase character under cursor
if (buffer[1] < buffer[0]) buffer.DeleteRight();
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 3];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
makestartposgood ();
}
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
break; break;
@ -1377,10 +1430,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
if (HistPos) if (HistPos)
{ {
strcpy ((char *)&buffer[2], HistPos->String); buffer.SetString(HistPos->String);
buffer[0] = buffer[1] = (BYTE)strlen ((char *)&buffer[2]);
buffer[len+4] = 0;
makestartposgood();
} }
TabbedLast = false; TabbedLast = false;
@ -1392,17 +1442,13 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
if (HistPos && HistPos->Newer) if (HistPos && HistPos->Newer)
{ {
HistPos = HistPos->Newer; HistPos = HistPos->Newer;
buffer.SetString(HistPos->String);
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = (BYTE)strlen ((char *)&buffer[2]);
} }
else else
{ {
HistPos = NULL; HistPos = NULL;
buffer[0] = buffer[1] = 0; buffer.SetString("");
} }
buffer[len+4] = 0;
makestartposgood();
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
break; break;
@ -1410,24 +1456,19 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
case 'X': case 'X':
if (ev->data3 & GKM_CTRL) if (ev->data3 & GKM_CTRL)
{ {
buffer[1] = buffer[0] = 0; buffer.SetString("");
TabbedLast = TabbedList = false; TabbedLast = TabbedList = false;
} }
break; break;
case 'D': case 'D':
if (ev->data3 & GKM_CTRL && buffer[0] == 0) if (ev->data3 & GKM_CTRL && buffer.Text.Len() == 0)
{ // Control-D pressed on an empty line { // Control-D pressed on an empty line
int replen = (int)strlen (con_ctrl_d); if (strlen(con_ctrl_d) == 0)
{
if (replen == 0)
break; // Replacement is empty, so do nothing break; // Replacement is empty, so do nothing
}
if (replen > len) buffer.SetString(*con_ctrl_d);
replen = len;
memcpy (&buffer[2], con_ctrl_d, replen);
buffer[0] = buffer[1] = replen;
} }
else else
{ {
@ -1438,16 +1479,16 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
case '\r': case '\r':
// Execute command line (ENTER) // Execute command line (ENTER)
buffer[2 + buffer[0]] = 0; buffer.Text.StripLeftRight();
Printf(127, TEXTCOLOR_WHITE "]%s\n", buffer.Text.GetChars());
AddCommandString(buffer.Text.LockBuffer());
buffer.Text.UnlockBuffer();
for (i = 0; i < buffer[0] && isspace(buffer[2+i]); ++i) if (buffer.Text.Len() == 0)
{
}
if (i == buffer[0])
{ {
// Command line is empty, so do nothing to the history // Command line is empty, so do nothing to the history
} }
else if (HistHead && stricmp (HistHead->String, (char *)&buffer[2]) == 0) else if (HistHead && HistHead->String.CompareNoCase(buffer.Text) == 0)
{ {
// Command line was the same as the previous one, // Command line was the same as the previous one,
// so leave the history list alone // so leave the history list alone
@ -1458,9 +1499,8 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
// or there is nothing in the history list, // or there is nothing in the history list,
// so add it to the history list. // so add it to the history list.
History *temp = (History *)M_Malloc (sizeof(struct History) + buffer[0]); History *temp = new History;
temp->String = buffer.Text;
strcpy (temp->String, (char *)&buffer[2]);
temp->Older = HistHead; temp->Older = HistHead;
if (HistHead) if (HistHead)
{ {
@ -1477,7 +1517,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
if (HistSize == MAXHISTSIZE) if (HistSize == MAXHISTSIZE)
{ {
HistTail = HistTail->Newer; HistTail = HistTail->Newer;
M_Free (HistTail->Older); delete HistTail->Older;
HistTail->Older = NULL; HistTail->Older = NULL;
} }
else else
@ -1486,9 +1526,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
} }
} }
HistPos = NULL; HistPos = NULL;
Printf (127, TEXTCOLOR_WHITE "]%s\n", &buffer[2]); buffer.SetString("");
buffer[0] = buffer[1] = buffer[len+4] = 0;
AddCommandString ((char *)&buffer[2]);
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
break; break;
@ -1514,7 +1552,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
} }
else else
{ {
buffer[0] = buffer[1] = buffer[len+4] = 0; buffer.SetString("");
HistPos = NULL; HistPos = NULL;
C_ToggleConsole (); C_ToggleConsole ();
} }
@ -1532,15 +1570,15 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
{ {
if (data1 == 'C') if (data1 == 'C')
{ // copy to clipboard { // copy to clipboard
if (buffer[0] > 0) if (buffer.Text.IsNotEmpty())
{ {
buffer[2 + buffer[0]] = 0; I_PutInClipboard(buffer.Text);
I_PutInClipboard ((char *)&buffer[2]);
} }
} }
else else
{ // paste from clipboard { // paste from clipboard
C_PasteText(I_GetFromClipboard(false), buffer, len); buffer.AddString(I_GetFromClipboard(false));
HistPos = NULL;
} }
break; break;
} }
@ -1550,7 +1588,8 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
#ifdef __unix__ #ifdef __unix__
case EV_GUI_MButtonDown: case EV_GUI_MButtonDown:
C_PasteText(I_GetFromClipboard(true), buffer, len); buffer.AddString(I_GetFromClipboard(true));
HistPos = NULL;
break; break;
#endif #endif
} }
@ -1560,36 +1599,6 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
return true; return true;
} }
static void C_PasteText(FString clip, BYTE *buffer, int len)
{
if (clip.IsNotEmpty())
{
// Only paste the first line.
long brk = clip.IndexOfAny("\r\n\b");
int cliplen = brk >= 0 ? brk : (int)clip.Len();
// Make sure there's room for the whole thing.
if (buffer[0] + cliplen > len)
{
cliplen = len - buffer[0];
}
if (cliplen > 0)
{
if (buffer[1] < buffer[0])
{
memmove (&buffer[2 + buffer[1] + cliplen],
&buffer[2 + buffer[1]], buffer[0] - buffer[1]);
}
memcpy (&buffer[2 + buffer[1]], clip, cliplen);
buffer[0] += cliplen;
buffer[1] += cliplen;
makestartposgood ();
HistPos = NULL;
}
}
}
bool C_Responder (event_t *ev) bool C_Responder (event_t *ev)
{ {
if (ev->type != EV_GUI_Event || if (ev->type != EV_GUI_Event ||
@ -1600,7 +1609,7 @@ bool C_Responder (event_t *ev)
return false; return false;
} }
return C_HandleKey (ev, CmdLine, 255); return C_HandleKey(ev, CmdLine);
} }
CCMD (history) CCMD (history)
@ -1793,7 +1802,7 @@ static int FindDiffPoint (FName name1, const char *str2)
static void C_TabComplete (bool goForward) static void C_TabComplete (bool goForward)
{ {
int i; unsigned i;
int diffpoint; int diffpoint;
if (!TabbedLast) if (!TabbedLast)
@ -1801,25 +1810,20 @@ static void C_TabComplete (bool goForward)
bool cancomplete; bool cancomplete;
// Skip any spaces at beginning of command line // Skip any spaces at beginning of command line
if (CmdLine[2] == ' ') for (i = 0; i < CmdLine.Text.Len(); ++i)
{ {
for (i = 0; i < CmdLine[0]; i++) if (CmdLine.Text[i] != ' ')
if (CmdLine[2+i] != ' ')
break; break;
TabStart = i + 2;
} }
else if (i == CmdLine.Text.Len())
{ { // Line was nothing but spaces
TabStart = 2; return;
} }
TabStart = i;
if (TabStart == CmdLine[0] + 2) TabSize = CmdLine.Text.Len() - TabStart;
return; // Line was nothing but spaces
TabSize = CmdLine[0] - TabStart + 2; if (!FindTabCommand(&CmdLine.Text[TabStart], &TabPos, TabSize))
if (!FindTabCommand ((char *)(CmdLine + TabStart), &TabPos, TabSize))
return; // No initial matches return; // No initial matches
// Show a list of possible completions, if more than one. // Show a list of possible completions, if more than one.
@ -1842,7 +1846,7 @@ static void C_TabComplete (bool goForward)
{ // Find the last matching tab, then go one past it. { // Find the last matching tab, then go one past it.
while (++TabPos < (int)TabCommands.Size()) while (++TabPos < (int)TabCommands.Size())
{ {
if (FindDiffPoint (TabCommands[TabPos].TabName, (char *)(CmdLine + TabStart)) < TabSize) if (FindDiffPoint(TabCommands[TabPos].TabName, &CmdLine.Text[TabStart]) < TabSize)
{ {
break; break;
} }
@ -1859,27 +1863,26 @@ static void C_TabComplete (bool goForward)
(!goForward && --TabPos < 0)) (!goForward && --TabPos < 0))
{ {
TabbedLast = false; TabbedLast = false;
CmdLine[0] = CmdLine[1] = TabSize; CmdLine.Text.Truncate(TabSize);
} }
else else
{ {
diffpoint = FindDiffPoint (TabCommands[TabPos].TabName, (char *)(CmdLine + TabStart)); diffpoint = FindDiffPoint(TabCommands[TabPos].TabName, &CmdLine.Text[TabStart]);
if (diffpoint < TabSize) if (diffpoint < TabSize)
{ {
// No more matches // No more matches
TabbedLast = false; TabbedLast = false;
CmdLine[0] = CmdLine[1] = TabSize + TabStart - 2; CmdLine.Text.Truncate(TabSize - TabStart);
} }
else else
{ {
strcpy ((char *)(CmdLine + TabStart), TabCommands[TabPos].TabName.GetChars()); CmdLine.Text.Truncate(TabStart);
CmdLine[0] = CmdLine[1] = (BYTE)strlen ((char *)(CmdLine + 2)) + 1; CmdLine.Text << TabCommands[TabPos].TabName << ' ';
CmdLine[CmdLine[0] + 1] = ' ';
} }
} }
CmdLine.CursorPos = CmdLine.Text.Len();
makestartposgood (); CmdLine.MakeStartPosGood();
} }
static bool C_TabCompleteList () static bool C_TabCompleteList ()
@ -1893,7 +1896,7 @@ static bool C_TabCompleteList ()
for (i = TabPos; i < (int)TabCommands.Size(); ++i) for (i = TabPos; i < (int)TabCommands.Size(); ++i)
{ {
if (FindDiffPoint (TabCommands[i].TabName, (char *)(CmdLine + TabStart)) < TabSize) if (FindDiffPoint (TabCommands[i].TabName, &CmdLine.Text[TabStart]) < TabSize)
{ {
break; break;
} }
@ -1918,7 +1921,7 @@ static bool C_TabCompleteList ()
{ {
size_t x = 0; size_t x = 0;
maxwidth += 3; maxwidth += 3;
Printf (TEXTCOLOR_BLUE "Completions for %s:\n", CmdLine+2); Printf (TEXTCOLOR_BLUE "Completions for %s:\n", CmdLine.Text.GetChars());
for (i = TabPos; nummatches > 0; ++i, --nummatches) for (i = TabPos; nummatches > 0; ++i, --nummatches)
{ {
// [Dusk] Print console commands blue, CVars green, aliases red. // [Dusk] Print console commands blue, CVars green, aliases red.
@ -1936,7 +1939,7 @@ static bool C_TabCompleteList ()
Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars()); Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars());
x += maxwidth; x += maxwidth;
if (x > ConCols - maxwidth) if (x > ConCols / active_con_scale() - maxwidth)
{ {
x = 0; x = 0;
Printf ("\n"); Printf ("\n");
@ -1950,9 +1953,9 @@ static bool C_TabCompleteList ()
if (TabSize != commonsize) if (TabSize != commonsize)
{ {
TabSize = commonsize; TabSize = commonsize;
strncpy ((char *)CmdLine + TabStart, TabCommands[TabPos].TabName.GetChars(), commonsize); CmdLine.Text.Truncate(TabStart);
CmdLine[0] = TabStart + commonsize - 2; CmdLine.Text.AppendCStrPart(TabCommands[TabPos].TabName.GetChars(), commonsize);
CmdLine[1] = CmdLine[0]; CmdLine.CursorPos = CmdLine.Text.Len();
} }
return false; return false;
} }

View file

@ -877,8 +877,6 @@ void DFrameBuffer::DrawRateStuff ()
int rate_x; int rate_x;
int textScale = active_con_scale(); int textScale = active_con_scale();
if (textScale == 0)
textScale = CleanXfac;
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount); chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]); rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]);

View file

@ -342,29 +342,75 @@ FString &FString::operator += (char tail)
} }
FString &FString::AppendCStrPart (const char *tail, size_t tailLen) FString &FString::AppendCStrPart (const char *tail, size_t tailLen)
{
if (tailLen > 0)
{ {
size_t len1 = Len(); size_t len1 = Len();
ReallocBuffer(len1 + tailLen); ReallocBuffer(len1 + tailLen);
StrCopy(Chars + len1, tail, tailLen); StrCopy(Chars + len1, tail, tailLen);
}
return *this; return *this;
} }
FString &FString::CopyCStrPart(const char *tail, size_t tailLen) FString &FString::CopyCStrPart(const char *tail, size_t tailLen)
{
if (tailLen > 0)
{ {
ReallocBuffer(tailLen); ReallocBuffer(tailLen);
StrCopy(Chars, tail, tailLen); StrCopy(Chars, tail, tailLen);
}
else
{
Data()->Release();
NullString.RefCount++;
Chars = &NullString.Nothing[0];
}
return *this; return *this;
} }
void FString::Truncate(long newlen) void FString::Truncate(long newlen)
{ {
if (newlen >= 0 && newlen < (long)Len()) if (newlen <= 0)
{
Data()->Release();
NullString.RefCount++;
Chars = &NullString.Nothing[0];
}
else if (newlen < (long)Len())
{ {
ReallocBuffer (newlen); ReallocBuffer (newlen);
Chars[newlen] = '\0'; Chars[newlen] = '\0';
} }
} }
void FString::Remove(size_t index, size_t remlen)
{
if (index < Len())
{
if (index + remlen >= Len())
{
Truncate((long)index);
}
else
{
remlen = Len() - remlen < remlen ? Len() - remlen : remlen;
if (Data()->RefCount == 1)
{ // Can do this in place
memmove(Chars + index, Chars + index + remlen, Len() - index - remlen);
Data()->Len -= remlen;
}
else
{ // Must do it in a copy
FStringData *old = Data();
AllocBuffer(old->Len - remlen);
StrCopy(Chars, old->Chars(), index);
StrCopy(Chars + index, old->Chars() + index + remlen, old->Len - index - remlen);
old->Release();
}
}
}
}
FString FString::Left (size_t numChars) const FString FString::Left (size_t numChars) const
{ {
size_t len = Len(); size_t len = Len();
@ -768,12 +814,14 @@ void FString::Insert (size_t index, const char *instr)
void FString::Insert (size_t index, const char *instr, size_t instrlen) void FString::Insert (size_t index, const char *instr, size_t instrlen)
{ {
size_t mylen = Len(); if (instrlen > 0)
if (index > mylen)
{ {
index = mylen; size_t mylen = Len();
if (index >= mylen)
{
AppendCStrPart(instr, instrlen);
} }
if (Data()->RefCount <= 1) else if (Data()->RefCount <= 1)
{ {
ReallocBuffer(mylen + instrlen); ReallocBuffer(mylen + instrlen);
memmove(Chars + index + instrlen, Chars + index, (mylen - index + 1) * sizeof(char)); memmove(Chars + index + instrlen, Chars + index, (mylen - index + 1) * sizeof(char));
@ -789,6 +837,7 @@ void FString::Insert (size_t index, const char *instr, size_t instrlen)
old->Release(); old->Release();
} }
} }
}
void FString::ReplaceChars (char oldchar, char newchar) void FString::ReplaceChars (char oldchar, char newchar)
{ {

View file

@ -268,6 +268,7 @@ public:
bool IsNotEmpty() const { return Len() != 0; } bool IsNotEmpty() const { return Len() != 0; }
void Truncate (long newlen); void Truncate (long newlen);
void Remove(size_t index, size_t remlen);
int Compare (const FString &other) const { return strcmp (Chars, other.Chars); } int Compare (const FString &other) const { return strcmp (Chars, other.Chars); }
int Compare (const char *other) const { return strcmp (Chars, other); } int Compare (const char *other) const { return strcmp (Chars, other); }