123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- #include <string.h>
- #include <ctype.h>
- #include "client.h"
- #include "qmenu.h"
- static void Action_DoEnter( menuaction_s *a );
- static void Action_Draw( menuaction_s *a );
- static void Menu_DrawStatusBar( const char *string );
- static void Menulist_DoEnter( menulist_s *l );
- static void MenuList_Draw( menulist_s *l );
- static void Separator_Draw( menuseparator_s *s );
- static void Slider_DoSlide( menuslider_s *s, int dir );
- static void Slider_Draw( menuslider_s *s );
- static void SpinControl_DoEnter( menulist_s *s );
- static void SpinControl_Draw( menulist_s *s );
- static void SpinControl_DoSlide( menulist_s *s, int dir );
- #define RCOLUMN_OFFSET 16
- #define LCOLUMN_OFFSET -16
- extern refexport_t re;
- extern viddef_t viddef;
- #define VID_WIDTH viddef.width
- #define VID_HEIGHT viddef.height
- #define Draw_Char re.DrawChar
- #define Draw_Fill re.DrawFill
- void Action_DoEnter( menuaction_s *a )
- {
- if ( a->generic.callback )
- a->generic.callback( a );
- }
- void Action_Draw( menuaction_s *a )
- {
- if ( a->generic.flags & QMF_LEFT_JUSTIFY )
- {
- if ( a->generic.flags & QMF_GRAYED )
- Menu_DrawStringDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
- else
- Menu_DrawString( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
- }
- else
- {
- if ( a->generic.flags & QMF_GRAYED )
- Menu_DrawStringR2LDark( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
- else
- Menu_DrawStringR2L( a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET, a->generic.y + a->generic.parent->y, a->generic.name );
- }
- if ( a->generic.ownerdraw )
- a->generic.ownerdraw( a );
- }
- qboolean Field_DoEnter( menufield_s *f )
- {
- if ( f->generic.callback )
- {
- f->generic.callback( f );
- return true;
- }
- return false;
- }
- void Field_Draw( menufield_s *f )
- {
- int i;
- char tempbuffer[128]="";
- if ( f->generic.name )
- Menu_DrawStringR2LDark( f->generic.x + f->generic.parent->x + LCOLUMN_OFFSET, f->generic.y + f->generic.parent->y, f->generic.name );
- strncpy( tempbuffer, f->buffer + f->visible_offset, f->visible_length );
- Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y - 4, 18 );
- Draw_Char( f->generic.x + f->generic.parent->x + 16, f->generic.y + f->generic.parent->y + 4, 24 );
- Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y - 4, 20 );
- Draw_Char( f->generic.x + f->generic.parent->x + 24 + f->visible_length * 8, f->generic.y + f->generic.parent->y + 4, 26 );
- for ( i = 0; i < f->visible_length; i++ )
- {
- Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y - 4, 19 );
- Draw_Char( f->generic.x + f->generic.parent->x + 24 + i * 8, f->generic.y + f->generic.parent->y + 4, 25 );
- }
- Menu_DrawString( f->generic.x + f->generic.parent->x + 24, f->generic.y + f->generic.parent->y, tempbuffer );
- if ( Menu_ItemAtCursor( f->generic.parent ) == f )
- {
- int offset;
- if ( f->visible_offset )
- offset = f->visible_length;
- else
- offset = f->cursor;
- if ( ( ( int ) ( Sys_Milliseconds() / 250 ) ) & 1 )
- {
- Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
- f->generic.y + f->generic.parent->y,
- 11 );
- }
- else
- {
- Draw_Char( f->generic.x + f->generic.parent->x + ( offset + 2 ) * 8 + 8,
- f->generic.y + f->generic.parent->y,
- ' ' );
- }
- }
- }
- qboolean Field_Key( menufield_s *f, int key )
- {
- extern int keydown[];
- switch ( key )
- {
- case K_KP_SLASH:
- key = '/';
- break;
- case K_KP_MINUS:
- key = '-';
- break;
- case K_KP_PLUS:
- key = '+';
- break;
- case K_KP_HOME:
- key = '7';
- break;
- case K_KP_UPARROW:
- key = '8';
- break;
- case K_KP_PGUP:
- key = '9';
- break;
- case K_KP_LEFTARROW:
- key = '4';
- break;
- case K_KP_5:
- key = '5';
- break;
- case K_KP_RIGHTARROW:
- key = '6';
- break;
- case K_KP_END:
- key = '1';
- break;
- case K_KP_DOWNARROW:
- key = '2';
- break;
- case K_KP_PGDN:
- key = '3';
- break;
- case K_KP_INS:
- key = '0';
- break;
- case K_KP_DEL:
- key = '.';
- break;
- }
- if ( key > 127 )
- {
- switch ( key )
- {
- case K_DEL:
- default:
- return false;
- }
- }
- /*
- ** support pasting from the clipboard
- */
- if ( ( toupper( key ) == 'V' && keydown[K_CTRL] ) ||
- ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && keydown[K_SHIFT] ) )
- {
- char *cbd;
-
- if ( ( cbd = Sys_GetClipboardData() ) != 0 )
- {
- strtok( cbd, "\n\r\b" );
- strncpy( f->buffer, cbd, f->length - 1 );
- f->cursor = strlen( f->buffer );
- f->visible_offset = f->cursor - f->visible_length;
- if ( f->visible_offset < 0 )
- f->visible_offset = 0;
- free( cbd );
- }
- return true;
- }
- switch ( key )
- {
- case K_KP_LEFTARROW:
- case K_LEFTARROW:
- case K_BACKSPACE:
- if ( f->cursor > 0 )
- {
- memmove( &f->buffer[f->cursor-1], &f->buffer[f->cursor], strlen( &f->buffer[f->cursor] ) + 1 );
- f->cursor--;
- if ( f->visible_offset )
- {
- f->visible_offset--;
- }
- }
- break;
- case K_KP_DEL:
- case K_DEL:
- memmove( &f->buffer[f->cursor], &f->buffer[f->cursor+1], strlen( &f->buffer[f->cursor+1] ) + 1 );
- break;
- case K_KP_ENTER:
- case K_ENTER:
- case K_ESCAPE:
- case K_TAB:
- return false;
- case K_SPACE:
- default:
- if ( !isdigit( key ) && ( f->generic.flags & QMF_NUMBERSONLY ) )
- return false;
- if ( f->cursor < f->length )
- {
- f->buffer[f->cursor++] = key;
- f->buffer[f->cursor] = 0;
- if ( f->cursor > f->visible_length )
- {
- f->visible_offset++;
- }
- }
- }
- return true;
- }
- void Menu_AddItem( menuframework_s *menu, void *item )
- {
- if ( menu->nitems == 0 )
- menu->nslots = 0;
- if ( menu->nitems < MAXMENUITEMS )
- {
- menu->items[menu->nitems] = item;
- ( ( menucommon_s * ) menu->items[menu->nitems] )->parent = menu;
- menu->nitems++;
- }
- menu->nslots = Menu_TallySlots( menu );
- }
- /*
- ** Menu_AdjustCursor
- **
- ** This function takes the given menu, the direction, and attempts
- ** to adjust the menu's cursor so that it's at the next available
- ** slot.
- */
- void Menu_AdjustCursor( menuframework_s *m, int dir )
- {
- menucommon_s *citem;
- /*
- ** see if it's in a valid spot
- */
- if ( m->cursor >= 0 && m->cursor < m->nitems )
- {
- if ( ( citem = Menu_ItemAtCursor( m ) ) != 0 )
- {
- if ( citem->type != MTYPE_SEPARATOR )
- return;
- }
- }
- /*
- ** it's not in a valid spot, so crawl in the direction indicated until we
- ** find a valid spot
- */
- if ( dir == 1 )
- {
- while ( 1 )
- {
- citem = Menu_ItemAtCursor( m );
- if ( citem )
- if ( citem->type != MTYPE_SEPARATOR )
- break;
- m->cursor += dir;
- if ( m->cursor >= m->nitems )
- m->cursor = 0;
- }
- }
- else
- {
- while ( 1 )
- {
- citem = Menu_ItemAtCursor( m );
- if ( citem )
- if ( citem->type != MTYPE_SEPARATOR )
- break;
- m->cursor += dir;
- if ( m->cursor < 0 )
- m->cursor = m->nitems - 1;
- }
- }
- }
- void Menu_Center( menuframework_s *menu )
- {
- int height;
- height = ( ( menucommon_s * ) menu->items[menu->nitems-1])->y;
- height += 10;
- menu->y = ( VID_HEIGHT - height ) / 2;
- }
- void Menu_Draw( menuframework_s *menu )
- {
- int i;
- menucommon_s *item;
- /*
- ** draw contents
- */
- for ( i = 0; i < menu->nitems; i++ )
- {
- switch ( ( ( menucommon_s * ) menu->items[i] )->type )
- {
- case MTYPE_FIELD:
- Field_Draw( ( menufield_s * ) menu->items[i] );
- break;
- case MTYPE_SLIDER:
- Slider_Draw( ( menuslider_s * ) menu->items[i] );
- break;
- case MTYPE_LIST:
- MenuList_Draw( ( menulist_s * ) menu->items[i] );
- break;
- case MTYPE_SPINCONTROL:
- SpinControl_Draw( ( menulist_s * ) menu->items[i] );
- break;
- case MTYPE_ACTION:
- Action_Draw( ( menuaction_s * ) menu->items[i] );
- break;
- case MTYPE_SEPARATOR:
- Separator_Draw( ( menuseparator_s * ) menu->items[i] );
- break;
- }
- }
- item = Menu_ItemAtCursor( menu );
- if ( item && item->cursordraw )
- {
- item->cursordraw( item );
- }
- else if ( menu->cursordraw )
- {
- menu->cursordraw( menu );
- }
- else if ( item && item->type != MTYPE_FIELD )
- {
- if ( item->flags & QMF_LEFT_JUSTIFY )
- {
- Draw_Char( menu->x + item->x - 24 + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
- }
- else
- {
- Draw_Char( menu->x + item->cursor_offset, menu->y + item->y, 12 + ( ( int ) ( Sys_Milliseconds()/250 ) & 1 ) );
- }
- }
- if ( item )
- {
- if ( item->statusbarfunc )
- item->statusbarfunc( ( void * ) item );
- else if ( item->statusbar )
- Menu_DrawStatusBar( item->statusbar );
- else
- Menu_DrawStatusBar( menu->statusbar );
- }
- else
- {
- Menu_DrawStatusBar( menu->statusbar );
- }
- }
- void Menu_DrawStatusBar( const char *string )
- {
- if ( string )
- {
- int l = strlen( string );
- int maxrow = VID_HEIGHT / 8;
- int maxcol = VID_WIDTH / 8;
- int col = maxcol / 2 - l / 2;
- Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 4 );
- Menu_DrawString( col*8, VID_HEIGHT - 8, string );
- }
- else
- {
- Draw_Fill( 0, VID_HEIGHT-8, VID_WIDTH, 8, 0 );
- }
- }
- void Menu_DrawString( int x, int y, const char *string )
- {
- unsigned i;
- for ( i = 0; i < strlen( string ); i++ )
- {
- Draw_Char( ( x + i*8 ), y, string[i] );
- }
- }
- void Menu_DrawStringDark( int x, int y, const char *string )
- {
- unsigned i;
- for ( i = 0; i < strlen( string ); i++ )
- {
- Draw_Char( ( x + i*8 ), y, string[i] + 128 );
- }
- }
- void Menu_DrawStringR2L( int x, int y, const char *string )
- {
- unsigned i;
- for ( i = 0; i < strlen( string ); i++ )
- {
- Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1] );
- }
- }
- void Menu_DrawStringR2LDark( int x, int y, const char *string )
- {
- unsigned i;
- for ( i = 0; i < strlen( string ); i++ )
- {
- Draw_Char( ( x - i*8 ), y, string[strlen(string)-i-1]+128 );
- }
- }
- void *Menu_ItemAtCursor( menuframework_s *m )
- {
- if ( m->cursor < 0 || m->cursor >= m->nitems )
- return 0;
- return m->items[m->cursor];
- }
- qboolean Menu_SelectItem( menuframework_s *s )
- {
- menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
- if ( item )
- {
- switch ( item->type )
- {
- case MTYPE_FIELD:
- return Field_DoEnter( ( menufield_s * ) item ) ;
- case MTYPE_ACTION:
- Action_DoEnter( ( menuaction_s * ) item );
- return true;
- case MTYPE_LIST:
- // Menulist_DoEnter( ( menulist_s * ) item );
- return false;
- case MTYPE_SPINCONTROL:
- // SpinControl_DoEnter( ( menulist_s * ) item );
- return false;
- }
- }
- return false;
- }
- void Menu_SetStatusBar( menuframework_s *m, const char *string )
- {
- m->statusbar = string;
- }
- void Menu_SlideItem( menuframework_s *s, int dir )
- {
- menucommon_s *item = ( menucommon_s * ) Menu_ItemAtCursor( s );
- if ( item )
- {
- switch ( item->type )
- {
- case MTYPE_SLIDER:
- Slider_DoSlide( ( menuslider_s * ) item, dir );
- break;
- case MTYPE_SPINCONTROL:
- SpinControl_DoSlide( ( menulist_s * ) item, dir );
- break;
- }
- }
- }
- int Menu_TallySlots( menuframework_s *menu )
- {
- int i;
- int total = 0;
- for ( i = 0; i < menu->nitems; i++ )
- {
- if ( ( ( menucommon_s * ) menu->items[i] )->type == MTYPE_LIST )
- {
- int nitems = 0;
- const char **n = ( ( menulist_s * ) menu->items[i] )->itemnames;
- while (*n)
- nitems++, n++;
- total += nitems;
- }
- else
- {
- total++;
- }
- }
- return total;
- }
- void Menulist_DoEnter( menulist_s *l )
- {
- int start;
- start = l->generic.y / 10 + 1;
- l->curvalue = l->generic.parent->cursor - start;
- if ( l->generic.callback )
- l->generic.callback( l );
- }
- void MenuList_Draw( menulist_s *l )
- {
- const char **n;
- int y = 0;
- Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y, l->generic.name );
- n = l->itemnames;
- Draw_Fill( l->generic.x - 112 + l->generic.parent->x, l->generic.parent->y + l->generic.y + l->curvalue*10 + 10, 128, 10, 16 );
- while ( *n )
- {
- Menu_DrawStringR2LDark( l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, l->generic.y + l->generic.parent->y + y + 10, *n );
- n++;
- y += 10;
- }
- }
- void Separator_Draw( menuseparator_s *s )
- {
- if ( s->generic.name )
- Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->generic.name );
- }
- void Slider_DoSlide( menuslider_s *s, int dir )
- {
- s->curvalue += dir;
- if ( s->curvalue > s->maxvalue )
- s->curvalue = s->maxvalue;
- else if ( s->curvalue < s->minvalue )
- s->curvalue = s->minvalue;
- if ( s->generic.callback )
- s->generic.callback( s );
- }
- #define SLIDER_RANGE 10
- void Slider_Draw( menuslider_s *s )
- {
- int i;
- Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
- s->generic.y + s->generic.parent->y,
- s->generic.name );
- s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
- if ( s->range < 0)
- s->range = 0;
- if ( s->range > 1)
- s->range = 1;
- Draw_Char( s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET, s->generic.y + s->generic.parent->y, 128);
- for ( i = 0; i < SLIDER_RANGE; i++ )
- Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 129);
- Draw_Char( RCOLUMN_OFFSET + s->generic.x + i*8 + s->generic.parent->x + 8, s->generic.y + s->generic.parent->y, 130);
- 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);
- }
- void SpinControl_DoEnter( menulist_s *s )
- {
- s->curvalue++;
- if ( s->itemnames[s->curvalue] == 0 )
- s->curvalue = 0;
- if ( s->generic.callback )
- s->generic.callback( s );
- }
- void SpinControl_DoSlide( menulist_s *s, int dir )
- {
- s->curvalue += dir;
- if ( s->curvalue < 0 )
- s->curvalue = 0;
- else if ( s->itemnames[s->curvalue] == 0 )
- s->curvalue--;
- if ( s->generic.callback )
- s->generic.callback( s );
- }
- void SpinControl_Draw( menulist_s *s )
- {
- char buffer[100];
- if ( s->generic.name )
- {
- Menu_DrawStringR2LDark( s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
- s->generic.y + s->generic.parent->y,
- s->generic.name );
- }
- if ( !strchr( s->itemnames[s->curvalue], '\n' ) )
- {
- Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, s->itemnames[s->curvalue] );
- }
- else
- {
- strcpy( buffer, s->itemnames[s->curvalue] );
- *strchr( buffer, '\n' ) = 0;
- Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y, buffer );
- strcpy( buffer, strchr( s->itemnames[s->curvalue], '\n' ) + 1 );
- Menu_DrawString( RCOLUMN_OFFSET + s->generic.x + s->generic.parent->x, s->generic.y + s->generic.parent->y + 10, buffer );
- }
- }
|