TokenIterator::value_type TokenIterator::NextToken(const char* input) { if ( !input || *input == '\0' ) { return value_type(); } if ( input[0] == Constants::ESCAPE ) { if ( input[1] == Constants::ESCAPE ) { return value_type( input, input+2, value_type::TokenType::ESCAPE ); } else if ( input[1] == Constants::NULL_COLOR ) { return value_type( input, input+2, parent->DefaultColor() ); } else if ( Str::ctoupper( input[1] ) >= '0' && Str::ctoupper( input[1] ) < 'P' ) { return value_type( input, input+2, detail::Indexed( input[1] - '0' ) ); } else if ( Str::ctolower( input[1] ) == 'x' && Str::cisxdigit( input[2] ) && Str::cisxdigit( input[3] ) && Str::cisxdigit( input[4] ) ) { return value_type( input, input+5, Color( Str::GetHex( input[2] ) / 15.f, Str::GetHex( input[3] ) / 15.f, Str::GetHex( input[4] ) / 15.f, 1 ) ); } else if ( input[1] == '#' ) { bool long_hex = true; for ( int i = 0; i < 6; i++ ) { if ( !Str::cisxdigit( input[i+2] ) ) { long_hex = false; break; } } if ( long_hex ) { return value_type( input, input+8, Color( ( (Str::GetHex( input[2] ) << 4) | Str::GetHex( input[3] ) ) / 255.f, ( (Str::GetHex( input[4] ) << 4) | Str::GetHex( input[5] ) ) / 255.f, ( (Str::GetHex( input[6] ) << 4) | Str::GetHex( input[7] ) ) / 255.f, 1 ) ); } } } return value_type( input, input + Q_UTF8_Width( input ), value_type::TokenType::CHARACTER ); }
static int CON_CursorPosFromScroll( void ) { // if we have wide char support, we have ncurses, and probably wcwidth too. int i, p = Field_ScrollToOffset( &input_field ), c = 0; for ( i = input_field.scroll; i < input_field.cursor; ++i ) { c += CON_wcwidth( input_field.buffer + p ); p += Q_UTF8_Width( input_field.buffer + p ); } return c; }
/* =============== IN_ProcessEvents =============== */ static void IN_ProcessEvents( bool dropInput ) { SDL_Event e; keyNum_t key = (keyNum_t) 0; static keyNum_t lastKeyDown = (keyNum_t) 0; if ( !SDL_WasInit( SDL_INIT_VIDEO ) ) { return; } while ( SDL_PollEvent( &e ) ) { switch ( e.type ) { case SDL_KEYDOWN: if ( !dropInput && ( !e.key.repeat || cls.keyCatchers ) ) { key = IN_TranslateSDLToQ3Key( &e.key.keysym, true ); if ( key ) { Com_QueueEvent( 0, sysEventType_t::SE_KEY, key, true, 0, nullptr ); } lastKeyDown = key; } break; case SDL_KEYUP: if ( !dropInput ) { key = IN_TranslateSDLToQ3Key( &e.key.keysym, false ); if ( key ) { Com_QueueEvent( 0, sysEventType_t::SE_KEY, key, false, 0, nullptr ); } lastKeyDown = (keyNum_t) 0; } break; case SDL_TEXTINPUT: if ( lastKeyDown != K_CONSOLE ) { char *c = e.text.text; while ( *c ) { int width = Q_UTF8_Width( c ); int sc = Q_UTF8_Store( c ); Com_QueueEvent( 0, sysEventType_t::SE_CHAR, sc, 0, 0, nullptr ); c += width; } } break; case SDL_MOUSEMOTION: if ( !dropInput ) { if ( mouse_mode != MouseMode::Deltas ) { Com_QueueEvent( 0, sysEventType_t::SE_MOUSE_POS, e.motion.x, e.motion.y, 0, nullptr ); } else { Com_QueueEvent( 0, sysEventType_t::SE_MOUSE, e.motion.xrel, e.motion.yrel, 0, nullptr ); #if defined( __linux__ ) || defined( __BSD__ ) if ( !in_nograb->integer ) { // work around X window managers and edge-based workspace flipping // - without this, we get LeaveNotify, no mouse button events, EnterNotify; // we would likely miss some button presses and releases. IN_CenterMouse(); } #endif } } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: if ( !dropInput ) { unsigned char b; switch ( e.button.button ) { case SDL_BUTTON_LEFT: b = K_MOUSE1; break; case SDL_BUTTON_MIDDLE: b = K_MOUSE3; break; case SDL_BUTTON_RIGHT: b = K_MOUSE2; break; case SDL_BUTTON_X1: b = K_MOUSE4; break; case SDL_BUTTON_X2: b = K_MOUSE5; break; default: b = K_AUX1 + ( e.button.button - ( SDL_BUTTON_X2 + 1 ) ) % 16; break; } Com_QueueEvent( 0, sysEventType_t::SE_KEY, b, ( e.type == SDL_MOUSEBUTTONDOWN ? true : false ), 0, nullptr ); } break; case SDL_MOUSEWHEEL: // FIXME: mouse wheel support shouldn't use keys! if ( e.wheel.y > 0 ) { Com_QueueEvent( 0, sysEventType_t::SE_KEY, K_MWHEELUP, true, 0, nullptr ); Com_QueueEvent( 0, sysEventType_t::SE_KEY, K_MWHEELUP, false, 0, nullptr ); } else { Com_QueueEvent( 0, sysEventType_t::SE_KEY, K_MWHEELDOWN, true, 0, nullptr ); Com_QueueEvent( 0, sysEventType_t::SE_KEY, K_MWHEELDOWN, false, 0, nullptr ); } break; case SDL_WINDOWEVENT: switch( e.window.event ) { case SDL_WINDOWEVENT_RESIZED: { char width[32], height[32]; Com_sprintf( width, sizeof( width ), "%d", e.window.data1 ); Com_sprintf( height, sizeof( height ), "%d", e.window.data2 ); Cvar_Set( "r_customwidth", width ); Cvar_Set( "r_customheight", height ); Cvar_Set( "r_mode", "-1" ); } break; case SDL_WINDOWEVENT_MINIMIZED: Cvar_SetValue( "com_minimized", 1 ); break; case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_MAXIMIZED: Cvar_SetValue( "com_minimized", 0 ); break; case SDL_WINDOWEVENT_FOCUS_LOST: Cvar_SetValue( "com_unfocused", 1 ); break; case SDL_WINDOWEVENT_FOCUS_GAINED: Cvar_SetValue( "com_unfocused", 0 ); break; } break; case SDL_QUIT: Cmd::ExecuteCommand("quit Closed window"); break; default: break; } } }
/* =============== IN_ProcessEvents =============== */ static void IN_ProcessEvents( qboolean dropInput ) { SDL_Event e; keyNum_t key = (keyNum_t) 0; static keyNum_t lastKeyDown = (keyNum_t) 0; if ( !SDL_WasInit( SDL_INIT_VIDEO ) ) { return; } #if !SDL_VERSION_ATLEAST( 2, 0, 0 ) if ( cls.keyCatchers == 0 && keyRepeatEnabled ) { SDL_EnableKeyRepeat( 0, 0 ); keyRepeatEnabled = qfalse; } else if ( !keyRepeatEnabled ) { SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL ); keyRepeatEnabled = qtrue; } #endif while ( SDL_PollEvent( &e ) ) { switch ( e.type ) { case SDL_KEYDOWN: #if SDL_VERSION_ATLEAST( 2, 0, 0 ) if ( !dropInput && ( !e.key.repeat || cls.keyCatchers ) ) #else if ( !dropInput ) #endif { key = IN_TranslateSDLToQ3Key( &e.key.keysym, qtrue ); if ( key ) { Com_QueueEvent( 0, SE_KEY, key, qtrue, 0, NULL ); #if !SDL_VERSION_ATLEAST( 2, 0, 0 ) if ( key != K_CONSOLE ) { Com_QueueEvent( 0, SE_CHAR, Q_UTF8_Store( Q_UTF8_Encode( e.key.keysym.unicode ) ), 0, 0, NULL ); } #endif } lastKeyDown = key; } break; case SDL_KEYUP: if ( !dropInput ) { key = IN_TranslateSDLToQ3Key( &e.key.keysym, qfalse ); if ( key ) { Com_QueueEvent( 0, SE_KEY, key, qfalse, 0, NULL ); } lastKeyDown = (keyNum_t) 0; } break; #if SDL_VERSION_ATLEAST( 2, 0, 0 ) case SDL_TEXTINPUT: if ( lastKeyDown != K_CONSOLE ) { char *c = e.text.text; while ( *c ) { int width = Q_UTF8_Width( c ); int sc = Q_UTF8_Store( c ); Com_QueueEvent( 0, SE_CHAR, sc, 0, 0, NULL ); c += width; } } break; #endif case SDL_MOUSEMOTION: if ( !dropInput ) { if ( mouseActive ) { Com_QueueEvent( 0, SE_MOUSE, e.motion.xrel, e.motion.yrel, 0, NULL ); #if ( defined( __linux__ ) || defined( __BSD__ ) ) && SDL_VERSION_ATLEAST( 2, 0, 0 ) { // work around X window managers and edge-based workspace flipping // - without this, we get LeaveNotify, no mouse button events, EnterNotify; // we would likely miss some button presses and releases. int w, h; SDL_GetWindowSize( window, &w, &h ); SDL_WarpMouseInWindow( window, w / 2, h / 2 ); } #endif } else if ( uivm ) { // TODO (after no compatibility needed with alpha 8): remove argument int mousepos = VM_Call( uivm, UI_MOUSE_POSITION, 0 ); int cursorx = mousepos & 0xFFFF; int cursory = mousepos >> 16; VM_Call( uivm, UI_MOUSE_EVENT, e.motion.x - cursorx, e.motion.y - cursory ); } } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: if ( !dropInput ) { unsigned char b; switch ( e.button.button ) { case SDL_BUTTON_LEFT: b = K_MOUSE1; break; case SDL_BUTTON_MIDDLE: b = K_MOUSE3; break; case SDL_BUTTON_RIGHT: b = K_MOUSE2; break; #if !SDL_VERSION_ATLEAST( 2, 0, 0 ) case SDL_BUTTON_WHEELUP: b = K_MWHEELUP; break; case SDL_BUTTON_WHEELDOWN: b = K_MWHEELDOWN; break; #endif case SDL_BUTTON_X1: b = K_MOUSE4; break; case SDL_BUTTON_X2: b = K_MOUSE5; break; default: b = K_AUX1 + ( e.button.button - ( SDL_BUTTON_X2 + 1 ) ) % 16; break; } Com_QueueEvent( 0, SE_KEY, b, ( e.type == SDL_MOUSEBUTTONDOWN ? qtrue : qfalse ), 0, NULL ); } break; #if SDL_VERSION_ATLEAST( 2, 0, 0 ) case SDL_MOUSEWHEEL: // FIXME: mouse wheel support shouldn't use keys! if ( e.wheel.y > 0 ) { Com_QueueEvent( 0, SE_KEY, K_MWHEELUP, qtrue, 0, NULL ); Com_QueueEvent( 0, SE_KEY, K_MWHEELUP, qfalse, 0, NULL ); } else { Com_QueueEvent( 0, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL ); Com_QueueEvent( 0, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL ); } break; case SDL_WINDOWEVENT: switch( e.window.event ) { case SDL_WINDOWEVENT_RESIZED: { char width[32], height[32]; Com_sprintf( width, sizeof( width ), "%d", e.window.data1 ); Com_sprintf( height, sizeof( height ), "%d", e.window.data2 ); Cvar_Set( "r_customwidth", width ); Cvar_Set( "r_customheight", height ); Cvar_Set( "r_mode", "-1" ); } break; case SDL_WINDOWEVENT_MINIMIZED: Cvar_SetValue( "com_minimized", 1 ); break; case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_MAXIMIZED: Cvar_SetValue( "com_minimized", 0 ); break; case SDL_WINDOWEVENT_FOCUS_LOST: Cvar_SetValue( "com_unfocused", 1 ); break; case SDL_WINDOWEVENT_FOCUS_GAINED: Cvar_SetValue( "com_unfocused", 0 ); break; } break; #else case SDL_VIDEORESIZE: { char width[32], height[32]; Com_sprintf( width, sizeof( width ), "%d", e.resize.w ); Com_sprintf( height, sizeof( height ), "%d", e.resize.h ); Cvar_Set( "r_customwidth", width ); Cvar_Set( "r_customheight", height ); Cvar_Set( "r_mode", "-1" ); } break; case SDL_ACTIVEEVENT: if ( e.active.state & SDL_APPINPUTFOCUS ) { Cvar_SetValue( "com_unfocused", !e.active.gain ); } if ( e.active.state & SDL_APPACTIVE ) { Cvar_SetValue( "com_minimized", !e.active.gain ); } break; #endif case SDL_QUIT: Cmd::ExecuteCommand("quit Closed window"); break; default: break; } } }
qboolean CL_InternalConsolePrint( const char *text ) { int y; int c, i, l; int color; // for some demos we don't want to ever show anything on the console if ( cl_noprint && cl_noprint->integer ) { return qtrue; } if ( !consoleState.initialized ) { consoleState.textWidthInChars = -1; consoleState.initialized = Con_CheckResize(); } //Video hasn't been initialized if ( ! cls.glconfig.vidWidth ) { return qfalse; } // NERVE - SMF - work around for text that shows up in console but not in notify if ( !Q_strncmp( text, S_SKIPNOTIFY, 12 ) ) { text += 12; } else if ( !consoleState.isOpened && strncmp( text, "EXCL: ", 6 ) ) { // feed the text to cgame Cmd_SaveCmdContext(); Cmd_TokenizeString( Cmd::Escape(text).c_str() ); CL_GameConsoleText(); Cmd_RestoreCmdContext(); } color = ColorIndex( CONSOLE_COLOR ); while ( ( c = *text & 0xFF ) != 0 ) { if ( Q_IsColorString( text ) ) { color = ( text[ 1 ] == COLOR_NULL ) ? ColorIndex( CONSOLE_COLOR ) : ColorIndex( text[ 1 ] ); text += 2; continue; } // count word length for ( i = l = 0; l < consoleState.textWidthInChars; ++l ) { if ( text[ i ] <= ' ' && text[ i ] >= 0 ) { break; } if ( text[ i ] == Q_COLOR_ESCAPE && text[ i + 1 ] == Q_COLOR_ESCAPE ) { ++i; } i += Q_UTF8_Width( text + i ); } // word wrap if ( l != consoleState.textWidthInChars && ( consoleState.horizontalCharOffset + l >= consoleState.textWidthInChars ) ) { Con_Linefeed( ); } switch ( c ) { case '\n': Con_Linefeed( ); break; case '\r': consoleState.horizontalCharOffset = 0; break; case Q_COLOR_ESCAPE: if ( text[ 1 ] == Q_COLOR_ESCAPE ) { ++text; } /* no break */ default: // display character and advance y = consoleState.currentLine % consoleState.maxScrollbackLengthInLines; // rain - sign extension caused the character to carry over // into the color info for high ascii chars; casting c to unsigned consoleState.text[ y * consoleState.textWidthInChars + consoleState.horizontalCharOffset ].ch = Q_UTF8_CodePoint( text ); consoleState.text[ y * consoleState.textWidthInChars + consoleState.horizontalCharOffset ].ink = color; ++consoleState.horizontalCharOffset; if ( consoleState.horizontalCharOffset >= consoleState.textWidthInChars ) { Con_Linefeed( ); consoleState.horizontalCharOffset = 0; } break; } text += Q_UTF8_Width( text ); } return qtrue; }
/* ================== SCR_DrawBigString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. ================== */ void SCR_DrawStringExt(int x, int y, float w, float h, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape, qboolean dropShadow, qboolean nativeResolution) { vec4_t color; const char *s; int xx; if (dropShadow) { // draw the drop shadow Vector4Copy(colorBlack, color); color[3] = setColor[3]; re.SetColor(color); s = string; xx = x; while (*s) { if (!noColorEscape && Q_IsColorString(s)) { s += 2; continue; } SCR_DrawChar(xx + 2, y + 2, w, h, Q_UTF8_CodePoint(s), nativeResolution); xx += w; s += Q_UTF8_Width(s); } } // draw the colored text s = string; xx = x; re.SetColor(setColor); while (*s) { if (Q_IsColorString(s)) { if (!forceColor) { if (*(s + 1) == COLOR_NULL) { memcpy(color, setColor, sizeof(color)); } else { memcpy(color, g_color_table[ColorIndex(*(s + 1))], sizeof(color)); color[3] = setColor[3]; } color[3] = setColor[3]; re.SetColor(color); } if (!noColorEscape) { s += 2; continue; } } SCR_DrawChar(xx, y, w, h, Q_UTF8_CodePoint(s), nativeResolution); xx += w; s += Q_UTF8_Width(s); } re.SetColor(NULL); }