https://bugs.winehq.org/show_bug.cgi?id=51899
Bug ID: 51899 Summary: 16-bit Collins Dictionary has black background. Product: Wine Version: 6.19 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: gdi32 Assignee: wine-bugs@winehq.org Reporter: zzhang@codeweavers.com Distribution: ---
This is a split from bug 51802. Bisect points to
6f095cea53787f03a159f0464b9881ace3724e6b is the first bad commit commit 6f095cea53787f03a159f0464b9881ace3724e6b Author: Jacek Caban jacek@codeweavers.com Date: Tue Aug 3 12:56:49 2021 +0200
gdi32: Use NtGdiPatBlt for PatBlt implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
https://bugs.winehq.org/show_bug.cgi?id=51899
Zhiyi Zhang zzhang@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- URL| |https://archive.org/details | |/collins_win31 Regression SHA1| |6f095cea53787f03a159f0464b9 | |881ace3724e6b
https://bugs.winehq.org/show_bug.cgi?id=51899
Zhiyi Zhang zzhang@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jacek@codeweavers.com
https://bugs.winehq.org/show_bug.cgi?id=51899
clinton@concernednetizen.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |clinton@concernednetizen.co | |m
https://bugs.winehq.org/show_bug.cgi?id=51899
O. Nykyforchyn oleh.nyk@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |oleh.nyk@gmail.com
--- Comment #1 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70849 --> https://bugs.winehq.org/attachment.cgi?id=70849 Screenshot of WinEdt 1.41e
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #2 from O. Nykyforchyn oleh.nyk@gmail.com --- It is not only related to Collins Dictionary. WinEdt 16 bit version
http://ftp.itam.mx/pub/academico/investig/latex/LaTeXWin/winedt16.zip
also has a black background in the text input area. Moreover, when text is scrolled, the background is not cleared, so now lines are drawn over old ones.
https://bugs.winehq.org/show_bug.cgi?id=51899
Fabian Maurer dark.shadow4@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dark.shadow4@web.de
https://bugs.winehq.org/show_bug.cgi?id=51899
Julian Rüger jr98@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jr98@gmx.net
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #3 from O. Nykyforchyn oleh.nyk@gmail.com --- I localized a narrow place in dlls/gdi32/dc. There is a function
DC_ATTR *get_dc_attr( HDC hdc ) { DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr; if ((type & 0x1f0000) != NTGDI_OBJ_DC || !(dc_attr = get_gdi_client_ptr( hdc, 0 ))) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } return dc_attr->disabled ? NULL : dc_attr; }
If the first of two OR'ed conditions is dropped:
DC_ATTR *get_dc_attr( HDC hdc ) { DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr;
TRACE("Got type %x\n", type);
if (!(dc_attr = get_gdi_client_ptr( hdc, 0 ))) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } return dc_attr->disabled ? NULL : dc_attr; }
then background is OK. Splitting like
DC_ATTR *get_dc_attr( HDC hdc ) { DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr;
if ((type & 0x1f0000) != NTGDI_OBJ_DC) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; }
if (!(dc_attr = get_gdi_client_ptr( hdc, 0 ))) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } return dc_attr->disabled ? NULL : dc_attr; }
does not help. Seems like a compiler bug, maybe in oplimization or inlining.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #4 from O. Nykyforchyn oleh.nyk@gmail.com --- Have to add that ((type & 0x1f0000) != NTGDI_OBJ_DC) fails, so there is no function return in the block below.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #5 from Bruni earns.61@gmail.com --- Try to forbid a compiler to reorder instructions using mutex locks (by inserting memory barriers) with something like
... #include <pthread.h> ...
DC_ATTR *get_dc_attr( HDC hdc ) { pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock( &lock ); DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr; if ((type & 0x1f0000) != NTGDI_OBJ_DC || !(dc_attr = get_gdi_client_ptr( hdc, 0 ))) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } pthread_mutex_unlock( &lock ); return dc_attr->disabled ? NULL : dc_attr; }
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #6 from Bruni earns.61@gmail.com --- My bad
According to PTHREAD specification, it does not guarantee that instructions inside the lock itself are protected from reordering.
So, it's better to put multiple locks.
DC_ATTR *get_dc_attr( HDC hdc ) { pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock( &lock ); DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr; pthread_mutex_unlock( &lock );
pthread_mutex_lock( &lock ); unsigned int comparedType = type & 0x1f0000; pthread_mutex_unlock( &lock );
pthread_mutex_lock( &lock ); unsigned int ntgdiObjDc = comparedType & NTGDI_OBJ_DC; pthread_mutex_unlock( &lock );
pthread_mutex_lock( &lock ); dc_attr = get_gdi_client_ptr( hdc, 0 ); pthread_mutex_unlock( &lock );
pthread_mutex_lock( &lock ); if (!ntgdiObjDc) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } pthread_mutex_unlock( &lock );
pthread_mutex_lock( &lock ); if (!dc_attr) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; } pthread_mutex_unlock( &lock ); return dc_attr->disabled ? NULL : dc_attr; }
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #7 from O. Nykyforchyn oleh.nyk@gmail.com --- I found out what causes the bug. When background is erased, a handle to DC is passed through USER16 functions, namely CallWindowProc16 (USER.122) and DefDriverProc16 (USER.255), whose respective parameters are of type WPARAM16, hence the upper part of the handle is cut. Later the returned handle is rejected by get_dc_attr() in GDI32 because its type is 0, although such handles are accepted by handle_entry(). Allowing type==0 in get_dc_attr() solves the problem both in WinEdt and Collins Dictionary. If there are no objections, I will submit the patch.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #8 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70871 --> https://bugs.winehq.org/attachment.cgi?id=70871 patch to GDI32
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #9 from Bruni earns.61@gmail.com --- (In reply to O. Nykyforchyn from comment #7)
I found out what causes the bug. When background is erased, a handle to DC is passed through USER16 functions, namely CallWindowProc16 (USER.122) and DefDriverProc16 (USER.255), whose respective parameters are of type WPARAM16, hence the upper part of the handle is cut. Later the returned handle is rejected by get_dc_attr() in GDI32 because its type is 0, although such handles are accepted by handle_entry(). Allowing type==0 in get_dc_attr() solves the problem both in WinEdt and Collins Dictionary. If there are no objections, I will submit the patch.
BTW, have you managed to figure out what's the 0x1f0000 magic number stands for? I could not find an explanation in Wine source.
It seems it may take really long time to investigate DC attributes with unclear semantics the next time it will be broken (which seems inevitable).
Each time someone fixes a bug and the expression if this 'if' becomes more monstrous.
If you have found out what the beast is 0x1f0000 there is a point to decomposite that monster expression in 'if' into a few branches.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #10 from O. Nykyforchyn oleh.nyk@gmail.com --- (In reply to Bruni from comment #9)
BTW, have you managed to figure out what's the 0x1f0000 magic number stands for? I could not find an explanation in Wine source.
Yes, it's just a mask for bits that contain handle type.
It seems it may take really long time to investigate DC attributes with unclear semantics the next time it will be broken (which seems inevitable).
I am afraid nobody can do anything with this because Windows behaves this way.
Each time someone fixes a bug and the expression if this 'if' becomes more monstrous.
If you have found out what the beast is 0x1f0000 there is a point to decomposite that monster expression in 'if' into a few branches.
This expression tests whether the supplied handle is valid, I see no way to make the code with it simpler.
BTW, I submitted
https://source.winehq.org/patches/data/218030
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #11 from Bruni earns.61@gmail.com --- (In reply to O. Nykyforchyn from comment #10)
This expression tests whether the supplied handle is valid, I see no way to make the code with it simpler.
How about this code? Also, where can one see if your patch was accepted? (before a new wine release)
DC_ATTR *get_dc_attr( HDC hdc ) { DWORD handle_type_bit_mask = 0x1f0000; DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr = get_gdi_client_ptr( hdc, 0 );
if (!type) return dc_attr->disabled ? NULL : dc_attr;
if ((type & handle_type_bit_mask) != NTGDI_OBJ_DC) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; }
if (!dc_attr) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; }
return dc_attr->disabled ? NULL : dc_attr; }
Explanation:
In (type && (type & 0x1f0000) != NTGDI_OBJ_DC),
!= has higher precedence than &&, both have left-to-right associativity
That is, it is grouped as (type && ((type & 0x1f0000) != NTGDI_OBJ_DC)).
If we let
if ((type && (type & 0x1f0000) != NTGDI_OBJ_DC) || !(dc_attr = get_gdi_client_ptr( hdc, 0 )))
be
if ((x && y) || !z))
where `type` stands for x
`(type & 0x1f0000) != NTGDI_OBJ_DC` stands for y
`(dc_attr = get_gdi_client_ptr( hdc, 0 ))` stands for z
then
Both && and || are affected by "Short-circuit evaluation" rule.
So in if ((x && y) || !z) { body } expression,
it's enough for both x and y to be true or for z to be false to execute if's body.
So z can be split into separate if, which can be placed after original if, copying its body.
Which results in if (x && y) { body } if (!z) { body }
In if (x && y) { body } expression,
it's enough for x to be false to not execute if's body. And one can immediately return in our case, where if's body is the last block before `return`.
So one can decompose it as follows
if (!x) return if (y) { body } if (!z) { body }
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #12 from Bruni earns.61@gmail.com --- I've realized my previous comment contains a mistake.
So in if ((x && y) || !z) { body } expression,
it's enough for both x and y to be true or for z to be false to execute if's body.
So z can be split into separate if, which can be placed after original if, copying its body.
Which results in if (x && y) { body } if (!z) { body }
In if (x && y) { body } expression,
it's enough for x to be false to not execute if's body. And one can immediately return in our case, where if's body is the last block before `return`.
So one can decompose it as follows
if (!x) return if (y) { body } if (!z) { body }
Even if `x` is false, execution framework cannot leave the whole test expression until z is testified.
So `x` can be split from `y` only with testifying `z`
So get_dc_attr function body must be as follows.
DC_ATTR *get_dc_attr( HDC hdc ) { DWORD handle_type_bit_mask = 0x1f0000; DWORD type = gdi_handle_type( hdc ); DC_ATTR *dc_attr = get_gdi_client_ptr( hdc, 0 );
if (!type && dc_attr) return dc_attr->disabled ? NULL : dc_attr;
if ((type & handle_type_bit_mask) != NTGDI_OBJ_DC) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; }
if (!dc_attr) { SetLastError( ERROR_INVALID_HANDLE ); return NULL; }
return dc_attr->disabled ? NULL : dc_attr; }
This variant looks correct to me.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #13 from Fabian Maurer dark.shadow4@web.de --- The patch from Nikolay Sivov works fine for me: https://www.winehq.org/pipermail/wine-devel/2021-October/199147.html
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #14 from O. Nykyforchyn oleh.nyk@gmail.com --- Posted to wine-devel:
I agree that to restore the missing upper part is better. Could You submit the patch and mark my patch as superceded?
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #15 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70878 --> https://bugs.winehq.org/attachment.cgi?id=70878 patch to USER16
Patch by Nikolay Sivov extended to cover one more case when handle is rejected after parameters conversion.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #16 from Nikolay Sivov bunglehead@gmail.com --- (In reply to O. Nykyforchyn from comment #15)
Created attachment 70878 [details] patch to USER16
Patch by Nikolay Sivov extended to cover one more case when handle is rejected after parameters conversion.
I don't see this helping this truncation case, according to logs. One case that still shows up is WM_CTLCOLOR message in default procedure. Converting that results in different Edit control background, which is probably wrong.
Another issue that could be a pre-existing issue - word selection paints black with black text, making selected parts unreadable. I don't know what it supposed to look like on Windows.
https://bugs.winehq.org/show_bug.cgi?id=51899
O. Nykyforchyn oleh.nyk@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #70878|0 |1 is obsolete| |
--- Comment #17 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70881 --> https://bugs.winehq.org/attachment.cgi?id=70881 patch to USER16
What if the following (just a quick copy-paste to see what happens)?
https://bugs.winehq.org/show_bug.cgi?id=51899
O. Nykyforchyn oleh.nyk@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #70881|0 |1 is obsolete| |
--- Comment #18 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70883 --> https://bugs.winehq.org/attachment.cgi?id=70883 patch to USER16
Sorry, paranthesis is missed.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #19 from O. Nykyforchyn oleh.nyk@gmail.com --- Created attachment 70885 --> https://bugs.winehq.org/attachment.cgi?id=70885 Screenshot of Collins Dictionary
I compiled Wine with the latter patch, and logs show that all handles pass through get_dc_attr() for EDTWIN.EXE. Is this the required goal or am I miss something?
Selected text is unreadable indeed.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #20 from Bruni earns.61@gmail.com --- (In reply to O. Nykyforchyn from comment #19)
Created attachment 70885 [details] Screenshot of Collins Dictionary
I compiled Wine with the latter patch, and logs show that all handles pass through get_dc_attr() for EDTWIN.EXE. Is this the required goal or am I miss something?
Selected text is unreadable indeed.
BTW, Can EM_GETSEL be broken here by posting an incorrect selection position? Can Wine just cut a 'hole' in the background, instead of applying a style for selected text?
According to "Programming Windows" by Charles Petzold, sending an edit control an EM_GETSEL message returns an integer containing this information:
LRESULT iSelect = SendMessage (hwndEdit, EM_GETSEL, 0, 0);
The low word of iSelect is the position of the first selected character; the high word of iSelect is the position of the character following the selection. If these two words are equal, no text has been selected.
Maybe, it's worthwhile to trace those positions inside the message loop for the control like this?
LRESULT iSelect = SendMessage (hwndEdit, EM_GETSEL, 0, 0); if (HIWORD(iSelect) != LOWORD(iSelect)) { TRACE("Start position of the selected text %x\n", LOWORD(iSelect)); TRACE("End position of the selected text %x\n", HIWORD(iSelect)); }
I don't know how to insert these lines in dlls/user.exe16/message.c without infinite recursion in SendMessage, though.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #21 from Nikolay Sivov bunglehead@gmail.com --- (In reply to O. Nykyforchyn from comment #19)
Created attachment 70885 [details] Screenshot of Collins Dictionary
I compiled Wine with the latter patch, and logs show that all handles pass through get_dc_attr() for EDTWIN.EXE. Is this the required goal or am I miss something?
Selected text is unreadable indeed.
The ultimate goal is to make it work correctly. For specific HDC truncation issue, yes, if you don't see it at gdi32 side any more, it's probably fixed, for cases that application cares about.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #22 from clinton@concernednetizen.com --- Created attachment 70891 --> https://bugs.winehq.org/attachment.cgi?id=70891 Collins Dictionary
Here is what it looks like on my 286 with Windows 3.1
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #23 from Nikolay Sivov bunglehead@gmail.com --- Regarding selection color, it seems to be about how text color is handled, or maybe some issue with interpreting color value in dib engine. After SetTextColor(0xffffffff), color gets reset internally to 0 (black):
get_pixel_color(0xffffffff) -> make_rgb_colorref() -> color & (1 << 24) -> 0.
Masking out high byte at 16-bit SetTextColor, fixes selection for me, but I don't know what the right solution would look like.
(In reply to clinton from comment #22)
Created attachment 70891 [details] Collins Dictionary
Here is what it looks like on my 286 with Windows 3.1
This is beautiful, thanks.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #24 from Bruni earns.61@gmail.com --- (In reply to Nikolay Sivov from comment #23)
Regarding selection color, it seems to be about how text color is handled, or maybe some issue with interpreting color value in dib engine. After SetTextColor(0xffffffff), color gets reset internally to 0 (black):
If you observed SetTextColor(0xffffffff) instead of SetTextColor(0x00ffffff), most likely, this means you've discovered a bug either in SetTextColor's implementation or in the implementation of its caller!
Explanation:
An old book "Using Visual C++ 6" by Kate Gregory states that the parameter to SetTextColor() is a COLORREF, and you can directly specify combinations of red, green, and blue as hex numbers in the form 0x00bbggrr, so that, for example, 0x000000FF is bright red. Most people prefer to use the RGB macro, which takes hex numbers from 0x0 to 0xFF, specifying the amount of each color; bright red is RGB(FF,0,0), for instance.
That book gives an example: pointerToDC->SetTextColor(RGB(0,0,0)); //black
Wine has RGB macro and defines it as
#define RGB(r,g,b) ((COLORREF)((BYTE)(r) | ((BYTE)(g) << 8) | ((BYTE)(b) << 16)))
https://source.winehq.org/git/wine.git/blob/ababea0fd7036ab13ec17d31afbd584c...
There is also a definition of RGB macro from Windows 3.1:
/* Color data type */ typedef DWORD COLORREF;
/* Macros to manipulate RGB color values */ #define RGB( r, g, b ) \ ((COLORREF)(((BYTE)(r) | ((WORD)(g) << 8)) | (((DWORD)(BYTE)(b)) << 16)))
http://www.rdos.net/svn/tags/V9.2.5/watcom/bld/w16api/include/win16.mh
Then I decided to check both Windows' macro and Wine's one just in case:
#include <stdio.h> typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD, COLORREF;
#define RGBfromwine(r,g,b) ((COLORREF)((BYTE)(r) | ((BYTE)(g) << 8) | ((BYTE)(b) << 16))) #define RGBfromoldwindows( r, g, b ) \ ((COLORREF)(((BYTE)(r) | ((WORD)(g) << 8)) | (((DWORD)(BYTE)(b)) << 16)))
int main() { printf("White in hex given by Wine's RGB macro: \t%#010x\n", RGBfromwine(255,255,255)); printf("White in hex given by Windows 3.1's RGB macro: \t%#010x\n", RGBfromoldwindows(255,255,255));
return 0; }
http://coliru.stacked-crooked.com/a/c9b111d5ab7f728f
Result:
White in hex given by Wine's RGB macro: 0x00ffffff White in hex given by Windows 3.1's RGB macro: 0x00ffffff
So the book told truth, seemingly.
(In reply to Nikolay Sivov from comment #23)
get_pixel_color(0xffffffff) -> make_rgb_colorref() -> color & (1 << 24) -> 0.
Masking out high byte at 16-bit SetTextColor, fixes selection for me, but I don't know what the right solution would look like.
So if dib engine gives white color for SetTextColor(0x00ffffff), this means dib engine is ok
This narrows bug area to SetTextColor's implementation or to its callers
Trace would be useful.
I believe SetBkColor has similar problems.
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #25 from Bruni earns.61@gmail.com --- Some tests on real Windows' SetTextColor show how it reacts to misformed COLORREF argument. SetTextColor from Windows 7 behaves the same way as SetTextColor from Wine in regards to 0xFFFFFFFF: it makes the text black.
Consider the following program: (Note the lines ... case WM_CTLCOLORSTATIC:> case WM_CTLCOLORSTATIC: { SetBkMode((HDC)wParam,TRANSPARENT); SetTextColor((HDC)wParam, 0x00FF0000); ... )
//Main.cpp #ifndef UNICODE #define UNICODE #endif #ifndef _UNICODE #define _UNICODE #endif #include <windows.h> #define IDC_LABEL1 2000
LRESULT CALLBACK fnWndProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { HINSTANCE hIns = ((LPCREATESTRUCT)lParam)->hInstance; HWND hCtl = CreateWindowEx(0,L"static",L"Label1", WS_CHILD|WS_VISIBLE,40,40,80,30,hWnd,(HMENU)IDC_LABEL1,hIns,0); return 0; } case WM_CTLCOLORSTATIC: // Do not allow DefWindowProc() to process this message! // When a WM_CTLCOLORSTATIC message comes through, return // from the Window Procedure call without a DefWindowProc() // call. Instead return the HBRUSH stored as an instance // variable as part of the WNDCLASSEX object. { SetBkMode((HDC)wParam,TRANSPARENT); SetTextColor((HDC)wParam, 0x00FF0000); return GetWindowLongPtr(hWnd,0*sizeof(void*)); } case WM_DESTROY: { PostQuitMessage(0); return 0; } }
return (DefWindowProc(hWnd, msg, wParam, lParam)); }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow) { wchar_t szClassName[]=L"Form1"; WNDCLASSEX wc; MSG messages; HWND hWnd;
memset(&wc,0,sizeof(WNDCLASSEX)); HBRUSH hBrush = CreateSolidBrush(RGB(255,255,222)); wc.lpszClassName = szClassName; wc.lpfnWndProc = fnWndProc; wc.cbSize = sizeof(WNDCLASSEX); wc.hbrBackground = hBrush; wc.hInstance = hInstance; wc.cbWndExtra = sizeof(void*); RegisterClassEx(&wc); hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW, 200,175,320,200,HWND_DESKTOP,0,hInstance,0); SetWindowLongPtr(hWnd,0*sizeof(void*),(LONG_PTR)hBrush); ShowWindow(hWnd,iShow); while(GetMessage(&messages,NULL,0,0)) { TranslateMessage(&messages); DispatchMessage(&messages); } DeleteObject(hBrush);
return messages.wParam; }
Results:
SetTextColor((HDC)wParam, 0x00FF0000); => blue text in Windows 7 SetTextColor((HDC)wParam, 0x0000FF00); => green text in Windows 7 SetTextColor((HDC)wParam, 0x000000FF); => red text in Windows 7 SetTextColor((HDC)wParam, 0x00000000); => black text in Windows 7 SetTextColor((HDC)wParam, 0x00FFFFFF); => white text in Windows 7
But
SetTextColor((HDC)wParam, 0xFFFFFFFF); => black text in Windows 7!
So Wine's dib engine behaves just like the dib engine from Windows in this aspect.
The bug is definitely in SetTextColor or in its callers.
https://bugs.winehq.org/show_bug.cgi?id=51899
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, win16
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #26 from Bruni earns.61@gmail.com --- Created attachment 70940 --> https://bugs.winehq.org/attachment.cgi?id=70940 Collins Dictionary 16-bit run in Windows XP through QEMU
Collins Dictionary has a pure black color for selected text background even in Windows XP (0x00000000). Text color is white. (0x00FFFFFF)
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #27 from O. Nykyforchyn oleh.nyk@gmail.com --- Resent patch that corrects (at least part of) failures in 16 bit <-> 32 bit handles conversion:
https://source.winehq.org/patches/data/220679
Tested with wine-6.22
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #28 from Nikolay Sivov bunglehead@gmail.com --- Please retest with current wine, this should be fixed now:
1bfae238c861f83e6ccb9e8821d5fb0de5a48a61 0f16aa1842d2bb9f5b8410cfd342680a9a1844ac
https://bugs.winehq.org/show_bug.cgi?id=51899
--- Comment #29 from O. Nykyforchyn oleh.nyk@gmail.com --- (In reply to Nikolay Sivov from comment #28)
Please retest with current wine, this should be fixed now:
1bfae238c861f83e6ccb9e8821d5fb0de5a48a61 0f16aa1842d2bb9f5b8410cfd342680a9a1844ac
In fact the committed changes are the ones proposed before by Nikolay Sivov and Jacek Caban, so there is no surprise that behavior is the same. Everything works except for black text on black background in selected areas.