2006-03-20 17:12:09 +00:00
|
|
|
|
/*
|
2014-06-01 17:55:23 +00:00
|
|
|
|
* Portions of this file are copyright Rebirth contributors and licensed as
|
|
|
|
|
* described in COPYING.txt.
|
|
|
|
|
* Portions of this file are copyright Parallax Software and licensed
|
|
|
|
|
* according to the Parallax license below.
|
|
|
|
|
* See COPYING.txt for license details.
|
|
|
|
|
|
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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
#pragma once
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2015-10-09 02:46:10 +00:00
|
|
|
|
#include "fwd-event.h"
|
2010-01-07 14:49:07 +00:00
|
|
|
|
|
2012-11-11 22:12:51 +00:00
|
|
|
|
#ifdef __cplusplus
|
2015-03-12 02:21:21 +00:00
|
|
|
|
#include <cstdint>
|
2013-12-04 22:38:04 +00:00
|
|
|
|
#include <algorithm>
|
2015-07-25 23:10:45 +00:00
|
|
|
|
#include <memory>
|
2016-07-31 22:25:50 +00:00
|
|
|
|
#include <stdexcept>
|
2015-10-09 02:46:11 +00:00
|
|
|
|
#include <tuple>
|
2016-07-31 22:25:50 +00:00
|
|
|
|
#include <type_traits>
|
2015-10-09 02:46:11 +00:00
|
|
|
|
#include <utility>
|
2015-12-11 03:39:40 +00:00
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include "fwd-window.h"
|
|
|
|
|
#endif
|
2013-12-04 22:38:04 +00:00
|
|
|
|
#include "varutil.h"
|
|
|
|
|
#include "dxxsconf.h"
|
2013-12-08 23:37:40 +00:00
|
|
|
|
#include "fmtcheck.h"
|
2015-03-12 02:21:21 +00:00
|
|
|
|
#include "ntstring.h"
|
2012-11-11 22:12:51 +00:00
|
|
|
|
|
2013-12-22 22:03:07 +00:00
|
|
|
|
struct newmenu;
|
|
|
|
|
struct listbox;
|
2010-01-07 14:49:07 +00:00
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
|
#define NM_TYPE_MENU 0 // A menu item... when enter is hit on this, newmenu_do returns this item number
|
|
|
|
|
#define NM_TYPE_INPUT 1 // An input box... fills the text field in, and you need to fill in text_len field.
|
|
|
|
|
#define NM_TYPE_CHECK 2 // A check box. Set and get its status by looking at flags field (1=on, 0=off)
|
|
|
|
|
#define NM_TYPE_RADIO 3 // Same as check box, but only 1 in a group can be set at a time. Set group fields.
|
|
|
|
|
#define NM_TYPE_TEXT 4 // A line of text that does nothing.
|
|
|
|
|
#define NM_TYPE_NUMBER 5 // A numeric entry counter. Changes value from min_value to max_value;
|
|
|
|
|
#define NM_TYPE_INPUT_MENU 6 // A inputbox that you hit Enter to edit, when done, hit enter and menu leaves.
|
|
|
|
|
#define NM_TYPE_SLIDER 7 // A slider from min_value to max_value. Draws with text_len chars.
|
|
|
|
|
|
2006-04-05 18:31:09 +00:00
|
|
|
|
#define NM_MAX_TEXT_LEN 255
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2016-07-31 22:25:50 +00:00
|
|
|
|
class newmenu_item
|
2013-12-22 22:03:07 +00:00
|
|
|
|
{
|
2016-07-31 22:25:50 +00:00
|
|
|
|
struct radio_specific_type
|
|
|
|
|
{
|
|
|
|
|
static constexpr std::integral_constant<unsigned, NM_TYPE_RADIO> nm_type{};
|
|
|
|
|
int group; // What group this belongs to for radio buttons.
|
|
|
|
|
};
|
2016-07-31 22:25:50 +00:00
|
|
|
|
struct number_slider_common_type
|
|
|
|
|
{
|
2016-07-31 22:25:50 +00:00
|
|
|
|
int min_value;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
int max_value;
|
|
|
|
|
};
|
|
|
|
|
struct number_specific_type : number_slider_common_type
|
|
|
|
|
{
|
|
|
|
|
static constexpr std::integral_constant<unsigned, NM_TYPE_NUMBER> nm_type{};
|
|
|
|
|
};
|
2016-07-31 22:25:50 +00:00
|
|
|
|
struct imenu_specific_type
|
|
|
|
|
{
|
|
|
|
|
static constexpr std::integral_constant<unsigned, NM_TYPE_INPUT_MENU> nm_type{};
|
|
|
|
|
int group;
|
|
|
|
|
};
|
2016-07-31 22:25:50 +00:00
|
|
|
|
struct slider_specific_type : number_slider_common_type
|
|
|
|
|
{
|
|
|
|
|
static constexpr std::integral_constant<unsigned, NM_TYPE_SLIDER> nm_type{};
|
|
|
|
|
};
|
2016-07-31 22:25:50 +00:00
|
|
|
|
template <typename T, unsigned expected_type = T::nm_type>
|
|
|
|
|
T &get_union_member(T &v)
|
|
|
|
|
{
|
|
|
|
|
#ifdef DXX_CONSTANT_TRUE
|
|
|
|
|
if (DXX_CONSTANT_TRUE(type != expected_type))
|
|
|
|
|
DXX_ALWAYS_ERROR_FUNCTION(dxx_newmenu_trap_invalid_type, "invalid type access");
|
|
|
|
|
#endif
|
|
|
|
|
if (type != expected_type)
|
|
|
|
|
throw std::runtime_error("invalid type access");
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
public:
|
2006-03-20 17:12:09 +00:00
|
|
|
|
int type; // What kind of item this is, see NM_TYPE_????? defines
|
|
|
|
|
int value; // For checkboxes and radio buttons, this is 1 if marked initially, else 0
|
2016-07-31 22:25:50 +00:00
|
|
|
|
union {
|
|
|
|
|
radio_specific_type nm_private_radio;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
number_specific_type nm_private_number;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
imenu_specific_type nm_private_imenu;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
slider_specific_type nm_private_slider;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
};
|
|
|
|
|
radio_specific_type &radio() {
|
|
|
|
|
return get_union_member(nm_private_radio);
|
|
|
|
|
}
|
2016-07-31 22:25:50 +00:00
|
|
|
|
number_specific_type &number() {
|
|
|
|
|
return get_union_member(nm_private_number);
|
|
|
|
|
}
|
2016-07-31 22:25:50 +00:00
|
|
|
|
imenu_specific_type &imenu() {
|
|
|
|
|
return get_union_member(nm_private_imenu);
|
|
|
|
|
}
|
2016-07-31 22:25:50 +00:00
|
|
|
|
slider_specific_type &slider() {
|
|
|
|
|
return get_union_member(nm_private_slider);
|
|
|
|
|
}
|
|
|
|
|
number_slider_common_type *number_or_slider() {
|
|
|
|
|
return (type == nm_private_number.nm_type || type == nm_private_slider.nm_type)
|
|
|
|
|
? &nm_private_number
|
|
|
|
|
: nullptr;
|
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
int text_len; // The maximum length of characters that can be entered by this inputboxes
|
|
|
|
|
char *text; // The text associated with this item.
|
|
|
|
|
// The rest of these are used internally by by the menu system, so don't set 'em!!
|
|
|
|
|
short x, y;
|
|
|
|
|
short w, h;
|
|
|
|
|
short right_offset;
|
2015-03-12 02:21:21 +00:00
|
|
|
|
ntstring<NM_MAX_TEXT_LEN> saved_text;
|
2013-12-22 22:03:07 +00:00
|
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2013-12-03 23:33:59 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
class newmenu_subfunction_t
|
|
|
|
|
{
|
|
|
|
|
public:
|
2014-10-04 21:47:13 +00:00
|
|
|
|
typedef int (*type)(newmenu *menu,const d_event &event, T *userdata);
|
2013-12-03 23:33:59 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef newmenu_subfunction_t<void>::type newmenu_subfunction;
|
|
|
|
|
|
2013-12-04 22:45:33 +00:00
|
|
|
|
class unused_newmenu_userdata_t;
|
2016-07-16 16:52:04 +00:00
|
|
|
|
constexpr newmenu_subfunction_t<const unused_newmenu_userdata_t>::type unused_newmenu_subfunction = nullptr;
|
|
|
|
|
constexpr const unused_newmenu_userdata_t *unused_newmenu_userdata = nullptr;
|
2013-12-04 22:45:33 +00:00
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
int newmenu_do2(const char *title, const char *subtitle, uint_fast32_t nitems, newmenu_item *item, newmenu_subfunction subfunction, void *userdata, int citem, const char *filename);
|
2014-07-16 00:01:18 +00:00
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
|
// Pass an array of newmenu_items and it processes the menu. It will
|
|
|
|
|
// return a -1 if Esc is pressed, otherwise, it returns the index of
|
|
|
|
|
// the item that was current when Enter was was selected.
|
2010-01-07 14:49:07 +00:00
|
|
|
|
// The subfunction function accepts standard events, plus additional
|
2010-01-30 03:24:19 +00:00
|
|
|
|
// NEWMENU events in future. Just pass NULL if you don't want this,
|
|
|
|
|
// or return 0 where you don't want to override the default behaviour.
|
2006-03-20 17:12:09 +00:00
|
|
|
|
// Title draws big, Subtitle draw medium sized. You can pass NULL for
|
|
|
|
|
// either/both of these if you don't want them.
|
2013-12-04 22:45:33 +00:00
|
|
|
|
// Same as above, only you can pass through what background bitmap to use.
|
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
int newmenu_do2(const char *title, const char *subtitle, uint_fast32_t nitems, newmenu_item *item, typename newmenu_subfunction_t<T>::type subfunction, T *userdata, int citem, const char *filename)
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
return newmenu_do2(title, subtitle, nitems, item, reinterpret_cast<newmenu_subfunction_t<void>::type>(subfunction), static_cast<void *>(userdata), citem, filename );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
int newmenu_do2(const char *title, const char *subtitle, uint_fast32_t nitems, newmenu_item *item, typename newmenu_subfunction_t<const T>::type subfunction, const T *userdata, int citem, const char *filename)
|
2015-02-05 03:03:49 +00:00
|
|
|
|
{
|
|
|
|
|
return newmenu_do2(title, subtitle, nitems, item, reinterpret_cast<newmenu_subfunction_t<void>::type>(subfunction), static_cast<void *>(const_cast<T *>(userdata)), citem, filename );
|
2013-12-04 22:45:33 +00:00
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2013-12-04 22:45:33 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static inline int newmenu_do( const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, typename newmenu_subfunction_t<T>::type subfunction, T *userdata )
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
|
|
|
|
return newmenu_do2( title, subtitle, nitems, item, subfunction, userdata, 0, NULL );
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:32 +00:00
|
|
|
|
template <std::size_t N, typename T>
|
|
|
|
|
static inline int newmenu_do(const char *title, const char *subtitle, array<newmenu_item, N> &items, typename newmenu_subfunction_t<T>::type subfunction, T *userdata)
|
|
|
|
|
{
|
|
|
|
|
return newmenu_do(title, subtitle, items.size(), &items.front(), subfunction, userdata);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-04 22:45:33 +00:00
|
|
|
|
// Same as above, only you can pass through what item is initially selected.
|
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static inline int newmenu_do1( const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, typename newmenu_subfunction_t<T>::type subfunction, T *userdata, int citem )
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
|
|
|
|
return newmenu_do2( title, subtitle, nitems, item, subfunction, userdata, citem, NULL );
|
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
newmenu *newmenu_do4( const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, newmenu_subfunction subfunction, void *userdata, int citem, const char * filename, int TinyMode, int TabsFlag );
|
2014-07-16 00:01:18 +00:00
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static inline newmenu *newmenu_do3( const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, newmenu_subfunction subfunction, void *userdata, int citem, const char * filename )
|
2014-07-16 00:01:18 +00:00
|
|
|
|
{
|
|
|
|
|
return newmenu_do4( title, subtitle, nitems, item, subfunction, userdata, citem, filename, 0, 0 );
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-21 00:20:26 +00:00
|
|
|
|
// Same as above, but returns menu instead of citem
|
2013-12-04 22:45:33 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static newmenu *newmenu_do3(const char *title, const char *subtitle, uint_fast32_t nitems, newmenu_item *item, typename newmenu_subfunction_t<T>::type subfunction, T *userdata, int citem, const char *filename)
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
return newmenu_do3(title, subtitle, nitems, item, reinterpret_cast<newmenu_subfunction_t<void>::type>(subfunction), static_cast<void *>(userdata), citem, filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static newmenu *newmenu_do3(const char *title, const char *subtitle, uint_fast32_t nitems, newmenu_item *item, typename newmenu_subfunction_t<const T>::type subfunction, const T *userdata, int citem, const char *filename)
|
2015-02-05 03:03:49 +00:00
|
|
|
|
{
|
|
|
|
|
return newmenu_do3(title, subtitle, nitems, item, reinterpret_cast<newmenu_subfunction_t<void>::type>(subfunction), static_cast<void *>(const_cast<T *>(userdata)), citem, filename);
|
2013-12-04 22:45:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static inline newmenu *newmenu_dotiny( const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, int TabsFlag, newmenu_subfunction subfunction, void *userdata )
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
2014-07-16 00:01:18 +00:00
|
|
|
|
return newmenu_do4( title, subtitle, nitems, item, subfunction, userdata, 0, NULL, 1, TabsFlag );
|
2013-12-04 22:45:33 +00:00
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2009-07-01 11:35:33 +00:00
|
|
|
|
// Tiny menu with GAME_FONT
|
2013-12-04 22:45:33 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
static newmenu *newmenu_dotiny(const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item * item, int TabsFlag, typename newmenu_subfunction_t<T>::type subfunction, T *userdata)
|
2013-12-04 22:45:33 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
return newmenu_dotiny(title, subtitle, nitems, item, TabsFlag, reinterpret_cast<newmenu_subfunction_t<void>::type>(subfunction), static_cast<void *>(userdata));
|
2013-12-04 22:45:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-21 00:20:26 +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...
|
2015-03-12 02:21:21 +00:00
|
|
|
|
void newmenu_doreorder(const char * title, const char * subtitle, uint_fast32_t nitems, newmenu_item *item);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
|
|
// Sample Code:
|
|
|
|
|
/*
|
|
|
|
|
{
|
|
|
|
|
int mmn;
|
|
|
|
|
newmenu_item mm[8];
|
|
|
|
|
char xtext[21];
|
|
|
|
|
|
|
|
|
|
strcpy( xtext, "John" );
|
|
|
|
|
|
|
|
|
|
mm[0].type=NM_TYPE_MENU; mm[0].text="Play game";
|
|
|
|
|
mm[1].type=NM_TYPE_INPUT; mm[1].text=xtext; mm[1].text_len=20;
|
|
|
|
|
mm[2].type=NM_TYPE_CHECK; mm[2].value=0; mm[2].text="check box";
|
|
|
|
|
mm[3].type=NM_TYPE_TEXT; mm[3].text="-pickone-";
|
|
|
|
|
mm[4].type=NM_TYPE_RADIO; mm[4].value=1; mm[4].group=0; mm[4].text="Radio #1";
|
|
|
|
|
mm[5].type=NM_TYPE_RADIO; mm[5].value=1; mm[5].group=0; mm[5].text="Radio #2";
|
|
|
|
|
mm[6].type=NM_TYPE_RADIO; mm[6].value=1; mm[6].group=0; mm[6].text="Radio #3";
|
|
|
|
|
mm[7].type=NM_TYPE_PERCENT; mm[7].value=50; mm[7].text="Volume";
|
|
|
|
|
|
|
|
|
|
mmn = newmenu_do("Descent", "Sample Menu", 8, mm, NULL );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// This function pops up a messagebox and returns which choice was selected...
|
|
|
|
|
// Example:
|
|
|
|
|
// nm_messagebox( "Title", "Subtitle", 2, "Ok", "Cancel", "There are %d objects", nobjects );
|
|
|
|
|
// Returns 0 through nchoices-1.
|
2013-12-04 22:38:04 +00:00
|
|
|
|
//int nm_messagebox(const char *title, int nchoices, ...);
|
|
|
|
|
#define nm_messagebox(T,N,...) nm_messagebox_a##N((T), ##__VA_ARGS__)
|
|
|
|
|
#define nm_messagebox_a1(T,A1 ,F,...) vnm_messagebox_aN(T,nm_messagebox_tie(A1 ),F,##__VA_ARGS__)
|
|
|
|
|
#define nm_messagebox_a2(T,A1,A2 ,F,...) vnm_messagebox_aN(T,nm_messagebox_tie(A1,A2 ),F,##__VA_ARGS__)
|
|
|
|
|
#define nm_messagebox_a3(T,A1,A2,A3 ,F,...) vnm_messagebox_aN(T,nm_messagebox_tie(A1,A2,A3 ),F,##__VA_ARGS__)
|
|
|
|
|
#define nm_messagebox_a4(T,A1,A2,A3,A4 ,F,...) vnm_messagebox_aN(T,nm_messagebox_tie(A1,A2,A3,A4 ),F,##__VA_ARGS__)
|
|
|
|
|
#define nm_messagebox_a5(T,A1,A2,A3,A4,A5 ,F,...) vnm_messagebox_aN(T,nm_messagebox_tie(A1,A2,A3,A4,A5),F,##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
typedef cstring_tie<5> nm_messagebox_tie;
|
|
|
|
|
|
|
|
|
|
int nm_messagebox_str(const char *title, const nm_messagebox_tie &tie, const char *str) __attribute_nonnull((3));
|
|
|
|
|
int vnm_messagebox_aN(const char *title, const nm_messagebox_tie &tie, const char *format, ...) __attribute_format_printf(3, 4);
|
2013-12-08 23:37:40 +00:00
|
|
|
|
#define vnm_messagebox_aN(A1,A2,F,...) dxx_call_printf_checked(vnm_messagebox_aN,nm_messagebox_str,(A1,A2),(F),##__VA_ARGS__)
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2010-01-07 14:49:07 +00:00
|
|
|
|
newmenu_item *newmenu_get_items(newmenu *menu);
|
|
|
|
|
int newmenu_get_nitems(newmenu *menu);
|
|
|
|
|
int newmenu_get_citem(newmenu *menu);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
void nm_draw_background(int x1, int y1, int x2, int y2);
|
|
|
|
|
void nm_restore_background(int x, int y, int w, int h);
|
|
|
|
|
|
2012-07-22 23:17:54 +00:00
|
|
|
|
extern const char *Newmenu_allowed_chars;
|
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;
|
|
|
|
|
//
|
|
|
|
|
// if ( *keypress = KEY_CTRLED+KEY_D ) {
|
|
|
|
|
// if ( *nitems > 1 ) {
|
|
|
|
|
// unlink( items[*citem] ); // Delete the file
|
|
|
|
|
// for (i=*citem; i<*nitems-1; i++ ) {
|
|
|
|
|
// items[i] = items[i+1];
|
|
|
|
|
// }
|
|
|
|
|
// *nitems = *nitems - 1;
|
|
|
|
|
// free( items[*nitems] );
|
|
|
|
|
// items[*nitems] = NULL;
|
|
|
|
|
// return 1; // redraw;
|
|
|
|
|
// }
|
|
|
|
|
// *keypress = 0;
|
|
|
|
|
// }
|
|
|
|
|
// return 0;
|
|
|
|
|
// }
|
|
|
|
|
|
2013-09-02 23:21:13 +00:00
|
|
|
|
extern const char **listbox_get_items(listbox *lb);
|
2010-01-07 14:49:07 +00:00
|
|
|
|
extern int listbox_get_citem(listbox *lb);
|
2015-12-04 03:36:31 +00:00
|
|
|
|
#ifdef _WIN32
|
2015-12-11 03:39:40 +00:00
|
|
|
|
window *listbox_get_window(listbox *lb);
|
2015-12-04 03:36:31 +00:00
|
|
|
|
#endif
|
2010-01-07 14:49:07 +00:00
|
|
|
|
extern void listbox_delete_item(listbox *lb, int item);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2013-12-04 23:07:07 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
class listbox_subfunction_t
|
|
|
|
|
{
|
|
|
|
|
public:
|
2014-10-04 21:47:13 +00:00
|
|
|
|
typedef int (*type)(listbox *menu,const d_event &event, T *userdata);
|
2013-12-04 23:07:07 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class unused_listbox_userdata_t;
|
|
|
|
|
static listbox_subfunction_t<unused_listbox_userdata_t>::type *const unused_listbox_subfunction = NULL;
|
|
|
|
|
static unused_listbox_userdata_t *const unused_listbox_userdata = NULL;
|
|
|
|
|
|
2015-03-12 02:21:21 +00:00
|
|
|
|
listbox *newmenu_listbox1( const char * title, uint_fast32_t nitems, const char *items[], int allow_abort_flag, int default_item, listbox_subfunction_t<void>::type listbox_callback, void *userdata );
|
2014-07-16 00:01:18 +00:00
|
|
|
|
|
2013-12-04 23:07:07 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
listbox *newmenu_listbox1(const char *title, uint_fast32_t nitems, const char *items[], int allow_abort_flag, int default_item, typename listbox_subfunction_t<T>::type listbox_callback, T *userdata)
|
2013-12-04 23:07:07 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
return newmenu_listbox1(title, nitems, items, allow_abort_flag, default_item, reinterpret_cast<listbox_subfunction_t<void>::type>(listbox_callback), static_cast<void *>(userdata));
|
2013-12-04 23:07:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-22 04:35:47 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
listbox *newmenu_listbox1(const char *title, uint_fast32_t nitems, const char *items[], int allow_abort_flag, int default_item, typename listbox_subfunction_t<T>::type listbox_callback, std::unique_ptr<T> userdata)
|
2014-12-22 04:35:47 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
auto r = newmenu_listbox1(title, nitems, items, allow_abort_flag, default_item, reinterpret_cast<listbox_subfunction_t<void>::type>(listbox_callback), static_cast<void *>(userdata.get()));
|
2014-12-22 04:35:47 +00:00
|
|
|
|
userdata.release();
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-04 23:07:07 +00:00
|
|
|
|
template <typename T>
|
2015-03-12 02:21:21 +00:00
|
|
|
|
listbox *newmenu_listbox(const char *title, uint_fast32_t nitems, const char *items[], int allow_abort_flag, typename listbox_subfunction_t<T>::type listbox_callback, T *userdata)
|
2013-12-04 23:07:07 +00:00
|
|
|
|
{
|
2015-02-05 03:03:49 +00:00
|
|
|
|
return newmenu_listbox1(title, nitems, items, allow_abort_flag, 0, reinterpret_cast<listbox_subfunction_t<void>::type>(listbox_callback), static_cast<void *>(userdata));
|
2013-12-04 23:07:07 +00:00
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
|
|
//should be called whenever the palette changes
|
2010-07-31 12:09:38 +00:00
|
|
|
|
extern void newmenu_free_background();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
2015-01-18 01:58:31 +00:00
|
|
|
|
static inline void nm_set_item_menu(newmenu_item &ni, const char *text)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.type = NM_TYPE_MENU;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
__attribute_warn_unused_result
|
|
|
|
|
static inline newmenu_item nm_item_menu(const char *text)
|
|
|
|
|
{
|
|
|
|
|
newmenu_item i;
|
|
|
|
|
return nm_set_item_menu(i, text), i;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:31 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_input(newmenu_item &ni, unsigned len, char *text)
|
|
|
|
|
{
|
|
|
|
|
ni.type = NM_TYPE_INPUT;
|
|
|
|
|
ni.text = text;
|
2016-05-30 12:54:51 +00:00
|
|
|
|
ni.text_len = len-1;
|
2015-01-18 01:58:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <std::size_t len>
|
|
|
|
|
static inline void nm_set_item_input(newmenu_item &ni, char (&text)[len])
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_input(ni, len, text);
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-22 04:35:47 +00:00
|
|
|
|
template <std::size_t len>
|
|
|
|
|
static inline void nm_set_item_input(newmenu_item &ni, array<char, len> &text)
|
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_input(ni, len, text.data());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename... T>
|
|
|
|
|
__attribute_warn_unused_result
|
|
|
|
|
static inline newmenu_item nm_item_input(T &&... t)
|
|
|
|
|
{
|
|
|
|
|
newmenu_item i;
|
|
|
|
|
return nm_set_item_input(i, std::forward<T>(t)...), i;
|
2014-12-22 04:35:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:31 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_checkbox(newmenu_item &ni, const char *text, unsigned checked)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.type = NM_TYPE_CHECK;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.value = checked;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:31 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_text(newmenu_item &ni, const char *text)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.type = NM_TYPE_TEXT;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
__attribute_warn_unused_result
|
|
|
|
|
static inline newmenu_item nm_item_text(const char *text)
|
|
|
|
|
{
|
|
|
|
|
newmenu_item i;
|
|
|
|
|
return nm_set_item_text(i, text), i;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:31 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_radio(newmenu_item &ni, const char *text, unsigned checked, unsigned grp)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.type = NM_TYPE_RADIO;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:31 +00:00
|
|
|
|
ni.value = checked;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
auto &radio = ni.radio();
|
|
|
|
|
radio.group = grp;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:32 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_number(newmenu_item &ni, const char *text, unsigned now, unsigned low, unsigned high)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:32 +00:00
|
|
|
|
ni.type = NM_TYPE_NUMBER;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:32 +00:00
|
|
|
|
ni.value = now;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
auto &number = ni.number();
|
2016-07-31 22:25:50 +00:00
|
|
|
|
number.min_value = low;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
number.max_value = high;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-18 01:58:32 +00:00
|
|
|
|
__attribute_nonnull()
|
|
|
|
|
static inline void nm_set_item_slider(newmenu_item &ni, const char *text, unsigned now, unsigned low, unsigned high)
|
2012-11-24 20:57:15 +00:00
|
|
|
|
{
|
2015-01-18 01:58:32 +00:00
|
|
|
|
ni.type = NM_TYPE_SLIDER;
|
2015-02-05 03:03:49 +00:00
|
|
|
|
ni.text = const_cast<char *>(text);
|
2015-01-18 01:58:32 +00:00
|
|
|
|
ni.value = now;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
auto &slider = ni.slider();
|
2016-07-31 22:25:50 +00:00
|
|
|
|
slider.min_value = low;
|
2016-07-31 22:25:50 +00:00
|
|
|
|
slider.max_value = high;
|
2012-11-24 20:57:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 11:01:36 +00:00
|
|
|
|
#define NEWMENU_MOUSE
|
2007-05-14 13:38:44 +00:00
|
|
|
|
|
2011-02-10 13:09:10 +00:00
|
|
|
|
// #define NORMAL_CHECK_BOX "<22>"
|
|
|
|
|
// #define CHECKED_CHECK_BOX "<22>"
|
|
|
|
|
//
|
|
|
|
|
// #define NORMAL_RADIO_BOX ""
|
|
|
|
|
// #define CHECKED_RADIO_BOX "<22>"
|
|
|
|
|
// #define CURSOR_STRING "_"
|
|
|
|
|
// #define SLIDER_LEFT "<22>" // 131
|
|
|
|
|
// #define SLIDER_RIGHT "<22>" // 132
|
|
|
|
|
// #define SLIDER_MIDDLE "<22>" // 133
|
|
|
|
|
// #define SLIDER_MARKER "<22>" // 134
|
|
|
|
|
// #define UP_ARROW_MARKER "<22>" // 135
|
|
|
|
|
// #define DOWN_ARROW_MARKER "<22>" // 136
|
|
|
|
|
#define NORMAL_CHECK_BOX "\201"
|
|
|
|
|
#define CHECKED_CHECK_BOX "\202"
|
|
|
|
|
|
|
|
|
|
#define NORMAL_RADIO_BOX "\177"
|
|
|
|
|
#define CHECKED_RADIO_BOX "\200"
|
2006-08-18 09:47:07 +00:00
|
|
|
|
#define CURSOR_STRING "_"
|
2011-02-10 13:09:10 +00:00
|
|
|
|
#define SLIDER_LEFT "\203" // 131
|
|
|
|
|
#define SLIDER_RIGHT "\204" // 132
|
|
|
|
|
#define SLIDER_MIDDLE "\205" // 133
|
|
|
|
|
#define SLIDER_MARKER "\206" // 134
|
2013-03-03 01:03:33 +00:00
|
|
|
|
#if defined(DXX_BUILD_DESCENT_I)
|
|
|
|
|
#define UP_ARROW_MARKER "+" // 135
|
|
|
|
|
#define DOWN_ARROW_MARKER "+" // 136
|
|
|
|
|
#elif defined(DXX_BUILD_DESCENT_II)
|
2014-07-20 03:48:27 +00:00
|
|
|
|
#define UP_ARROW_MARKER ((grd_curcanv->cv_font==GAME_FONT.get())?"\202":"\207") // 135
|
|
|
|
|
#define DOWN_ARROW_MARKER ((grd_curcanv->cv_font==GAME_FONT.get())?"\200":"\210") // 136
|
2013-03-03 01:03:33 +00:00
|
|
|
|
#endif
|
2008-02-24 14:41:27 +00:00
|
|
|
|
|
|
|
|
|
#define BORDERX (15*(SWIDTH/320))
|
|
|
|
|
#define BORDERY (15*(SHEIGHT/200))
|
|
|
|
|
|
2013-08-17 15:21:44 +00:00
|
|
|
|
#define DXX_NEWMENU_VARIABLE m
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM(VERB, TYPE, ...) DXX_MENUITEM_V_##VERB(TYPE, ## __VA_ARGS__)
|
|
|
|
|
#define DXX_MENUITEM_V_ENUM(TYPE,S,OPT,...) OPT,
|
|
|
|
|
#define DXX_MENUITEM_V_COUNT(TYPE,...) +1
|
|
|
|
|
#define DXX_MENUITEM_V_ADD(TYPE,S,OPT,...) DXX_MENUITEM_V_ADD_T_##TYPE(S, OPT, ## __VA_ARGS__)
|
|
|
|
|
#define DXX_MENUITEM_V_READ(TYPE,S,OPT,...) DXX_MENUITEM_V_READ_T_##TYPE(S, OPT, ## __VA_ARGS__)
|
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_CHECK(S,OPT,V) \
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_checkbox(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S), (V));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_RADIO(S,OPT,C,G) \
|
2015-03-07 17:20:41 +00:00
|
|
|
|
nm_set_item_radio(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S), (C), (G));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_NUMBER(S,OPT,V,MIN,MAX) \
|
2015-03-28 17:18:02 +00:00
|
|
|
|
nm_set_item_number(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S), (V), (MIN), (MAX));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_SLIDER(S,OPT,V,MIN,MAX) \
|
2015-01-18 01:58:32 +00:00
|
|
|
|
nm_set_item_slider(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S), (V), (MIN), (MAX));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_SCALE_SLIDER(S,OPT,V,MIN,MAX,SCALE) \
|
|
|
|
|
DXX_MENUITEM_V_ADD_T_SLIDER((S),(OPT),(V) / (SCALE),(MIN),(MAX))
|
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_MENU(S,OPT) \
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_menu(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_TEXT(S,OPT) \
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_text(((DXX_NEWMENU_VARIABLE)[(OPT)]), (S));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_ADD_T_INPUT(S,OPT) \
|
2015-01-18 01:58:31 +00:00
|
|
|
|
nm_set_item_input(((DXX_NEWMENU_VARIABLE)[(OPT)]),(S));
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_READ_T_CHECK(S,OPT,V) \
|
2015-03-28 17:18:02 +00:00
|
|
|
|
(V) = (DXX_NEWMENU_VARIABLE)[(OPT)].value;
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_READ_T_RADIO(S,OPT,C,G) /* handled specially */
|
|
|
|
|
#define DXX_MENUITEM_V_READ_T_NUMBER(S,OPT,V,MIN,MAX) \
|
2015-03-28 17:18:02 +00:00
|
|
|
|
(V) = (DXX_NEWMENU_VARIABLE)[(OPT)].value;
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_READ_T_SLIDER(S,OPT,V,MIN,MAX) \
|
2015-03-28 17:18:02 +00:00
|
|
|
|
(V) = (DXX_NEWMENU_VARIABLE)[(OPT)].value;
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_READ_T_SCALE_SLIDER(S,OPT,V,MIN,MAX,SCALE) \
|
2015-03-28 17:18:02 +00:00
|
|
|
|
(V) = (DXX_NEWMENU_VARIABLE)[(OPT)].value * (SCALE);
|
2016-01-09 16:38:17 +00:00
|
|
|
|
#define DXX_MENUITEM_V_READ_T_MENU(S,OPT) /* handled specially */
|
|
|
|
|
#define DXX_MENUITEM_V_READ_T_TEXT(S,OPT) /* handled specially */
|
|
|
|
|
#define DXX_MENUITEM_V_READ_T_INPUT(S,OPT) /* handled specially */
|
2013-08-17 15:21:44 +00:00
|
|
|
|
|
2015-03-28 17:18:02 +00:00
|
|
|
|
template <typename T, typename B>
|
|
|
|
|
class menu_bit_wrapper_t
|
|
|
|
|
{
|
2015-10-09 02:46:11 +00:00
|
|
|
|
using M = decltype(std::declval<const T &>() & std::declval<B>());
|
|
|
|
|
std::tuple<T &, B> m_data;
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
m_mask = 0,
|
|
|
|
|
m_bit = 1,
|
|
|
|
|
};
|
|
|
|
|
T &get_mask()
|
|
|
|
|
{
|
|
|
|
|
return std::get<m_mask>(m_data);
|
|
|
|
|
}
|
|
|
|
|
const T &get_mask() const
|
|
|
|
|
{
|
|
|
|
|
return std::get<m_mask>(m_data);
|
|
|
|
|
}
|
|
|
|
|
B get_bit() const
|
|
|
|
|
{
|
|
|
|
|
return std::get<m_bit>(m_data);
|
|
|
|
|
}
|
2015-03-28 17:18:02 +00:00
|
|
|
|
public:
|
|
|
|
|
constexpr menu_bit_wrapper_t(T &t, B bit) :
|
2015-10-09 02:46:11 +00:00
|
|
|
|
m_data(t, bit)
|
2015-03-28 17:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2015-10-09 02:46:11 +00:00
|
|
|
|
constexpr operator M() const
|
2015-03-28 17:18:02 +00:00
|
|
|
|
{
|
2015-10-09 02:46:11 +00:00
|
|
|
|
return get_mask() & get_bit();
|
2015-03-28 17:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
menu_bit_wrapper_t &operator=(bool n)
|
|
|
|
|
{
|
|
|
|
|
if (n)
|
2015-10-09 02:46:11 +00:00
|
|
|
|
get_mask() |= get_bit();
|
2015-03-28 17:18:02 +00:00
|
|
|
|
else
|
2015-10-09 02:46:11 +00:00
|
|
|
|
get_mask() &= ~get_bit();
|
2015-03-28 17:18:02 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T, typename B>
|
|
|
|
|
static constexpr menu_bit_wrapper_t<T, B> menu_bit_wrapper(T &t, B b)
|
|
|
|
|
{
|
|
|
|
|
return {t, b};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T, typename B>
|
|
|
|
|
class menu_number_bias_wrapper_t
|
|
|
|
|
{
|
|
|
|
|
T &m_value;
|
|
|
|
|
B m_bias;
|
|
|
|
|
public:
|
|
|
|
|
constexpr menu_number_bias_wrapper_t(T &t, B bias) :
|
|
|
|
|
m_value(t), m_bias(bias)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
constexpr operator T() const
|
|
|
|
|
{
|
|
|
|
|
return m_value + m_bias;
|
|
|
|
|
}
|
|
|
|
|
menu_number_bias_wrapper_t &operator=(T n)
|
|
|
|
|
{
|
|
|
|
|
m_value = n - m_bias;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T, typename B>
|
|
|
|
|
static constexpr menu_number_bias_wrapper_t<T, B> menu_number_bias_wrapper(T &t, B b)
|
|
|
|
|
{
|
|
|
|
|
return {t, b};
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-11 22:12:51 +00:00
|
|
|
|
#endif
|