Allow longer mission titles in New Game dialog

This commit is contained in:
Kp 2018-06-27 03:34:34 +00:00
parent d1a4e3b7a1
commit 60a99f1ea2
5 changed files with 66 additions and 14 deletions

View file

@ -282,6 +282,7 @@ void gr_printt(grs_canvas &, const grs_font &, int x, int y, const char *format,
#define gr_uprintf(A1,A2,A3,A4,F,...) dxx_call_printf_checked(gr_printfus,gr_ustring,(A1,A2,A3,A4),(F),##__VA_ARGS__)
std::pair<const char *, unsigned> gr_get_string_wrap(const grs_font &, const char *s, unsigned limit);
void gr_get_string_size(const grs_font &, const char *s, int *string_width, int *string_height, int *average_width);
void gr_get_string_size(const grs_font &, const char *s, int *string_width, int *string_height, int *average_width, const unsigned max_chars_per_line);
// From scale.c
void scale_bitmap(const grs_bitmap &bp, const array<grs_point, 3> &vertbuf, int orientation, grs_bitmap &);

View file

@ -55,8 +55,6 @@ public:
{
return copy_if(out_offset, static_cast<I &&>(i), this->size());
}
template <std::size_t N>
void copy_if(std::size_t, const ntstring<N> &, std::size_t = 0) = delete;
template <std::size_t N>
std::size_t copy_if(std::size_t out_offset, const array<char, N> &i, std::size_t n = N)
{

View file

@ -769,6 +769,11 @@ void gr_ustring(grs_canvas &canvas, const grs_font &cv_font, const int x, const
}
void gr_get_string_size(const grs_font &cv_font, const char *s, int *const string_width, int *const string_height, int *const average_width)
{
gr_get_string_size(cv_font, s, string_width, string_height, average_width, UINT_MAX);
}
void gr_get_string_size(const grs_font &cv_font, const char *s, int *const string_width, int *const string_height, int *const average_width, const unsigned max_chars_per_line)
{
float longest_width=0.0,string_width_f=0.0;
unsigned lines = 0;
@ -778,6 +783,7 @@ void gr_get_string_size(const grs_font &cv_font, const char *s, int *const strin
return;
if (s)
{
unsigned remaining_chars_this_line = max_chars_per_line;
while (*s)
{
if (*s == '\n')
@ -792,12 +798,15 @@ void gr_get_string_size(const grs_font &cv_font, const char *s, int *const strin
lines += s - os;
if (!*s)
break;
remaining_chars_this_line = max_chars_per_line;
}
const auto &result = get_char_width<float>(cv_font, s[0], s[1]);
const auto &spacing = result.spacing;
string_width_f += spacing;
s++;
if (!--remaining_chars_this_line)
break;
}
}
if (string_width)

View file

@ -79,7 +79,7 @@ using mission_candidate_search_path = array<char, PATH_MAX>;
struct mle : Mission_path
{
int builtin_hogsize; // if it's the built-in mission, used for determining the version
ntstring<MISSION_NAME_LEN> mission_name;
ntstring<75> mission_name;
#if defined(DXX_BUILD_DESCENT_II)
descent_version_type descent_version; // descent 1 or descent 2?
#endif
@ -326,7 +326,7 @@ static char *get_value(char *buf)
}
//reads a line, returns ptr to value of passed parm. returns NULL if none
static char *get_parm_value(PHYSFSX_gets_line_t<80> &buf, const char *parm,PHYSFS_File *f)
static char *get_parm_value(PHYSFSX_gets_line_t<80> &buf, const char *const parm, PHYSFS_File *const f)
{
if (!PHYSFSX_fgets(buf,f))
return NULL;
@ -740,7 +740,7 @@ static int load_mission(const mle *mission)
#endif
Current_mission = make_unique<Mission>();
Current_mission->builtin_hogsize = mission->builtin_hogsize;
Current_mission->mission_name = mission->mission_name;
Current_mission->mission_name.copy_if(mission->mission_name);
#if defined(DXX_BUILD_DESCENT_II)
Current_mission->descent_version = mission->descent_version;
#endif

View file

@ -1912,12 +1912,59 @@ static void listbox_create_structure( listbox *lb)
lb->box_w = 0;
const auto &&fspacx = FSPACX();
range_for (auto &i, unchecked_partial_range(lb->item, lb->nitems))
const auto &&fspacx10 = fspacx(10);
const unsigned max_box_width = SWIDTH - (BORDERX * 2);
unsigned marquee_maxchars = UINT_MAX;
range_for (const auto i, unchecked_partial_range(lb->item, lb->nitems))
{
int w;
gr_get_string_size(medium3_font, i, &w, nullptr, nullptr);
if ( w > lb->box_w )
lb->box_w = w + fspacx(10);
w += fspacx10;
if (w > max_box_width)
{
unsigned mmc = 1;
for (;; ++mmc)
{
int w2;
gr_get_string_size(medium3_font, i, &w2, nullptr, nullptr, mmc);
if (w2 > max_box_width)
break;
}
/* mmc is now the shortest initial subsequence that is wider
* than max_box_width.
*
* Next, search for whether any internal subsequences of
* lesser length are also too wide. This can happen if all
* the initial characters are narrow, then characters
* outside the initial subsequence are wide.
*/
for (auto j = i;;)
{
int w2;
gr_get_string_size(medium3_font, j, &w2, nullptr, nullptr, mmc);
if (w2 > max_box_width)
{
/* This subsequence is too long. Reduce the length
* and retry.
*/
if (!--mmc)
break;
}
else
{
/* This subsequence fits. Move to the next
* character.
*/
if (!*++j)
break;
}
}
w = max_box_width;
if (marquee_maxchars > mmc)
marquee_maxchars = mmc;
}
if (lb->box_w < w)
lb->box_w = w;
}
{
@ -1929,13 +1976,10 @@ static void listbox_create_structure( listbox *lb)
}
// 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)
if (marquee_maxchars != UINT_MAX)
{
int w;
const auto box_w = lb->box_w = SWIDTH - (BORDERX*2);
gr_get_string_size(medium3_font, "O", &w, nullptr, nullptr);
lb->marquee = listbox::marquee::allocate(box_w / w);
lb->box_w = max_box_width;
lb->marquee = listbox::marquee::allocate(marquee_maxchars);
lb->marquee->lasttime = timer_query();
}