2006-03-20 17:12:09 +00:00
/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Routines for menus .
*
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <ctype.h>
# include "pstypes.h"
2009-11-15 08:22:08 +00:00
# include "error.h"
2006-03-20 17:12:09 +00:00
# include "gr.h"
2006-12-24 09:15:37 +00:00
# include "grdef.h"
2009-12-26 01:08:57 +00:00
# include "window.h"
2006-03-20 17:12:09 +00:00
# include "songs.h"
# include "key.h"
# include "palette.h"
# include "game.h"
# include "text.h"
# include "menu.h"
# include "newmenu.h"
# include "gamefont.h"
# include "iff.h"
# include "pcx.h"
# include "u_mem.h"
# include "mouse.h"
# include "joy.h"
# include "digi.h"
# include "multi.h"
# include "endlevel.h"
# include "screens.h"
# include "config.h"
# include "player.h"
2007-05-21 11:24:27 +00:00
# include "state.h"
2006-03-20 17:12:09 +00:00
# include "newdemo.h"
# include "kconfig.h"
# include "strutil.h"
2006-10-10 09:53:58 +00:00
# include "vers_id.h"
2007-03-22 11:32:22 +00:00
# include "timer.h"
2008-04-13 00:28:36 +00:00
# include "playsave.h"
2009-11-15 08:22:08 +00:00
# include "automap.h"
2009-03-03 12:55:27 +00:00
# include "rbaudio.h"
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
# ifdef OGL
# include "ogl_init.h"
# endif
2006-03-20 17:12:09 +00:00
2008-02-24 14:41:27 +00:00
# define MAXDISPLAYABLEITEMS 14
# define MESSAGEBOX_TEXT_SIZE 2176 // How many characters in messagebox
# define MAX_TEXT_WIDTH FSPACX(120) // How many pixels wide a input box can be
2006-03-20 17:12:09 +00:00
2010-01-07 14:49:07 +00:00
struct newmenu
2009-12-26 01:08:57 +00:00
{
2010-04-03 07:24:50 +00:00
window * wind ;
2009-12-26 01:08:57 +00:00
int x , y , w , h ;
2010-06-23 13:39:52 +00:00
short swidth , sheight ; float fntscalex , fntscaley ; // with these we check if resolution or fonts have changed so menu structure can be recreated
2009-12-26 01:08:57 +00:00
char * title ;
char * subtitle ;
int nitems ;
newmenu_item * items ;
2010-01-07 14:49:07 +00:00
int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) ;
2009-12-26 01:08:57 +00:00
int citem ;
char * filename ;
int tiny_mode ;
2010-06-30 15:26:27 +00:00
int tabs_flag ;
int reorderitems ;
2009-12-26 01:08:57 +00:00
int scroll_offset , last_scroll_check , max_displayable ;
int all_text ; //set true if all text items
int is_scroll_box ; // Is this a scrolling box? Set to false at init
int max_on_menu ;
2010-03-24 07:26:52 +00:00
int mouse_state , dblclick_flag ;
2010-07-31 12:09:38 +00:00
int * rval ; // Pointer to return value (for polling newmenus)
2010-01-07 14:49:07 +00:00
void * userdata ; // For whatever - like with window system
} ;
2009-12-26 01:08:57 +00:00
2009-12-05 09:48:18 +00:00
grs_bitmap nm_background , nm_background1 ;
grs_bitmap * nm_background_sub = NULL ;
2010-06-30 15:26:27 +00:00
newmenu * newmenu_do4 ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem , char * filename , int TinyMode , int TabsFlag ) ;
2009-12-05 09:48:18 +00:00
2010-07-31 12:09:38 +00:00
void newmenu_free_background ( ) {
2007-03-22 11:32:22 +00:00
if ( nm_background . bm_data )
2008-10-28 13:28:10 +00:00
{
2009-11-30 22:42:55 +00:00
if ( nm_background_sub )
{
gr_free_sub_bitmap ( nm_background_sub ) ;
nm_background_sub = NULL ;
}
2007-10-29 21:40:49 +00:00
gr_free_bitmap_data ( & nm_background ) ;
2008-10-28 13:28:10 +00:00
}
2007-03-22 11:32:22 +00:00
if ( nm_background1 . bm_data )
2007-10-29 21:40:49 +00:00
gr_free_bitmap_data ( & nm_background1 ) ;
2007-03-22 11:32:22 +00:00
}
2006-03-20 17:12:09 +00:00
2010-02-06 01:19:40 +00:00
extern char last_palette_loaded [ ] ;
2010-04-03 10:16:53 +00:00
// Draws the custom menu background pcx, if available
2006-03-20 17:12:09 +00:00
void nm_draw_background1 ( char * filename )
{
int pcx_error ;
2007-03-29 00:13:08 +00:00
2008-02-24 14:41:27 +00:00
if ( filename ! = NULL )
2007-03-22 11:32:22 +00:00
{
if ( nm_background1 . bm_data = = NULL )
{
gr_init_bitmap_data ( & nm_background1 ) ;
2008-03-20 23:23:46 +00:00
pcx_error = pcx_read_bitmap ( filename , & nm_background1 , BM_LINEAR , gr_palette ) ;
2007-03-22 11:32:22 +00:00
Assert ( pcx_error = = PCX_ERROR_NONE ) ;
}
2007-04-03 22:12:54 +00:00
gr_palette_load ( gr_palette ) ;
2007-03-22 11:32:22 +00:00
show_fullscr ( & nm_background1 ) ;
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
2010-02-06 01:19:40 +00:00
strcpy ( last_palette_loaded , " " ) ; //force palette load next time
2006-03-20 17:12:09 +00:00
}
# define MENU_BACKGROUND_BITMAP_HIRES (cfexist("scoresb.pcx")?"scoresb.pcx":"scores.pcx")
2009-12-26 01:08:57 +00:00
# define MENU_BACKGROUND_BITMAP_LORES (cfexist("scores.pcx")?"scores.pcx":"scoresb.pcx")
2008-02-24 14:41:27 +00:00
# define MENU_BACKGROUND_BITMAP (HIRESMODE?MENU_BACKGROUND_BITMAP_HIRES:MENU_BACKGROUND_BITMAP_LORES)
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
// Draws the frame background for menus
2006-03-20 17:12:09 +00:00
void nm_draw_background ( int x1 , int y1 , int x2 , int y2 )
{
2008-10-28 13:28:10 +00:00
int w , h , init_sub = 0 ;
2008-02-24 14:41:27 +00:00
static float BGScaleX = 1 , BGScaleY = 1 ;
2007-03-31 00:37:58 +00:00
grs_canvas * tmp , * old ;
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
if ( nm_background . bm_data = = NULL )
{
2006-03-20 17:12:09 +00:00
int pcx_error ;
2008-03-20 23:23:46 +00:00
ubyte background_palette [ 768 ] ;
2009-12-05 09:48:18 +00:00
gr_init_bitmap_data ( & nm_background ) ;
2007-03-22 11:32:22 +00:00
pcx_error = pcx_read_bitmap ( MENU_BACKGROUND_BITMAP , & nm_background , BM_LINEAR , background_palette ) ;
2006-03-20 17:12:09 +00:00
Assert ( pcx_error = = PCX_ERROR_NONE ) ;
2007-03-22 11:32:22 +00:00
gr_remap_bitmap_good ( & nm_background , background_palette , - 1 , - 1 ) ;
2008-02-24 14:41:27 +00:00
BGScaleX = ( ( float ) SWIDTH / nm_background . bm_w ) ;
BGScaleY = ( ( float ) SHEIGHT / nm_background . bm_h ) ;
2008-10-28 13:28:10 +00:00
init_sub = 1 ;
2006-03-20 17:12:09 +00:00
}
if ( x1 < 0 ) x1 = 0 ;
if ( y1 < 0 ) y1 = 0 ;
2008-04-08 12:51:21 +00:00
if ( x2 > SWIDTH - 1 ) x2 = SWIDTH - 1 ;
if ( y2 > SHEIGHT - 1 ) y2 = SHEIGHT - 1 ;
2006-03-20 17:12:09 +00:00
2008-02-24 14:41:27 +00:00
w = x2 - x1 ;
h = y2 - y1 ;
if ( w > SWIDTH ) w = SWIDTH ;
if ( h > SHEIGHT ) h = SHEIGHT ;
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
old = grd_curcanv ;
tmp = gr_create_sub_canvas ( old , x1 , y1 , w , h ) ;
gr_set_current_canvas ( tmp ) ;
2007-03-29 00:13:08 +00:00
gr_palette_load ( gr_palette ) ;
2008-10-28 13:28:10 +00:00
show_fullscr ( & nm_background ) ; // show so we load all necessary data for the sub-bitmap
2008-10-28 15:32:12 +00:00
if ( ! init_sub & & ( ( nm_background_sub - > bm_w ! = w * ( ( ( float ) nm_background . bm_w ) / SWIDTH ) ) | | ( nm_background_sub - > bm_h ! = h * ( ( ( float ) nm_background . bm_h ) / SHEIGHT ) ) ) )
{
init_sub = 1 ;
gr_free_sub_bitmap ( nm_background_sub ) ;
2009-12-05 09:48:18 +00:00
nm_background_sub = NULL ;
2008-10-28 15:32:12 +00:00
}
2008-10-28 13:28:10 +00:00
if ( init_sub )
nm_background_sub = gr_create_sub_bitmap ( & nm_background , 0 , 0 , w * ( ( ( float ) nm_background . bm_w ) / SWIDTH ) , h * ( ( ( float ) nm_background . bm_h ) / SHEIGHT ) ) ;
show_fullscr ( nm_background_sub ) ;
2007-03-22 11:32:22 +00:00
gr_set_current_canvas ( old ) ;
gr_free_sub_canvas ( tmp ) ;
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
Gr_scanline_darkening_level = 2 * 7 ;
2008-02-24 14:41:27 +00:00
gr_setcolor ( BM_XRGB ( 1 , 1 , 1 ) ) ;
2008-03-25 12:28:02 +00:00
for ( w = 5 * BGScaleX ; w > 0 ; w - - )
2008-02-24 14:41:27 +00:00
gr_urect ( x2 - w , y1 + w * ( BGScaleY / BGScaleX ) , x2 - w , y2 - w * ( BGScaleY / BGScaleX ) ) ; //right edge
2007-03-22 11:32:22 +00:00
gr_setcolor ( BM_XRGB ( 0 , 0 , 0 ) ) ;
2008-02-24 14:41:27 +00:00
for ( h = 5 * BGScaleY ; h > 0 ; h - - )
gr_urect ( x1 + h * ( BGScaleX / BGScaleY ) , y2 - h , x2 - h * ( BGScaleX / BGScaleY ) , y2 - h ) ; //bottom edge
2007-03-22 11:32:22 +00:00
Gr_scanline_darkening_level = GR_FADE_LEVELS ;
2006-03-20 17:12:09 +00:00
}
// Draw a left justfied string
2010-06-30 15:26:27 +00:00
void nm_string ( int w1 , int x , int y , char * s , int tabs_flag )
2006-03-20 17:12:09 +00:00
{
int w , h , aw , tx = 0 , t = 0 , i ;
char * p , * s1 , * s2 , measure [ 2 ] ;
2010-07-01 09:08:30 +00:00
int XTabs [ ] = { 18 , 90 , 127 , 165 , 231 , 256 } ;
2007-03-22 11:32:22 +00:00
2006-03-20 17:12:09 +00:00
p = s1 = NULL ;
s2 = d_strdup ( s ) ;
for ( i = 0 ; i < 6 ; i + + ) {
2008-02-24 14:41:27 +00:00
XTabs [ i ] = FSPACX ( XTabs [ i ] ) ;
2006-03-20 17:12:09 +00:00
XTabs [ i ] + = x ;
}
2010-06-23 11:44:12 +00:00
2006-03-20 17:12:09 +00:00
measure [ 1 ] = 0 ;
2010-06-30 15:26:27 +00:00
if ( ! tabs_flag ) {
2006-03-20 17:12:09 +00:00
p = strchr ( s2 , ' \t ' ) ;
if ( p & & ( w1 > 0 ) ) {
* p = ' \0 ' ;
s1 = p + 1 ;
}
}
gr_get_string_size ( s2 , & w , & h , & aw ) ;
if ( w1 > 0 )
w = w1 ;
2010-06-30 15:26:27 +00:00
if ( tabs_flag ) {
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < strlen ( s2 ) ; i + + ) {
2010-06-30 15:26:27 +00:00
if ( s2 [ i ] = = ' \t ' & & tabs_flag ) {
2006-03-20 17:12:09 +00:00
x = XTabs [ t ] ;
t + + ;
continue ;
}
measure [ 0 ] = s2 [ i ] ;
gr_get_string_size ( measure , & tx , & h , & aw ) ;
gr_string ( x , y , measure ) ;
x + = tx ;
}
}
else
gr_string ( x , y , s2 ) ;
2006-09-04 22:24:09 +00:00
2010-06-30 15:26:27 +00:00
if ( ! tabs_flag & & p & & ( w1 > 0 ) ) {
2006-03-20 17:12:09 +00:00
gr_get_string_size ( s1 , & w , & h , & aw ) ;
gr_string ( x + w1 - w , y , s1 ) ;
* p = ' \t ' ;
}
d_free ( s2 ) ;
}
// Draw a slider and it's string
2008-10-28 13:28:10 +00:00
void nm_string_slider ( int w1 , int x , int y , char * s )
2006-03-20 17:12:09 +00:00
{
int w , h , aw ;
char * p , * s1 ;
s1 = NULL ;
p = strchr ( s , ' \t ' ) ;
if ( p ) {
* p = ' \0 ' ;
s1 = p + 1 ;
}
gr_get_string_size ( s , & w , & h , & aw ) ;
2007-03-22 11:32:22 +00:00
gr_string ( x , y , s ) ;
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
if ( p ) {
gr_get_string_size ( s1 , & w , & h , & aw ) ;
gr_string ( x + w1 - w , y , s1 ) ;
2006-03-20 17:12:09 +00:00
2007-03-22 11:32:22 +00:00
* p = ' \t ' ;
}
2006-03-20 17:12:09 +00:00
}
// Draw a left justfied string with black background.
2008-10-28 13:28:10 +00:00
void nm_string_black ( int w1 , int x , int y , char * s )
2006-03-20 17:12:09 +00:00
{
int w , h , aw ;
gr_get_string_size ( s , & w , & h , & aw ) ;
2008-10-28 13:28:10 +00:00
2006-03-20 17:12:09 +00:00
if ( w1 = = 0 ) w1 = w ;
2008-02-24 14:41:27 +00:00
gr_setcolor ( BM_XRGB ( 5 , 5 , 5 ) ) ;
gr_rect ( x - FSPACX ( 2 ) , y - FSPACY ( 1 ) , x + w1 , y + h ) ;
gr_setcolor ( BM_XRGB ( 2 , 2 , 2 ) ) ;
gr_rect ( x - FSPACX ( 2 ) , y - FSPACY ( 1 ) , x , y + h ) ;
gr_setcolor ( BM_XRGB ( 0 , 0 , 0 ) ) ;
gr_rect ( x - FSPACX ( 1 ) , y - FSPACY ( 1 ) , x + w1 - FSPACX ( 1 ) , y + h ) ;
2010-06-23 11:44:12 +00:00
2008-02-24 14:41:27 +00:00
gr_string ( x , y , s ) ;
2006-03-20 17:12:09 +00:00
}
// Draw a right justfied string
2008-10-28 13:28:10 +00:00
void nm_rstring ( int w1 , int x , int y , char * s )
2006-03-20 17:12:09 +00:00
{
int w , h , aw ;
gr_get_string_size ( s , & w , & h , & aw ) ;
2010-07-01 09:08:30 +00:00
x - = FSPACX ( 3 ) ;
2006-03-20 17:12:09 +00:00
if ( w1 = = 0 ) w1 = w ;
gr_string ( x - w , y , s ) ;
}
2008-10-28 13:28:10 +00:00
void nm_string_inputbox ( int w , int x , int y , char * text , int current )
2006-03-20 17:12:09 +00:00
{
int w1 , h1 , aw ;
2008-11-01 01:19:52 +00:00
// even with variable char widths and a box that goes over the whole screen, we maybe never get more than 75 chars on the line
if ( strlen ( text ) > 75 )
text + = strlen ( text ) - 75 ;
2006-03-20 17:12:09 +00:00
while ( * text ) {
gr_get_string_size ( text , & w1 , & h1 , & aw ) ;
2008-11-01 01:19:52 +00:00
if ( w1 > w - FSPACX ( 10 ) )
2006-03-20 17:12:09 +00:00
text + + ;
else
break ;
}
if ( * text = = 0 )
w1 = 0 ;
2008-10-28 13:28:10 +00:00
nm_string_black ( w , x , y , text ) ;
2009-12-05 09:48:18 +00:00
2010-12-10 23:18:17 +00:00
if ( current & & timer_query ( ) & 0x8000 )
2008-02-24 14:41:27 +00:00
gr_string ( x + w1 , y , CURSOR_STRING ) ;
2006-03-20 17:12:09 +00:00
}
2010-06-30 15:26:27 +00:00
void draw_item ( newmenu_item * item , int is_current , int tiny , int tabs_flag )
2006-03-20 17:12:09 +00:00
{
2006-09-04 22:24:09 +00:00
if ( tiny )
{
if ( is_current )
gr_set_fontcolor ( gr_find_closest_color_current ( 57 , 49 , 20 ) , - 1 ) ;
else
gr_set_fontcolor ( gr_find_closest_color_current ( 29 , 29 , 47 ) , - 1 ) ;
2010-06-23 11:44:12 +00:00
2006-09-04 22:24:09 +00:00
if ( item - > text [ 0 ] = = ' \t ' )
gr_set_fontcolor ( gr_find_closest_color_current ( 63 , 63 , 63 ) , - 1 ) ;
}
else
{
if ( is_current )
2008-02-24 14:41:27 +00:00
gr_set_curfont ( MEDIUM2_FONT ) ;
2006-09-04 22:24:09 +00:00
else
2008-02-24 14:41:27 +00:00
gr_set_curfont ( MEDIUM1_FONT ) ;
2006-03-20 17:12:09 +00:00
}
switch ( item - > type ) {
2007-08-27 23:01:34 +00:00
case NM_TYPE_TEXT :
case NM_TYPE_MENU :
2010-06-30 15:26:27 +00:00
nm_string ( item - > w , item - > x , item - > y , item - > text , tabs_flag ) ;
2007-08-27 23:01:34 +00:00
break ;
case NM_TYPE_SLIDER :
{
int i , j ;
if ( item - > value < item - > min_value ) item - > value = item - > min_value ;
2009-12-05 09:48:18 +00:00
if ( item - > value > item - > max_value ) item - > value = item - > max_value ;
i = sprintf ( item - > saved_text , " %s \t %s " , item - > text , SLIDER_LEFT ) ;
2007-08-27 23:01:34 +00:00
for ( j = 0 ; j < ( item - > max_value - item - > min_value + 1 ) ; j + + ) {
i + = sprintf ( item - > saved_text + i , " %s " , SLIDER_MIDDLE ) ;
}
sprintf ( item - > saved_text + i , " %s " , SLIDER_RIGHT ) ;
2010-06-23 11:44:12 +00:00
2007-08-27 23:01:34 +00:00
item - > saved_text [ item - > value + 1 + strlen ( item - > text ) + 1 ] = SLIDER_MARKER [ 0 ] ;
2010-06-23 11:44:12 +00:00
2008-10-28 13:28:10 +00:00
nm_string_slider ( item - > w , item - > x , item - > y , item - > saved_text ) ;
2006-03-20 17:12:09 +00:00
}
2007-08-27 23:01:34 +00:00
break ;
case NM_TYPE_INPUT_MENU :
if ( item - > group = = 0 )
{
2010-06-30 15:26:27 +00:00
nm_string ( item - > w , item - > x , item - > y , item - > text , tabs_flag ) ;
2007-08-27 23:01:34 +00:00
} else {
2008-10-28 13:28:10 +00:00
nm_string_inputbox ( item - > w , item - > x , item - > y , item - > text , is_current ) ;
2007-08-27 23:01:34 +00:00
}
break ;
case NM_TYPE_INPUT :
2008-10-28 13:28:10 +00:00
nm_string_inputbox ( item - > w , item - > x , item - > y , item - > text , is_current ) ;
2007-08-27 23:01:34 +00:00
break ;
case NM_TYPE_CHECK :
2010-06-30 15:26:27 +00:00
nm_string ( item - > w , item - > x , item - > y , item - > text , tabs_flag ) ;
2007-08-27 23:01:34 +00:00
if ( item - > value )
2008-10-28 13:28:10 +00:00
nm_rstring ( item - > right_offset , item - > x , item - > y , CHECKED_CHECK_BOX ) ;
2007-08-27 23:01:34 +00:00
else
2008-10-28 13:28:10 +00:00
nm_rstring ( item - > right_offset , item - > x , item - > y , NORMAL_CHECK_BOX ) ;
2007-08-27 23:01:34 +00:00
break ;
case NM_TYPE_RADIO :
2010-06-30 15:26:27 +00:00
nm_string ( item - > w , item - > x , item - > y , item - > text , tabs_flag ) ;
2007-08-27 23:01:34 +00:00
if ( item - > value )
2008-10-28 13:28:10 +00:00
nm_rstring ( item - > right_offset , item - > x , item - > y , CHECKED_RADIO_BOX ) ;
2007-08-27 23:01:34 +00:00
else
2008-10-28 13:28:10 +00:00
nm_rstring ( item - > right_offset , item - > x , item - > y , NORMAL_RADIO_BOX ) ;
2007-08-27 23:01:34 +00:00
break ;
case NM_TYPE_NUMBER :
{
char text [ 10 ] ;
if ( item - > value < item - > min_value ) item - > value = item - > min_value ;
2009-12-05 09:48:18 +00:00
if ( item - > value > item - > max_value ) item - > value = item - > max_value ;
2010-06-30 15:26:27 +00:00
nm_string ( item - > w , item - > x , item - > y , item - > text , tabs_flag ) ;
2007-08-27 23:01:34 +00:00
sprintf ( text , " %d " , item - > value ) ;
2008-10-28 13:28:10 +00:00
nm_rstring ( item - > right_offset , item - > x , item - > y , text ) ;
2006-03-20 17:12:09 +00:00
}
2007-08-27 23:01:34 +00:00
break ;
2006-03-20 17:12:09 +00:00
}
}
char * Newmenu_allowed_chars = NULL ;
//returns true if char is allowed
int char_allowed ( char c )
{
char * p = Newmenu_allowed_chars ;
if ( ! p )
return 1 ;
while ( * p ) {
Assert ( p [ 1 ] ) ;
if ( c > = p [ 0 ] & & c < = p [ 1 ] )
return 1 ;
p + = 2 ;
}
return 0 ;
}
void strip_end_whitespace ( char * text )
{
int i , l ;
l = strlen ( text ) ;
for ( i = l - 1 ; i > = 0 ; i - - ) {
if ( isspace ( text [ i ] ) )
text [ i ] = 0 ;
else
return ;
}
}
2010-01-07 14:49:07 +00:00
int newmenu_do ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata )
2006-03-20 17:12:09 +00:00
{
2010-04-03 07:24:50 +00:00
return newmenu_do2 ( title , subtitle , nitems , item , subfunction , userdata , 0 , NULL ) ;
2006-03-20 17:12:09 +00:00
}
2010-06-30 15:26:27 +00:00
newmenu * newmenu_dotiny ( char * title , char * subtitle , int nitems , newmenu_item * item , int TabsFlag , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata )
2006-03-20 17:12:09 +00:00
{
2010-06-30 15:26:27 +00:00
return newmenu_do4 ( title , subtitle , nitems , item , subfunction , userdata , 0 , NULL , 1 , TabsFlag ) ;
2006-03-20 17:12:09 +00:00
}
2010-01-07 14:49:07 +00:00
int newmenu_do1 ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem )
2006-03-20 17:12:09 +00:00
{
2010-04-03 07:24:50 +00:00
return newmenu_do2 ( title , subtitle , nitems , item , subfunction , userdata , citem , NULL ) ;
2006-03-20 17:12:09 +00:00
}
2010-01-07 14:49:07 +00:00
int newmenu_do2 ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem , char * filename )
2006-03-20 17:12:09 +00:00
{
2010-04-03 07:24:50 +00:00
newmenu * menu ;
2010-04-03 10:16:53 +00:00
window * wind ;
2010-04-03 07:24:50 +00:00
int rval = - 1 ;
2010-06-23 11:44:12 +00:00
menu = newmenu_do3 ( title , subtitle , nitems , item , subfunction , userdata , citem , filename ) ;
2010-04-03 07:24:50 +00:00
if ( ! menu )
return - 1 ;
2010-07-31 12:09:38 +00:00
menu - > rval = & rval ;
2010-04-03 10:16:53 +00:00
wind = menu - > wind ; // avoid dereferencing a freed 'menu'
2010-06-23 11:44:12 +00:00
2010-04-03 07:24:50 +00:00
// newmenu_do2 and simpler get their own event loop
// This is so the caller doesn't have to provide a callback that responds to EVENT_NEWMENU_SELECTED
2010-04-03 10:16:53 +00:00
while ( window_exists ( wind ) )
2010-04-03 07:24:50 +00:00
event_process ( ) ;
2010-06-23 11:44:12 +00:00
2010-04-03 07:24:50 +00:00
return rval ;
2006-03-20 17:12:09 +00:00
}
2010-06-30 15:26:27 +00:00
// Basically the same as do2 but sets reorderitems flag for weapon priority menu a bit redundant to get lose of a global variable but oh well...
int newmenu_doreorder ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata )
{
newmenu * menu ;
window * wind ;
int rval = - 1 ;
menu = newmenu_do3 ( title , subtitle , nitems , item , subfunction , userdata , 0 , NULL ) ;
if ( ! menu )
return - 1 ;
menu - > reorderitems = 1 ;
2010-07-31 12:09:38 +00:00
menu - > rval = & rval ;
2010-06-30 15:26:27 +00:00
wind = menu - > wind ; // avoid dereferencing a freed 'menu'
// newmenu_do2 and simpler get their own event loop
// This is so the caller doesn't have to provide a callback that responds to EVENT_NEWMENU_SELECTED
while ( window_exists ( wind ) )
event_process ( ) ;
return rval ;
}
2010-06-23 11:44:12 +00:00
newmenu * newmenu_do3 ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem , char * filename )
2009-12-05 09:48:18 +00:00
{
2010-06-30 15:26:27 +00:00
return newmenu_do4 ( title , subtitle , nitems , item , subfunction , userdata , citem , filename , 0 , 0 ) ;
2009-12-05 09:48:18 +00:00
}
2006-03-20 17:12:09 +00:00
2010-06-23 11:44:12 +00:00
newmenu * newmenu_do_fixedfont ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem , char * filename ) {
2010-06-30 15:26:27 +00:00
return newmenu_do4 ( title , subtitle , nitems , item , subfunction , userdata , citem , filename , 0 , 0 ) ;
2006-03-20 17:12:09 +00:00
}
# ifdef NEWMENU_MOUSE
ubyte Hack_DblClick_MenuMode = 0 ;
# endif
2010-01-07 14:49:07 +00:00
newmenu_item * newmenu_get_items ( newmenu * menu )
{
return menu - > items ;
}
int newmenu_get_nitems ( newmenu * menu )
{
return menu - > nitems ;
}
int newmenu_get_citem ( newmenu * menu )
{
return menu - > citem ;
}
2010-04-03 07:24:50 +00:00
window * newmenu_get_window ( newmenu * menu )
{
return menu - > wind ;
}
2010-03-24 07:26:52 +00:00
int newmenu_mouse ( window * wind , d_event * event , newmenu * menu )
{
int old_choice , i ;
grs_canvas * menu_canvas = window_get_canvas ( wind ) , * save_canvas = grd_curcanv ;
int mx = 0 , my = 0 , mz = 0 , x1 = 0 , x2 , y1 , y2 ;
int changed = 0 ;
gr_set_current_canvas ( menu_canvas ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
old_choice = menu - > citem ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( event - > type = = EVENT_MOUSE_BUTTON_DOWN ) & & ! menu - > all_text )
{
mouse_get_pos ( & mx , & my , & mz ) ;
for ( i = 0 ; i < menu - > max_on_menu ; i + + ) {
x1 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ i ] . x - FSPACX ( 13 ) /*- menu->items[i].right_offset - 6*/ ;
x2 = x1 + menu - > items [ i ] . w + FSPACX ( 13 ) ;
y1 = grd_curcanv - > cv_bitmap . bm_y + menu - > items [ i ] . y ;
y2 = y1 + menu - > items [ i ] . h ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) ) {
if ( i + menu - > scroll_offset ! = menu - > citem ) {
2010-06-23 11:44:12 +00:00
if ( Hack_DblClick_MenuMode ) menu - > dblclick_flag = 0 ;
2010-03-24 07:26:52 +00:00
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
menu - > citem = i + menu - > scroll_offset ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
switch ( menu - > items [ menu - > citem ] . type ) {
case NM_TYPE_CHECK :
if ( menu - > items [ menu - > citem ] . value )
menu - > items [ menu - > citem ] . value = 0 ;
else
menu - > items [ menu - > citem ] . value = 1 ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( menu - > is_scroll_box )
menu - > last_scroll_check = - 1 ;
changed = 1 ;
break ;
case NM_TYPE_RADIO :
for ( i = 0 ; i < menu - > nitems ; i + + ) {
if ( ( i ! = menu - > citem ) & & ( menu - > items [ i ] . type = = NM_TYPE_RADIO ) & & ( menu - > items [ i ] . group = = menu - > items [ menu - > citem ] . group ) & & ( menu - > items [ i ] . value ) ) {
menu - > items [ i ] . value = 0 ;
changed = 1 ;
}
}
menu - > items [ menu - > citem ] . value = 1 ;
break ;
case NM_TYPE_TEXT :
menu - > citem = old_choice ;
menu - > mouse_state = 0 ;
break ;
}
break ;
}
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( menu - > mouse_state & & menu - > all_text )
{
2010-07-31 12:09:38 +00:00
window_close ( menu - > wind ) ;
2010-03-24 07:26:52 +00:00
gr_set_current_canvas ( save_canvas ) ;
return 1 ;
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( menu - > mouse_state & & ! menu - > all_text ) {
mouse_get_pos ( & mx , & my , & mz ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
// check possible scrollbar stuff first
if ( menu - > is_scroll_box ) {
2010-12-10 23:18:17 +00:00
int arrow_width , arrow_height , aw , ScrollAllow = 0 ;
2010-03-24 07:26:52 +00:00
static fix ScrollTime = 0 ;
2010-12-10 23:18:17 +00:00
if ( ScrollTime + F1_0 / 5 < timer_query ( ) )
2010-03-24 07:26:52 +00:00
{
2010-12-10 23:18:17 +00:00
ScrollTime = timer_query ( ) ;
2010-03-24 07:26:52 +00:00
ScrollAllow = 1 ;
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( menu - > scroll_offset ! = 0 ) {
gr_get_string_size ( UP_ARROW_MARKER , & arrow_width , & arrow_height , & aw ) ;
x2 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ menu - > scroll_offset ] . x - FSPACX ( 13 ) ;
y1 = grd_curcanv - > cv_bitmap . bm_y + menu - > items [ menu - > scroll_offset ] . y - ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
x1 = x2 - arrow_width ;
y2 = y1 + arrow_height ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) & & ScrollAllow ) {
menu - > citem - - ;
menu - > last_scroll_check = - 1 ;
if ( menu - > citem - 4 < menu - > scroll_offset & & menu - > scroll_offset > 0 )
{
menu - > scroll_offset - - ;
}
}
}
if ( menu - > scroll_offset + menu - > max_displayable < menu - > nitems ) {
gr_get_string_size ( DOWN_ARROW_MARKER , & arrow_width , & arrow_height , & aw ) ;
x2 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ menu - > scroll_offset + menu - > max_displayable - 1 ] . x - FSPACX ( 13 ) ;
y1 = grd_curcanv - > cv_bitmap . bm_y + menu - > items [ menu - > scroll_offset + menu - > max_displayable - 1 ] . y - ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
x1 = x2 - arrow_width ;
y2 = y1 + arrow_height ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) & & ScrollAllow ) {
menu - > citem + + ;
menu - > last_scroll_check = - 1 ;
if ( menu - > citem + 4 > = menu - > max_on_menu + menu - > scroll_offset & & menu - > scroll_offset < menu - > nitems - menu - > max_on_menu )
{
menu - > scroll_offset + + ;
}
}
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
for ( i = 0 ; i < menu - > max_on_menu ; i + + ) {
x1 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ i ] . x - FSPACX ( 13 ) ;
x2 = x1 + menu - > items [ i ] . w + FSPACX ( 13 ) ;
y1 = grd_curcanv - > cv_bitmap . bm_y + menu - > items [ i ] . y ;
y2 = y1 + menu - > items [ i ] . h ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) & & ( menu - > items [ i ] . type ! = NM_TYPE_TEXT ) ) {
if ( i + menu - > scroll_offset ! = menu - > citem ) {
2010-06-23 11:44:12 +00:00
if ( Hack_DblClick_MenuMode ) menu - > dblclick_flag = 0 ;
2010-03-24 07:26:52 +00:00
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
menu - > citem = i + menu - > scroll_offset ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( menu - > items [ menu - > citem ] . type = = NM_TYPE_SLIDER ) {
char slider_text [ NM_MAX_TEXT_LEN + 1 ] , * p , * s1 ;
int slider_width , height , aw , sleft_width , sright_width , smiddle_width ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
strcpy ( slider_text , menu - > items [ menu - > citem ] . saved_text ) ;
p = strchr ( slider_text , ' \t ' ) ;
if ( p ) {
* p = ' \0 ' ;
s1 = p + 1 ;
}
if ( p ) {
gr_get_string_size ( s1 , & slider_width , & height , & aw ) ;
gr_get_string_size ( SLIDER_LEFT , & sleft_width , & height , & aw ) ;
gr_get_string_size ( SLIDER_RIGHT , & sright_width , & height , & aw ) ;
gr_get_string_size ( SLIDER_MIDDLE , & smiddle_width , & height , & aw ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
x1 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ menu - > citem ] . x + menu - > items [ menu - > citem ] . w - slider_width ;
x2 = x1 + slider_width + sright_width ;
if ( ( mx > x1 ) & & ( mx < ( x1 + sleft_width ) ) & & ( menu - > items [ menu - > citem ] . value ! = menu - > items [ menu - > citem ] . min_value ) ) {
menu - > items [ menu - > citem ] . value = menu - > items [ menu - > citem ] . min_value ;
changed = 1 ;
} else if ( ( mx < x2 ) & & ( mx > ( x2 - sright_width ) ) & & ( menu - > items [ menu - > citem ] . value ! = menu - > items [ menu - > citem ] . max_value ) ) {
menu - > items [ menu - > citem ] . value = menu - > items [ menu - > citem ] . max_value ;
changed = 1 ;
} else if ( ( mx > ( x1 + sleft_width ) ) & & ( mx < ( x2 - sright_width ) ) ) {
int num_values , value_width , new_value ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
num_values = menu - > items [ menu - > citem ] . max_value - menu - > items [ menu - > citem ] . min_value + 1 ;
value_width = ( slider_width - sleft_width - sright_width ) / num_values ;
new_value = ( mx - x1 - sleft_width ) / value_width ;
if ( menu - > items [ menu - > citem ] . value ! = new_value ) {
menu - > items [ menu - > citem ] . value = new_value ;
changed = 1 ;
}
}
* p = ' \t ' ;
}
}
if ( menu - > citem = = old_choice )
break ;
if ( ( menu - > items [ menu - > citem ] . type = = NM_TYPE_INPUT ) & & ( menu - > citem ! = old_choice ) )
menu - > items [ menu - > citem ] . value = - 1 ;
if ( ( old_choice > - 1 ) & & ( menu - > items [ old_choice ] . type = = NM_TYPE_INPUT_MENU ) & & ( old_choice ! = menu - > citem ) ) {
menu - > items [ old_choice ] . group = 0 ;
strcpy ( menu - > items [ old_choice ] . text , menu - > items [ old_choice ] . saved_text ) ;
menu - > items [ old_choice ] . value = - 1 ;
}
break ;
}
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( event - > type = = EVENT_MOUSE_BUTTON_UP ) & & ! menu - > all_text & & ( menu - > citem ! = - 1 ) & & ( menu - > items [ menu - > citem ] . type = = NM_TYPE_MENU ) )
{
mouse_get_pos ( & mx , & my , & mz ) ;
for ( i = 0 ; i < menu - > nitems ; i + + ) {
x1 = grd_curcanv - > cv_bitmap . bm_x + menu - > items [ i ] . x - FSPACX ( 13 ) ;
x2 = x1 + menu - > items [ i ] . w + FSPACX ( 13 ) ;
y1 = grd_curcanv - > cv_bitmap . bm_y + menu - > items [ i ] . y ;
y2 = y1 + menu - > items [ i ] . h ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) ) {
if ( Hack_DblClick_MenuMode ) {
if ( menu - > dblclick_flag )
{
// Tell callback, allow staying in menu
event - > type = EVENT_NEWMENU_SELECTED ;
if ( menu - > subfunction & & ( * menu - > subfunction ) ( menu , event , menu - > userdata ) )
return 1 ;
2010-06-23 11:44:12 +00:00
2010-07-31 12:09:38 +00:00
if ( menu - > rval )
* menu - > rval = menu - > citem ;
window_close ( menu - > wind ) ;
2010-03-24 07:26:52 +00:00
gr_set_current_canvas ( save_canvas ) ;
return 1 ;
}
else menu - > dblclick_flag = 1 ;
}
else
{
// Tell callback, allow staying in menu
event - > type = EVENT_NEWMENU_SELECTED ;
if ( menu - > subfunction & & ( * menu - > subfunction ) ( menu , event , menu - > userdata ) )
return 1 ;
2010-06-23 11:44:12 +00:00
2010-07-31 12:09:38 +00:00
if ( menu - > rval )
* menu - > rval = menu - > citem ;
window_close ( menu - > wind ) ;
2010-03-24 07:26:52 +00:00
gr_set_current_canvas ( save_canvas ) ;
return 1 ;
}
}
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( event - > type = = EVENT_MOUSE_BUTTON_UP ) & & ( menu - > citem > - 1 ) & & ( menu - > items [ menu - > citem ] . type = = NM_TYPE_INPUT_MENU ) & & ( menu - > items [ menu - > citem ] . group = = 0 ) )
{
menu - > items [ menu - > citem ] . group = 1 ;
if ( ! strnicmp ( menu - > items [ menu - > citem ] . saved_text , TXT_EMPTY , strlen ( TXT_EMPTY ) ) ) {
menu - > items [ menu - > citem ] . text [ 0 ] = 0 ;
menu - > items [ menu - > citem ] . value = - 1 ;
} else {
strip_end_whitespace ( menu - > items [ menu - > citem ] . text ) ;
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
gr_set_current_canvas ( save_canvas ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( changed & & menu - > subfunction )
{
event - > type = EVENT_NEWMENU_CHANGED ;
( * menu - > subfunction ) ( menu , event , menu - > userdata ) ;
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
return 0 ;
}
2010-01-30 03:24:19 +00:00
int newmenu_key_command ( window * wind , d_event * event , newmenu * menu )
2006-03-20 17:12:09 +00:00
{
2010-02-01 06:55:38 +00:00
newmenu_item * item = & menu - > items [ menu - > citem ] ;
2010-01-30 03:24:19 +00:00
int k = ( ( d_event_keycommand * ) event ) - > keycode ;
int old_choice , i ;
2006-08-18 09:47:07 +00:00
char * Temp , TempVal ;
2010-02-01 06:55:38 +00:00
int changed = 0 ;
2010-01-30 03:24:19 +00:00
int rval = 1 ;
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
switch ( k )
{
case KEY_PAD0 : k = KEY_0 ; break ;
case KEY_PAD1 : k = KEY_1 ; break ;
case KEY_PAD2 : k = KEY_2 ; break ;
case KEY_PAD3 : k = KEY_3 ; break ;
case KEY_PAD4 : k = KEY_4 ; break ;
case KEY_PAD5 : k = KEY_5 ; break ;
case KEY_PAD6 : k = KEY_6 ; break ;
case KEY_PAD7 : k = KEY_7 ; break ;
case KEY_PAD8 : k = KEY_8 ; break ;
case KEY_PAD9 : k = KEY_9 ; break ;
case KEY_PADPERIOD : k = KEY_PERIOD ; break ;
}
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
old_choice = menu - > citem ;
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
switch ( k ) {
2006-03-20 17:12:09 +00:00
case KEY_TAB + KEY_SHIFTED :
case KEY_UP :
case KEY_PAD8 :
2009-12-26 01:08:57 +00:00
if ( menu - > all_text ) break ;
2006-03-20 17:12:09 +00:00
do {
2009-12-26 01:08:57 +00:00
menu - > citem - - ;
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
if ( menu - > is_scroll_box )
2008-01-08 21:02:06 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > last_scroll_check = - 1 ;
if ( menu - > citem < 0 )
2008-11-01 01:19:52 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > citem = menu - > nitems - 1 ;
menu - > scroll_offset = menu - > nitems - menu - > max_on_menu ;
2008-11-01 01:19:52 +00:00
break ;
}
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
if ( menu - > citem - 4 < menu - > scroll_offset & & menu - > scroll_offset > 0 )
2008-01-08 21:02:06 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > scroll_offset - - ;
2008-01-08 21:02:06 +00:00
}
}
else
2006-09-04 22:24:09 +00:00
{
2009-12-26 01:08:57 +00:00
if ( menu - > citem > = menu - > nitems ) menu - > citem = 0 ;
if ( menu - > citem < 0 ) menu - > citem = menu - > nitems - 1 ;
2006-09-04 22:24:09 +00:00
}
2009-12-26 01:08:57 +00:00
} while ( menu - > items [ menu - > citem ] . type = = NM_TYPE_TEXT ) ;
2010-06-23 11:44:12 +00:00
if ( ( menu - > items [ menu - > citem ] . type = = NM_TYPE_INPUT ) & & ( menu - > citem ! = old_choice ) )
2009-12-26 01:08:57 +00:00
menu - > items [ menu - > citem ] . value = - 1 ;
if ( ( old_choice > - 1 ) & & ( menu - > items [ old_choice ] . type = = NM_TYPE_INPUT_MENU ) & & ( old_choice ! = menu - > citem ) ) {
menu - > items [ old_choice ] . group = 0 ;
strcpy ( menu - > items [ old_choice ] . text , menu - > items [ old_choice ] . saved_text ) ;
menu - > items [ old_choice ] . value = - 1 ;
2006-03-20 17:12:09 +00:00
}
break ;
2010-01-30 03:24:19 +00:00
case KEY_TAB :
case KEY_DOWN :
case KEY_PAD2 :
2009-12-26 01:08:57 +00:00
if ( menu - > all_text ) break ;
2008-01-08 21:02:06 +00:00
do {
2009-12-26 01:08:57 +00:00
menu - > citem + + ;
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
if ( menu - > is_scroll_box )
2006-09-04 22:24:09 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > last_scroll_check = - 1 ;
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
if ( menu - > citem = = menu - > nitems )
2010-06-23 11:44:12 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > citem = 0 ;
menu - > scroll_offset = 0 ;
2008-11-01 01:19:52 +00:00
break ;
}
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
if ( menu - > citem + 4 > = menu - > max_on_menu + menu - > scroll_offset & & menu - > scroll_offset < menu - > nitems - menu - > max_on_menu )
2006-09-04 22:24:09 +00:00
{
2009-12-26 01:08:57 +00:00
menu - > scroll_offset + + ;
2006-09-04 22:24:09 +00:00
}
}
2008-01-08 21:02:06 +00:00
else
{
2009-12-26 01:08:57 +00:00
if ( menu - > citem < 0 ) menu - > citem = menu - > nitems - 1 ;
if ( menu - > citem > = menu - > nitems ) menu - > citem = 0 ;
2008-01-08 21:02:06 +00:00
}
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
} while ( menu - > items [ menu - > citem ] . type = = NM_TYPE_TEXT ) ;
2010-06-23 11:44:12 +00:00
if ( ( menu - > items [ menu - > citem ] . type = = NM_TYPE_INPUT ) & & ( menu - > citem ! = old_choice ) )
2009-12-26 01:08:57 +00:00
menu - > items [ menu - > citem ] . value = - 1 ;
if ( ( old_choice > - 1 ) & & ( menu - > items [ old_choice ] . type = = NM_TYPE_INPUT_MENU ) & & ( old_choice ! = menu - > citem ) ) {
menu - > items [ old_choice ] . group = 0 ;
2010-06-23 11:44:12 +00:00
strcpy ( menu - > items [ old_choice ] . text , menu - > items [ old_choice ] . saved_text ) ;
2009-12-26 01:08:57 +00:00
menu - > items [ old_choice ] . value = - 1 ;
2006-03-20 17:12:09 +00:00
}
break ;
2010-01-30 03:24:19 +00:00
case KEY_SPACEBAR :
2009-12-26 01:08:57 +00:00
if ( menu - > citem > - 1 ) {
2010-02-01 06:55:38 +00:00
switch ( item - > type ) {
2009-12-26 01:08:57 +00:00
case NM_TYPE_MENU :
case NM_TYPE_INPUT :
case NM_TYPE_INPUT_MENU :
break ;
case NM_TYPE_CHECK :
2010-02-01 06:55:38 +00:00
if ( item - > value )
item - > value = 0 ;
2009-12-26 01:08:57 +00:00
else
2010-02-01 06:55:38 +00:00
item - > value = 1 ;
2009-12-26 01:08:57 +00:00
if ( menu - > is_scroll_box )
2008-01-08 21:02:06 +00:00
{
2009-12-26 01:08:57 +00:00
if ( menu - > citem = = ( menu - > max_on_menu + menu - > scroll_offset - 1 ) | | menu - > citem = = menu - > scroll_offset )
{
menu - > last_scroll_check = - 1 ;
}
2008-01-08 21:02:06 +00:00
}
2010-06-23 11:44:12 +00:00
2010-02-01 06:55:38 +00:00
changed = 1 ;
2009-12-26 01:08:57 +00:00
break ;
2010-01-30 03:24:19 +00:00
case NM_TYPE_RADIO :
2009-12-26 01:08:57 +00:00
for ( i = 0 ; i < menu - > nitems ; i + + ) {
2010-02-01 06:55:38 +00:00
if ( ( i ! = menu - > citem ) & & ( menu - > items [ i ] . type = = NM_TYPE_RADIO ) & & ( menu - > items [ i ] . group = = item - > group ) & & ( menu - > items [ i ] . value ) ) {
2009-12-26 01:08:57 +00:00
menu - > items [ i ] . value = 0 ;
2010-02-01 06:55:38 +00:00
changed = 1 ;
2009-12-26 01:08:57 +00:00
}
2006-03-20 17:12:09 +00:00
}
2010-02-01 06:55:38 +00:00
item - > value = 1 ;
changed = 1 ;
2009-12-26 01:08:57 +00:00
break ;
2010-06-23 11:44:12 +00:00
}
2006-03-20 17:12:09 +00:00
}
break ;
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
case KEY_SHIFTED + KEY_UP :
2010-06-30 15:26:27 +00:00
if ( menu - > reorderitems & & menu - > citem ! = 0 )
2006-09-04 22:24:09 +00:00
{
2009-12-26 01:08:57 +00:00
Temp = menu - > items [ menu - > citem ] . text ;
TempVal = menu - > items [ menu - > citem ] . value ;
menu - > items [ menu - > citem ] . text = menu - > items [ menu - > citem - 1 ] . text ;
menu - > items [ menu - > citem ] . value = menu - > items [ menu - > citem - 1 ] . value ;
menu - > items [ menu - > citem - 1 ] . text = Temp ;
menu - > items [ menu - > citem - 1 ] . value = TempVal ;
menu - > citem - - ;
2010-02-01 06:55:38 +00:00
changed = 1 ;
2006-09-04 22:24:09 +00:00
}
break ;
2010-01-30 03:24:19 +00:00
case KEY_SHIFTED + KEY_DOWN :
2010-06-30 15:26:27 +00:00
if ( menu - > reorderitems & & menu - > citem ! = ( menu - > nitems - 1 ) )
2006-09-04 22:24:09 +00:00
{
2009-12-26 01:08:57 +00:00
Temp = menu - > items [ menu - > citem ] . text ;
TempVal = menu - > items [ menu - > citem ] . value ;
menu - > items [ menu - > citem ] . text = menu - > items [ menu - > citem + 1 ] . text ;
menu - > items [ menu - > citem ] . value = menu - > items [ menu - > citem + 1 ] . value ;
menu - > items [ menu - > citem + 1 ] . text = Temp ;
menu - > items [ menu - > citem + 1 ] . value = TempVal ;
menu - > citem + + ;
2010-02-01 06:55:38 +00:00
changed = 1 ;
2006-09-04 22:24:09 +00:00
}
break ;
2010-01-30 03:24:19 +00:00
case KEY_ENTER :
case KEY_PADENTER :
2010-02-01 06:55:38 +00:00
if ( ( menu - > citem > - 1 ) & & ( item - > type = = NM_TYPE_INPUT_MENU ) & & ( item - > group = = 0 ) ) {
item - > group = 1 ;
if ( ! strnicmp ( item - > saved_text , TXT_EMPTY , strlen ( TXT_EMPTY ) ) ) {
item - > text [ 0 ] = 0 ;
item - > value = - 1 ;
2010-06-23 11:44:12 +00:00
} else {
2010-02-01 06:55:38 +00:00
strip_end_whitespace ( item - > text ) ;
2006-03-20 17:12:09 +00:00
}
} else
2009-12-26 01:08:57 +00:00
{
2010-02-26 08:42:44 +00:00
if ( item - > type = = NM_TYPE_INPUT_MENU )
item - > group = 0 ; // go out of editing mode
2010-01-08 01:55:12 +00:00
// Tell callback, allow staying in menu
event - > type = EVENT_NEWMENU_SELECTED ;
if ( menu - > subfunction & & ( * menu - > subfunction ) ( menu , event , menu - > userdata ) )
return 1 ;
2010-06-23 11:44:12 +00:00
2010-07-31 12:09:38 +00:00
if ( menu - > rval )
* menu - > rval = menu - > citem ;
window_close ( menu - > wind ) ;
2009-12-26 01:08:57 +00:00
return 1 ;
}
2006-03-20 17:12:09 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
case KEY_ESC :
2010-02-01 06:55:38 +00:00
if ( ( menu - > citem > - 1 ) & & ( item - > type = = NM_TYPE_INPUT_MENU ) & & ( item - > group = = 1 ) ) {
item - > group = 0 ;
2010-06-23 11:44:12 +00:00
strcpy ( item - > text , item - > saved_text ) ;
2010-02-01 06:55:38 +00:00
item - > value = - 1 ;
2006-03-20 17:12:09 +00:00
} else {
2010-07-31 12:09:38 +00:00
window_close ( menu - > wind ) ;
2009-12-26 01:08:57 +00:00
return 1 ;
2006-03-20 17:12:09 +00:00
}
break ;
2010-06-23 11:44:12 +00:00
2008-12-07 12:26:43 +00:00
# ifndef NDEBUG
2010-06-23 11:44:12 +00:00
case KEY_BACKSP :
2010-02-01 06:55:38 +00:00
if ( ( menu - > citem > - 1 ) & & ( item - > type ! = NM_TYPE_INPUT ) & & ( item - > type ! = NM_TYPE_INPUT_MENU ) )
2010-06-23 11:44:12 +00:00
Int3 ( ) ;
2006-03-20 17:12:09 +00:00
break ;
2009-12-05 09:48:18 +00:00
# endif
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
default :
rval = 0 ;
break ;
}
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
if ( menu - > citem > - 1 ) {
int ascii ;
2010-06-23 11:44:12 +00:00
2010-02-01 06:55:38 +00:00
// Alerting callback of every keypress for NM_TYPE_INPUT. Alternatively, just respond to EVENT_NEWMENU_SELECTED
if ( ( ( item - > type = = NM_TYPE_INPUT ) | | ( ( item - > type = = NM_TYPE_INPUT_MENU ) & & ( item - > group = = 1 ) ) ) & & ( old_choice = = menu - > citem ) ) {
2010-01-30 03:24:19 +00:00
if ( k = = KEY_LEFT | | k = = KEY_BACKSP | | k = = KEY_PAD4 ) {
2010-02-01 06:55:38 +00:00
if ( item - > value = = - 1 ) item - > value = strlen ( item - > text ) ;
if ( item - > value > 0 )
item - > value - - ;
item - > text [ item - > value ] = 0 ;
2010-06-23 11:44:12 +00:00
2010-02-01 06:55:38 +00:00
if ( item - > type = = NM_TYPE_INPUT )
changed = 1 ;
2010-01-30 03:24:19 +00:00
rval = 1 ;
} else {
ascii = key_ascii ( ) ;
2010-02-01 06:55:38 +00:00
if ( ( ascii < 255 ) & & ( item - > value < item - > text_len ) )
2010-01-30 03:24:19 +00:00
{
int allowed ;
2010-06-23 11:44:12 +00:00
2010-02-01 06:55:38 +00:00
if ( item - > value = = - 1 ) {
item - > value = 0 ;
2010-03-24 07:26:52 +00:00
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
allowed = char_allowed ( ascii ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ! allowed & & ascii = = ' ' & & char_allowed ( ' _ ' ) ) {
ascii = ' _ ' ;
allowed = 1 ;
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( allowed ) {
item - > text [ item - > value + + ] = ascii ;
item - > text [ item - > value ] = 0 ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( item - > type = = NM_TYPE_INPUT )
2010-02-01 06:55:38 +00:00
changed = 1 ;
2006-03-20 17:12:09 +00:00
}
2009-12-26 01:08:57 +00:00
}
2006-03-20 17:12:09 +00:00
}
}
2010-03-24 07:26:52 +00:00
else if ( ( item - > type ! = NM_TYPE_INPUT ) & & ( item - > type ! = NM_TYPE_INPUT_MENU ) )
{
ascii = key_ascii ( ) ;
if ( ascii < 255 ) {
int choice1 = menu - > citem ;
ascii = toupper ( ascii ) ;
do {
int i , ch ;
choice1 + + ;
if ( choice1 > = menu - > nitems )
choice1 = 0 ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
for ( i = 0 ; ( ch = menu - > items [ choice1 ] . text [ i ] ) ! = 0 & & ch = = ' ' ; i + + ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( ( menu - > items [ choice1 ] . type = = NM_TYPE_MENU ) | |
( menu - > items [ choice1 ] . type = = NM_TYPE_CHECK ) | |
( menu - > items [ choice1 ] . type = = NM_TYPE_RADIO ) | |
( menu - > items [ choice1 ] . type = = NM_TYPE_NUMBER ) | |
( menu - > items [ choice1 ] . type = = NM_TYPE_SLIDER ) )
& & ( ascii = = toupper ( ch ) ) )
2009-12-26 01:08:57 +00:00
{
2010-03-24 07:26:52 +00:00
k = 0 ;
menu - > citem = choice1 ;
2007-09-24 08:05:56 +00:00
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
while ( menu - > citem > menu - > scroll_offset + menu - > max_displayable - 1 )
{
menu - > scroll_offset + + ;
}
while ( menu - > citem < menu - > scroll_offset )
{
menu - > scroll_offset - - ;
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
} while ( choice1 ! = menu - > citem ) ;
2006-03-20 17:12:09 +00:00
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( ( item - > type = = NM_TYPE_NUMBER ) | | ( item - > type = = NM_TYPE_SLIDER ) )
{
switch ( k ) {
case KEY_PAD4 :
case KEY_LEFT :
case KEY_MINUS :
case KEY_MINUS + KEY_SHIFTED :
case KEY_PADMINUS :
item - > value - = 1 ;
changed = 1 ;
rval = 1 ;
break ;
case KEY_RIGHT :
case KEY_PAD6 :
case KEY_EQUAL :
case KEY_EQUAL + KEY_SHIFTED :
case KEY_PADPLUS :
item - > value + + ;
changed = 1 ;
rval = 1 ;
break ;
case KEY_PAGEUP :
case KEY_PAD9 :
case KEY_SPACEBAR :
item - > value + = 10 ;
changed = 1 ;
rval = 1 ;
break ;
case KEY_PAGEDOWN :
case KEY_BACKSP :
case KEY_PAD3 :
item - > value - = 10 ;
changed = 1 ;
rval = 1 ;
break ;
}
if ( item - > value < item - > min_value ) item - > value = item - > min_value ;
if ( item - > value > item - > max_value ) item - > value = item - > max_value ;
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
2010-02-01 06:55:38 +00:00
if ( changed & & menu - > subfunction )
{
2010-03-24 07:26:52 +00:00
event - > type = EVENT_NEWMENU_CHANGED ;
( * menu - > subfunction ) ( menu , event , menu - > userdata ) ;
2010-02-01 06:55:38 +00:00
}
2010-01-31 07:45:26 +00:00
2010-06-23 11:44:12 +00:00
return rval ;
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
void newmenu_create_structure ( newmenu * menu )
2009-12-26 01:08:57 +00:00
{
int i , j , aw , tw , th , twidth , fm , right_offset ;
int nmenus , nothers ;
2010-06-23 11:44:12 +00:00
grs_font * save_font ;
grs_canvas * save_canvas ;
2009-12-26 01:08:57 +00:00
int string_width , string_height , average_width ;
save_canvas = grd_curcanv ;
gr_set_current_canvas ( NULL ) ;
save_font = grd_curcanv - > cv_font ;
tw = th = 0 ;
2010-06-23 11:44:12 +00:00
if ( menu - > title ) {
2009-12-26 01:08:57 +00:00
gr_set_curfont ( HUGE_FONT ) ;
2010-06-23 11:44:12 +00:00
gr_get_string_size ( menu - > title , & string_width , & string_height , & average_width ) ;
2009-12-26 01:08:57 +00:00
tw = string_width ;
th = string_height ;
}
2010-06-23 11:44:12 +00:00
if ( menu - > subtitle ) {
2009-12-26 01:08:57 +00:00
gr_set_curfont ( MEDIUM3_FONT ) ;
2010-06-23 11:44:12 +00:00
gr_get_string_size ( menu - > subtitle , & string_width , & string_height , & average_width ) ;
2009-12-26 01:08:57 +00:00
if ( string_width > tw )
tw = string_width ;
th + = string_height ;
}
th + = FSPACY ( 5 ) ; //put some space between titles & body
2010-06-23 11:44:12 +00:00
if ( menu - > tiny_mode )
2009-12-26 01:08:57 +00:00
gr_set_curfont ( GAME_FONT ) ;
2010-06-23 11:44:12 +00:00
else
2009-12-26 01:08:57 +00:00
gr_set_curfont ( MEDIUM1_FONT ) ;
2010-01-31 04:30:48 +00:00
menu - > w = aw = 0 ;
menu - > h = th ;
2009-12-26 01:08:57 +00:00
nmenus = nothers = 0 ;
// Find menu height & width (store in w,h)
2010-06-23 11:44:12 +00:00
for ( i = 0 ; i < menu - > nitems ; i + + ) {
menu - > items [ i ] . y = menu - > h ;
gr_get_string_size ( menu - > items [ i ] . text , & string_width , & string_height , & average_width ) ;
menu - > items [ i ] . right_offset = 0 ;
2009-12-26 01:08:57 +00:00
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . saved_text [ 0 ] = ' \0 ' ;
2009-12-26 01:08:57 +00:00
2010-06-23 11:44:12 +00:00
if ( menu - > items [ i ] . type = = NM_TYPE_SLIDER ) {
2009-12-26 01:08:57 +00:00
int index , w1 , h1 , aw1 ;
nothers + + ;
2010-06-23 11:44:12 +00:00
index = sprintf ( menu - > items [ i ] . saved_text , " %s " , SLIDER_LEFT ) ;
for ( j = 0 ; j < ( menu - > items [ i ] . max_value - menu - > items [ i ] . min_value + 1 ) ; j + + ) {
index + = sprintf ( menu - > items [ i ] . saved_text + index , " %s " , SLIDER_MIDDLE ) ;
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
sprintf ( menu - > items [ i ] . saved_text + index , " %s " , SLIDER_RIGHT ) ;
gr_get_string_size ( menu - > items [ i ] . saved_text , & w1 , & h1 , & aw1 ) ;
2009-12-26 01:08:57 +00:00
string_width + = w1 + aw ;
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
if ( menu - > items [ i ] . type = = NM_TYPE_MENU ) {
2009-12-26 01:08:57 +00:00
nmenus + + ;
}
2006-03-20 17:12:09 +00:00
2010-06-23 11:44:12 +00:00
if ( menu - > items [ i ] . type = = NM_TYPE_CHECK ) {
2009-12-26 01:08:57 +00:00
int w1 , h1 , aw1 ;
nothers + + ;
gr_get_string_size ( NORMAL_CHECK_BOX , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . right_offset = w1 ;
2009-12-26 01:08:57 +00:00
gr_get_string_size ( CHECKED_CHECK_BOX , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
if ( w1 > menu - > items [ i ] . right_offset )
menu - > items [ i ] . right_offset = w1 ;
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
if ( menu - > items [ i ] . type = = NM_TYPE_RADIO ) {
2009-12-26 01:08:57 +00:00
int w1 , h1 , aw1 ;
nothers + + ;
gr_get_string_size ( NORMAL_RADIO_BOX , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . right_offset = w1 ;
2009-12-26 01:08:57 +00:00
gr_get_string_size ( CHECKED_RADIO_BOX , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
if ( w1 > menu - > items [ i ] . right_offset )
menu - > items [ i ] . right_offset = w1 ;
2009-12-26 01:08:57 +00:00
}
2008-02-24 14:41:27 +00:00
2010-06-23 11:44:12 +00:00
if ( menu - > items [ i ] . type = = NM_TYPE_NUMBER ) {
2009-12-26 01:08:57 +00:00
int w1 , h1 , aw1 ;
char test_text [ 20 ] ;
nothers + + ;
2010-06-23 11:44:12 +00:00
sprintf ( test_text , " %d " , menu - > items [ i ] . max_value ) ;
2009-12-26 01:08:57 +00:00
gr_get_string_size ( test_text , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . right_offset = w1 ;
sprintf ( test_text , " %d " , menu - > items [ i ] . min_value ) ;
2009-12-26 01:08:57 +00:00
gr_get_string_size ( test_text , & w1 , & h1 , & aw1 ) ;
2010-06-23 11:44:12 +00:00
if ( w1 > menu - > items [ i ] . right_offset )
menu - > items [ i ] . right_offset = w1 ;
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
if ( ( menu - > items [ i ] . type = = NM_TYPE_INPUT ) | | ( menu - > items [ i ] . type = = NM_TYPE_INPUT_MENU ) )
2010-02-26 08:42:44 +00:00
{
2010-06-23 11:44:12 +00:00
Assert ( strlen ( menu - > items [ i ] . text ) < NM_MAX_TEXT_LEN ) ;
strcpy ( menu - > items [ i ] . saved_text , menu - > items [ i ] . text ) ;
2010-02-26 08:42:44 +00:00
2010-06-23 11:44:12 +00:00
string_width = menu - > items [ i ] . text_len * FSPACX ( 8 ) + menu - > items [ i ] . text_len ;
if ( menu - > items [ i ] . type = = NM_TYPE_INPUT & & string_width > MAX_TEXT_WIDTH )
2009-12-26 01:08:57 +00:00
string_width = MAX_TEXT_WIDTH ;
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . value = - 1 ;
menu - > items [ i ] . group = 0 ;
if ( menu - > items [ i ] . type = = NM_TYPE_INPUT_MENU )
2010-02-26 08:42:44 +00:00
nmenus + + ;
else
nothers + + ;
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . w = string_width ;
menu - > items [ i ] . h = string_height ;
2009-12-26 01:08:57 +00:00
2010-01-31 04:30:48 +00:00
if ( string_width > menu - > w )
menu - > w = string_width ; // Save maximum width
2009-12-26 01:08:57 +00:00
if ( average_width > aw )
aw = average_width ;
2010-01-31 04:30:48 +00:00
menu - > h + = string_height + FSPACY ( 1 ) ; // Find the height of all strings
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
if ( ! menu - > tiny_mode & & i > menu - > max_on_menu )
2009-12-26 01:08:57 +00:00
{
2010-01-31 04:30:48 +00:00
menu - > is_scroll_box = 1 ;
2010-06-23 11:44:12 +00:00
menu - > h = ( ( menu - > max_on_menu + ( menu - > subtitle ? 1 : 0 ) ) * LINE_SPACING ) ;
2010-01-31 04:30:48 +00:00
menu - > max_displayable = menu - > max_on_menu ;
2010-06-23 11:44:12 +00:00
2010-01-31 04:30:48 +00:00
// if our last citem was > menu->max_on_menu, make sure we re-scroll when we call this menu again
2010-06-23 11:44:12 +00:00
if ( menu - > citem > menu - > max_on_menu - 4 )
2006-09-04 22:24:09 +00:00
{
2010-06-23 11:44:12 +00:00
menu - > scroll_offset = menu - > citem - ( menu - > max_on_menu - 4 ) ;
if ( menu - > scroll_offset + menu - > max_on_menu > menu - > nitems )
menu - > scroll_offset = menu - > nitems - menu - > max_on_menu ;
2009-12-26 01:08:57 +00:00
}
}
else
{
2010-01-31 04:30:48 +00:00
menu - > is_scroll_box = 0 ;
menu - > max_on_menu = i ;
2009-12-26 01:08:57 +00:00
}
right_offset = 0 ;
2010-06-23 11:44:12 +00:00
for ( i = 0 ; i < menu - > nitems ; i + + ) {
menu - > items [ i ] . w = menu - > w ;
if ( menu - > items [ i ] . right_offset > right_offset )
right_offset = menu - > items [ i ] . right_offset ;
2009-12-26 01:08:57 +00:00
}
2010-01-31 04:30:48 +00:00
menu - > w + = right_offset ;
2009-12-26 01:08:57 +00:00
twidth = 0 ;
2010-01-31 04:30:48 +00:00
if ( tw > menu - > w ) {
twidth = ( tw - menu - > w ) / 2 ;
menu - > w = tw ;
2009-12-26 01:08:57 +00:00
}
// Find min point of menu border
2010-01-31 04:30:48 +00:00
menu - > w + = BORDERX * 2 ;
menu - > h + = BORDERY * 2 ;
2009-12-26 01:08:57 +00:00
2010-01-31 04:30:48 +00:00
menu - > x = ( GWIDTH - menu - > w ) / 2 ;
menu - > y = ( GHEIGHT - menu - > h ) / 2 ;
2009-12-26 01:08:57 +00:00
2010-01-31 04:30:48 +00:00
if ( menu - > x < 0 ) menu - > x = 0 ;
if ( menu - > y < 0 ) menu - > y = 0 ;
2009-12-26 01:08:57 +00:00
2010-01-31 04:30:48 +00:00
nm_draw_background1 ( menu - > filename ) ;
2009-12-26 01:08:57 +00:00
// Update all item's x & y values.
2010-06-23 11:44:12 +00:00
for ( i = 0 ; i < menu - > nitems ; i + + ) {
menu - > items [ i ] . x = BORDERX + twidth + right_offset ;
menu - > items [ i ] . y + = BORDERY ;
if ( menu - > items [ i ] . type = = NM_TYPE_RADIO ) {
2009-12-26 01:08:57 +00:00
fm = - 1 ; // find first marked one
2010-06-23 11:44:12 +00:00
for ( j = 0 ; j < menu - > nitems ; j + + ) {
if ( menu - > items [ j ] . type = = NM_TYPE_RADIO & & menu - > items [ j ] . group = = menu - > items [ i ] . group ) {
if ( fm = = - 1 & & menu - > items [ j ] . value )
2009-12-26 01:08:57 +00:00
fm = j ;
2010-06-23 11:44:12 +00:00
menu - > items [ j ] . value = 0 ;
2009-12-26 01:08:57 +00:00
}
}
2010-06-23 11:44:12 +00:00
if ( fm > = 0 )
menu - > items [ fm ] . value = 1 ;
2008-02-24 14:41:27 +00:00
else
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . value = 1 ;
2006-09-04 22:24:09 +00:00
}
2006-03-20 17:12:09 +00:00
}
2010-06-23 11:44:12 +00:00
if ( menu - > citem ! = - 1 )
{
if ( menu - > citem < 0 ) menu - > citem = 0 ;
if ( menu - > citem > menu - > nitems - 1 ) menu - > citem = menu - > nitems - 1 ;
2006-03-20 17:12:09 +00:00
2009-12-26 01:08:57 +00:00
# ifdef NEWMENU_MOUSE
2010-01-31 04:30:48 +00:00
menu - > dblclick_flag = 1 ;
2009-12-26 01:08:57 +00:00
# endif
2010-06-23 11:44:12 +00:00
i = 0 ;
while ( menu - > items [ menu - > citem ] . type = = NM_TYPE_TEXT ) {
2010-01-31 04:30:48 +00:00
menu - > citem + + ;
2010-06-23 11:44:12 +00:00
i + + ;
if ( menu - > citem > = menu - > nitems ) {
menu - > citem = 0 ;
2009-12-26 01:08:57 +00:00
}
2010-06-23 11:44:12 +00:00
if ( i > menu - > nitems ) {
menu - > citem = 0 ;
2010-01-31 04:30:48 +00:00
menu - > all_text = 1 ;
2010-06-23 11:44:12 +00:00
break ;
2009-12-26 01:08:57 +00:00
}
}
}
2006-03-20 17:12:09 +00:00
2010-03-24 07:26:52 +00:00
menu - > mouse_state = 0 ;
2010-06-23 11:44:12 +00:00
menu - > swidth = SWIDTH ;
menu - > sheight = SHEIGHT ;
menu - > fntscalex = FNTScaleX ;
menu - > fntscaley = FNTScaleY ;
gr_set_curfont ( save_font ) ;
gr_set_current_canvas ( save_canvas ) ;
}
int newmenu_draw ( window * wind , newmenu * menu )
{
grs_canvas * menu_canvas = window_get_canvas ( wind ) , * save_canvas = grd_curcanv ;
int tw , th = 0 , ty , sx , sy ;
int i ;
int string_width , string_height , average_width ;
if ( menu - > swidth ! = SWIDTH | | menu - > sheight ! = SHEIGHT | | menu - > fntscalex ! = FNTScaleX | | menu - > fntscalex ! = FNTScaleY )
{
newmenu_create_structure ( menu ) ;
if ( menu_canvas )
{
gr_init_sub_canvas ( menu_canvas , & grd_curscreen - > sc_canvas , menu - > x , menu - > y , menu - > w , menu - > h ) ;
}
}
gr_set_current_canvas ( NULL ) ;
nm_draw_background1 ( menu - > filename ) ;
if ( menu - > filename = = NULL )
nm_draw_background ( menu - > x - ( menu - > is_scroll_box ? FSPACX ( 5 ) : 0 ) , menu - > y , menu - > x + menu - > w , menu - > y + menu - > h ) ;
gr_set_current_canvas ( menu_canvas ) ;
ty = BORDERY ;
if ( menu - > title ) {
gr_set_curfont ( HUGE_FONT ) ;
gr_set_fontcolor ( BM_XRGB ( 31 , 31 , 31 ) , - 1 ) ;
gr_get_string_size ( menu - > title , & string_width , & string_height , & average_width ) ;
tw = string_width ;
th = string_height ;
gr_printf ( 0x8000 , ty , menu - > title ) ;
}
if ( menu - > subtitle ) {
gr_set_curfont ( MEDIUM3_FONT ) ;
gr_set_fontcolor ( BM_XRGB ( 21 , 21 , 21 ) , - 1 ) ;
gr_get_string_size ( menu - > subtitle , & string_width , & string_height , & average_width ) ;
tw = string_width ;
gr_printf ( 0x8000 , ty + th , menu - > subtitle ) ;
}
if ( menu - > tiny_mode )
gr_set_curfont ( GAME_FONT ) ;
else
gr_set_curfont ( MEDIUM1_FONT ) ;
// Redraw everything...
for ( i = menu - > scroll_offset ; i < menu - > max_displayable + menu - > scroll_offset ; i + + )
{
menu - > items [ i ] . y - = ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
2010-06-30 15:26:27 +00:00
draw_item ( & menu - > items [ i ] , ( i = = menu - > citem & & ! menu - > all_text ) , menu - > tiny_mode , menu - > tabs_flag ) ;
2010-06-23 11:44:12 +00:00
menu - > items [ i ] . y + = ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
}
if ( menu - > is_scroll_box )
{
menu - > last_scroll_check = menu - > scroll_offset ;
gr_set_curfont ( MEDIUM2_FONT ) ;
sy = menu - > items [ menu - > scroll_offset ] . y - ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
sx = menu - > items [ menu - > scroll_offset ] . x - FSPACX ( 11 ) ;
if ( menu - > scroll_offset ! = 0 )
nm_rstring ( FSPACX ( 11 ) , sx , sy , UP_ARROW_MARKER ) ;
else
nm_rstring ( FSPACX ( 11 ) , sx , sy , " " ) ;
sy = menu - > items [ menu - > scroll_offset + menu - > max_displayable - 1 ] . y - ( ( ( int ) LINE_SPACING ) * menu - > scroll_offset ) ;
sx = menu - > items [ menu - > scroll_offset + menu - > max_displayable - 1 ] . x - FSPACX ( 11 ) ;
if ( menu - > scroll_offset + menu - > max_displayable < menu - > nitems )
nm_rstring ( FSPACX ( 11 ) , sx , sy , DOWN_ARROW_MARKER ) ;
else
nm_rstring ( FSPACX ( 11 ) , sx , sy , " " ) ;
}
{
d_event event ;
event . type = EVENT_NEWMENU_DRAW ;
if ( menu - > subfunction )
( * menu - > subfunction ) ( menu , & event , menu - > userdata ) ;
}
2009-12-26 01:08:57 +00:00
gr_set_current_canvas ( save_canvas ) ;
2010-06-23 11:44:12 +00:00
return 1 ;
}
int newmenu_handler ( window * wind , d_event * event , newmenu * menu )
{
if ( event - > type = = EVENT_WINDOW_CLOSED )
return 0 ;
2010-07-31 12:09:38 +00:00
if ( menu - > subfunction )
2010-06-23 11:44:12 +00:00
{
int rval = ( * menu - > subfunction ) ( menu , event , menu - > userdata ) ;
if ( rval )
{
if ( rval < - 1 )
{
2010-07-31 12:09:38 +00:00
if ( menu - > rval )
* menu - > rval = rval ;
window_close ( wind ) ;
2010-06-23 11:44:12 +00:00
}
return 1 ; // event handled
}
}
switch ( event - > type )
{
case EVENT_WINDOW_ACTIVATED :
game_flush_inputs ( ) ;
2010-07-16 11:07:42 +00:00
mouse_toggle_cursor ( 1 ) ;
2010-06-23 11:44:12 +00:00
break ;
case EVENT_WINDOW_DEACTIVATED :
2010-07-16 11:07:42 +00:00
mouse_toggle_cursor ( 0 ) ;
2010-06-23 11:44:12 +00:00
menu - > mouse_state = 0 ;
break ;
case EVENT_MOUSE_BUTTON_DOWN :
case EVENT_MOUSE_BUTTON_UP :
if ( mouse_get_button ( event ) ! = 0 )
return 0 ;
menu - > mouse_state = event - > type = = EVENT_MOUSE_BUTTON_DOWN ;
return newmenu_mouse ( wind , event , menu ) ;
case EVENT_KEY_COMMAND :
return newmenu_key_command ( wind , event , menu ) ;
break ;
case EVENT_IDLE :
timer_delay2 ( 50 ) ;
return newmenu_mouse ( wind , event , menu ) ;
break ;
case EVENT_WINDOW_DRAW :
return newmenu_draw ( wind , menu ) ;
break ;
case EVENT_WINDOW_CLOSE :
2010-07-31 12:09:38 +00:00
d_free ( menu ) ;
2010-06-23 11:44:12 +00:00
break ;
default :
break ;
}
return 0 ;
}
2010-06-30 15:26:27 +00:00
newmenu * newmenu_do4 ( char * title , char * subtitle , int nitems , newmenu_item * item , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int citem , char * filename , int TinyMode , int TabsFlag )
2010-06-23 11:44:12 +00:00
{
window * wind = NULL ;
newmenu * menu ;
grs_canvas * menu_canvas ;
MALLOC ( menu , newmenu , 1 ) ;
if ( ! menu )
return NULL ;
memset ( menu , 0 , sizeof ( newmenu ) ) ;
menu - > citem = citem ;
menu - > scroll_offset = 0 ;
menu - > last_scroll_check = - 1 ;
menu - > all_text = 0 ;
menu - > is_scroll_box = 0 ;
menu - > max_on_menu = MAXDISPLAYABLEITEMS ;
menu - > dblclick_flag = 0 ;
menu - > title = title ;
menu - > subtitle = subtitle ;
menu - > nitems = nitems ;
menu - > subfunction = subfunction ;
menu - > items = item ;
menu - > filename = filename ;
menu - > tiny_mode = TinyMode ;
2010-06-30 15:26:27 +00:00
menu - > tabs_flag = TabsFlag ;
menu - > reorderitems = 0 ; // will be set if needed
2010-07-31 12:09:38 +00:00
menu - > rval = NULL ; // Default to not returning a value - respond to EVENT_NEWMENU_SELECTED instead
2010-06-23 11:44:12 +00:00
menu - > userdata = userdata ;
2010-07-31 12:09:38 +00:00
newmenu_free_background ( ) ;
2010-06-23 11:44:12 +00:00
if ( nitems < 1 )
{
d_free ( menu ) ;
return NULL ;
}
menu - > max_displayable = nitems ;
2010-07-29 08:30:46 +00:00
set_screen_mode ( SCREEN_MENU ) ; //hafta set the screen mode here or fonts might get changed/freed up if screen res changes
2010-06-23 11:44:12 +00:00
newmenu_create_structure ( menu ) ;
// Create the basic window
if ( menu )
wind = window_create ( & grd_curscreen - > sc_canvas , menu - > x , menu - > y , menu - > w , menu - > h , ( int ( * ) ( window * , d_event * , void * ) ) newmenu_handler , menu ) ;
if ( ! wind )
{
d_free ( menu ) ;
return NULL ;
}
menu - > wind = wind ;
menu_canvas = window_get_canvas ( wind ) ;
2010-04-03 07:24:50 +00:00
return menu ;
2006-03-20 17:12:09 +00:00
}
2010-01-07 14:49:07 +00:00
int nm_messagebox1 ( char * title , int ( * subfunction ) ( newmenu * menu , d_event * event , void * userdata ) , void * userdata , int nchoices , . . . )
2006-03-20 17:12:09 +00:00
{
int i ;
char * format ;
va_list args ;
char * s ;
char nm_text [ MESSAGEBOX_TEXT_SIZE ] ;
newmenu_item nm_message_items [ 5 ] ;
va_start ( args , nchoices ) ;
Assert ( nchoices < = 5 ) ;
for ( i = 0 ; i < nchoices ; i + + ) {
2009-12-05 09:48:18 +00:00
s = va_arg ( args , char * ) ;
nm_message_items [ i ] . type = NM_TYPE_MENU ; nm_message_items [ i ] . text = s ;
2006-03-20 17:12:09 +00:00
}
format = va_arg ( args , char * ) ;
strcpy ( nm_text , " " ) ;
vsprintf ( nm_text , format , args ) ;
va_end ( args ) ;
Assert ( strlen ( nm_text ) < MESSAGEBOX_TEXT_SIZE ) ;
2010-01-07 14:49:07 +00:00
return newmenu_do ( title , nm_text , nchoices , nm_message_items , subfunction , userdata ) ;
2006-03-20 17:12:09 +00:00
}
int nm_messagebox ( char * title , int nchoices , . . . )
{
int i ;
char * format ;
va_list args ;
char * s ;
char nm_text [ MESSAGEBOX_TEXT_SIZE ] ;
newmenu_item nm_message_items [ 5 ] ;
va_start ( args , nchoices ) ;
Assert ( nchoices < = 5 ) ;
for ( i = 0 ; i < nchoices ; i + + ) {
s = va_arg ( args , char * ) ;
nm_message_items [ i ] . type = NM_TYPE_MENU ; nm_message_items [ i ] . text = s ;
}
format = va_arg ( args , char * ) ;
strcpy ( nm_text , " " ) ;
vsprintf ( nm_text , format , args ) ;
va_end ( args ) ;
Assert ( strlen ( nm_text ) < MESSAGEBOX_TEXT_SIZE ) ;
2010-01-07 14:49:07 +00:00
return newmenu_do ( title , nm_text , nchoices , nm_message_items , NULL , NULL ) ;
2006-03-20 17:12:09 +00:00
}
// Example listbox callback function...
// int lb_callback( int * citem, int *nitems, char * items[], int *keypress )
// {
// int i;
2010-06-23 11:44:12 +00:00
//
2006-03-20 17:12:09 +00:00
// if ( *keypress = KEY_CTRLED+KEY_D ) {
// if ( *nitems > 1 ) {
// PHYSFS_delete(items[*citem]); // Delete the file
// for (i=*citem; i<*nitems-1; i++ ) {
// items[i] = items[i+1];
// }
// *nitems = *nitems - 1;
// d_free( items[*nitems] );
// items[*nitems] = NULL;
// return 1; // redraw;
// }
// *keypress = 0;
2010-06-23 11:44:12 +00:00
// }
2006-03-20 17:12:09 +00:00
// return 0;
// }
# define LB_ITEMS_ON_SCREEN 8
2010-01-07 14:49:07 +00:00
struct listbox
2006-03-20 17:12:09 +00:00
{
2010-08-31 13:25:45 +00:00
window * wind ;
2009-12-27 05:00:45 +00:00
char * title ;
int nitems ;
char * * item ;
int allow_abort_flag ;
2010-01-07 14:49:07 +00:00
int ( * listbox_callback ) ( listbox * lb , d_event * event , void * userdata ) ;
2010-03-18 07:02:38 +00:00
int citem , first_item ;
2010-12-10 23:18:17 +00:00
int marquee_maxchars , marquee_charpos , marquee_scrollback ;
fix64 marquee_lasttime ; // to scroll text if string does not fit in box
2009-12-27 05:00:45 +00:00
int box_w , height , box_x , box_y , title_height ;
2010-06-23 13:39:52 +00:00
short swidth , sheight ; float fntscalex , fntscaley ; // with these we check if resolution or fonts have changed so listbox structure can be recreated
2010-03-24 07:26:52 +00:00
int mouse_state ;
2010-01-07 14:49:07 +00:00
void * userdata ;
} ;
char * * listbox_get_items ( listbox * lb )
{
return lb - > item ;
}
int listbox_get_nitems ( listbox * lb )
{
return lb - > nitems ;
}
int listbox_get_citem ( listbox * lb )
{
return lb - > citem ;
}
2010-08-31 13:25:45 +00:00
window * listbox_get_window ( listbox * lb )
{
return lb - > wind ;
}
2010-01-07 14:49:07 +00:00
void listbox_delete_item ( listbox * lb , int item )
{
int i ;
2010-06-23 11:44:12 +00:00
2010-01-07 14:49:07 +00:00
Assert ( item > = 0 ) ;
if ( lb - > nitems )
{
for ( i = item ; i < lb - > nitems - 1 ; i + + )
lb - > item [ i ] = lb - > item [ i + 1 ] ;
lb - > nitems - - ;
lb - > item [ lb - > nitems ] = NULL ;
2010-06-23 11:44:12 +00:00
2010-01-07 14:49:07 +00:00
if ( lb - > citem > = lb - > nitems )
lb - > citem = lb - > nitems ? lb - > nitems - 1 : 0 ;
}
}
2006-03-20 17:12:09 +00:00
2010-02-06 01:41:38 +00:00
void update_scroll_position ( listbox * lb )
{
if ( lb - > citem < 0 )
lb - > citem = 0 ;
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
if ( lb - > citem > = lb - > nitems )
lb - > citem = lb - > nitems - 1 ;
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
if ( lb - > citem < lb - > first_item )
lb - > first_item = lb - > citem ;
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
if ( lb - > citem > = ( lb - > first_item + LB_ITEMS_ON_SCREEN ) )
lb - > first_item = lb - > citem - LB_ITEMS_ON_SCREEN + 1 ;
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
if ( lb - > nitems < = LB_ITEMS_ON_SCREEN )
lb - > first_item = 0 ;
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
if ( lb - > first_item > lb - > nitems - LB_ITEMS_ON_SCREEN )
lb - > first_item = lb - > nitems - LB_ITEMS_ON_SCREEN ;
if ( lb - > first_item < 0 ) lb - > first_item = 0 ;
}
2010-03-24 07:26:52 +00:00
int listbox_mouse ( window * wind , d_event * event , listbox * lb )
{
int i ;
int mx , my , mz , x1 , x2 , y1 , y2 ; //, dblclick_flag;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( lb - > mouse_state )
{
int w , h , aw ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
mouse_get_pos ( & mx , & my , & mz ) ;
for ( i = lb - > first_item ; i < lb - > first_item + LB_ITEMS_ON_SCREEN ; i + + ) {
if ( i > = lb - > nitems )
break ;
gr_get_string_size ( lb - > item [ i ] , & w , & h , & aw ) ;
x1 = lb - > box_x ;
x2 = lb - > box_x + lb - > box_w ;
y1 = ( i - lb - > first_item ) * LINE_SPACING + lb - > box_y ;
y2 = y1 + h ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) ) {
lb - > citem = i ;
return 1 ;
}
}
}
else if ( event - > type = = EVENT_MOUSE_BUTTON_UP )
{
int w , h , aw ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
if ( lb - > citem < 0 )
return 0 ;
mouse_get_pos ( & mx , & my , & mz ) ;
gr_get_string_size ( lb - > item [ lb - > citem ] , & w , & h , & aw ) ;
x1 = lb - > box_x ;
x2 = lb - > box_x + lb - > box_w ;
y1 = ( lb - > citem - lb - > first_item ) * LINE_SPACING + lb - > box_y ;
y2 = y1 + h ;
if ( ( ( mx > x1 ) & & ( mx < x2 ) ) & & ( ( my > y1 ) & & ( my < y2 ) ) )
{
// Tell callback, allow staying in menu
event - > type = EVENT_NEWMENU_SELECTED ;
if ( lb - > listbox_callback & & ( * lb - > listbox_callback ) ( lb , event , lb - > userdata ) )
return 1 ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
window_close ( wind ) ;
return 1 ;
}
}
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
return 0 ;
}
2010-01-30 03:24:19 +00:00
int listbox_key_command ( window * wind , d_event * event , listbox * lb )
2006-03-20 17:12:09 +00:00
{
2010-01-30 03:24:19 +00:00
int key = ( ( d_event_keycommand * ) event ) - > keycode ;
int rval = 1 ;
2010-06-23 11:44:12 +00:00
2009-12-27 05:00:45 +00:00
switch ( key ) {
2006-03-20 17:12:09 +00:00
case KEY_HOME :
case KEY_PAD7 :
2009-12-27 05:00:45 +00:00
lb - > citem = 0 ;
2006-03-20 17:12:09 +00:00
break ;
case KEY_END :
case KEY_PAD1 :
2009-12-27 05:00:45 +00:00
lb - > citem = lb - > nitems - 1 ;
2006-03-20 17:12:09 +00:00
break ;
case KEY_UP :
case KEY_PAD8 :
2009-12-27 05:00:45 +00:00
lb - > citem - - ;
2006-03-20 17:12:09 +00:00
break ;
case KEY_DOWN :
case KEY_PAD2 :
2009-12-27 05:00:45 +00:00
lb - > citem + + ;
2006-03-20 17:12:09 +00:00
break ;
2009-12-05 09:48:18 +00:00
case KEY_PAGEDOWN :
2006-03-20 17:12:09 +00:00
case KEY_PAD3 :
2009-12-27 05:00:45 +00:00
lb - > citem + = LB_ITEMS_ON_SCREEN ;
2006-03-20 17:12:09 +00:00
break ;
case KEY_PAGEUP :
case KEY_PAD9 :
2009-12-27 05:00:45 +00:00
lb - > citem - = LB_ITEMS_ON_SCREEN ;
2006-03-20 17:12:09 +00:00
break ;
case KEY_ESC :
2009-12-27 05:00:45 +00:00
if ( lb - > allow_abort_flag ) {
lb - > citem = - 1 ;
2010-03-18 07:02:38 +00:00
window_close ( wind ) ;
2009-12-27 05:00:45 +00:00
return 1 ;
2006-03-20 17:12:09 +00:00
}
break ;
2010-01-20 11:04:09 +00:00
case KEY_ENTER :
case KEY_PADENTER :
2010-01-08 01:55:12 +00:00
// Tell callback, allow staying in menu
event - > type = EVENT_NEWMENU_SELECTED ;
if ( lb - > listbox_callback & & ( * lb - > listbox_callback ) ( lb , event , lb - > userdata ) )
return 1 ;
2010-06-23 11:44:12 +00:00
2010-03-18 07:02:38 +00:00
window_close ( wind ) ;
2009-12-27 05:00:45 +00:00
return 1 ;
2006-03-20 17:12:09 +00:00
break ;
2010-06-23 11:44:12 +00:00
default :
2009-12-27 05:00:45 +00:00
{
int ascii = key_ascii ( ) ;
if ( ascii < 255 ) {
int cc , cc1 ;
cc = cc1 = lb - > citem + 1 ;
if ( cc1 < 0 ) cc1 = 0 ;
if ( cc1 > = lb - > nitems ) cc1 = 0 ;
while ( 1 ) {
if ( cc < 0 ) cc = 0 ;
if ( cc > = lb - > nitems ) cc = 0 ;
if ( lb - > citem = = cc ) break ;
2010-06-23 11:44:12 +00:00
2009-12-27 05:00:45 +00:00
if ( toupper ( lb - > item [ cc ] [ 0 ] ) = = toupper ( ascii ) ) {
lb - > citem = cc ;
break ;
2006-03-20 17:12:09 +00:00
}
2009-12-27 05:00:45 +00:00
cc + + ;
2006-03-20 17:12:09 +00:00
}
}
2010-01-30 03:24:19 +00:00
rval = 0 ;
2006-03-20 17:12:09 +00:00
}
2009-12-27 05:00:45 +00:00
}
2010-06-23 11:44:12 +00:00
2010-02-06 01:41:38 +00:00
update_scroll_position ( lb ) ;
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
return rval ;
}
2010-06-23 11:44:12 +00:00
void listbox_create_structure ( listbox * lb )
{
int i = 0 ;
gr_set_current_canvas ( NULL ) ;
gr_set_curfont ( MEDIUM3_FONT ) ;
lb - > box_w = 0 ;
for ( i = 0 ; i < lb - > nitems ; i + + ) {
int w , h , aw ;
gr_get_string_size ( lb - > item [ i ] , & w , & h , & aw ) ;
if ( w > lb - > box_w )
lb - > box_w = w + FSPACX ( 10 ) ;
}
lb - > height = LINE_SPACING * LB_ITEMS_ON_SCREEN ;
{
int w , h , aw ;
gr_get_string_size ( lb - > title , & w , & h , & aw ) ;
if ( w > lb - > box_w )
lb - > box_w = w ;
lb - > title_height = h + FSPACY ( 5 ) ;
}
2010-11-01 12:42:36 +00:00
lb - > marquee_maxchars = lb - > marquee_charpos = lb - > marquee_scrollback = lb - > marquee_lasttime = 0 ;
// The box is bigger than we can fit on the screen since at least one string is too long. Check how many chars we can fit on the screen (at least only - MEDIUM*_FONT is variable font!) so we can make a marquee-like effect.
if ( lb - > box_w + ( BORDERX * 2 ) > SWIDTH )
{
int w = 0 , h = 0 , aw = 0 ;
lb - > box_w = SWIDTH - ( BORDERX * 2 ) ;
gr_get_string_size ( " O " , & w , & h , & aw ) ;
lb - > marquee_maxchars = lb - > box_w / w ;
2010-12-10 23:18:17 +00:00
lb - > marquee_lasttime = timer_query ( ) ;
2010-11-01 12:42:36 +00:00
}
2010-06-23 11:44:12 +00:00
lb - > box_x = ( grd_curcanv - > cv_bitmap . bm_w - lb - > box_w ) / 2 ;
lb - > box_y = ( grd_curcanv - > cv_bitmap . bm_h - ( lb - > height + lb - > title_height ) ) / 2 + lb - > title_height ;
if ( lb - > box_y < lb - > title_height )
lb - > box_y = lb - > title_height ;
if ( lb - > citem < 0 ) lb - > citem = 0 ;
if ( lb - > citem > = lb - > nitems ) lb - > citem = 0 ;
lb - > first_item = 0 ;
update_scroll_position ( lb ) ;
lb - > mouse_state = 0 ; //dblclick_flag = 0;
lb - > swidth = SWIDTH ;
lb - > sheight = SHEIGHT ;
lb - > fntscalex = FNTScaleX ;
lb - > fntscaley = FNTScaleY ;
}
2010-01-30 03:24:19 +00:00
int listbox_draw ( window * wind , listbox * lb )
2010-01-20 11:04:09 +00:00
{
int i ;
2010-06-23 11:44:12 +00:00
if ( lb - > swidth ! = SWIDTH | | lb - > sheight ! = SHEIGHT | | lb - > fntscalex ! = FNTScaleX | | lb - > fntscalex ! = FNTScaleY )
listbox_create_structure ( lb ) ;
2010-04-02 05:24:47 +00:00
gr_set_current_canvas ( NULL ) ;
2010-01-20 11:04:09 +00:00
nm_draw_background ( lb - > box_x - BORDERX , lb - > box_y - lb - > title_height - BORDERY , lb - > box_x + lb - > box_w + BORDERX , lb - > box_y + lb - > height + BORDERY ) ;
gr_set_curfont ( MEDIUM3_FONT ) ;
gr_string ( 0x8000 , lb - > box_y - lb - > title_height , lb - > title ) ;
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
gr_setcolor ( BM_XRGB ( 0 , 0 , 0 ) ) ;
for ( i = lb - > first_item ; i < lb - > first_item + LB_ITEMS_ON_SCREEN ; i + + ) {
int y = ( i - lb - > first_item ) * LINE_SPACING + lb - > box_y ;
if ( i > = lb - > nitems ) {
gr_setcolor ( BM_XRGB ( 5 , 5 , 5 ) ) ;
gr_rect ( lb - > box_x + lb - > box_w - FSPACX ( 1 ) , y - FSPACY ( 1 ) , lb - > box_x + lb - > box_w , y + LINE_SPACING ) ;
gr_setcolor ( BM_XRGB ( 2 , 2 , 2 ) ) ;
gr_rect ( lb - > box_x - FSPACX ( 1 ) , y - FSPACY ( 1 ) , lb - > box_x , y + LINE_SPACING ) ;
gr_setcolor ( BM_XRGB ( 0 , 0 , 0 ) ) ;
gr_rect ( lb - > box_x , y - FSPACY ( 1 ) , lb - > box_x + lb - > box_w - FSPACX ( 1 ) , y + LINE_SPACING ) ;
} else {
2010-06-23 11:44:12 +00:00
if ( i = = lb - > citem )
2010-01-20 11:04:09 +00:00
gr_set_curfont ( MEDIUM2_FONT ) ;
2010-06-23 11:44:12 +00:00
else
2010-01-20 11:04:09 +00:00
gr_set_curfont ( MEDIUM1_FONT ) ;
gr_setcolor ( BM_XRGB ( 5 , 5 , 5 ) ) ;
gr_rect ( lb - > box_x + lb - > box_w - FSPACX ( 1 ) , y - FSPACY ( 1 ) , lb - > box_x + lb - > box_w , y + LINE_SPACING ) ;
gr_setcolor ( BM_XRGB ( 2 , 2 , 2 ) ) ;
gr_rect ( lb - > box_x - FSPACX ( 1 ) , y - FSPACY ( 1 ) , lb - > box_x , y + LINE_SPACING ) ;
gr_setcolor ( BM_XRGB ( 0 , 0 , 0 ) ) ;
gr_rect ( lb - > box_x , y - FSPACY ( 1 ) , lb - > box_x + lb - > box_w - FSPACX ( 1 ) , y + LINE_SPACING ) ;
2010-11-01 12:42:36 +00:00
if ( lb - > marquee_maxchars & & strlen ( lb - > item [ i ] ) > lb - > marquee_maxchars )
{
char * shrtstr = d_malloc ( lb - > marquee_maxchars + 1 ) ;
static int prev_citem = - 1 ;
if ( prev_citem ! = lb - > citem )
{
lb - > marquee_charpos = lb - > marquee_scrollback = 0 ;
2010-12-10 23:18:17 +00:00
lb - > marquee_lasttime = timer_query ( ) ;
2010-11-01 12:42:36 +00:00
prev_citem = lb - > citem ;
}
memset ( shrtstr , ' \0 ' , lb - > marquee_maxchars + 1 ) ;
if ( i = = lb - > citem )
{
2010-12-10 23:18:17 +00:00
if ( lb - > marquee_lasttime + ( F1_0 / 3 ) < timer_query ( ) )
2010-11-01 12:42:36 +00:00
{
lb - > marquee_charpos = lb - > marquee_charpos + ( lb - > marquee_scrollback ? - 1 : + 1 ) ;
2010-12-10 23:18:17 +00:00
lb - > marquee_lasttime = timer_query ( ) ;
2010-11-01 12:42:36 +00:00
}
if ( lb - > marquee_charpos < 0 ) // reached beginning of string -> scroll forward
{
lb - > marquee_charpos = 0 ;
lb - > marquee_scrollback = 0 ;
}
if ( lb - > marquee_charpos + lb - > marquee_maxchars - 1 > strlen ( lb - > item [ i ] ) ) // reached end of string -> scroll backward
{
lb - > marquee_charpos = strlen ( lb - > item [ i ] ) - lb - > marquee_maxchars + 1 ;
lb - > marquee_scrollback = 1 ;
}
snprintf ( shrtstr , lb - > marquee_maxchars , " %s " , lb - > item [ i ] + lb - > marquee_charpos ) ;
}
else
{
snprintf ( shrtstr , lb - > marquee_maxchars , " %s " , lb - > item [ i ] ) ;
}
gr_string ( lb - > box_x + FSPACX ( 5 ) , y , shrtstr ) ;
d_free ( shrtstr ) ;
}
else
{
gr_string ( lb - > box_x + FSPACX ( 5 ) , y , lb - > item [ i ] ) ;
}
2010-01-20 11:04:09 +00:00
}
}
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
{
d_event event ;
event . type = EVENT_NEWMENU_DRAW ;
if ( lb - > listbox_callback )
( * lb - > listbox_callback ) ( lb , & event , lb - > userdata ) ;
}
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
return 1 ;
}
int listbox_handler ( window * wind , d_event * event , listbox * lb )
{
2010-02-02 07:52:03 +00:00
if ( event - > type = = EVENT_WINDOW_CLOSED )
return 0 ;
2010-01-30 03:24:19 +00:00
if ( lb - > listbox_callback )
{
int rval = ( * lb - > listbox_callback ) ( lb , event , lb - > userdata ) ;
if ( rval )
return 1 ; // event handled
}
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
switch ( event - > type )
{
2010-01-28 04:24:25 +00:00
case EVENT_WINDOW_ACTIVATED :
2010-02-25 08:00:15 +00:00
game_flush_inputs ( ) ;
2010-07-16 11:07:42 +00:00
mouse_toggle_cursor ( 1 ) ;
2010-01-28 04:24:25 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-02-02 03:38:29 +00:00
case EVENT_WINDOW_DEACTIVATED :
2010-07-16 11:07:42 +00:00
mouse_toggle_cursor ( 0 ) ;
2010-02-02 03:38:29 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
case EVENT_MOUSE_BUTTON_DOWN :
case EVENT_MOUSE_BUTTON_UP :
if ( mouse_get_button ( event ) ! = 0 )
return 0 ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
lb - > mouse_state = event - > type = = EVENT_MOUSE_BUTTON_DOWN ;
return listbox_mouse ( wind , event , lb ) ;
2010-06-23 11:44:12 +00:00
2010-01-30 03:24:19 +00:00
case EVENT_KEY_COMMAND :
return listbox_key_command ( wind , event , lb ) ;
break ;
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
case EVENT_IDLE :
2010-03-24 07:26:52 +00:00
timer_delay2 ( 50 ) ;
2010-06-23 11:44:12 +00:00
2010-03-24 07:26:52 +00:00
return listbox_mouse ( wind , event , lb ) ;
2010-01-20 11:04:09 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
case EVENT_WINDOW_DRAW :
2010-01-30 03:24:19 +00:00
return listbox_draw ( wind , lb ) ;
2010-01-20 11:04:09 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
case EVENT_WINDOW_CLOSE :
2010-01-31 04:30:48 +00:00
d_free ( lb ) ;
2010-01-20 11:04:09 +00:00
break ;
2010-06-23 11:44:12 +00:00
2010-01-20 11:04:09 +00:00
default :
break ;
}
2010-01-30 03:24:19 +00:00
return 0 ;
2009-12-27 05:00:45 +00:00
}
2006-03-20 17:12:09 +00:00
2010-03-18 07:02:38 +00:00
listbox * newmenu_listbox ( char * title , int nitems , char * items [ ] , int allow_abort_flag , int ( * listbox_callback ) ( listbox * lb , d_event * event , void * userdata ) , void * userdata )
2009-12-27 05:00:45 +00:00
{
2010-01-07 14:49:07 +00:00
return newmenu_listbox1 ( title , nitems , items , allow_abort_flag , 0 , listbox_callback , userdata ) ;
2009-12-27 05:00:45 +00:00
}
2006-03-20 17:12:09 +00:00
2010-03-18 07:02:38 +00:00
listbox * newmenu_listbox1 ( char * title , int nitems , char * items [ ] , int allow_abort_flag , int default_item , int ( * listbox_callback ) ( listbox * lb , d_event * event , void * userdata ) , void * userdata )
2009-12-27 05:00:45 +00:00
{
2010-01-31 04:30:48 +00:00
listbox * lb ;
2009-12-27 05:00:45 +00:00
window * wind ;
2006-03-20 17:12:09 +00:00
2010-01-31 04:30:48 +00:00
MALLOC ( lb , listbox , 1 ) ;
2010-06-23 11:44:12 +00:00
2010-01-31 04:30:48 +00:00
if ( ! lb )
2010-03-18 07:02:38 +00:00
return NULL ;
2010-01-31 21:51:59 +00:00
2010-06-23 11:44:12 +00:00
memset ( lb , 0 , sizeof ( listbox ) ) ;
2010-07-31 12:09:38 +00:00
newmenu_free_background ( ) ;
2010-06-23 11:44:12 +00:00
2010-01-31 04:30:48 +00:00
lb - > title = title ;
lb - > nitems = nitems ;
lb - > item = items ;
2010-06-23 11:44:12 +00:00
lb - > citem = default_item ;
2010-01-31 04:30:48 +00:00
lb - > allow_abort_flag = allow_abort_flag ;
lb - > listbox_callback = listbox_callback ;
lb - > userdata = userdata ;
2006-03-20 17:12:09 +00:00
2010-07-29 08:30:46 +00:00
set_screen_mode ( SCREEN_MENU ) ; //hafta set the screen mode here or fonts might get changed/freed up if screen res changes
2010-06-23 11:44:12 +00:00
listbox_create_structure ( lb ) ;
2006-03-20 17:12:09 +00:00
2010-01-31 04:30:48 +00:00
wind = window_create ( & grd_curscreen - > sc_canvas , lb - > box_x - BORDERX , lb - > box_y - lb - > title_height - BORDERY , lb - > box_w + 2 * BORDERX , lb - > height + 2 * BORDERY , ( int ( * ) ( window * , d_event * , void * ) ) listbox_handler , lb ) ;
2009-12-27 05:00:45 +00:00
if ( ! wind )
{
2010-01-31 04:30:48 +00:00
d_free ( lb ) ;
2010-06-23 11:44:12 +00:00
2010-03-18 07:02:38 +00:00
return NULL ;
2006-03-20 17:12:09 +00:00
}
2010-08-31 13:25:45 +00:00
lb - > wind = wind ;
2006-03-20 17:12:09 +00:00
2010-03-18 07:02:38 +00:00
return lb ;
2006-03-20 17:12:09 +00:00
}
//added on 10/14/98 by Victor Rachels to attempt a fixedwidth font messagebox
2010-04-03 07:24:50 +00:00
newmenu * nm_messagebox_fixedfont ( char * title , int nchoices , . . . )
2006-03-20 17:12:09 +00:00
{
int i ;
char * format ;
va_list args ;
char * s ;
char nm_text [ MESSAGEBOX_TEXT_SIZE ] ;
newmenu_item nm_message_items [ 5 ] ;
va_start ( args , nchoices ) ;
Assert ( nchoices < = 5 ) ;
for ( i = 0 ; i < nchoices ; i + + ) {
s = va_arg ( args , char * ) ;
nm_message_items [ i ] . type = NM_TYPE_MENU ; nm_message_items [ i ] . text = s ;
}
format = va_arg ( args , char * ) ;
//sprintf( nm_text, "" ); // adb: ?
vsprintf ( nm_text , format , args ) ;
va_end ( args ) ;
Assert ( strlen ( nm_text ) < MESSAGEBOX_TEXT_SIZE ) ;
2010-06-23 11:44:12 +00:00
return newmenu_do_fixedfont ( title , nm_text , nchoices , nm_message_items , NULL , NULL , 0 , NULL ) ;
2006-03-20 17:12:09 +00:00
}
//end this section addition - Victor Rachels