We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2425 - SDL_ShowSimpleMessageBox cuts off last character of message when its longer than 3 character
Summary: SDL_ShowSimpleMessageBox cuts off last character of message when its longer t...
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.1
Hardware: All Windows (All)
: P2 minor
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.4
Depends on:
Blocks:
 
Reported: 2014-03-02 22:34 UTC by Coriiander
Modified: 2016-01-04 09:17 UTC (History)
4 users (show)

See Also:


Attachments
Image of truncated text (13.66 KB, image/png)
2015-05-29 11:30 UTC, igor
Details
Windows 8.1, text not truncated (5.43 KB, image/png)
2015-06-08 02:37 UTC, Sam Lantinga
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Coriiander 2014-03-02 22:34:45 UTC
When I was just checking out SDL_ShowSimpleMessageBox (just to see how it looked like, I don't need it myself), I noticed a bug. When a message that is longer than 3 characters, the displayed message is incorrect. It cuts off the last character. It 'works fine' for messages upto and including 3 characters in length. I'm building this with Microsoft Visual Studio 2008, with in the build options Character Set = 'Not Set'.

Code to reproduce this bug:

#include "SDL.h"
int main(int argc, char* argv[])
{
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Title", "abc", NULL);
    return 0;
}

Here's the various output messages for various input messages:
a: a
ab: ab
abc: abc
abcd: abc
abcde: abcd
abcdef: abcde
abcdefg: abcdef
abc..xyz: abc..xy

I have not dived into SDL's source code to find out where the problem is, though I can imagine it may have something to do with a bug related to null-terminator char while converting the string format.
Comment 1 Ryan C. Gordon 2015-02-19 05:22:17 UTC
Marking a large number of bugs with the "triage-2.0.4" keyword at once. Sorry if you got a lot of email from this. This is to help me sort through some bugs in regards to a 2.0.4 release. We may or may not fix this bug for 2.0.4, though!
Comment 2 Ryan C. Gordon 2015-04-07 04:57:54 UTC
(sorry if you get a lot of copies of this email, I'm marking several bugs at once)

Marking bugs for the (mostly) final 2.0.4 TODO list. This means we're hoping to resolve this bug before 2.0.4 ships if possible. In a perfect world, the open bug count with the target-2.0.4 keyword is zero when we ship.

(Note that closing a bug report as WONTFIX, INVALID or WORKSFORME might still happen.)

--ryan.
Comment 3 igor 2015-05-01 16:21:11 UTC
Also it would be nice to have this function implemented for Android.
Comment 4 Alex Szpakowski 2015-05-02 00:53:55 UTC
(In reply to igor from comment #3)
> Also it would be nice to have this function implemented for Android.

It is implemented for SDL 2.0.4: https://hg.libsdl.org/SDL/rev/6cd8e6b54f4d
Comment 5 igor 2015-05-02 10:09:28 UTC
It's awesome, need to get hg version...
Comment 6 Sam Lantinga 2015-05-28 19:15:29 UTC
I'm not able to reproduce this. Are you still seeing this problem with the latest SDL build?
http://www.libsdl.org/tmp/SDL-2.0.zip

If so, can you set a breakpoint in WIN_ShowMessageBox() and see what's happening?

Do you have display scaling turned on?
Comment 7 igor 2015-05-28 21:02:42 UTC
I'm not a reporter but had issue some time ago too, I was getting last word cut off. Try to use message from e.g 9 words in one line.
Comment 8 igor 2015-05-28 21:10:52 UTC
Try this one.

 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "FLARE: Default mod not found", "Default mod should be installed to proceed. Game will exit.", NULL);

If it works, then I will need to double-check it, not sure if above linecwas failing...
Comment 9 Coriiander 2015-05-29 02:21:27 UTC
I did the original report. I cannot check right now, though I will be able tomorrow. I'll report back once tested.
Comment 10 igor 2015-05-29 11:30:47 UTC
Created attachment 2167 [details]
Image of truncated text
Comment 11 igor 2015-05-29 11:31:43 UTC
Windows 7 x64
Mingw32 build of application and of provided sdl snapshot http://www.libsdl.org/tmp/SDL-2.0.zip

Call:
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "FLARE", "ERROR: No \"default\" mod found.", NULL);

Image attached.
Comment 12 igor 2015-05-29 14:50:09 UTC
Not providing nCount (string size) to DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT);
causes issue. If -1 is replaced with positive number, all is ok. So DrawText doesn't calculate wmessage size correctly.
Comment 13 igor 2015-05-29 15:00:02 UTC
wcslen(wmessage) reports 30... So maybe it's something with last two parameters...
Comment 14 igor 2015-05-29 15:34:53 UTC
Replacing DT_CALCRECT with e.g. DT_BOTTOM and setting TextSize manually fixes issue. There are some threads in internet about TextSize is not calculated correctly when using DT_CALCRECT, but no idea how to calculate it correctly.
Comment 15 igor 2015-06-02 12:01:12 UTC
I propose to split input text into lines manually, and calculate each char width, then sum each char widths. DT_CALCRECT doesn't provide correct result, and we don't use any other flags(like text wrapping), so manual calculation should be ok.
Comment 16 igor 2015-06-03 07:57:08 UTC
When looking here: https://msdn.microsoft.com/en-us/library/dd144938(VS.85).aspx
you can see that: "Because some devices kern characters, the sum of the extents of the characters in a string may not be equal to the extent of the string."

When calculating text width with next code:

	int widthInUnits = 0;
	for (int i = 0; i < wcslen(wmessage); i++)
	{
		SIZE size;
		size.cx = 0;
		size.cy = 0;
		GetTextExtentPoint32(hdc, wmessage + i, 1, &size);
		widthInUnits += size.cx;
	}

I get the same result as DrawText(...DT_CALCRECT). So I guess both GetTextExtentPoint32() and DrawText(...DT_CALCRECT) do the same work. And in both cases we ignore kerning. A fast hack would be just add one pixel to each symbol (I guess doesn't matter what of two approaches we use - whole text width calculation, or sum of all character widths). The hard fix will be to take kerning into account somehow, but no idea how to do this...
Comment 17 igor 2015-06-03 07:59:22 UTC
GetTextExtentPoint32(hdc, wmessage, wcslen(wmessage), &size) gives the same result, so it really ignores kerning in all cases
Comment 18 igor 2015-06-03 08:08:35 UTC
Well, not sure how to call it, kerning or spacing, but sum of character widths is the same as text width in our case, so in case of spaces between characters, calculated width will be smaller then real text width, so text will not fit.
Comment 19 igor 2015-06-05 10:59:47 UTC
I got more info. I have "medium font size 125%" set in Windows 7 Display preferences, if I change it to smallest (100%), text fits nicely. So this is definitely issue with winAPI. Can we do something with this?
Comment 20 Coriiander 2015-06-05 16:38:06 UTC
First of all sorry for my late reply. I wasn't at home and didn't have the time for looking into it. Here's my reply. It's lenghty, and I already say: it's a relatively complicated thing for such a small feature.

The bug is related to the Windows text/display scaling. Like you mentioned at, for example, 125% text scaling. One might think only the visually impaired use this feature, but that's far from the case; it's an often used thing. I use it myself as well (150% even), hence I ran into the bug I suppose.

But yes, there is things that can be done. Taking a look at the .NET-framework controls/forms, you'll see they use an AutoScale-property. This property can be set to things like Font and DPI. The rendering framework will then take care of appropriate scaling, taking the system-defined scaling into account. The system-defined scaling value can be obtained in two ways.

Method 1:
desktopDc = GetDC(NULL);
horizontalDPI = GetDeviceCaps(desktopDc,LOGPIXELSX);
verticalDPI = GetDeviceCaps(desktopDc,LOGPIXELSY);

Method2:
Windows Registry (Win32): HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics/AppliedDPI
Windows Registry (WinRT): HKEY_CURRENT_USERControlPanel\Desktop\LogPixels

The values can be:
96 = 100% scaling on every display
120 = 125% scaling on every display
144 = 150% scaling on every display
192 = 200% scaling on every display
<other> = <other>*100/96 scaling on every display

These numbers can be used to calculate the approriate dialog size. As a matter of fact, these values *SHOULD* also be used for Window creation in fullscreen mode! I don't know if there are currently issues with this, but I can remember a while ago there was an (unreported) bug when toggling from fullscreen back to windowed on scaled systems.  

Now the difficulty is there in that it might actually differ from display to display. This has to do with the amount of scanlines or vertical resolution on the various displays. By using Method1 (GetDeviceCaps) we should query the desired display where the dialog is to be displayed. We query its vertical resolution and its LogPixelsX/Y. 

For further information, see this article at TechNet:
https://technet.microsoft.com/en-us/library/dn528846.aspx#scalingmode


Cheers
Comment 21 Coriiander 2015-06-05 17:31:52 UTC
To add to my previous comment:

Forget about the registry values. Older versions of Windows have a system-wide key, while newer version have a user-specific key as well. It's best to just use the API (GetDeviceCaps). For WinRT other quite useful APIs have been introduced. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx for more in-depth information for both Win32 and WinRT.

Also a suggestion:
Seeing that display querying is already built-in to SDL, it might be a good idea to store scaling with the display info. These scaling values can be used by entire SDL, so also for things like toggling fullscreen, acquiring and calculating correct window-position/size, etc. I figure this should be especially important on touch-enabled devices.
Comment 22 Alex Szpakowski 2015-06-05 17:38:37 UTC
How does that interact with the SetProcessDpiAwareness / SetProcessDpiAware functions (which SDL doesn't use at all yet), and the SDL_WINDOW_ALLOW_HIGHDPI flag (which also isn't used in Windows yet)?

e.g. https://msdn.microsoft.com/en-ca/magazine/dn574798.aspx &
Comment 23 Coriiander 2015-06-05 18:19:40 UTC
I don't know. I have no experience with the WinRT API myself. I believe David Ludwig has done work on SDL with regards to WinRT; perhaps he knows. SetProcessDpiAware isn't available on older Windows-versions so I don't think that's the road to take.
Comment 24 Alex Szpakowski 2015-06-05 18:23:48 UTC
They are for Windows desktop apps. SetProcessDpiAware was added in Windows Vista to allow for high-DPI / retina support in programs (i.e. DPI scaling awareness.) SetProcessDpiAwareness was added in Windows 8.1 and allows programs to account for per-monitor DPI scaling differences.
Comment 25 Alex Szpakowski 2015-06-05 18:27:36 UTC
Here's some more info: https://msdn.microsoft.com/en-us/library/windows/desktop/dd464659(v=vs.85).aspx

If a program reports itself as DPI-aware, then Windows no longer does automatic scaling for it. This is important for games, since the framebuffer resolution will be a lot higher (and performance will be drastically affected) when this happens in high-DPI situations – that's why it's an opt-in feature in windows, OS X, and in SDL's own API.
Comment 26 Sam Lantinga 2015-06-08 02:37:59 UTC
Created attachment 2173 [details]
Windows 8.1, text not truncated

Maybe this is specific to Windows 7? I just tried on Windows 8.1 and there was no issue here.

Out of curiosity, is your game DPI aware?
Comment 27 Coriiander 2015-06-08 03:17:23 UTC
I don't know about Windows versions post 7. The report was filed as an issue on Windows 7. Note that the OS's display/text scaling is enabled; it's set to 150%. This is mostlikely cause of the problem. The project I was using this in (merely for testing purposes) was not DPI-aware.
Comment 28 Coriiander 2015-06-08 03:21:04 UTC
Like issues with text scaling, there's also other issues with regards to window metrics when text/desktop scaling is enabled (e.g. metric values, toggling back and forth between windowed and fullscreen). It seems the 'bug' resides on a deeper level as SDL doesn't really take the system's DPI scaling into account. As suggested in a prior reply this might be worthwhile to look into. It shouldn't be too difficult as display information retrieval is already implemented within SDL anyway.
Comment 29 igor 2015-06-08 08:01:32 UTC
I have tried on Windows 8. No issue on 100% text scaling, but issue present on 125% text scaling. Sam, are you sure you have changed text scaling?
Comment 30 igor 2015-06-08 08:04:31 UTC
Note that my test application doesn;t have any WinAPI calls, only cross-platform code, so I guess my app doesn't have any DPI related non-default settings.
Comment 31 Coriiander 2015-07-18 19:59:58 UTC
I recently had to add a custom manifest to one of my Visual C projects (somehow never had to do it before). This led me to how users should request DPI-awareness by embedding a dpiAware-entry in the application manifest (note: application, not shared library).

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

And 'lo, behold - correct metrics!

As MSDN states @ https://msdn.microsoft.com/en-us/library/windows/desktop/ms633543(v=vs.85).aspx

DLLs should accept the dpi setting of the host process rather than call SetProcessDPIAware themselves. To be set properly, dpiAware should be specified as part of the application (.exe) manifest. (dpiAware defined in an embedded DLL manifest has no affect.) The following markup shows how to set dpiAware as part of an application (.exe) manifest.
Comment 32 Ryan C. Gordon 2015-12-28 19:24:45 UTC
Ok, just following up here: was the consensus that apps should set a value in their manifests, and there's nothing SDL needs to (or even should) do here?

Trying to decide if I should close this bug or fix something.

--ryan.
Comment 33 igor 2016-01-04 09:17:55 UTC
I was unable to fix issue with manifest file under Windows 7 with VS... Can you guys re-check it?