mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-03-13 22:23:04 +00:00
added console mark mode
This commit is contained in:
parent
3f189e58be
commit
533e0872c1
9 changed files with 280 additions and 32 deletions
|
@ -4,6 +4,10 @@ See the end of this file for known issues.
|
|||
|
||||
DD Mmm 20 - 1.53
|
||||
|
||||
add: console mark mode (selection mode) can be toggled with Ctrl-M
|
||||
use arrow keys, home/end or page up/down to move the cursor or extend the area when pressing shift
|
||||
Ctrl-C/enter copies the selected text to the clipboard without color codes and exits mark mode
|
||||
|
||||
add: /searchconsole begins a new console search
|
||||
press ctrl-F when the console is down to bring up the command
|
||||
press (shift-)F3 to find the next match going up or down
|
||||
|
|
|
@ -37,7 +37,10 @@ static cvar_t* con_drawHelp;
|
|||
X(Border, "4778B2FF", qtrue, "RGBA color of the border") \
|
||||
X(Arrow, "4778B2FF", qtrue, "RGBA color of backscroll arrows") \
|
||||
X(Shadow, "000000FF", qtrue, "RGBA color of text shadows") \
|
||||
X(MkBG, "BFBFBFFF", qtrue, "RGBA color of the mark background") \
|
||||
X(MkShadow, "FFFFFF00", qtrue, "RGBA color of the mark text shadows") \
|
||||
X(Text, "E2E2E2", qfalse, "RGB color of text") \
|
||||
X(MkText, "000000", qfalse, "RGB color of mark text") \
|
||||
X(CVar, "4778B2", qfalse, "RGB color of variable names") \
|
||||
X(Cmd, "4FA7BD", qfalse, "RGB color of command names") \
|
||||
X(Value, "E5BC39", qfalse, "RGB color of variable values") \
|
||||
|
@ -55,6 +58,11 @@ COLOR_LIST( COLOR_LIST_ITEM )
|
|||
|
||||
#define CON_TEXTSIZE (256*1024)
|
||||
|
||||
#define COLOR_INVALID '\xFF'
|
||||
#define COLOR_MKTEXT '\xFE'
|
||||
#define COLOR_MKSHAD '\xFD'
|
||||
#define COLOR_SHAD '\xFC'
|
||||
|
||||
// con_drawHelp flags
|
||||
#define DRAWHELP_ENABLE_BIT 1
|
||||
#define DRAWHELP_NOTFOUND_BIT 2
|
||||
|
@ -87,17 +95,24 @@ struct console_t {
|
|||
|
||||
qbool wasActive; // was active before Con_PushConsoleInvisible was called?
|
||||
|
||||
char helpText[MAXPRINTMSG];
|
||||
int helpX; // char index
|
||||
float helpY; // top coordinate
|
||||
int helpWidth; // char count of the longest line
|
||||
int helpLines; // line count
|
||||
qbool helpDraw;
|
||||
float helpXAdjust;
|
||||
char helpText[MAXPRINTMSG];
|
||||
int helpX; // char index
|
||||
float helpY; // top coordinate
|
||||
int helpWidth; // char count of the longest line
|
||||
int helpLines; // line count
|
||||
qbool helpDraw;
|
||||
float helpXAdjust;
|
||||
|
||||
char searchPattern[256];
|
||||
qbool searchLineIndex;
|
||||
qbool searchStarted;
|
||||
|
||||
qbool markMode;
|
||||
int markX; // cursor X: offset in the row
|
||||
int markY; // cursor Y: row index
|
||||
int markStartX;
|
||||
int markStartY;
|
||||
char markText[CON_TEXTSIZE + CON_TEXTSIZE / 100]; // some extra for line endings and the final newline
|
||||
};
|
||||
|
||||
static console_t con;
|
||||
|
@ -175,6 +190,12 @@ const float* ConsoleColorFromChar( char ccode )
|
|||
return colValue;
|
||||
if ( ccode == COLOR_HELP )
|
||||
return colHelp;
|
||||
if ( ccode == COLOR_MKTEXT )
|
||||
return colMkText;
|
||||
if ( ccode == COLOR_MKSHAD )
|
||||
return colMkShadow;
|
||||
if ( ccode == COLOR_SHAD )
|
||||
return colShadow;
|
||||
|
||||
return ColorFromChar( ccode );
|
||||
}
|
||||
|
@ -201,6 +222,7 @@ void Con_ToggleConsole_f()
|
|||
|
||||
Con_ClearNotify();
|
||||
cls.keyCatchers ^= KEYCATCH_CONSOLE;
|
||||
con.markMode = qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -561,7 +583,7 @@ static void Con_DrawInput()
|
|||
re.SetColor( colText );
|
||||
SCR_DrawChar( con.xadjust, y, con.cw, con.ch, ']' );
|
||||
|
||||
Field_Draw( &g_consoleField, con.xadjust + con.cw, y, con.cw, con.ch, qtrue );
|
||||
Field_Draw( &g_consoleField, con.xadjust + con.cw, y, con.cw, con.ch, qtrue, !Con_IsInMarkMode() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -768,20 +790,23 @@ static void Con_DrawSolidConsole( float frac )
|
|||
SCR_DrawChar( x, scanlines - (SMALLCHAR_HEIGHT * 1.5), SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, Q3_VERSION[i] );
|
||||
}
|
||||
|
||||
const int cw = (int)ceilf( con.cw );
|
||||
const int ch = (int)ceilf( con.ch );
|
||||
|
||||
re.SetColor( NULL );
|
||||
rows = (scanlines - con.ch) / con.ch;
|
||||
rows = (scanlines - ch) / ch;
|
||||
con.y = scanlines;
|
||||
|
||||
y = scanlines - (con.ch * 3);
|
||||
y = scanlines - (ch * 3);
|
||||
|
||||
// draw the console text from the bottom up
|
||||
if (con.display != con.current) {
|
||||
// draw arrows to show the buffer is backscrolled
|
||||
const int xEnd = ( cls.glconfig.vidWidth - con.xadjust ) / con.cw;
|
||||
const int xEnd = ( cls.glconfig.vidWidth - con.xadjust ) / cw;
|
||||
re.SetColor( colArrow );
|
||||
for (x = 0; x < xEnd; x += 4)
|
||||
SCR_DrawChar( con.xadjust + x * con.cw, y, con.cw, con.ch, '^' );
|
||||
y -= con.ch;
|
||||
SCR_DrawChar( con.xadjust + x * cw, y, cw, ch, '^' );
|
||||
y -= ch;
|
||||
--rows;
|
||||
}
|
||||
|
||||
|
@ -790,11 +815,29 @@ static void Con_DrawSolidConsole( float frac )
|
|||
row--;
|
||||
}
|
||||
|
||||
char color = COLOR_WHITE;
|
||||
re.SetColor( ConsoleColorFromChar( color ) );
|
||||
const int markStartX = min( con.markStartX, con.markX );
|
||||
const int markStartY = min( con.markStartY, con.markY );
|
||||
const int markEndX = max( con.markStartX, con.markX );
|
||||
const int markEndY = max( con.markStartY, con.markY );
|
||||
qbool drawMark = qfalse;
|
||||
if (con.markMode) {
|
||||
// draw the mark area background, if any
|
||||
const float mhu = ( markEndY - markStartY + 1 ) * ch; // unclipped
|
||||
const float mh = min( mhu, (float)(con.display - markStartY) * ch );
|
||||
drawMark =
|
||||
markEndX != markStartX ||
|
||||
markEndY != markStartY ||
|
||||
Sys_Milliseconds() % 1000 < 500;
|
||||
if (drawMark && mh > 0.0f) {
|
||||
const float mx = con.xadjust + markStartX * cw;
|
||||
const float my = y - ( con.display - markStartY - 1 ) * ch;
|
||||
const float mw = ( markEndX - markStartX + 1 ) * cw;
|
||||
Con_FillRect( mx, my, mw, mh, colMkBG );
|
||||
}
|
||||
}
|
||||
|
||||
con.rowsVisible = 0;
|
||||
for (i = 0; i < rows; ++i, --row, y -= con.ch )
|
||||
for (i = 0; i < rows; ++i, --row, y -= ch )
|
||||
{
|
||||
if (row < 0)
|
||||
break;
|
||||
|
@ -806,25 +849,36 @@ static void Con_DrawSolidConsole( float frac )
|
|||
if (y >= 0)
|
||||
con.rowsVisible++;
|
||||
|
||||
const short* text = con.text + (row % con.totallines)*con.linewidth;
|
||||
|
||||
re.SetColor( colShadow );
|
||||
const short* const text = con.text + (row % con.totallines)*con.linewidth;
|
||||
const qbool markRow = drawMark && row >= markStartY && row <= markEndY;
|
||||
|
||||
char color = COLOR_INVALID;
|
||||
for (int j = 0; j < con.linewidth; ++j) {
|
||||
SCR_DrawChar( 1 + con.xadjust + j * con.cw, 1 + y, con.cw, con.ch, (text[j] & 0xFF) );
|
||||
char newColor = COLOR_SHAD;
|
||||
if (markRow && j >= markStartX && j <= markEndX)
|
||||
newColor = COLOR_MKSHAD;
|
||||
if (newColor != color) {
|
||||
color = newColor;
|
||||
re.SetColor( ConsoleColorFromChar( color ) );
|
||||
}
|
||||
SCR_DrawChar( 1 + con.xadjust + j * cw, 1 + y, cw, ch, (text[j] & 0xFF) );
|
||||
}
|
||||
|
||||
if ((row % con.totallines) == con.searchLineIndex) {
|
||||
re.SetColor( colSearch );
|
||||
SCR_DrawChar( con.xadjust - con.cw, y, con.cw, con.ch, 141 );
|
||||
}
|
||||
|
||||
re.SetColor( colText );
|
||||
|
||||
color = COLOR_INVALID;
|
||||
for (int j = 0; j < con.linewidth; ++j) {
|
||||
if ((text[j] >> 8) != color) {
|
||||
color = (text[j] >> 8);
|
||||
char newColor = text[j] >> 8;
|
||||
if (markRow && j >= markStartX && j <= markEndX)
|
||||
newColor = COLOR_MKTEXT;
|
||||
if (newColor != color) {
|
||||
color = newColor;
|
||||
re.SetColor( ConsoleColorFromChar( color ) );
|
||||
}
|
||||
SCR_DrawChar( con.xadjust + j * con.cw, y, con.cw, con.ch, (text[j] & 0xFF) );
|
||||
SCR_DrawChar( con.xadjust + j * cw, y, cw, ch, (text[j] & 0xFF) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1022,3 +1076,151 @@ void Con_ContinueSearch( qbool forward )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Con_AutoScrollMarkPosition()
|
||||
{
|
||||
if (con.markY >= con.display) {
|
||||
con.display = con.markY + 1;
|
||||
} else if (con.markY < con.display - con.rowsVisible) {
|
||||
// we need to jump past 1 more line when we're all the way at the bottom
|
||||
const int extra = con.display == con.current ? 1 : 0;
|
||||
con.display += con.markY - ( con.display - con.rowsVisible ) - extra;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
qbool Con_HandleMarkMode( qbool ctrlDown, qbool shiftDown, int key )
|
||||
{
|
||||
// ctrl-m = toggle mark mode
|
||||
if ( ctrlDown && tolower(key) == 'm' ) {
|
||||
con.markMode = !con.markMode;
|
||||
if (con.markMode) {
|
||||
con.markX = 0;
|
||||
con.markY = con.display - 1;
|
||||
con.markStartX = 0;
|
||||
con.markStartY = con.display - 1;
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (!con.markMode) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if (key == K_HOME) {
|
||||
if (ctrlDown)
|
||||
return qfalse;
|
||||
con.markX = 0;
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if(key == K_END) {
|
||||
if (ctrlDown)
|
||||
return qfalse;
|
||||
con.markX = con.linewidth - 1;
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (key == K_LEFTARROW) {
|
||||
con.markX = max( con.markX - 1, 0 );
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (key == K_RIGHTARROW) {
|
||||
con.markX = min( con.markX + 1, con.linewidth );
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (key == K_UPARROW) {
|
||||
con.markY = max( con.markY - 1, con.totallines - 1 );
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (key == K_DOWNARROW) {
|
||||
con.markY = min( con.markY + 1, con.current - 1 );
|
||||
if (!shiftDown) {
|
||||
con.markStartX = con.markX;
|
||||
con.markStartY = con.markY;
|
||||
}
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (shiftDown && key == K_PGUP) {
|
||||
con.markY = max( con.markY - 6, con.totallines - 1 );
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (shiftDown && key == K_PGDN) {
|
||||
con.markY = min( con.markY + 6, con.current - 1 );
|
||||
Con_AutoScrollMarkPosition();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if ((ctrlDown && tolower(key) == 'c') || key == K_ENTER) {
|
||||
const int markStartX = min( con.markStartX, con.markX );
|
||||
const int markStartY = min( con.markStartY, con.markY );
|
||||
const int markEndX = max( con.markStartX, con.markX );
|
||||
const int markEndY = max( con.markStartY, con.markY );
|
||||
char* dst = con.markText;
|
||||
|
||||
for (int y = markStartY; y <= markEndY; ++y) {
|
||||
if (y > markStartY) {
|
||||
*dst++ = '\r';
|
||||
*dst++ = '\n';
|
||||
}
|
||||
const int row = y % con.totallines;
|
||||
const short* const text = con.text + row * con.linewidth;
|
||||
for (int x = markStartX; x <= markEndX; ++x) {
|
||||
*dst++ = text[x] & 0xFF;
|
||||
}
|
||||
}
|
||||
*dst++ = '\0';
|
||||
|
||||
Sys_SetClipboardData( con.markText );
|
||||
con.markMode = qfalse;
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// let the original scrolling code run...
|
||||
if (key == K_PGDN || key == K_PGUP ||
|
||||
key == K_MWHEELDOWN || key == K_MWHEELUP) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// ...but block everything else
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
qbool Con_IsInMarkMode()
|
||||
{
|
||||
return con.markMode;
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ EDIT FIELDS
|
|||
// handles horizontal scrolling and cursor blinking
|
||||
// position and char sizes are in pixels
|
||||
|
||||
void Field_Draw( field_t* edit, int x, int y, int cw, int ch, qbool extColors )
|
||||
void Field_Draw( field_t* edit, int x, int y, int cw, int ch, qbool extColors, qbool drawCaret )
|
||||
{
|
||||
int len;
|
||||
int drawLen;
|
||||
|
@ -263,8 +263,8 @@ void Field_Draw( field_t* edit, int x, int y, int cw, int ch, qbool extColors )
|
|||
firstColor = extColors ? ConsoleColorFromChar( colorCode ) : ColorFromChar( colorCode );
|
||||
SCR_DrawStringEx( x, y, cw, ch, str, extColors ? DSC_CONSOLE : DSC_NORMAL, qtrue, firstColor );
|
||||
|
||||
if ( (int)( cls.realtime >> 8 ) & 1 ) {
|
||||
return; // off blink
|
||||
if ( !drawCaret || Sys_Milliseconds() % 500 < 250 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( key_overstrikeMode ) {
|
||||
|
@ -469,6 +469,10 @@ CONSOLE LINE EDITING
|
|||
|
||||
static void Console_Key( int key )
|
||||
{
|
||||
if ( Con_HandleMarkMode( keys[K_CTRL].down, keys[K_SHIFT].down, key ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear auto-completion buffer when not pressing tab
|
||||
if ( key != K_TAB )
|
||||
g_consoleField.acOffset = 0;
|
||||
|
@ -1227,7 +1231,10 @@ void CL_CharEvent( int key ) {
|
|||
// distribute the key down event to the appropriate handler
|
||||
if ( cls.keyCatchers & KEYCATCH_CONSOLE )
|
||||
{
|
||||
Field_CharEvent( &g_consoleField, key );
|
||||
if ( !Con_IsInMarkMode() )
|
||||
{
|
||||
Field_CharEvent( &g_consoleField, key );
|
||||
}
|
||||
}
|
||||
else if ( cls.keyCatchers & KEYCATCH_UI )
|
||||
{
|
||||
|
|
|
@ -445,6 +445,8 @@ void Con_Top();
|
|||
void Con_Bottom();
|
||||
void Con_Close();
|
||||
void Con_ContinueSearch( qbool forward );
|
||||
qbool Con_HandleMarkMode( qbool ctrlDown, qbool shiftDown, int key );
|
||||
qbool Con_IsInMarkMode();
|
||||
const float* ConsoleColorFromChar( char ccode );
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "keycodes.h"
|
||||
|
||||
|
||||
void Field_Draw( field_t* edit, int x, int y, int cw, int ch, qbool extColors );
|
||||
void Field_Draw( field_t* edit, int x, int y, int cw, int ch, qbool extColors, qbool drawCaret = qtrue );
|
||||
|
||||
extern history_t g_history;
|
||||
extern field_t g_consoleField;
|
||||
|
|
|
@ -194,10 +194,16 @@ void* QDECL Sys_LoadDll( const char* name, dllSyscall_t *entryPoint, dllSyscall_
|
|||
}
|
||||
|
||||
#ifdef DEDICATED
|
||||
char *Sys_GetClipboardData(void)
|
||||
|
||||
char* Sys_GetClipboardData()
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sys_SetClipboardData( const char* )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Sys_Init()
|
||||
|
|
|
@ -608,6 +608,12 @@ char* Sys_GetClipboardData()
|
|||
}
|
||||
|
||||
|
||||
void Sys_SetClipboardData( const char* text )
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
|
||||
void Lin_MatchStartAlert()
|
||||
{
|
||||
const int alerts = cl_matchAlerts->integer;
|
||||
|
|
|
@ -1107,6 +1107,7 @@ void QDECL Sys_Error( const char *error, ...);
|
|||
// if it succeeds, returns memory allocated by Z_Malloc
|
||||
// note that this isn't journaled
|
||||
char *Sys_GetClipboardData( void );
|
||||
void Sys_SetClipboardData( const char* text );
|
||||
|
||||
void Sys_Print( const char *msg );
|
||||
|
||||
|
|
|
@ -339,6 +339,26 @@ char *Sys_GetClipboardData( void )
|
|||
}
|
||||
|
||||
|
||||
void Sys_SetClipboardData( const char* text )
|
||||
{
|
||||
if ( OpenClipboard( NULL ) ) {
|
||||
const int l = strlen( text );
|
||||
const HGLOBAL hMemory = GlobalAlloc( GMEM_MOVEABLE, l + 1 );
|
||||
if ( hMemory ) {
|
||||
void* const dstMemory = GlobalLock( hMemory );
|
||||
if ( dstMemory ) {
|
||||
strcpy( (char*)dstMemory, text );
|
||||
GlobalUnlock( hMemory );
|
||||
EmptyClipboard();
|
||||
SetClipboardData( CF_TEXT, hMemory );
|
||||
}
|
||||
GlobalFree( hMemory );
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
|
|
Loading…
Reference in a new issue