Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ui_mfield.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 //
00023 #include "ui_local.h"
00024 
00025 /*
00026 ===================
00027 MField_Draw
00028 
00029 Handles horizontal scrolling and cursor blinking
00030 x, y, are in pixels
00031 ===================
00032 */
00033 void MField_Draw( mfield_t *edit, int x, int y, int style, vec4_t color ) {
00034     int     len;
00035     int     charw;
00036     int     drawLen;
00037     int     prestep;
00038     int     cursorChar;
00039     char    str[MAX_STRING_CHARS];
00040 
00041     drawLen = edit->widthInChars;
00042     len     = strlen( edit->buffer ) + 1;
00043 
00044     // guarantee that cursor will be visible
00045     if ( len <= drawLen ) {
00046         prestep = 0;
00047     } else {
00048         if ( edit->scroll + drawLen > len ) {
00049             edit->scroll = len - drawLen;
00050             if ( edit->scroll < 0 ) {
00051                 edit->scroll = 0;
00052             }
00053         }
00054         prestep = edit->scroll;
00055     }
00056 
00057     if ( prestep + drawLen > len ) {
00058         drawLen = len - prestep;
00059     }
00060 
00061     // extract <drawLen> characters from the field at <prestep>
00062     if ( drawLen >= MAX_STRING_CHARS ) {
00063         trap_Error( "drawLen >= MAX_STRING_CHARS" );
00064     }
00065     memcpy( str, edit->buffer + prestep, drawLen );
00066     str[ drawLen ] = 0;
00067 
00068     UI_DrawString( x, y, str, style, color );
00069 
00070     // draw the cursor
00071     if (!(style & UI_PULSE)) {
00072         return;
00073     }
00074 
00075     if ( trap_Key_GetOverstrikeMode() ) {
00076         cursorChar = 11;
00077     } else {
00078         cursorChar = 10;
00079     }
00080 
00081     style &= ~UI_PULSE;
00082     style |= UI_BLINK;
00083 
00084     if (style & UI_SMALLFONT)
00085     {
00086         charw = SMALLCHAR_WIDTH;
00087     }
00088     else if (style & UI_GIANTFONT)
00089     {
00090         charw = GIANTCHAR_WIDTH;
00091     }
00092     else
00093     {
00094         charw = BIGCHAR_WIDTH;
00095     }
00096 
00097     if (style & UI_CENTER)
00098     {
00099         len = strlen(str);
00100         x = x - len*charw/2;
00101     }
00102     else if (style & UI_RIGHT)
00103     {
00104         len = strlen(str);
00105         x = x - len*charw;
00106     }
00107     
00108     UI_DrawChar( x + ( edit->cursor - prestep ) * charw, y, cursorChar, style & ~(UI_CENTER|UI_RIGHT), color );
00109 }
00110 
00111 /*
00112 ================
00113 MField_Paste
00114 ================
00115 */
00116 void MField_Paste( mfield_t *edit ) {
00117     char    pasteBuffer[64];
00118     int     pasteLen, i;
00119 
00120     trap_GetClipboardData( pasteBuffer, 64 );
00121 
00122     // send as if typed, so insert / overstrike works properly
00123     pasteLen = strlen( pasteBuffer );
00124     for ( i = 0 ; i < pasteLen ; i++ ) {
00125         MField_CharEvent( edit, pasteBuffer[i] );
00126     }
00127 }
00128 
00129 /*
00130 =================
00131 MField_KeyDownEvent
00132 
00133 Performs the basic line editing functions for the console,
00134 in-game talk, and menu fields
00135 
00136 Key events are used for non-printable characters, others are gotten from char events.
00137 =================
00138 */
00139 void MField_KeyDownEvent( mfield_t *edit, int key ) {
00140     int     len;
00141 
00142     // shift-insert is paste
00143     if ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && trap_Key_IsDown( K_SHIFT ) ) {
00144         MField_Paste( edit );
00145         return;
00146     }
00147 
00148     len = strlen( edit->buffer );
00149 
00150     if ( key == K_DEL || key == K_KP_DEL ) {
00151         if ( edit->cursor < len ) {
00152             memmove( edit->buffer + edit->cursor, 
00153                 edit->buffer + edit->cursor + 1, len - edit->cursor );
00154         }
00155         return;
00156     }
00157 
00158     if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW ) 
00159     {
00160         if ( edit->cursor < len ) {
00161             edit->cursor++;
00162         }
00163         if ( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len )
00164         {
00165             edit->scroll++;
00166         }
00167         return;
00168     }
00169 
00170     if ( key == K_LEFTARROW || key == K_KP_LEFTARROW ) 
00171     {
00172         if ( edit->cursor > 0 ) {
00173             edit->cursor--;
00174         }
00175         if ( edit->cursor < edit->scroll )
00176         {
00177             edit->scroll--;
00178         }
00179         return;
00180     }
00181 
00182     if ( key == K_HOME || key == K_KP_HOME || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) {
00183         edit->cursor = 0;
00184         edit->scroll = 0;
00185         return;
00186     }
00187 
00188     if ( key == K_END || key == K_KP_END || ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) {
00189         edit->cursor = len;
00190         edit->scroll = len - edit->widthInChars + 1;
00191         if (edit->scroll < 0)
00192             edit->scroll = 0;
00193         return;
00194     }
00195 
00196     if ( key == K_INS || key == K_KP_INS ) {
00197         trap_Key_SetOverstrikeMode( !trap_Key_GetOverstrikeMode() );
00198         return;
00199     }
00200 }
00201 
00202 /*
00203 ==================
00204 MField_CharEvent
00205 ==================
00206 */
00207 void MField_CharEvent( mfield_t *edit, int ch ) {
00208     int     len;
00209 
00210     if ( ch == 'v' - 'a' + 1 ) {    // ctrl-v is paste
00211         MField_Paste( edit );
00212         return;
00213     }
00214 
00215     if ( ch == 'c' - 'a' + 1 ) {    // ctrl-c clears the field
00216         MField_Clear( edit );
00217         return;
00218     }
00219 
00220     len = strlen( edit->buffer );
00221 
00222     if ( ch == 'h' - 'a' + 1 )  {   // ctrl-h is backspace
00223         if ( edit->cursor > 0 ) {
00224             memmove( edit->buffer + edit->cursor - 1, 
00225                 edit->buffer + edit->cursor, len + 1 - edit->cursor );
00226             edit->cursor--;
00227             if ( edit->cursor < edit->scroll )
00228             {
00229                 edit->scroll--;
00230             }
00231         }
00232         return;
00233     }
00234 
00235     if ( ch == 'a' - 'a' + 1 ) {    // ctrl-a is home
00236         edit->cursor = 0;
00237         edit->scroll = 0;
00238         return;
00239     }
00240 
00241     if ( ch == 'e' - 'a' + 1 ) {    // ctrl-e is end
00242         edit->cursor = len;
00243         edit->scroll = edit->cursor - edit->widthInChars + 1;
00244         if (edit->scroll < 0)
00245             edit->scroll = 0;
00246         return;
00247     }
00248 
00249     //
00250     // ignore any other non printable chars
00251     //
00252     if ( ch < 32 ) {
00253         return;
00254     }
00255 
00256     if ( !trap_Key_GetOverstrikeMode() ) {  
00257         if ((edit->cursor == MAX_EDIT_LINE - 1) || (edit->maxchars && edit->cursor >= edit->maxchars))
00258             return;
00259     } else {
00260         // insert mode
00261         if (( len == MAX_EDIT_LINE - 1 ) || (edit->maxchars && len >= edit->maxchars))
00262             return;
00263         memmove( edit->buffer + edit->cursor + 1, edit->buffer + edit->cursor, len + 1 - edit->cursor );
00264     }
00265 
00266     edit->buffer[edit->cursor] = ch;
00267     if (!edit->maxchars || edit->cursor < edit->maxchars-1)
00268         edit->cursor++;
00269 
00270     if ( edit->cursor >= edit->widthInChars )
00271     {
00272         edit->scroll++;
00273     }
00274 
00275     if ( edit->cursor == len + 1) {
00276         edit->buffer[edit->cursor] = 0;
00277     }
00278 }
00279 
00280 /*
00281 ==================
00282 MField_Clear
00283 ==================
00284 */
00285 void MField_Clear( mfield_t *edit ) {
00286     edit->buffer[0] = 0;
00287     edit->cursor = 0;
00288     edit->scroll = 0;
00289 }
00290 
00291 /*
00292 ==================
00293 MenuField_Init
00294 ==================
00295 */
00296 void MenuField_Init( menufield_s* m ) {
00297     int l;
00298     int w;
00299     int h;
00300 
00301     MField_Clear( &m->field );
00302 
00303     if (m->generic.flags & QMF_SMALLFONT)
00304     {
00305         w = SMALLCHAR_WIDTH;
00306         h = SMALLCHAR_HEIGHT;
00307     }
00308     else
00309     {
00310         w = BIGCHAR_WIDTH;
00311         h = BIGCHAR_HEIGHT;
00312     }   
00313 
00314     if (m->generic.name) {
00315         l = (strlen( m->generic.name )+1) * w;      
00316     }
00317     else {
00318         l = 0;
00319     }
00320 
00321     m->generic.left   = m->generic.x - l;
00322     m->generic.top    = m->generic.y;
00323     m->generic.right  = m->generic.x + w + m->field.widthInChars*w;
00324     m->generic.bottom = m->generic.y + h;
00325 }
00326 
00327 /*
00328 ==================
00329 MenuField_Draw
00330 ==================
00331 */
00332 void MenuField_Draw( menufield_s *f )
00333 {
00334     int     x;
00335     int     y;
00336     int     w;
00337     int     h;
00338     int     style;
00339     qboolean focus;
00340     float   *color;
00341 
00342     x = f->generic.x;
00343     y = f->generic.y;
00344 
00345     if (f->generic.flags & QMF_SMALLFONT)
00346     {
00347         w = SMALLCHAR_WIDTH;
00348         h = SMALLCHAR_HEIGHT;
00349         style = UI_SMALLFONT;
00350     }
00351     else
00352     {
00353         w = BIGCHAR_WIDTH;
00354         h = BIGCHAR_HEIGHT;
00355         style = UI_BIGFONT;
00356     }   
00357 
00358     if (Menu_ItemAtCursor( f->generic.parent ) == f) {
00359         focus = qtrue;
00360         style |= UI_PULSE;
00361     }
00362     else {
00363         focus = qfalse;
00364     }
00365 
00366     if (f->generic.flags & QMF_GRAYED)
00367         color = text_color_disabled;
00368     else if (focus)
00369         color = text_color_highlight;
00370     else
00371         color = text_color_normal;
00372 
00373     if ( focus )
00374     {
00375         // draw cursor
00376         UI_FillRect( f->generic.left, f->generic.top, f->generic.right-f->generic.left+1, f->generic.bottom-f->generic.top+1, listbar_color ); 
00377         UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|style, color);
00378     }
00379 
00380     if ( f->generic.name ) {
00381         UI_DrawString( x - w, y, f->generic.name, style|UI_RIGHT, color );
00382     }
00383 
00384     MField_Draw( &f->field, x + w, y, style, color );
00385 }
00386 
00387 /*
00388 ==================
00389 MenuField_Key
00390 ==================
00391 */
00392 sfxHandle_t MenuField_Key( menufield_s* m, int* key )
00393 {
00394     int keycode;
00395 
00396     keycode = *key;
00397 
00398     switch ( keycode )
00399     {
00400         case K_KP_ENTER:
00401         case K_ENTER:
00402         case K_JOY1:
00403         case K_JOY2:
00404         case K_JOY3:
00405         case K_JOY4:
00406             // have enter go to next cursor point
00407             *key = K_TAB;
00408             break;
00409 
00410         case K_TAB:
00411         case K_KP_DOWNARROW:
00412         case K_DOWNARROW:
00413         case K_KP_UPARROW:
00414         case K_UPARROW:
00415             break;
00416 
00417         default:
00418             if ( keycode & K_CHAR_FLAG )
00419             {
00420                 keycode &= ~K_CHAR_FLAG;
00421 
00422                 if ((m->generic.flags & QMF_UPPERCASE) && Q_islower( keycode ))
00423                     keycode -= 'a' - 'A';
00424                 else if ((m->generic.flags & QMF_LOWERCASE) && Q_isupper( keycode ))
00425                     keycode -= 'A' - 'a';
00426                 else if ((m->generic.flags & QMF_NUMBERSONLY) && Q_isalpha( keycode ))
00427                     return (menu_buzz_sound);
00428 
00429                 MField_CharEvent( &m->field, keycode);
00430             }
00431             else
00432                 MField_KeyDownEvent( &m->field, keycode );
00433             break;
00434     }
00435 
00436     return (0);
00437 }
00438 
00439 

Generated on Thu Aug 25 12:37:42 2005 for Quake III Arena by  doxygen 1.3.9.1