mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 22:33:17 +00:00
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:
parent
fd31c84745
commit
3926ca13b0
4 changed files with 340 additions and 289 deletions
|
@ -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,27 +138,9 @@ static bool ConsoleDrawing;
|
||||||
static char *work = NULL;
|
static char *work = NULL;
|
||||||
static int worklen = 0;
|
static int worklen = 0;
|
||||||
|
|
||||||
|
CVAR(Float, con_notifytime, 3.f, CVAR_ARCHIVE)
|
||||||
struct History
|
CVAR(Bool, con_centernotify, false, CVAR_ARCHIVE)
|
||||||
{
|
CUSTOM_CVAR(Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions?
|
||||||
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 (Bool, con_centernotify, false, CVAR_ARCHIVE)
|
|
||||||
CUSTOM_CVAR (Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions?
|
|
||||||
{
|
{
|
||||||
if (self < 0) self = 0;
|
if (self < 0) self = 0;
|
||||||
if (self > 3) self = 3;
|
if (self > 3) self = 3;
|
||||||
|
@ -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()
|
||||||
|
@ -197,7 +184,195 @@ 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);
|
||||||
{
|
HistPos = NULL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -343,28 +343,74 @@ FString &FString::operator += (char tail)
|
||||||
|
|
||||||
FString &FString::AppendCStrPart (const char *tail, size_t tailLen)
|
FString &FString::AppendCStrPart (const char *tail, size_t tailLen)
|
||||||
{
|
{
|
||||||
size_t len1 = Len();
|
if (tailLen > 0)
|
||||||
ReallocBuffer (len1 + tailLen);
|
{
|
||||||
StrCopy (Chars + len1, tail, tailLen);
|
size_t len1 = Len();
|
||||||
|
ReallocBuffer(len1 + 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)
|
||||||
{
|
{
|
||||||
ReallocBuffer(tailLen);
|
if (tailLen > 0)
|
||||||
StrCopy(Chars, tail, tailLen);
|
{
|
||||||
|
ReallocBuffer(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,25 +814,28 @@ 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)
|
||||||
if (Data()->RefCount <= 1)
|
{
|
||||||
{
|
AppendCStrPart(instr, instrlen);
|
||||||
ReallocBuffer (mylen + instrlen);
|
}
|
||||||
memmove (Chars + index + instrlen, Chars + index, (mylen - index + 1)*sizeof(char));
|
else if (Data()->RefCount <= 1)
|
||||||
memcpy (Chars + index, instr, instrlen*sizeof(char));
|
{
|
||||||
}
|
ReallocBuffer(mylen + instrlen);
|
||||||
else
|
memmove(Chars + index + instrlen, Chars + index, (mylen - index + 1) * sizeof(char));
|
||||||
{
|
memcpy(Chars + index, instr, instrlen * sizeof(char));
|
||||||
FStringData *old = Data();
|
}
|
||||||
AllocBuffer (mylen + instrlen);
|
else
|
||||||
StrCopy (Chars, old->Chars(), index);
|
{
|
||||||
StrCopy (Chars + index, instr, instrlen);
|
FStringData *old = Data();
|
||||||
StrCopy (Chars + index + instrlen, old->Chars() + index, mylen - index);
|
AllocBuffer(mylen + instrlen);
|
||||||
old->Release();
|
StrCopy(Chars, old->Chars(), index);
|
||||||
|
StrCopy(Chars + index, instr, instrlen);
|
||||||
|
StrCopy(Chars + index + instrlen, old->Chars() + index, mylen - index);
|
||||||
|
old->Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
Loading…
Reference in a new issue