@ -99,6 +99,62 @@ const char *const TownerNames[] = {
N_ ( " Wirt " ) ,
} ;
constexpr int PaddingTop = 32 ;
// For most languages, line height is always 12.
// This includes blank lines and divider line.
constexpr int SmallLineHeight = 12 ;
constexpr int SmallTextHeight = 12 ;
// For larger small fonts (Chinese and Japanese), text lines are
// taller and overflow.
// We space out blank lines a bit more to give space to 3-line store items.
constexpr int LargeLineHeight = SmallLineHeight + 1 ;
constexpr int LargeTextHeight = 18 ;
/**
* The line index with the Back / Leave button .
* This is a special button that is always the last line .
*
* For lists with a scrollbar , it is not selectable ( mouse - only ) .
*/
int BackButtonLine ( )
{
if ( IsSmallFontTall ( ) ) {
return stextscrl ? 21 : 20 ;
}
return 22 ;
}
int LineHeight ( )
{
return IsSmallFontTall ( ) ? LargeLineHeight : SmallLineHeight ;
}
int TextHeight ( )
{
return IsSmallFontTall ( ) ? LargeTextHeight : SmallTextHeight ;
}
void CalculateLineHeights ( )
{
stext [ 0 ] . y = 0 ;
if ( IsSmallFontTall ( ) ) {
for ( int i = 1 ; i < STORE_LINES ; + + i ) {
// Space out consecutive text lines, unless they are both selectable (never the case currently).
if ( stext [ i ] . IsText ( ) & & stext [ i - 1 ] . IsText ( ) & & ! ( stext [ i ] . _ssel & & stext [ i - 1 ] . _ssel ) ) {
stext [ i ] . y = stext [ i - 1 ] . y + LargeTextHeight ;
} else {
stext [ i ] . y = i * LargeLineHeight ;
}
}
} else {
for ( int i = 1 ; i < STORE_LINES ; + + i ) {
stext [ i ] . y = i * SmallLineHeight ;
}
}
}
void DrawSTextBack ( const Surface & out )
{
CelDrawTo ( out , { PANEL_X + 320 + 24 , 327 + UI_OFFSET_Y } , * pSTextBoxCels , 1 ) ;
@ -122,7 +178,7 @@ void DrawSSlider(const Surface &out, int y1, int y2)
for ( ; yd3 < yd2 ; yd3 + = 12 ) {
CelDrawTo ( out , { PANEL_X + 601 , yd3 } , * pSTextSlidCels , 14 ) ;
}
if ( stextsel = = 22 )
if ( stextsel = = BackButtonLine ( ) )
yd3 = stextlhold ;
else
yd3 = stextsel ;
@ -146,11 +202,6 @@ void AddSTextVal(int y, int val)
stext [ y ] . _sval = val ;
}
void OffsetSTextY ( int y , int yo )
{
stext [ y ] . _syoff = yo ;
}
void AddSText ( int x , int y , const char * str , UiFlags flags , bool sel )
{
stext [ y ] . _sx = x ;
@ -161,6 +212,26 @@ void AddSText(int x, int y, const char *str, UiFlags flags, bool sel)
stext [ y ] . _ssel = sel ;
}
void AddOptionsBackButton ( )
{
const int line = BackButtonLine ( ) ;
AddSText ( 0 , line , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
stext [ line ] . _syoff = IsSmallFontTall ( ) ? 0 : 6 ;
}
void AddItemListBackButton ( bool selectable = false )
{
const int line = BackButtonLine ( ) ;
const char * text = _ ( " Back " ) ;
if ( ! selectable & & IsSmallFontTall ( ) ) {
AddSText ( 0 , line , text , UiFlags : : ColorWhite | UiFlags : : AlignRight , selectable ) ;
} else {
AddSLine ( line - 1 ) ;
AddSText ( 0 , line , text , UiFlags : : ColorWhite | UiFlags : : AlignCenter , selectable ) ;
stext [ line ] . _syoff = 6 ;
}
}
void PrintStoreItem ( Item * x , int l , UiFlags flags )
{
char sstr [ 128 ] ;
@ -275,7 +346,7 @@ void ScrollSmithBuy(int idx)
}
}
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = 22 )
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = BackButtonLine ( ) )
stextsel = stextdown ;
}
@ -290,10 +361,8 @@ void StartSmithBuy()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithBuy ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
storenumh = 0 ;
for ( int i = 0 ; ! smithitem [ i ] . isEmpty ( ) ; i + + ) {
@ -326,7 +395,7 @@ void ScrollSmithPremiumBuy(int boughtitems)
}
idx + + ;
}
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = 22 )
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = BackButtonLine ( ) )
stextsel = stextdown ;
}
@ -352,9 +421,7 @@ bool StartSmithPremiumBuy()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
stextsmax = std : : max ( storenumh - 4 , 0 ) ;
@ -475,9 +542,7 @@ void StartSmithSell()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( /*selectable=*/ true ) ;
return ;
}
@ -490,10 +555,8 @@ void StartSmithSell()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithSell ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
}
bool SmithRepairOk ( int i )
@ -565,9 +628,7 @@ void StartSmithRepair()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( /*selectable=*/ true ) ;
return ;
}
@ -580,10 +641,9 @@ void StartSmithRepair()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithSell ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
}
void FillManaPlayer ( )
@ -639,7 +699,7 @@ void ScrollWitchBuy(int idx)
}
}
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = 22 )
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = BackButtonLine ( ) )
stextsel = stextdown ;
}
@ -655,10 +715,8 @@ void StartWitchBuy()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollWitchBuy ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
storenumh = 0 ;
for ( int i = 0 ; ! witchitem [ i ] . isEmpty ( ) ; i + + ) {
@ -747,9 +805,7 @@ void StartWitchSell()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( /*selectable=*/ true ) ;
return ;
}
@ -762,10 +818,8 @@ void StartWitchSell()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithSell ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
}
bool WitchRechargeOk ( int i )
@ -828,9 +882,7 @@ void StartWitchRecharge()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( /*selectable=*/ true ) ;
return ;
}
@ -843,10 +895,8 @@ void StartWitchRecharge()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithSell ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
}
void StoreNoMoney ( )
@ -958,7 +1008,7 @@ void SStartBoyBuy()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
UiFlags itemColor = boyitem . getTextColorWithStatCheck ( ) ;
if ( boyitem . _iMagical ! = ITEM_QUALITY_NORMAL )
@ -971,8 +1021,15 @@ void SStartBoyBuy()
else
AddSTextVal ( 10 , boyitem . _iIvalue + ( boyitem . _iIvalue / 2 ) ) ;
PrintStoreItem ( & boyitem , 11 , itemColor ) ;
AddSText ( 0 , 22 , _ ( " Leave " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
{
// Add a Leave button. Unlike the other item list back buttons,
// this one has different text and different layout in LargerSmallFont locales.
const int line = BackButtonLine ( ) ;
AddSLine ( line - 1 ) ;
AddSText ( 0 , line , _ ( " Leave " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
stext [ line ] . _syoff = 6 ;
}
}
void HealPlayer ( )
@ -1018,7 +1075,7 @@ void ScrollHealerBuy(int idx)
}
}
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = 22 )
if ( stextsel ! = - 1 & & ! stext [ stextsel ] . _ssel & & stextsel ! = BackButtonLine ( ) )
stextsel = stextdown ;
}
@ -1033,10 +1090,9 @@ void StartHealerBuy()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollHealerBuy ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
storenumh = 0 ;
for ( int i = 0 ; ! healitem [ i ] . isEmpty ( ) ; i + + ) {
@ -1150,9 +1206,7 @@ void StartStorytellerIdentify()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( /*selectable=*/ true ) ;
return ;
}
@ -1165,10 +1219,9 @@ void StartStorytellerIdentify()
AddSText ( 0 , 1 , tempstr , UiFlags : : ColorWhitegold | UiFlags : : AlignCenter , false ) ;
AddSLine ( 3 ) ;
AddSLine ( 21 ) ;
ScrollSmithSell ( stextsval ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
OffsetSTextY ( 22 , 6 ) ;
AddItemListBackButton ( ) ;
}
void StartStorytellerIdentifyShow ( )
@ -1202,7 +1255,7 @@ void StartTalk()
AddSText ( 0 , 12 , _ ( " is not available " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
AddSText ( 0 , 14 , _ ( " in the shareware " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
AddSText ( 0 , 16 , _ ( " version " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , false ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
AddOptionsBackButton ( ) ;
return ;
}
@ -1229,7 +1282,7 @@ void StartTalk()
}
}
AddSText ( 0 , sn2 , _ ( " Gossip " ) , UiFlags : : ColorBlue | UiFlags : : AlignCenter , true ) ;
AddSText ( 0 , 22 , _ ( " Back " ) , UiFlags : : ColorWhite | UiFlags : : AlignCenter , true ) ;
AddOptionsBackButton ( ) ;
}
void StartTavern ( )
@ -1324,7 +1377,7 @@ void SmithBuyItem()
void SmithBuyEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_SMITH ) ;
stextsel = 12 ;
return ;
@ -1384,7 +1437,7 @@ void SmithBuyPItem()
void SmithPremiumBuyEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_SMITH ) ;
stextsel = 14 ;
return ;
@ -1529,7 +1582,7 @@ void StoreSellItem()
void SmithSellEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_SMITH ) ;
stextsel = 16 ;
return ;
@ -1578,7 +1631,7 @@ void SmithRepairItem()
void SmithRepairEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_SMITH ) ;
stextsel = 18 ;
return ;
@ -1656,7 +1709,7 @@ void WitchBuyItem()
void WitchBuyEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_WITCH ) ;
stextsel = 14 ;
return ;
@ -1689,7 +1742,7 @@ void WitchBuyEnter()
void WitchSellEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_WITCH ) ;
stextsel = 16 ;
return ;
@ -1730,7 +1783,7 @@ void WitchRechargeItem()
void WitchRechargeEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_WITCH ) ;
stextsel = 18 ;
return ;
@ -1939,7 +1992,7 @@ void ConfirmEnter()
StartStore ( stextshold ) ;
if ( stextsel = = 22 )
if ( stextsel = = BackButtonLine ( ) )
return ;
stextsel = stextlhold ;
@ -1972,7 +2025,7 @@ void HealerEnter()
void HealerBuyEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_HEALER ) ;
stextsel = 16 ;
return ;
@ -2026,7 +2079,7 @@ void StorytellerEnter()
void StorytellerIdentifyEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( STORE_STORY ) ;
stextsel = 14 ;
return ;
@ -2048,7 +2101,7 @@ void StorytellerIdentifyEnter()
void TalkEnter ( )
{
if ( stextsel = = 22 ) {
if ( stextsel = = BackButtonLine ( ) ) {
StartStore ( stextshold ) ;
stextsel = stextlhold ;
return ;
@ -2252,7 +2305,7 @@ void PrintSString(const Surface &out, int margin, int line, const char *text, Ui
sx + = 320 ;
}
int sy = UI_OFFSET_Y + 32 + line * 12 + stext [ line ] . _syoff ;
const int sy = UI_OFFSET_Y + PaddingTop + stext [ line ] . y + stext [ line ] . _syoff ;
int width = stextsize ? 575 : 255 ;
if ( stextscrl & & line > = 4 & & line < = 20 ) {
@ -2276,7 +2329,7 @@ void PrintSString(const Surface &out, int margin, int line, const char *text, Ui
void DrawSLine ( const Surface & out , int y )
{
int sx = 26 ;
int sy = y * 1 2;
const int sy = PaddingTop + stext [ y ] . y + TextHeight ( ) / 2 ;
int width = 587 ;
if ( ! stextsize ) {
@ -2285,7 +2338,7 @@ void DrawSLine(const Surface &out, int y)
}
BYTE * src = out . at ( PANEL_LEFT + sx , UI_OFFSET_Y + 25 ) ;
BYTE * dst = out . at ( PANEL_X + sx , UI_OFFSET_Y + sy + 38 ) ;
BYTE * dst = out . at ( PANEL_X + sx , UI_OFFSET_Y + sy ) ;
for ( int i = 0 ; i < 3 ; i + + , src + = out . pitch ( ) , dst + = out . pitch ( ) )
memcpy ( dst , src , width ) ;
@ -2453,10 +2506,11 @@ void DrawSText(const Surface &out)
}
}
CalculateLineHeights ( ) ;
for ( int i = 0 ; i < STORE_LINES ; i + + ) {
if ( stext [ i ] . _sline ! = 0 )
if ( stext [ i ] . IsDivider ( ) )
DrawSLine ( out , i ) ;
if ( stext [ i ] . _sstr [ 0 ] ! = ' \0 ' )
if ( stext [ i ] . IsText ( ) )
PrintSString ( out , stext [ i ] . _sx , i , stext [ i ] . _sstr , stext [ i ] . flags , stext [ i ] . _sval ) ;
}
@ -2745,7 +2799,7 @@ void CheckStoreBtn()
qtextflag = false ;
if ( leveltype = = DTYPE_TOWN )
stream_stop ( ) ;
} else if ( stextsel ! = - 1 & & MousePosition . y > = ( 32 + UI_OFFSET_Y ) & & MousePosition . y < = ( 320 + UI_OFFSET_Y ) ) {
} else if ( stextsel ! = - 1 & & MousePosition . y > = ( PaddingTop + UI_OFFSET_Y ) & & MousePosition . y < = ( 320 + UI_OFFSET_Y ) ) {
if ( ! stextsize ) {
if ( MousePosition . x < 344 + PANEL_LEFT | | MousePosition . x > 616 + PANEL_LEFT )
return ;
@ -2753,8 +2807,12 @@ void CheckStoreBtn()
if ( MousePosition . x < 24 + PANEL_LEFT | | MousePosition . x > 616 + PANEL_LEFT )
return ;
}
int y = ( MousePosition . y - ( 32 + UI_OFFSET_Y ) ) / 12 ;
const int relativeY = MousePosition . y - ( UI_OFFSET_Y + PaddingTop ) ;
if ( stextscrl & & MousePosition . x > 600 + PANEL_LEFT ) {
// Scroll bar is always measured in terms of the small line height.
int y = relativeY / SmallLineHeight ;
if ( y = = 4 ) {
if ( stextscrlubtn < = 0 ) {
StoreUp ( ) ;
@ -2771,17 +2829,29 @@ void CheckStoreBtn()
stextscrldbtn - - ;
}
}
} else if ( y > = 5 ) {
if ( y > = 23 )
y = 22 ;
if ( stextscrl & & y < 21 & & ! stext [ y ] . _ssel ) {
return ;
}
int y = relativeY / LineHeight ( ) ;
// Large small fonts draw beyond LineHeight. Check if the click was on the overflow text.
if ( IsSmallFontTall ( ) & & y > 0 & & y < STORE_LINES
& & stext [ y - 1 ] . IsText ( ) & & ! stext [ y ] . IsText ( )
& & relativeY < stext [ y - 1 ] . y + LargeTextHeight ) {
- - y ;
}
if ( y > = 5 ) {
if ( y > = BackButtonLine ( ) + 1 )
y = BackButtonLine ( ) ;
if ( stextscrl & & y < = 20 & & ! stext [ y ] . _ssel ) {
if ( stext [ y - 2 ] . _ssel ) {
y - = 2 ;
} else if ( stext [ y - 1 ] . _ssel ) {
y - - ;
}
}
if ( stext [ y ] . _ssel | | ( stextscrl & & y = = 22 ) ) {
if ( stext [ y ] . _ssel | | ( stextscrl & & y = = BackButtonLine ( ) ) ) {
stextsel = y ;
StoreEnter ( ) ;
}