mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-26 12:21:19 +00:00
Console with moving cursor, selections, etc
This commit is contained in:
parent
bb20cfd6be
commit
e245cdfcbf
3 changed files with 322 additions and 213 deletions
355
src/console.c
355
src/console.c
|
@ -84,13 +84,16 @@ UINT32 con_scalefactor; // text size scale factor
|
||||||
|
|
||||||
// hold 32 last lines of input for history
|
// hold 32 last lines of input for history
|
||||||
#define CON_MAXPROMPTCHARS 256
|
#define CON_MAXPROMPTCHARS 256
|
||||||
#define CON_PROMPTCHAR '>'
|
#define CON_PROMPTCHAR '$'
|
||||||
|
|
||||||
static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines
|
static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines
|
||||||
|
|
||||||
static INT32 inputline; // current input line number
|
static INT32 inputline; // current input line number
|
||||||
static INT32 inputhist; // line number of history input line to restore
|
static INT32 inputhist; // line number of history input line to restore
|
||||||
static size_t input_cx; // position in current input line
|
static size_t input_cur; // position of cursor in line
|
||||||
|
static size_t input_sel; // position of selection marker (I.E.: anything between this and input_cur is "selected")
|
||||||
|
static size_t input_len; // length of current line, used to bound cursor and such
|
||||||
|
// notice: input does NOT include the "$" at the start of the line. - 11/3/16
|
||||||
|
|
||||||
// protos.
|
// protos.
|
||||||
static void CON_InputInit(void);
|
static void CON_InputInit(void);
|
||||||
|
@ -383,14 +386,10 @@ void CON_Init(void)
|
||||||
//
|
//
|
||||||
static void CON_InputInit(void)
|
static void CON_InputInit(void)
|
||||||
{
|
{
|
||||||
INT32 i;
|
|
||||||
|
|
||||||
// prepare the first prompt line
|
// prepare the first prompt line
|
||||||
memset(inputlines, 0, sizeof (inputlines));
|
memset(inputlines, 0, sizeof (inputlines));
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
inputlines[i][0] = CON_PROMPTCHAR;
|
|
||||||
inputline = 0;
|
inputline = 0;
|
||||||
input_cx = 1;
|
input_cur = input_sel = input_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
@ -615,6 +614,86 @@ void CON_Ticker(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ----
|
||||||
|
//
|
||||||
|
// Shortcuts for adding and deleting characters, strings, and sections
|
||||||
|
// Necessary due to moving cursor
|
||||||
|
//
|
||||||
|
|
||||||
|
static inline void CON_InputClear(void)
|
||||||
|
{
|
||||||
|
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
|
||||||
|
input_cur = input_sel = input_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CON_InputSetString(const char *c)
|
||||||
|
{
|
||||||
|
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
|
||||||
|
strcpy(inputlines[inputline], c);
|
||||||
|
input_cur = input_sel = input_len = strlen(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CON_InputAddString(const char *c)
|
||||||
|
{
|
||||||
|
size_t csize = strlen(c);
|
||||||
|
if (input_len + csize > CON_MAXPROMPTCHARS-1)
|
||||||
|
return;
|
||||||
|
if (input_cur != input_len)
|
||||||
|
memmove(&inputlines[inputline][input_cur+csize], &inputlines[inputline][input_cur], input_len-input_cur);
|
||||||
|
memcpy(&inputlines[inputline][input_cur], c, csize);
|
||||||
|
input_len += csize;
|
||||||
|
input_sel = (input_cur += csize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CON_InputDelSelection(void)
|
||||||
|
{
|
||||||
|
size_t start, end, len;
|
||||||
|
if (input_cur > input_sel)
|
||||||
|
{
|
||||||
|
start = input_sel;
|
||||||
|
end = input_cur;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start = input_cur;
|
||||||
|
end = input_sel;
|
||||||
|
}
|
||||||
|
len = (end - start);
|
||||||
|
|
||||||
|
if (end != input_len)
|
||||||
|
memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-input_cur);
|
||||||
|
memset(&inputlines[inputline][input_len - len], 0, len);
|
||||||
|
|
||||||
|
input_len -= len;
|
||||||
|
input_sel = input_cur = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CON_InputAddChar(char c)
|
||||||
|
{
|
||||||
|
if (input_len >= CON_MAXPROMPTCHARS-1)
|
||||||
|
return;
|
||||||
|
if (input_cur != input_len)
|
||||||
|
memmove(&inputlines[inputline][input_cur+1], &inputlines[inputline][input_cur], input_len-input_cur);
|
||||||
|
inputlines[inputline][input_cur++] = c;
|
||||||
|
inputlines[inputline][++input_len] = 0;
|
||||||
|
input_sel = input_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CON_InputDelChar(void)
|
||||||
|
{
|
||||||
|
if (!input_cur)
|
||||||
|
return;
|
||||||
|
if (input_cur != input_len)
|
||||||
|
memmove(&inputlines[inputline][input_cur-1], &inputlines[inputline][input_cur], input_len-input_cur);
|
||||||
|
inputlines[inputline][--input_len] = 0;
|
||||||
|
input_sel = --input_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ----
|
||||||
|
//
|
||||||
|
|
||||||
// Handles console key input
|
// Handles console key input
|
||||||
//
|
//
|
||||||
boolean CON_Responder(event_t *ev)
|
boolean CON_Responder(event_t *ev)
|
||||||
|
@ -689,12 +768,16 @@ boolean CON_Responder(event_t *ev)
|
||||||
// show all cvars/commands that match what we have inputted
|
// show all cvars/commands that match what we have inputted
|
||||||
if (key == KEY_TAB)
|
if (key == KEY_TAB)
|
||||||
{
|
{
|
||||||
size_t i, len = strlen(inputlines[inputline]+1);
|
size_t i, len;
|
||||||
|
|
||||||
if (input_cx < 2 || len >= 80 || strchr(inputlines[inputline]+1, ' '))
|
if (!completion[0])
|
||||||
return true;
|
{
|
||||||
|
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
|
||||||
strcpy(completion, inputlines[inputline]+1);
|
return true;
|
||||||
|
strcpy(completion, inputlines[inputline]);
|
||||||
|
comskips = varskips = 0;
|
||||||
|
}
|
||||||
|
len = strlen(completion);
|
||||||
|
|
||||||
//first check commands
|
//first check commands
|
||||||
CONS_Printf("\nCommands:\n");
|
CONS_Printf("\nCommands:\n");
|
||||||
|
@ -725,18 +808,38 @@ boolean CON_Responder(event_t *ev)
|
||||||
|
|
||||||
if (key == 'x' || key == 'X')
|
if (key == 'x' || key == 'X')
|
||||||
{
|
{
|
||||||
CONS_Printf("Cut\n");
|
if (input_sel > input_cur)
|
||||||
|
I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur);
|
||||||
|
else
|
||||||
|
I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel);
|
||||||
|
CON_InputDelSelection();
|
||||||
|
completion[0] = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (key == 'c' || key == 'C')
|
else if (key == 'c' || key == 'C')
|
||||||
{
|
{
|
||||||
CONS_Printf("Copy\n");
|
if (input_sel > input_cur)
|
||||||
I_ClipboardCopy(inputlines[inputline]+1, strlen(inputlines[inputline]+1));
|
I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur);
|
||||||
|
else
|
||||||
|
I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (key == 'v' || key == 'V')
|
else if (key == 'v' || key == 'V')
|
||||||
{
|
{
|
||||||
CONS_Printf("Paste: %s\n", I_ClipboardPaste());
|
const char *paste = I_ClipboardPaste();
|
||||||
|
if (input_sel != input_cur)
|
||||||
|
CON_InputDelSelection();
|
||||||
|
if (paste != NULL)
|
||||||
|
CON_InputAddString(paste);
|
||||||
|
completion[0] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select all
|
||||||
|
if (key == 'a' || key == 'A')
|
||||||
|
{
|
||||||
|
input_sel = 0;
|
||||||
|
input_cur = input_len;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,13 +853,11 @@ boolean CON_Responder(event_t *ev)
|
||||||
// sequential command completion forward and backward
|
// sequential command completion forward and backward
|
||||||
|
|
||||||
// remember typing for several completions (a-la-4dos)
|
// remember typing for several completions (a-la-4dos)
|
||||||
if (inputlines[inputline][input_cx-1] != ' ')
|
if (!completion[0])
|
||||||
{
|
{
|
||||||
if (strlen(inputlines[inputline]+1) < 80)
|
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
|
||||||
strcpy(completion, inputlines[inputline]+1);
|
return true;
|
||||||
else
|
strcpy(completion, inputlines[inputline]);
|
||||||
completion[0] = 0;
|
|
||||||
|
|
||||||
comskips = varskips = 0;
|
comskips = varskips = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -768,37 +869,26 @@ boolean CON_Responder(event_t *ev)
|
||||||
if (--varskips < 0)
|
if (--varskips < 0)
|
||||||
comskips = -comskips - 2;
|
comskips = -comskips - 2;
|
||||||
}
|
}
|
||||||
else if (comskips > 0)
|
else if (comskips > 0) comskips--;
|
||||||
comskips--;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (comskips < 0)
|
if (comskips < 0) varskips++;
|
||||||
varskips++;
|
else comskips++;
|
||||||
else
|
|
||||||
comskips++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comskips >= 0)
|
if (comskips >= 0)
|
||||||
{
|
{
|
||||||
cmd = COM_CompleteCommand(completion, comskips);
|
cmd = COM_CompleteCommand(completion, comskips);
|
||||||
if (!cmd)
|
if (!cmd) // dirty: make sure if comskips is zero, to have a neg value
|
||||||
// dirty: make sure if comskips is zero, to have a neg value
|
|
||||||
comskips = -comskips - 1;
|
comskips = -comskips - 1;
|
||||||
}
|
}
|
||||||
if (comskips < 0)
|
if (comskips < 0)
|
||||||
cmd = CV_CompleteVar(completion, varskips);
|
cmd = CV_CompleteVar(completion, varskips);
|
||||||
|
|
||||||
if (cmd)
|
if (cmd)
|
||||||
{
|
CON_InputSetString(va("%s ", cmd));
|
||||||
memset(inputlines[inputline]+1, 0, CON_MAXPROMPTCHARS-1);
|
|
||||||
strcpy(inputlines[inputline]+1, cmd);
|
|
||||||
input_cx = strlen(cmd) + 1;
|
|
||||||
inputlines[inputline][input_cx] = ' ';
|
|
||||||
input_cx++;
|
|
||||||
inputlines[inputline][input_cx] = 0;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (comskips > 0)
|
if (comskips > 0)
|
||||||
|
@ -824,38 +914,80 @@ boolean CON_Responder(event_t *ev)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key == KEY_LEFTARROW)
|
||||||
|
{
|
||||||
|
if (input_cur != 0)
|
||||||
|
--input_cur;
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == KEY_RIGHTARROW)
|
||||||
|
{
|
||||||
|
if (input_cur < input_len)
|
||||||
|
++input_cur;
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == KEY_HOME)
|
||||||
|
{
|
||||||
|
input_cur = 0;
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == KEY_END)
|
||||||
|
{
|
||||||
|
input_cur = input_len;
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we're messing with input
|
||||||
|
// Clear completion
|
||||||
|
completion[0] = 0;
|
||||||
|
|
||||||
// command enter
|
// command enter
|
||||||
if (key == KEY_ENTER)
|
if (key == KEY_ENTER)
|
||||||
{
|
{
|
||||||
if (input_cx < 2)
|
if (!input_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// push the command
|
// push the command
|
||||||
COM_BufAddText(inputlines[inputline]+1);
|
COM_BufAddText(inputlines[inputline]);
|
||||||
COM_BufAddText("\n");
|
COM_BufAddText("\n");
|
||||||
|
|
||||||
CONS_Printf("%s\n", inputlines[inputline]);
|
CONS_Printf("\x86""%c""\x80""%s\n", CON_PROMPTCHAR, inputlines[inputline]);
|
||||||
|
|
||||||
inputline = (inputline+1) & 31;
|
inputline = (inputline+1) & 31;
|
||||||
inputhist = inputline;
|
inputhist = inputline;
|
||||||
|
CON_InputClear();
|
||||||
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
|
|
||||||
inputlines[inputline][0] = CON_PROMPTCHAR;
|
|
||||||
input_cx = 1;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// backspace command prompt
|
// backspace and delete command prompt
|
||||||
if (key == KEY_BACKSPACE)
|
if (input_sel != input_cur)
|
||||||
{
|
{
|
||||||
if (input_cx > 1)
|
if (key == KEY_BACKSPACE || key == KEY_DEL)
|
||||||
{
|
{
|
||||||
input_cx--;
|
CON_InputDelSelection();
|
||||||
inputlines[inputline][input_cx] = 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (key == KEY_BACKSPACE)
|
||||||
|
{
|
||||||
|
CON_InputDelChar();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == KEY_DEL)
|
||||||
|
{
|
||||||
|
if (input_cur == input_len)
|
||||||
|
return true;
|
||||||
|
++input_cur;
|
||||||
|
CON_InputDelChar();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,18 +996,15 @@ boolean CON_Responder(event_t *ev)
|
||||||
{
|
{
|
||||||
// copy one of the previous inputlines to the current
|
// copy one of the previous inputlines to the current
|
||||||
do
|
do
|
||||||
{
|
|
||||||
inputhist = (inputhist - 1) & 31; // cycle back
|
inputhist = (inputhist - 1) & 31; // cycle back
|
||||||
} while (inputhist != inputline && !inputlines[inputhist][1]);
|
while (inputhist != inputline && !inputlines[inputhist][0]);
|
||||||
|
|
||||||
// stop at the last history input line, which is the
|
// stop at the last history input line, which is the
|
||||||
// current line + 1 because we cycle through the 32 input lines
|
// current line + 1 because we cycle through the 32 input lines
|
||||||
if (inputhist == inputline)
|
if (inputhist == inputline)
|
||||||
inputhist = (inputline + 1) & 31;
|
inputhist = (inputline + 1) & 31;
|
||||||
|
|
||||||
M_Memcpy(inputlines[inputline], inputlines[inputhist], CON_MAXPROMPTCHARS);
|
CON_InputSetString(inputlines[inputhist]);
|
||||||
input_cx = strlen(inputlines[inputline]);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,23 +1014,14 @@ boolean CON_Responder(event_t *ev)
|
||||||
if (inputhist == inputline)
|
if (inputhist == inputline)
|
||||||
return true;
|
return true;
|
||||||
do
|
do
|
||||||
{
|
|
||||||
inputhist = (inputhist + 1) & 31;
|
inputhist = (inputhist + 1) & 31;
|
||||||
} while (inputhist != inputline && !inputlines[inputhist][1]);
|
while (inputhist != inputline && !inputlines[inputhist][0]);
|
||||||
|
|
||||||
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
|
|
||||||
|
|
||||||
// back to currentline
|
// back to currentline
|
||||||
if (inputhist == inputline)
|
if (inputhist == inputline)
|
||||||
{
|
CON_InputClear();
|
||||||
inputlines[inputline][0] = CON_PROMPTCHAR;
|
|
||||||
input_cx = 1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
CON_InputSetString(inputlines[inputhist]);
|
||||||
strcpy(inputlines[inputline], inputlines[inputhist]);
|
|
||||||
input_cx = strlen(inputlines[inputline]);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,15 +1046,12 @@ boolean CON_Responder(event_t *ev)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// add key to cmd line here
|
// add key to cmd line here
|
||||||
if (input_cx < CON_MAXPROMPTCHARS)
|
if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers
|
||||||
{
|
key = key + 'a' - 'A';
|
||||||
if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers
|
|
||||||
key = key + 'a' - 'A';
|
|
||||||
|
|
||||||
inputlines[inputline][input_cx] = (char)key;
|
if (input_sel != input_cur)
|
||||||
inputlines[inputline][input_cx + 1] = 0;
|
CON_InputDelSelection();
|
||||||
input_cx++;
|
CON_InputAddChar(key);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1218,26 +1335,84 @@ void CONS_Error(const char *msg)
|
||||||
//
|
//
|
||||||
static void CON_DrawInput(void)
|
static void CON_DrawInput(void)
|
||||||
{
|
{
|
||||||
char *p;
|
|
||||||
size_t c;
|
|
||||||
INT32 x, y;
|
|
||||||
INT32 charwidth = (INT32)con_scalefactor << 3;
|
INT32 charwidth = (INT32)con_scalefactor << 3;
|
||||||
|
const char *p = inputlines[inputline];
|
||||||
// input line scrolls left if it gets too long
|
size_t c, clen, cend;
|
||||||
p = inputlines[inputline];
|
UINT8 lellip = 0, rellip = 0;
|
||||||
if (input_cx >= con_width-11)
|
INT32 x, y, i;
|
||||||
p += input_cx - (con_width-11) + 1;
|
|
||||||
|
|
||||||
y = con_curlines - 12 * con_scalefactor;
|
y = con_curlines - 12 * con_scalefactor;
|
||||||
|
x = charwidth*2;
|
||||||
|
|
||||||
for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth)
|
clen = con_width-12;
|
||||||
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
|
|
||||||
|
|
||||||
// draw the blinking cursor
|
if (input_len <= clen)
|
||||||
//
|
{
|
||||||
x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth);
|
c = 0;
|
||||||
if (con_tick < 4)
|
clen = input_len;
|
||||||
V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
|
}
|
||||||
|
else // input line scrolls left if it gets too long
|
||||||
|
{
|
||||||
|
clen -= 2; // There will always be some extra truncation -- but where is what we'll find out
|
||||||
|
|
||||||
|
if (input_cur <= clen/2)
|
||||||
|
{
|
||||||
|
// Close enough to right edge to show all
|
||||||
|
c = 0;
|
||||||
|
// Always will truncate right side from this position, so always draw right ellipsis
|
||||||
|
rellip = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cursor in the middle (or right side) of input
|
||||||
|
// Move over for the ellipsis
|
||||||
|
c = input_cur - (clen/2) + 2;
|
||||||
|
x += charwidth*2;
|
||||||
|
lellip = 1;
|
||||||
|
|
||||||
|
if (c + clen >= input_len)
|
||||||
|
{
|
||||||
|
// Cursor in the right side of input
|
||||||
|
// We were too far over, so move back
|
||||||
|
c = input_len - clen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cursor in the middle -- ellipses on both sides
|
||||||
|
clen -= 2;
|
||||||
|
rellip = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lellip)
|
||||||
|
{
|
||||||
|
for (i = 0, x -= charwidth*3; i < 3; ++i, x += charwidth)
|
||||||
|
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
|
||||||
|
for (cend = c + clen; c < cend; ++c, x += charwidth)
|
||||||
|
{
|
||||||
|
if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c))
|
||||||
|
{
|
||||||
|
V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 107 | V_NOSCALESTART);
|
||||||
|
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
|
||||||
|
if (c == input_cur && con_tick >= 4)
|
||||||
|
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
}
|
||||||
|
if (cend == input_cur && con_tick >= 4)
|
||||||
|
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
if (rellip)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 3; ++i, x += charwidth)
|
||||||
|
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw the last lines of console text to the top of the screen
|
// draw the last lines of console text to the top of the screen
|
||||||
|
|
|
@ -260,18 +260,6 @@ static char returnWadPath[256];
|
||||||
#include "../byteptr.h"
|
#include "../byteptr.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FAKE_CLIPBOARD simulates system clipboard, but is just local to our app
|
|
||||||
#ifndef FAKE_CLIPBOARD
|
|
||||||
#include "SDL_syswm.h"
|
|
||||||
|
|
||||||
#if defined (_WIN32) && !defined (_XBOX)
|
|
||||||
#include <winuser.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: clipboard support for other OSes
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \brief The JoyReset function
|
/** \brief The JoyReset function
|
||||||
|
|
||||||
\param JoySet Joystick info to reset
|
\param JoySet Joystick info to reset
|
||||||
|
@ -2659,86 +2647,30 @@ INT32 I_PutEnv(char *variable)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FAKE_CLIPBOARD
|
|
||||||
static char __clipboard[512] = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INT32 I_ClipboardCopy(const char *data, size_t size)
|
INT32 I_ClipboardCopy(const char *data, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef FAKE_CLIPBOARD
|
char storage[256];
|
||||||
if (size >= 512) size = 511;
|
if (size > 255)
|
||||||
memcpy(__clipboard, data, size);
|
size = 255;
|
||||||
__clipboard[size] = 0;
|
memcpy(storage, data, size);
|
||||||
return 0;
|
storage[size] = 0;
|
||||||
#else // !FAKE_CLIPBOARD
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
if (SDL_SetClipboardText(storage))
|
||||||
SDL_SysWMinfo syswm;
|
return 0;
|
||||||
HGLOBAL *storage_ptr;
|
|
||||||
char *storage_raw;
|
|
||||||
|
|
||||||
SDL_VERSION(&syswm.version);
|
|
||||||
|
|
||||||
// Get window (HWND) information, use that to open the clipboard
|
|
||||||
if (!SDL_GetWindowWMInfo(window, &syswm) || !(OpenClipboard(syswm.info.win.window)))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Erase clipboard contents -- if we have nothing to copy, just leave them blank
|
|
||||||
EmptyClipboard();
|
|
||||||
if (size == 0)
|
|
||||||
goto clipboardend;
|
|
||||||
|
|
||||||
// Allocate movable global memory to store our text.
|
|
||||||
if (!(storage_ptr = GlobalAlloc(GMEM_MOVEABLE, size+1))
|
|
||||||
|| !(storage_raw = (char *)GlobalLock(storage_ptr))) // Lock our pointer (gives us access to its data)
|
|
||||||
goto clipboardfail;
|
|
||||||
memcpy(storage_raw, data, size);
|
|
||||||
storage_raw[size] = 0;
|
|
||||||
GlobalUnlock(storage_ptr); // Unlock it before sending it off
|
|
||||||
if (!SetClipboardData(CF_TEXT, storage_ptr)) // NOTE: this removes our permissions from the pointer
|
|
||||||
goto clipboardfail;
|
|
||||||
|
|
||||||
clipboardend:
|
|
||||||
CloseClipboard();
|
|
||||||
return 0; //OpenClipboard();
|
|
||||||
clipboardfail:
|
|
||||||
CloseClipboard(); // Don't leave me hanging
|
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
|
||||||
(void)data;
|
|
||||||
(void)size;
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FAKE_CLIPBOARD
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *I_ClipboardPaste(void)
|
const char *I_ClipboardPaste(void)
|
||||||
{
|
{
|
||||||
#ifdef FAKE_CLIPBOARD
|
static char clipboard_modified[256];
|
||||||
return (const char *)&__clipboard;
|
char *clipboard_contents, *i = clipboard_modified;
|
||||||
#else // !FAKE_CLIPBOARD
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
if (!SDL_HasClipboardText())
|
||||||
HGLOBAL *clipboard_ptr;
|
|
||||||
const char *clipboard_raw;
|
|
||||||
static char clipboard_contents[512];
|
|
||||||
char *i = clipboard_contents;
|
|
||||||
|
|
||||||
if (!IsClipboardFormatAvailable(CF_TEXT))
|
|
||||||
return NULL; // Data either unavailable, or in wrong format
|
|
||||||
OpenClipboard(NULL); // NOTE: Don't need window pointer to get, only to set
|
|
||||||
if (!(clipboard_ptr = GetClipboardData(CF_TEXT))) // Get global pointer
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!(clipboard_raw = (const char *)GlobalLock(clipboard_ptr))) // Lock access -- gives us direct ptr to data
|
clipboard_contents = SDL_GetClipboardText();
|
||||||
{
|
memcpy(clipboard_modified, clipboard_contents, 255);
|
||||||
CloseClipboard(); // Don't leave me hanging if we fail
|
SDL_free(clipboard_contents);
|
||||||
return NULL;
|
clipboard_modified[255] = 0;
|
||||||
}
|
|
||||||
memcpy(clipboard_contents, clipboard_raw, 511);
|
|
||||||
GlobalUnlock(clipboard_ptr); // Unlock for other apps
|
|
||||||
CloseClipboard(); // And make sure to close the clipboard for other apps too
|
|
||||||
clipboard_contents[511] = 0; // Done after unlock to cause as little interference as possible
|
|
||||||
|
|
||||||
while (*i)
|
while (*i)
|
||||||
{
|
{
|
||||||
|
@ -2753,13 +2685,7 @@ const char *I_ClipboardPaste(void)
|
||||||
*i = '?'; // Nonprintable chars become question marks
|
*i = '?'; // Nonprintable chars become question marks
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
return (const char *)&clipboard_modified;
|
||||||
return (const char *)&clipboard_contents;
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FAKE_CLIPBOARD
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief The isWadPathOk function
|
/** \brief The isWadPathOk function
|
||||||
|
|
|
@ -774,43 +774,51 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
||||||
if (!screens[0])
|
if (!screens[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
if (c & V_NOSCALESTART)
|
||||||
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
|
|
||||||
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest = screens[0] + y*dupy*vid.width + x*dupx;
|
|
||||||
deststop = screens[0] + vid.rowbytes * vid.height;
|
|
||||||
|
|
||||||
if (w == BASEVIDWIDTH)
|
|
||||||
w = vid.width;
|
|
||||||
else
|
|
||||||
w *= dupx;
|
|
||||||
if (h == BASEVIDHEIGHT)
|
|
||||||
h = vid.height;
|
|
||||||
else
|
|
||||||
h *= dupy;
|
|
||||||
|
|
||||||
if (x && y && x + w < vid.width && y + h < vid.height)
|
|
||||||
{
|
{
|
||||||
// Center it if necessary
|
dest = screens[0] + y*vid.width + x;
|
||||||
if (vid.width != BASEVIDWIDTH * dupx)
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||||
{
|
}
|
||||||
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
else
|
||||||
// so center this imaginary screen
|
{
|
||||||
if (c & V_SNAPTORIGHT)
|
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||||
dest += (vid.width - (BASEVIDWIDTH * dupx));
|
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
|
||||||
else if (!(c & V_SNAPTOLEFT))
|
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
|
||||||
dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
return;
|
||||||
}
|
}
|
||||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
|
||||||
|
dest = screens[0] + y*dupy*vid.width + x*dupx;
|
||||||
|
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||||
|
|
||||||
|
if (w == BASEVIDWIDTH)
|
||||||
|
w = vid.width;
|
||||||
|
else
|
||||||
|
w *= dupx;
|
||||||
|
if (h == BASEVIDHEIGHT)
|
||||||
|
h = vid.height;
|
||||||
|
else
|
||||||
|
h *= dupy;
|
||||||
|
|
||||||
|
if (x && y && x + w < vid.width && y + h < vid.height)
|
||||||
{
|
{
|
||||||
// same thing here
|
// Center it if necessary
|
||||||
if (c & V_SNAPTOBOTTOM)
|
if (vid.width != BASEVIDWIDTH * dupx)
|
||||||
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width;
|
{
|
||||||
else if (!(c & V_SNAPTOTOP))
|
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
||||||
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2;
|
// so center this imaginary screen
|
||||||
|
if (c & V_SNAPTORIGHT)
|
||||||
|
dest += (vid.width - (BASEVIDWIDTH * dupx));
|
||||||
|
else if (!(c & V_SNAPTOLEFT))
|
||||||
|
dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||||
|
}
|
||||||
|
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||||
|
{
|
||||||
|
// same thing here
|
||||||
|
if (c & V_SNAPTOBOTTOM)
|
||||||
|
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width;
|
||||||
|
else if (!(c & V_SNAPTOTOP))
|
||||||
|
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue