Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

qmenu.c (15302B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 #include <string.h>
     21 #include <ctype.h>
     22 
     23 #include "client.h"
     24 #include "qmenu.h"
     25 
     26 static void	 Action_DoEnter( menuaction_s *a );
     27 static void	 Action_Draw( menuaction_s *a );
     28 static void  Menu_DrawStatusBar( const char *string );
     29 static void	 Menulist_DoEnter( menulist_s *l );
     30 static void	 MenuList_Draw( menulist_s *l );
     31 static void	 Separator_Draw( menuseparator_s *s );
     32 static void	 Slider_DoSlide( menuslider_s *s, int dir );
     33 static void	 Slider_Draw( menuslider_s *s );
     34 static void	 SpinControl_DoEnter( menulist_s *s );
     35 static void	 SpinControl_Draw( menulist_s *s );
     36 static void	 SpinControl_DoSlide( menulist_s *s, int dir );
     37 
     38 #define RCOLUMN_OFFSET  16
     39 #define LCOLUMN_OFFSET -16
     40 
     41 extern refexport_t re;
     42 extern viddef_t viddef;
     43 
     44 #define VID_WIDTH viddef.width
     45 #define VID_HEIGHT viddef.height
     46 
     47 #define Draw_Char re.DrawChar
     48 #define Draw_Fill re.DrawFill
     49 
     50 void Action_DoEnter( menuaction_s *a )
     51 {
     52 	if ( a->generic.callback )
     53 		a->generic.callback( a );
     54 }
     55 
     56 void Action_Draw( menuaction_s *a )
     57 {
     58 	if ( a->generic.flags & QMF_LEFT_JUSTIFY )
     59 	{
     60 		if ( a->generic.flags & QMF_GRAYED )
     61 			Menu_DrawStringDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
     62 		else
     63 			Menu_DrawString( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
     64 	}
     65 	else
     66 	{
     67 		if ( a->generic.flags & QMF_GRAYED )
     68 			Menu_DrawStringR2LDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
     69 		else
     70 			Menu_DrawStringR2L( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
     71 	}
     72 	if ( a->generic.ownerdraw )
     73 		a->generic.ownerdraw( a );
     74 }
     75 
     76 qboolean Field_DoEnter( menufield_s *f )
     77 {
     78 	if ( f->generic.callback )
     79 	{
     80 		f->generic.callback( f );
     81 		return true;
     82 	}
     83 	return false;
     84 }
     85 
     86 void Field_Draw( menufield_s *f )
     87 {
     88 	int i;
     89 	char tempbuffer[128]="";
     90 
     91 	if ( f->generic.name )
     92 		Menu_DrawStringR2LDark( f->generic.x + f->generic.parent->x + LCOLUMN_OFFSET, f->generic.y + f->generic.parent->y, f->generic.name );
     93 
     94 	strncpy( tempbuffer, f->buffer + f->visible_offset, f->visible_length );
     95 
     96 	Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y - 4, 18 );
     97 	Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y + 4, 24 );
     98 
     99 	Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y - 4, 20 );
    100 	Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y + 4, 26 );
    101 
    102 	for ( i = 0; i < f->visible_length; i++ )
    103 	{
    104 		Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y - 4, 19 );
    105 		Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y + 4, 25 );
    106 	}
    107 
    108 	Menu_DrawString( f->generic.x + f->generic.parent->x + 24, f->generic.y + f->generic.parent->y, tempbuffer );
    109 
    110 	if ( Menu_ItemAtCursor( f->generic.parent ) == f )
    111 	{
    112 		int offset;
    113 
    114 		if ( f->visible_offset )
    115 			offset = f->visible_length;
    116 		else
    117 			offset = f->cursor;
    118 
    119 		if ( ( ( int ) ( Sys_Milliseconds() / 250 ) ) & 1 )
    120 		{
    121 			Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
    122 					   f->generic.y + f->generic.parent->y,
    123 					   11 );
    124 		}
    125 		else
    126 		{
    127 			Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
    128 					   f->generic.y + f->generic.parent->y,
    129 					   ' ' );
    130 		}
    131 	}
    132 }
    133 
    134 qboolean Field_Key( menufield_s *f, int key )
    135 {
    136 	extern int keydown[];
    137 
    138 	switch ( key )
    139 	{
    140 	case K_KP_SLASH:
    141 		key = '/';
    142 		break;
    143 	case K_KP_MINUS:
    144 		key = '-';
    145 		break;
    146 	case K_KP_PLUS:
    147 		key = '+';
    148 		break;
    149 	case K_KP_HOME:
    150 		key = '7';
    151 		break;
    152 	case K_KP_UPARROW:
    153 		key = '8';
    154 		break;
    155 	case K_KP_PGUP:
    156 		key = '9';
    157 		break;
    158 	case K_KP_LEFTARROW:
    159 		key = '4';
    160 		break;
    161 	case K_KP_5:
    162 		key = '5';
    163 		break;
    164 	case K_KP_RIGHTARROW:
    165 		key = '6';
    166 		break;
    167 	case K_KP_END:
    168 		key = '1';
    169 		break;
    170 	case K_KP_DOWNARROW:
    171 		key = '2';
    172 		break;
    173 	case K_KP_PGDN:
    174 		key = '3';
    175 		break;
    176 	case K_KP_INS:
    177 		key = '0';
    178 		break;
    179 	case K_KP_DEL:
    180 		key = '.';
    181 		break;
    182 	}
    183 
    184 	if ( key > 127 )
    185 	{
    186 		switch ( key )
    187 		{
    188 		case K_DEL:
    189 		default:
    190 			return false;
    191 		}
    192 	}
    193 
    194 	/*
    195 	** support pasting from the clipboard
    196 	*/
    197 	if ( ( toupper( key ) == 'V' && keydown[K_CTRL] ) ||
    198 		 ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && keydown[K_SHIFT] ) )
    199 	{
    200 		char *cbd;
    201 		
    202 		if ( ( cbd = Sys_GetClipboardData() ) != 0 )
    203 		{
    204 			strtok( cbd, "\n\r\b" );
    205 
    206 			strncpy( f->buffer, cbd, f->length - 1 );
    207 			f->cursor = strlen( f->buffer );
    208 			f->visible_offset = f->cursor - f->visible_length;
    209 			if ( f->visible_offset < 0 )
    210 				f->visible_offset = 0;
    211 
    212 			free( cbd );
    213 		}
    214 		return true;
    215 	}
    216 
    217 	switch ( key )
    218 	{
    219 	case K_KP_LEFTARROW:
    220 	case K_LEFTARROW:
    221 	case K_BACKSPACE:
    222 		if ( f->cursor > 0 )
    223 		{
    224 			memmove( &f->buffer[f->cursor-1], &f->buffer[f->cursor], strlen( &f->buffer[f->cursor] ) + 1 );
    225 			f->cursor--;
    226 
    227 			if ( f->visible_offset )
    228 			{
    229 				f->visible_offset--;
    230 			}
    231 		}
    232 		break;
    233 
    234 	case K_KP_DEL:
    235 	case K_DEL:
    236 		memmove( &f->buffer[f->cursor], &f->buffer[f->cursor+1], strlen( &f->buffer[f->cursor+1] ) + 1 );
    237 		break;
    238 
    239 	case K_KP_ENTER:
    240 	case K_ENTER:
    241 	case K_ESCAPE:
    242 	case K_TAB:
    243 		return false;
    244 
    245 	case K_SPACE:
    246 	default:
    247 		if ( !isdigit( key ) && ( f->generic.flags & QMF_NUMBERSONLY ) )
    248 			return false;
    249 
    250 		if ( f->cursor < f->length )
    251 		{
    252 			f->buffer[f->cursor++] = key;
    253 			f->buffer[f->cursor] = 0;
    254 
    255 			if ( f->cursor > f->visible_length )
    256 			{
    257 				f->visible_offset++;
    258 			}
    259 		}
    260 	}
    261 
    262 	return true;
    263 }
    264 
    265 void Menu_AddItem( menuframework_s *menu, void *item )
    266 {
    267 	if ( menu->nitems == 0 )
    268 		menu->nslots = 0;
    269 
    270 	if ( menu->nitems < MAXMENUITEMS )
    271 	{
    272 		menu->items[menu->nitems] = item;
    273 		( ( menucommon_s * ) menu->items[menu->nitems] )->parent = menu;
    274 		menu->nitems++;
    275 	}
    276 
    277 	menu->nslots = Menu_TallySlots( menu );
    278 }
    279 
    280 /*
    281 ** Menu_AdjustCursor
    282 **
    283 ** This function takes the given menu, the direction, and attempts
    284 ** to adjust the menu's cursor so that it's at the next available
    285 ** slot.
    286 */
    287 void Menu_AdjustCursor( menuframework_s *m, int dir )
    288 {
    289 	menucommon_s *citem;
    290 
    291 	/*
    292 	** see if it's in a valid spot
    293 	*/
    294 	if ( m->cursor >= 0 && m->cursor < m->nitems )
    295 	{
    296 		if ( ( citem = Menu_ItemAtCursor( m ) ) != 0 )
    297 		{
    298 			if ( citem->type != MTYPE_SEPARATOR )
    299 				return;
    300 		}
    301 	}
    302 
    303 	/*
    304 	** it's not in a valid spot, so crawl in the direction indicated until we
    305 	** find a valid spot
    306 	*/
    307 	if ( dir == 1 )
    308 	{
    309 		while ( 1 )
    310 		{
    311 			citem = Menu_ItemAtCursor( m );
    312 			if ( citem )
    313 				if ( citem->type != MTYPE_SEPARATOR )
    314 					break;
    315 			m->cursor += dir;
    316 			if ( m->cursor >= m->nitems )
    317 				m->cursor = 0;
    318 		}
    319 	}
    320 	else
    321 	{
    322 		while ( 1 )
    323 		{
    324 			citem = Menu_ItemAtCursor( m );
    325 			if ( citem )
    326 				if ( citem->type != MTYPE_SEPARATOR )
    327 					break;
    328 			m->cursor += dir;
    329 			if ( m->cursor < 0 )
    330 				m->cursor = m->nitems - 1;
    331 		}
    332 	}
    333 }
    334 
    335 void Menu_Center( menuframework_s *menu )
    336 {
    337 	int height;
    338 
    339 	height = ( ( menucommon_s * ) menu->items[menu->nitems-1])->y;
    340 	height += 10;
    341 
    342 	menu->y = ( VID_HEIGHT - height ) / 2;
    343 }
    344 
    345 void Menu_Draw( menuframework_s *menu )
    346 {
    347 	int i;
    348 	menucommon_s *item;
    349 
    350 	/*
    351 	** draw contents
    352 	*/
    353 	for ( i = 0; i < menu->nitems; i++ )
    354 	{
    355 		switch ( ( ( menucommon_s * ) menu->items[i] )->type )
    356 		{
    357 		case MTYPE_FIELD:
    358 			Field_Draw( ( menufield_s * ) menu->items[i] );
    359 			break;
    360 		case MTYPE_SLIDER:
    361 			Slider_Draw( ( menuslider_s * ) menu->items[i] );
    362 			break;
    363 		case MTYPE_LIST:
    364 			MenuList_Draw( ( menulist_s * ) menu->items[i] );
    365 			break;
    366 		case MTYPE_SPINCONTROL:
    367 			SpinControl_Draw( ( menulist_s * ) menu->items[i] );
    368 			break;
    369 		case MTYPE_ACTION:
    370 			Action_Draw( ( menuaction_s * ) menu->items[i] );
    371 			break;
    372 		case MTYPE_SEPARATOR:
    373 			Separator_Draw( ( menuseparator_s * ) menu->items[i] );
    374 			break;
    375 		}
    376 	}
    377 
    378 	item = Menu_ItemAtCursor( menu );
    379 
    380 	if ( item && item->cursordraw )
    381 	{
    382 		item->cursordraw( item );
    383 	}
    384 	else if ( menu->cursordraw )
    385 	{
    386 		menu->cursordraw( menu );
    387 	}
    388 	else if ( item && item->type != MTYPE_FIELD )
    389 	{
    390 		if ( item->flags & QMF_LEFT_JUSTIFY )
    391 		{
    392 			Draw_Char( menu->x + item->x - 24 + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
    393 		}
    394 		else
    395 		{
    396 			Draw_Char( menu->x + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
    397 		}
    398 	}
    399 
    400 	if ( item )
    401 	{
    402 		if ( item->statusbarfunc )
    403 			item->statusbarfunc( ( void * ) item );
    404 		else if ( item->statusbar )
    405 			Menu_DrawStatusBar( item->statusbar );
    406 		else
    407 			Menu_DrawStatusBar( menu->statusbar );
    408 
    409 	}
    410 	else
    411 	{
    412 		Menu_DrawStatusBar( menu->statusbar );
    413 	}
    414 }
    415 
    416 void Menu_DrawStatusBar( const char *string )
    417 {
    418 	if ( string )
    419 	{
    420 		int l = strlen( string );
    421 		int maxrow = VID_HEIGHT / 8;
    422 		int maxcol = VID_WIDTH / 8;
    423 		int col = maxcol / 2 - l / 2;
    424 
    425 		Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 4 );
    426 		Menu_DrawString( col*8, VID_HEIGHT - 8, string );
    427 	}
    428 	else
    429 	{
    430 		Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 0 );
    431 	}
    432 }
    433 
    434 void Menu_DrawString( int x, int y, const char *string )
    435 {
    436 	unsigned i;
    437 
    438 	for ( i = 0; i < strlen( string ); i++ )
    439 	{
    440 		Draw_Char( ( x + i*8 ), y, string[i] );
    441 	}
    442 }
    443 
    444 void Menu_DrawStringDark( int x, int y, const char *string )
    445 {
    446 	unsigned i;
    447 
    448 	for ( i = 0; i < strlen( string ); i++ )
    449 	{
    450 		Draw_Char( ( x + i*8 ), y, string[i] + 128 );
    451 	}
    452 }
    453 
    454 void Menu_DrawStringR2L( int x, int y, const char *string )
    455 {
    456 	unsigned i;
    457 
    458 	for ( i = 0; i < strlen( string ); i++ )
    459 	{
    460 		Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1] );
    461 	}
    462 }
    463 
    464 void Menu_DrawStringR2LDark( int x, int y, const char *string )
    465 {
    466 	unsigned i;
    467 
    468 	for ( i = 0; i < strlen( string ); i++ )
    469 	{
    470 		Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1]+128 );
    471 	}
    472 }
    473 
    474 void *Menu_ItemAtCursor( menuframework_s *m )
    475 {
    476 	if ( m->cursor < 0 || m->cursor >= m->nitems )
    477 		return 0;
    478 
    479 	return m->items[m->cursor];
    480 }
    481 
    482 qboolean Menu_SelectItem( menuframework_s *s )
    483 {
    484 	menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
    485 
    486 	if ( item )
    487 	{
    488 		switch ( item->type )
    489 		{
    490 		case MTYPE_FIELD:
    491 			return Field_DoEnter( ( menufield_s * ) item ) ;
    492 		case MTYPE_ACTION:
    493 			Action_DoEnter( ( menuaction_s * ) item );
    494 			return true;
    495 		case MTYPE_LIST:
    496 //			Menulist_DoEnter( ( menulist_s * ) item );
    497 			return false;
    498 		case MTYPE_SPINCONTROL:
    499 //			SpinControl_DoEnter( ( menulist_s * ) item );
    500 			return false;
    501 		}
    502 	}
    503 	return false;
    504 }
    505 
    506 void Menu_SetStatusBar( menuframework_s *m, const char *string )
    507 {
    508 	m->statusbar = string;
    509 }
    510 
    511 void Menu_SlideItem( menuframework_s *s, int dir )
    512 {
    513 	menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
    514 
    515 	if ( item )
    516 	{
    517 		switch ( item->type )
    518 		{
    519 		case MTYPE_SLIDER:
    520 			Slider_DoSlide( ( menuslider_s * ) item, dir );
    521 			break;
    522 		case MTYPE_SPINCONTROL:
    523 			SpinControl_DoSlide( ( menulist_s * ) item, dir );
    524 			break;
    525 		}
    526 	}
    527 }
    528 
    529 int Menu_TallySlots( menuframework_s *menu )
    530 {
    531 	int i;
    532 	int total = 0;
    533 
    534 	for ( i = 0; i < menu->nitems; i++ )
    535 	{
    536 		if ( ( ( menucommon_s * ) menu->items[i] )->type == MTYPE_LIST )
    537 		{
    538 			int nitems = 0;
    539 			const char **n = ( ( menulist_s * ) menu->items[i] )->itemnames;
    540 
    541 			while (*n)
    542 				nitems++, n++;
    543 
    544 			total += nitems;
    545 		}
    546 		else
    547 		{
    548 			total++;
    549 		}
    550 	}
    551 
    552 	return total;
    553 }
    554 
    555 void Menulist_DoEnter( menulist_s *l )
    556 {
    557 	int start;
    558 
    559 	start = l->generic.y / 10 + 1;
    560 
    561 	l->curvalue = l->generic.parent->cursor - start;
    562 
    563 	if ( l->generic.callback )
    564 		l->generic.callback( l );
    565 }
    566 
    567 void MenuList_Draw( menulist_s *l )
    568 {
    569 	const char **n;
    570 	int y = 0;
    571 
    572 	Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y, l->generic.name );
    573 
    574 	n = l->itemnames;
    575 
    576   	Draw_Fill( l->generic.x - 112 + l->generic.parent->x, l->generic.parent->y + l->generic.y + l->curvalue*10 + 10, 128, 10, 16 );
    577 	while ( *n )
    578 	{
    579 		Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y + y + 10, *n );
    580 
    581 		n++;
    582 		y += 10;
    583 	}
    584 }
    585 
    586 void Separator_Draw( menuseparator_s *s )
    587 {
    588 	if ( s->generic.name )
    589 		Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->generic.name );
    590 }
    591 
    592 void Slider_DoSlide( menuslider_s *s, int dir )
    593 {
    594 	s->curvalue += dir;
    595 
    596 	if ( s->curvalue > s->maxvalue )
    597 		s->curvalue = s->maxvalue;
    598 	else if ( s->curvalue < s->minvalue )
    599 		s->curvalue = s->minvalue;
    600 
    601 	if ( s->generic.callback )
    602 		s->generic.callback( s );
    603 }
    604 
    605 #define SLIDER_RANGE 10
    606 
    607 void Slider_Draw( menuslider_s *s )
    608 {
    609 	int	i;
    610 
    611 	Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
    612 		                s->generic.y + s->generic.parent->y, 
    613 						s->generic.name );
    614 
    615 	s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
    616 
    617 	if ( s->range < 0)
    618 		s->range = 0;
    619 	if ( s->range > 1)
    620 		s->range = 1;
    621 	Draw_Char( s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET, s->generic.y + s->generic.parent->y, 128);
    622 	for ( i = 0; i < SLIDER_RANGE; i++ )
    623 		Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 129);
    624 	Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 130);
    625 	Draw_Char( ( int ) ( 8 + RCOLUMN_OFFSET + s->generic.parent->x + s->generic.x + (SLIDER_RANGE-1)*8 * s->range ), s->generic.y + s->generic.parent->y, 131);
    626 }
    627 
    628 void SpinControl_DoEnter( menulist_s *s )
    629 {
    630 	s->curvalue++;
    631 	if ( s->itemnames[s->curvalue] == 0 )
    632 		s->curvalue = 0;
    633 
    634 	if ( s->generic.callback )
    635 		s->generic.callback( s );
    636 }
    637 
    638 void SpinControl_DoSlide( menulist_s *s, int dir )
    639 {
    640 	s->curvalue += dir;
    641 
    642 	if ( s->curvalue < 0 )
    643 		s->curvalue = 0;
    644 	else if ( s->itemnames[s->curvalue] == 0 )
    645 		s->curvalue--;
    646 
    647 	if ( s->generic.callback )
    648 		s->generic.callback( s );
    649 }
    650 
    651 void SpinControl_Draw( menulist_s *s )
    652 {
    653 	char buffer[100];
    654 
    655 	if ( s->generic.name )
    656 	{
    657 		Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET, 
    658 							s->generic.y + s->generic.parent->y, 
    659 							s->generic.name );
    660 	}
    661 	if ( !strchr( s->itemnames[s->curvalue], '\n' ) )
    662 	{
    663 		Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->itemnames[s->curvalue] );
    664 	}
    665 	else
    666 	{
    667 		strcpy( buffer, s->itemnames[s->curvalue] );
    668 		*strchr( buffer, '\n' ) = 0;
    669 		Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, buffer );
    670 		strcpy( buffer, strchr( s->itemnames[s->curvalue], '\n' ) + 1 );
    671 		Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y + 10, buffer );
    672 	}
    673 }
    674