void CG_PanelButton_RenderEdit( panel_button_t* button ) { qboolean useCvar = button->data[0] ? qfalse : qtrue; int offset = -1; if( useCvar ) { char buffer[256 + 1]; trap_Cvar_VariableStringBuffer( button->text, buffer, sizeof(buffer) ); if( cg_focusButton == button && ((cg.time / 1000) % 2)) { if( trap_Key_GetOverstrikeMode() ) Q_strcat( buffer, sizeof(buffer), "^0|" ); else Q_strcat( buffer, sizeof(buffer), "^0_" ); } else { Q_strcat( buffer, sizeof(buffer), " " ); } do { offset++; if( buffer + offset == '\0' ) break; } while( CG_Text_Width_Ext( buffer + offset, button->font->scalex, 0, button->font->font ) > button->rect.w ); CG_Text_Paint_Ext( button->rect.x, button->rect.y + button->rect.h, button->font->scalex, button->font->scaley, button->font->colour, va( "^7%s", buffer + offset ), 0, 0, button->font->style, button->font->font ); // CG_FillRect( button->rect.x, button->rect.y, button->rect.w, button->rect.h, colorRed ); } else { int maxlen = button->data[0]; char *s; if( cg_focusButton == button && ((cg.time / 1000) % 2)) { if( trap_Key_GetOverstrikeMode() ) s = va( "^7%s^0|", button->text ); else s = va( "^7%s^0_", button->text ); } else { s = va( "^7%s ", button->text ); // space hack to make the text not blink } do { offset++; if( s + offset == '\0' ) break; } while( CG_Text_Width_Ext( s + offset, button->font->scalex, 0, button->font->font ) > button->rect.w ); CG_Text_Paint_Ext( button->rect.x, button->rect.y + button->rect.h, button->font->scalex, button->font->scaley, button->font->colour, s + offset, 0, 0, button->font->style, button->font->font ); // CG_FillRect( button->rect.x, button->rect.y, button->rect.w, button->rect.h, colorRed ); } }
/* ================= UI_CDKeyMenu_DrawKey ================= */ static void UI_CDKeyMenu_DrawKey( void *self ) { menufield_s *f; qboolean focus; int style; char c; float *color; int x, y; int val; f = (menufield_s *)self; focus = (f->generic.parent->cursor == f->generic.menuPosition); style = UI_LEFT; if( focus ) { color = color_yellow; } else { color = color_orange; } x = 320 - 8 * BIGCHAR_WIDTH; y = 240 - BIGCHAR_HEIGHT / 2; UI_FillRect( x, y, 16 * BIGCHAR_WIDTH, BIGCHAR_HEIGHT, listbar_color ); UI_DrawString( x, y, f->field.buffer, style, color ); // draw cursor if we have focus if( focus ) { if ( trap_Key_GetOverstrikeMode() ) { c = 11; } else { c = 10; } style &= ~UI_PULSE; style |= UI_BLINK; UI_DrawChar( x + f->field.cursor * BIGCHAR_WIDTH, y, c, style, color_white ); } val = UI_CDKeyMenu_PreValidateKey( f->field.buffer ); if( val == 1 ) { UI_DrawProportionalString( 320, 376, "Please enter your CD Key", UI_CENTER|UI_SMALLFONT, color_yellow ); } else if ( val == 0 ) { UI_DrawProportionalString( 320, 376, "The CD Key appears to be valid, thank you", UI_CENTER|UI_SMALLFONT, color_white ); } else { UI_DrawProportionalString( 320, 376, "The CD Key is not valid", UI_CENTER|UI_SMALLFONT, color_red ); } }
/* =================== MField_Draw Handles horizontal scrolling and cursor blinking x, y, charWidth, charHeight, are in 640*480 virtual screen size =================== */ void MField_Draw( mfield_t *edit, int x, int y, int style, vec4_t color, qboolean drawCursor ) { int i; int len; int drawLen; int prestep; int cursorChar; char str[MAX_STRING_CHARS]; drawLen = edit->widthInChars; len = edit->len + 1; // guarantee that cursor will be visible if ( len <= drawLen ) { prestep = 0; } else { if ( edit->scroll + drawLen > len ) { edit->scroll = len - drawLen; if ( edit->scroll < 0 ) { edit->scroll = 0; } } prestep = edit->scroll; } if ( prestep + drawLen > len ) { drawLen = len - prestep; } // extract <drawLen> characters from the field at <prestep> str[0] = 0; for ( i = 0; i < drawLen; i++ ) { Q_strcat( str, sizeof( str ), Q_UTF8_Encode( edit->buffer[prestep+i] ) ); } if ( drawCursor ) { // if overstrike and not at end of buffer if ( trap_Key_GetOverstrikeMode() && edit->cursor != edit->len ) { cursorChar = GLYPH_OVERSTRIKE; } else { cursorChar = GLYPH_INSERT; } } else { cursorChar = -1; } CG_DrawStringWithCursor( x, y, str, style, color, ( edit->cursor - prestep ), cursorChar ); }
/* ================= PlayerSettings_DrawName ================= */ static void PlayerSettings_DrawName(void* self) { menufield_s* f; qboolean focus; int style; char* txt; char c; float* color; int n; int basex, x, y; char name[32]; f = (menufield_s*)self; basex = f->generic.x; y = f->generic.y; focus = (f->generic.parent->cursor == f->generic.menuPosition); style = UI_LEFT | UI_SMALLFONT; color = text_color_normal; if (focus) { style |= UI_PULSE; color = text_color_highlight; } UI_DrawProportionalString(basex, y, "Name", style, color); // draw the actual name basex += 64; y += PROP_HEIGHT; txt = f->field.buffer; color = g_color_table[ColorIndex(COLOR_WHITE)]; x = basex; while ((c = *txt) != 0) { if (!focus && Q_IsColorString(txt)) { n = ColorIndex(*(txt + 1)); if (n == 0) { n = 7; } color = g_color_table[n]; txt += 2; continue; } UI_DrawChar(x, y, c, style, color); txt++; x += SMALLCHAR_WIDTH; } // draw cursor if we have focus if (focus) { if (trap_Key_GetOverstrikeMode()) { c = 11; } else { c = 10; } style &= ~UI_PULSE; style |= UI_BLINK; UI_DrawChar(basex + f->field.cursor * SMALLCHAR_WIDTH, y, c, style, color_white); } // draw at bottom also using proportional font Q_strncpyz(name, f->field.buffer, sizeof(name)); Q_CleanStr(name); UI_DrawProportionalString(320, 440, name, UI_CENTER | UI_BIGFONT, text_color_normal); }
/* =================== UI_Field_Draw Handles horizontal scrolling and cursor blinking x, y, are in pixels =================== */ void UI_Field_Draw( mfield_t *edit, int x, int y, int style, vec4_t color ) { int len; int charw; int drawLen; int prestep; int cursorChar; char str[MAX_STRING_CHARS]; drawLen = edit->widthInChars; len = strlen( edit->buffer ) + 1; // guarantee that cursor will be visible if ( len <= drawLen ) { prestep = 0; } else { if ( edit->scroll + drawLen > len ) { edit->scroll = len - drawLen; if ( edit->scroll < 0 ) { edit->scroll = 0; } } prestep = edit->scroll; } if ( prestep + drawLen > len ) { drawLen = len - prestep; } // extract <drawLen> characters from the field at <prestep> if ( drawLen >= MAX_STRING_CHARS ) { trap_Error( "drawLen >= MAX_STRING_CHARS" ); } memcpy( str, edit->buffer + prestep, drawLen ); str[ drawLen ] = 0; UI_DrawString( x, y, str, style, color ); // draw the cursor if (!(style & UI_PULSE)) { return; } if ( trap_Key_GetOverstrikeMode() ) { cursorChar = 11; } else { cursorChar = 10; } style &= ~UI_PULSE; style |= UI_BLINK; if (style & UI_SMALLFONT) { charw = SMALLCHAR_WIDTH; } else if (style & UI_GIANTFONT) { charw = GIANTCHAR_WIDTH; } else { charw = BIGCHAR_WIDTH; } if (style & UI_CENTER) { len = strlen(str); x = x - len*charw/2; } else if (style & UI_RIGHT) { len = strlen(str); x = x - len*charw; } UI_DrawChar( x + ( edit->cursor - prestep ) * charw, y, cursorChar, style & ~(UI_CENTER|UI_RIGHT), color ); }
/* ================== MField_CharEvent ================== */ void MField_CharEvent( mfield_t *edit, int ch ) { int i; if ( ch == 'v' - 'a' + 1 ) { // ctrl-v is paste MField_Paste( edit ); return; } if ( ch == 'c' - 'a' + 1 ) { // ctrl-c clears the field MField_Clear( edit ); return; } if ( ch == 'h' - 'a' + 1 ) { // ctrl-h is backspace if ( edit->cursor > 0 ) { for ( i = edit->cursor; i < edit->len+1; i++ ) { edit->buffer[i-1] = edit->buffer[i]; } edit->cursor--; if ( edit->cursor < edit->scroll ) { edit->scroll--; } edit->len--; } return; } if ( ch == 'a' - 'a' + 1 ) { // ctrl-a is home edit->cursor = 0; edit->scroll = 0; return; } if ( ch == 'e' - 'a' + 1 ) { // ctrl-e is end edit->cursor = edit->len; edit->scroll = edit->cursor - edit->widthInChars + 1; if (edit->scroll < 0) edit->scroll = 0; return; } // // ignore any other non printable chars // if ( ch < 32 ) { return; } if ( trap_Key_GetOverstrikeMode() ) { if ((edit->cursor == MAX_EDIT_LINE - 1) || (edit->maxchars && edit->cursor >= edit->maxchars)) return; } else { // insert mode if (( edit->len == MAX_EDIT_LINE - 1 ) || (edit->maxchars && edit->len >= edit->maxchars)) return; for ( i = edit->len + 1; i >= edit->cursor; i-- ) { edit->buffer[i+1] = edit->buffer[i]; } edit->len++; } edit->buffer[edit->cursor] = ch; if (!edit->maxchars || edit->cursor < edit->maxchars-1) edit->cursor++; if ( edit->cursor >= edit->widthInChars ) { edit->scroll++; } if ( edit->cursor == edit->len + 1) { edit->buffer[edit->cursor] = 0; edit->len++; } }
/* ================= MField_KeyDownEvent Performs the basic line editing functions for the console, in-game talk, and menu fields Key events are used for non-printable characters, others are gotten from char events. ================= */ void MField_KeyDownEvent( mfield_t *edit, int key ) { // shift-insert is paste if ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && trap_Key_IsDown( K_SHIFT ) ) { MField_Paste( edit ); return; } if ( key == K_DEL || key == K_KP_DEL ) { int i; if ( edit->cursor < edit->len ) { for ( i = edit->cursor; i < edit->len; i++ ) { edit->buffer[i] = edit->buffer[i+1]; } edit->len--; } return; } if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW ) { if ( edit->cursor < edit->len ) { edit->cursor++; } if ( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= edit->len ) { edit->scroll++; } return; } if ( key == K_LEFTARROW || key == K_KP_LEFTARROW ) { if ( edit->cursor > 0 ) { edit->cursor--; } if ( edit->cursor < edit->scroll ) { edit->scroll--; } return; } if ( key == K_HOME || key == K_KP_HOME || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) { edit->cursor = 0; edit->scroll = 0; return; } if ( key == K_END || key == K_KP_END || ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) { edit->cursor = edit->len; edit->scroll = edit->len - edit->widthInChars + 1; if (edit->scroll < 0) edit->scroll = 0; return; } if ( key == K_INS || key == K_KP_INS ) { trap_Key_SetOverstrikeMode( !trap_Key_GetOverstrikeMode() ); return; } }
/* ================== MField_CharEvent ================== */ void MField_CharEvent( mfield_t *edit, int ch ) { int len; if ( ch == 'v' - 'a' + 1 ) { // ctrl-v is paste MField_Paste( edit ); return; } if ( ch == 'c' - 'a' + 1 ) { // ctrl-c clears the field MField_Clear( edit ); return; } len = strlen( edit->buffer ); if ( ch == 'h' - 'a' + 1 ) { // ctrl-h is backspace if ( edit->cursor > 0 ) { memmove( edit->buffer + edit->cursor - 1, edit->buffer + edit->cursor, len + 1 - edit->cursor ); edit->cursor--; if ( edit->cursor < edit->scroll ) { edit->scroll--; } } return; } if ( ch == 'a' - 'a' + 1 ) { // ctrl-a is home edit->cursor = 0; edit->scroll = 0; return; } if ( ch == 'e' - 'a' + 1 ) { // ctrl-e is end edit->cursor = len; edit->scroll = edit->cursor - edit->widthInChars + 1; if (edit->scroll < 0) edit->scroll = 0; return; } // // ignore any other non printable chars // if ( ch < 32 ) { return; } if ( !trap_Key_GetOverstrikeMode() ) { if ((edit->cursor == MAX_EDIT_LINE - 1) || (edit->maxchars && edit->cursor >= edit->maxchars)) return; } else { // insert mode if (( len == MAX_EDIT_LINE - 1 ) || (edit->maxchars && len >= edit->maxchars)) return; memmove( edit->buffer + edit->cursor + 1, edit->buffer + edit->cursor, len + 1 - edit->cursor ); } edit->buffer[edit->cursor] = ch; if (!edit->maxchars || edit->cursor < edit->maxchars-1) edit->cursor++; if ( edit->cursor >= edit->widthInChars ) { edit->scroll++; } if ( edit->cursor == len + 1) { edit->buffer[edit->cursor] = 0; } }