in doom_py/src/vizdoom/src/c_console.cpp [1083:1469]
static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
{
int i;
int data1 = ev->data1;
switch (ev->subtype)
{
default:
return false;
case EV_GUI_Char:
// Add keypress to command line
if (buffer[0] < len)
{
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;
TabbedList = false;
break;
case EV_GUI_WheelUp:
case EV_GUI_WheelDown:
if (!(ev->data3 & GKM_SHIFT))
{
data1 = GK_PGDN + EV_GUI_WheelDown - ev->subtype;
}
else
{
data1 = GK_DOWN + EV_GUI_WheelDown - ev->subtype;
}
// Intentional fallthrough
case EV_GUI_KeyDown:
case EV_GUI_KeyRepeat:
switch (data1)
{
case '\t':
// Try to do tab-completion
C_TabComplete ((ev->data3 & GKM_SHIFT) ? false : true);
break;
case GK_PGUP:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer up one page
RowAdjust += (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3;
}
else if (RowAdjust < conbuffer->GetFormattedLineCount())
{ // Scroll console buffer up
if (ev->subtype == EV_GUI_WheelUp)
{
RowAdjust += 3;
}
else
{
RowAdjust++;
}
if (RowAdjust > conbuffer->GetFormattedLineCount())
{
RowAdjust = conbuffer->GetFormattedLineCount();
}
}
break;
case GK_PGDN:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer down one page
const int scrollamt = (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3;
if (RowAdjust < scrollamt)
{
RowAdjust = 0;
}
else
{
RowAdjust -= scrollamt;
}
}
else if (RowAdjust > 0)
{ // Scroll console buffer down
if (ev->subtype == EV_GUI_WheelDown)
{
RowAdjust = MAX (0, RowAdjust - 3);
}
else
{
RowAdjust--;
}
}
break;
case GK_HOME:
if (ev->data3 & GKM_CTRL)
{ // Move to top of console buffer
RowAdjust = conbuffer->GetFormattedLineCount();
}
else
{ // Move cursor to start of line
buffer[1] = buffer[len+4] = 0;
}
break;
case GK_END:
if (ev->data3 & GKM_CTRL)
{ // Move to bottom of console buffer
RowAdjust = 0;
}
else
{ // Move cursor to end of line
buffer[1] = buffer[0];
makestartposgood ();
}
break;
case GK_LEFT:
// Move cursor left one character
if (buffer[1])
{
buffer[1]--;
makestartposgood ();
}
break;
case GK_RIGHT:
// Move cursor right one character
if (buffer[1] < buffer[0])
{
buffer[1]++;
makestartposgood ();
}
break;
case '\b':
// Erase character to left of cursor
if (buffer[0] && buffer[1])
{
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;
TabbedList = false;
break;
case GK_DEL:
// Erase character under cursor
if (buffer[1] < buffer[0])
{
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;
TabbedList = false;
break;
case GK_UP:
// Move to previous entry in the command history
if (HistPos == NULL)
{
HistPos = HistHead;
}
else if (HistPos->Older)
{
HistPos = HistPos->Older;
}
if (HistPos)
{
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = (BYTE)strlen ((char *)&buffer[2]);
buffer[len+4] = 0;
makestartposgood();
}
TabbedLast = false;
TabbedList = false;
break;
case GK_DOWN:
// Move to next entry in the command history
if (HistPos && HistPos->Newer)
{
HistPos = HistPos->Newer;
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = (BYTE)strlen ((char *)&buffer[2]);
}
else
{
HistPos = NULL;
buffer[0] = buffer[1] = 0;
}
buffer[len+4] = 0;
makestartposgood();
TabbedLast = false;
TabbedList = false;
break;
case 'X':
if (ev->data3 & GKM_CTRL)
{
buffer[1] = buffer[0] = 0;
TabbedLast = TabbedList = false;
}
break;
case 'D':
if (ev->data3 & GKM_CTRL && buffer[0] == 0)
{ // Control-D pressed on an empty line
int replen = (int)strlen (con_ctrl_d);
if (replen == 0)
break; // Replacement is empty, so do nothing
if (replen > len)
replen = len;
memcpy (&buffer[2], con_ctrl_d, replen);
buffer[0] = buffer[1] = replen;
}
else
{
break;
}
// Intentional fall-through for command(s) added with Ctrl-D
case '\r':
// Execute command line (ENTER)
buffer[2 + buffer[0]] = 0;
for (i = 0; i < buffer[0] && isspace(buffer[2+i]); ++i)
{
}
if (i == buffer[0])
{
// Command line is empty, so do nothing to the history
}
else if (HistHead && stricmp (HistHead->String, (char *)&buffer[2]) == 0)
{
// Command line was the same as the previous one,
// so leave the history list alone
}
else
{
// Command line is different from last command line,
// or there is nothing in the history list,
// so add it to the history list.
History *temp = (History *)M_Malloc (sizeof(struct History) + buffer[0]);
strcpy (temp->String, (char *)&buffer[2]);
temp->Older = HistHead;
if (HistHead)
{
HistHead->Newer = temp;
}
temp->Newer = NULL;
HistHead = temp;
if (!HistTail)
{
HistTail = temp;
}
if (HistSize == MAXHISTSIZE)
{
HistTail = HistTail->Newer;
M_Free (HistTail->Older);
HistTail->Older = NULL;
}
else
{
HistSize++;
}
}
HistPos = NULL;
Printf (127, TEXTCOLOR_WHITE "]%s\n", &buffer[2]);
buffer[0] = buffer[1] = buffer[len+4] = 0;
AddCommandString ((char *)&buffer[2]);
TabbedLast = false;
TabbedList = false;
break;
case '`':
// Check to see if we have ` bound to the console before accepting
// it as a way to close the console.
if (Bindings.GetBinding(KEY_GRAVE).CompareNoCase("toggleconsole"))
{
break;
}
case GK_ESCAPE:
// Close console and clear command line. But if we're in the
// fullscreen console mode, there's nothing to fall back on
// if it's closed, so open the main menu instead.
if (gamestate == GS_STARTUP)
{
return false;
}
else if (gamestate == GS_FULLCONSOLE)
{
C_DoCommand ("menu_main");
}
else
{
buffer[0] = buffer[1] = buffer[len+4] = 0;
HistPos = NULL;
C_ToggleConsole ();
}
break;
case 'C':
case 'V':
TabbedLast = false;
TabbedList = false;
#ifdef __APPLE__
if (ev->data3 & GKM_META)
#else // !__APPLE__
if (ev->data3 & GKM_CTRL)
#endif // __APPLE__
{
if (data1 == 'C')
{ // copy to clipboard
if (buffer[0] > 0)
{
buffer[2 + buffer[0]] = 0;
I_PutInClipboard ((char *)&buffer[2]);
}
}
else
{ // paste from clipboard
C_PasteText(I_GetFromClipboard(false), buffer, len);
}
break;
}
break;
}
break;
#ifdef __unix__
case EV_GUI_MButtonDown:
C_PasteText(I_GetFromClipboard(true), buffer, len);
break;
#endif
}
// Ensure that the cursor is always visible while typing
CursorTicker = C_BLINKRATE;
cursoron = 1;
return true;
}