Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2018
- 68 participants
- 1149 messages
[PATCH 1/3] testbot/build: Move GitPull() and call it a bit later in Reconfig.pl.
by Francois Gouget
The functions are now declared in the order in which they are called.
Reconfig.pl now builds the TestBot tools and only then grabs the latest
Wine and recompiles it.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/build/Reconfig.pl | 64 +++++++++++++++++------------------
1 file changed, 31 insertions(+), 33 deletions(-)
diff --git a/testbot/bin/build/Reconfig.pl b/testbot/bin/build/Reconfig.pl
index 977df6e12..bc179951d 100755
--- a/testbot/bin/build/Reconfig.pl
+++ b/testbot/bin/build/Reconfig.pl
@@ -6,6 +6,7 @@
# 32 and 64 bit winetest binaries.
#
# Copyright 2009 Ge van Geldorp
+# Copyright 2012-2014, 2017-2018 Francois Gouget
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -70,35 +71,6 @@ sub FatalError(@)
exit 1;
}
-sub GitPull()
-{
- InfoMsg "Updating the Wine source\n";
- system("cd $DataDir/wine && git pull >> $LogDir/Reconfig.log 2>&1");
- if ($? != 0)
- {
- LogMsg "Git pull failed\n";
- return !1;
- }
-
- if (open(my $fh, ">", "$DataDir/testlist.txt"))
- {
- foreach my $TestFile (glob("$DataDir/wine/*/*/tests/*.c"),
- glob("$DataDir/wine/*/*/tests/*.spec"))
- {
- next if ($TestFile =~ m=/testlist\.c$=);
- $TestFile =~ s=^$DataDir/wine/==;
- print $fh "$TestFile\n";
- }
- close($fh);
- }
- else
- {
- LogMsg "Could not open 'testlist.txt' for writing: $!\n";
- }
-
- return 1;
-}
-
my $ncpus;
sub CountCPUs()
{
@@ -156,6 +128,35 @@ sub BuildTestLauncher()
return 1;
}
+sub GitPull()
+{
+ InfoMsg "Updating the Wine source\n";
+ system("cd $DataDir/wine && git pull >> $LogDir/Reconfig.log 2>&1");
+ if ($? != 0)
+ {
+ LogMsg "Git pull failed\n";
+ return !1;
+ }
+
+ if (open(my $fh, ">", "$DataDir/testlist.txt"))
+ {
+ foreach my $TestFile (glob("$DataDir/wine/*/*/tests/*.c"),
+ glob("$DataDir/wine/*/*/tests/*.spec"))
+ {
+ next if ($TestFile =~ m=/testlist\.c$=);
+ $TestFile =~ s=^$DataDir/wine/==;
+ print $fh "$TestFile\n";
+ }
+ close($fh);
+ }
+ else
+ {
+ LogMsg "Could not open 'testlist.txt' for writing: $!\n";
+ }
+
+ return 1;
+}
+
sub BuildNative()
{
mkdir "$DataDir/build-native" if (! -d "$DataDir/build-native");
@@ -211,15 +212,12 @@ if (! -d "$DataDir/staging" and ! mkdir "$DataDir/staging")
LogMsg "Unable to create '$DataDir/staging': $!\n";
exit(1);
}
-if (! GitPull())
-{
- exit(1);
-}
CountCPUs();
if (!BuildTestAgentd() ||
!BuildTestLauncher() ||
+ !GitPull() ||
!BuildNative() ||
!BuildCross(32) ||
!BuildCross(64))
--
2.17.1
June 13, 2018
Re: [PATCH 3/3] msvcrt: Implement quick_exit and _crt_at_quick_exit
by Piotr Caban
On 06/13/18 08:16, Fabian Maurer wrote:
> Should I also send in a patch for MSVCRT__onexit to use
> _register_onexit_function, and for __MSVCRT__call_atexit to use
> _execute_onexit_table?
Sure, it makes sense to use this helpers there as well.
Thanks,
Piotr
June 13, 2018
Re: [PATCH] msxml3/tests: Use the available ARRAY_SIZE() macro
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
June 13, 2018
Re: [PATCH v2] comctl32/taskdialog: Create buttons without templates.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
June 13, 2018
Re: [PATCH 2/5] wined3d: Get rid of unnecessary enum wined3d_data_type values.
by Józef Kucia
On Tue, Jun 12, 2018 at 6:41 PM, Matteo Bruni <mbruni(a)codeweavers.com> wrote:
> diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
> index 20d4f0773dd..a2c3f00559a 100644
> --- a/dlls/wined3d/shader.c
> +++ b/dlls/wined3d/shader.c
> @@ -2134,14 +2134,6 @@ static void shader_dump_decl_usage(struct wined3d_string_buffer *buffer,
> shader_addline(buffer, " (uint)");
> break;
>
> - case WINED3D_DATA_UNORM:
> - shader_addline(buffer, " (unorm)");
> - break;
> -
> - case WINED3D_DATA_SNORM:
> - shader_addline(buffer, " (snorm)");
> - break;
> -
I don't like that it won't print the correct data type for
declarations. For example, after the patch "dcl_uav_typed_texture2d
(snorm) u0" is "dcl_uav_typed_texture2d (float) u0".
June 13, 2018
[PATCH 2/2] testbot: Create a single Job per patch even for multiple modules.
by Francois Gouget
So far a build task could only provide the 32 and 64 bit test
executables for a single dll or program. Also, because of the lack of
proper dependency support between steps it was impossible to have
multiple build steps. So the TestBot used to create one job per module.
However the patch status site can only keep track of one job per patch.
This means some failures could be missed if they did not happen in the
one job tracked by the patch status site.
Now that Build.pl rebuilds all the impacted test executables the
Testbot systematically creates a single job and a single build task and
retrieves all the test executables in one go. This also has the
advantage of reducing the number of VM reverts.
Another side-effect of this change is that if the patch modifies the
tests of multiple modules and the compilation of one them fails, no
test will be run. Before only the tests impacted by the failed
compilation would have been skipped. However a compilation error is
grounds for resubmitting the patch, at which time the tests will be
rerun anyway.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineRunBuild.pl | 65 ++++---------
testbot/lib/WineTestBot/Patches.pm | 143 +++++++++++++----------------
2 files changed, 85 insertions(+), 123 deletions(-)
diff --git a/testbot/bin/WineRunBuild.pl b/testbot/bin/WineRunBuild.pl
index 12e34d5c7..61deb50a6 100755
--- a/testbot/bin/WineRunBuild.pl
+++ b/testbot/bin/WineRunBuild.pl
@@ -43,6 +43,7 @@ $Name0 =~ s+^.*/++;
use WineTestBot::Config;
use WineTestBot::Jobs;
+use WineTestBot::PatchUtils;
use WineTestBot::VMs;
use WineTestBot::Log;
use WineTestBot::Engine::Notify;
@@ -323,31 +324,15 @@ elsif ($Debug and !$VM->GetDomain()->IsPoweredOn())
# Figure out what to build
#
-my ($Run64, $BaseName);
-foreach my $OtherStep (@{$Job->Steps->GetItems()})
+my (%Bitnesses, %TestExes);
+foreach my $TestStep (@{$Job->Steps->GetItems()})
{
- next if ($OtherStep->No == $StepNo);
-
- $Run64 = 1 if ($OtherStep->FileType eq "exe64");
- my $OtherFileName = $OtherStep->FileName;
- if ($OtherFileName =~ m/^([\w_.]+)_test(?:64)?\.exe$/)
+ if ($TestStep->FileType =~ /^exe([0-9]+)$/)
{
- my $OtherBaseName = $1;
- if ($Step->FileType eq "patchprograms")
- {
- $OtherBaseName =~ s/\.exe$//;
- }
- if (defined $BaseName and $BaseName ne $OtherBaseName)
- {
- FatalError("$OtherBaseName doesn't match previously found $BaseName\n");
- }
- $BaseName = $OtherBaseName;
+ $Bitnesses{$1} = 1;
+ $TestExes{$TestStep->FileName} = 1;
}
}
-if (!defined $BaseName)
-{
- FatalError("Could not determine the test executable's base name\n");
-}
#
@@ -363,9 +348,8 @@ if (!$TA->SendFile($FileName, "staging/patch.diff", 0))
}
my $Script = "#!/bin/sh\n" .
"rm -f Build.log\n" .
- "../bin/build/Build.pl patch.diff 32";
-$Script .= ",64"if ($Run64);
-$Script .= " >>Build.log 2>&1\n";
+ "../bin/build/Build.pl patch.diff ". join(",", keys %Bitnesses) .
+ " >>Build.log 2>&1\n";
Debug(Elapsed($Start), " Sending the script: [$Script]\n");
if (!$TA->SendFileFromString($Script, "task", $TestAgent::SENDFILE_EXE))
{
@@ -456,34 +440,25 @@ FatalTAError(undef, $TAError) if (defined $TAError);
# Grab the executables for the next steps
#
-# Don't try copying the test executables if the build step failed
-if ($NewStatus eq "completed")
+my $Impacts = GetPatchImpact($FileName, "nounit");
+my $StepDir = $Step->CreateDir();
+foreach my $TestInfo (values %{$Impacts->{Tests}})
{
- my $StepDir = $Step->CreateDir();
- foreach my $OtherStep (@{$Job->Steps->GetItems()})
+ foreach my $Bits ("", "64")
{
- next if ($OtherStep->No == $StepNo);
-
- my $OtherFileName = $OtherStep->FileName;
- next if ($OtherFileName !~ /^[\w_.]+_test(?:64)?\.exe$/);
+ my $Local = "$TestInfo->{ExeBase}$Bits.exe";
+ next if (!$TestExes{$Local});
- my $Bits = $OtherStep->FileType eq "exe64" ? "64" : "32";
- my $TestExecutable;
- if ($Step->FileType ne "patchprograms")
- {
- $TestExecutable = "build-mingw$Bits/dlls/$BaseName/tests/${BaseName}_test.exe";
- }
- else
+ my $Remote = "build-mingw". ($Bits || "32") ."/$TestInfo->{Path}/$TestInfo->{ExeBase}.exe";
+ Debug(Elapsed($Start), " Retrieving '$Local'\n");
+ if ($TA->GetFile($Remote, "$StepDir/$Local"))
{
- $TestExecutable = "build-mingw$Bits/programs/$BaseName/tests/${BaseName}.exe_test.exe";
+ chmod 0664, "$StepDir/$Local";
}
-
- Debug(Elapsed($Start), " Retrieving '$OtherFileName'\n");
- if (!$TA->GetFile($TestExecutable, "$StepDir/$OtherFileName"))
+ elsif ($TA->GetLastError() !~ /: No such file or directory/)
{
- FatalTAError($TA, "Could not retrieve '$OtherFileName'");
+ FatalTAError($TA, "Could not retrieve '$Local'");
}
- chmod 0664, "$StepDir/$OtherFileName";
}
}
$TA->Disconnect();
diff --git a/testbot/lib/WineTestBot/Patches.pm b/testbot/lib/WineTestBot/Patches.pm
index e349dfe88..258aa2c19 100644
--- a/testbot/lib/WineTestBot/Patches.pm
+++ b/testbot/lib/WineTestBot/Patches.pm
@@ -157,59 +157,55 @@ sub Submit($$$)
$User = GetBatchUser();
}
- my $Disposition = "Submitted job ";
- my $First = 1;
- foreach my $Module (sort keys %{$Impacts->{Tests}})
- {
- my $TestInfo = $Impacts->{Tests}->{$Module};
- my $Jobs = CreateJobs();
-
- # Create a new job for this patch
- my $NewJob = $Jobs->Add();
- $NewJob->User($User);
- $NewJob->Priority(6);
- my $PropertyDescriptor = $Jobs->GetPropertyDescriptorByName("Remarks");
- my $Subject = $self->Subject;
- $Subject =~ s/\[PATCH[^\]]*]//i;
- $Subject =~ s/[[\(]?\d+\/\d+[\)\]]?//;
- $Subject =~ s/^\s*//;
- $NewJob->Remarks(substr("[wine-patches] " . $Subject, 0,
- $PropertyDescriptor->GetMaxLength()));
- $NewJob->Patch($self);
+ # Create a new job for this patch
+ my $Jobs = CreateJobs();
+ my $NewJob = $Jobs->Add();
+ $NewJob->User($User);
+ $NewJob->Priority(6);
+ my $PropertyDescriptor = $Jobs->GetPropertyDescriptorByName("Remarks");
+ my $Subject = $self->Subject;
+ $Subject =~ s/\[PATCH[^\]]*]//i;
+ $Subject =~ s/[[\(]?\d+\/\d+[\)\]]?//;
+ $Subject =~ s/^\s*//;
+ $NewJob->Remarks(substr("[wine-patches] " . $Subject, 0,
+ $PropertyDescriptor->GetMaxLength()));
+ $NewJob->Patch($self);
+
+ # Add build step to the job
+ my $BuildStep = $NewJob->Steps->Add();
+ $BuildStep->FileName("patch.diff");
+ $BuildStep->FileType("patchdlls"); # This is irrelevant now
+ $BuildStep->InStaging(!1);
+ $BuildStep->Type("build");
+ $BuildStep->DebugLevel(0);
- # Add build step to the job
- my $Steps = $NewJob->Steps;
- my $NewStep = $Steps->Add();
- $NewStep->FileName("patch.diff");
- $NewStep->FileType($TestInfo->{Type});
- $NewStep->InStaging(!1);
- $NewStep->Type("build");
- $NewStep->DebugLevel(0);
-
- # Add build task
- my $VMs = CreateVMs();
- $VMs->AddFilter("Type", ["build"]);
- $VMs->AddFilter("Role", ["base"]);
- my $BuildVM = ${$VMs->GetItems()}[0];
- my $Task = $NewStep->Tasks->Add();
- $Task->VM($BuildVM);
- $Task->Timeout($BuildTimeout);
-
- # Save the build step so other steps can reference it
- my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
- if (defined($ErrMessage))
- {
- $self->Disposition("Failed to submit build step");
- return $ErrMessage;
- }
+ # Add build task
+ my $VMs = CreateVMs();
+ $VMs->AddFilter("Type", ["build"]);
+ $VMs->AddFilter("Role", ["base"]);
+ my $BuildVM = ${$VMs->GetItems()}[0];
+ my $Task = $BuildStep->Tasks->Add();
+ $Task->VM($BuildVM);
+ $Task->Timeout($BuildTimeout);
+
+ # Save the build step so the others can reference it.
+ my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined($ErrMessage))
+ {
+ $self->Disposition("Failed to submit build step");
+ return $ErrMessage;
+ }
- # Stage the patch so it can be picked up by the job
- if (!link($PatchFileName, "$DataDir/staging/job". $NewJob->Id ."_patch.diff"))
- {
- $self->Disposition("Failed to prepare patch file");
- return $!;
- }
+ # Stage the patch so it can be picked up by the job
+ if (!link($PatchFileName, "$DataDir/staging/job". $NewJob->Id ."_patch.diff"))
+ {
+ $self->Disposition("Failed to stage the patch file");
+ return $!;
+ }
+ foreach my $Module (sort keys %{$Impacts->{Tests}})
+ {
+ my $TestInfo = $Impacts->{Tests}->{$Module};
foreach my $Unit (sort keys %{$TestInfo->{Units}})
{
# Add 32 and 64-bit tasks
@@ -221,8 +217,8 @@ sub Submit($$$)
if (@{$VMs->GetKeys()})
{
# Create the corresponding Step
- my $NewStep = $Steps->Add();
- $NewStep->PreviousNo(1);
+ my $NewStep = $NewJob->Steps->Add();
+ $NewStep->PreviousNo($BuildStep->No);
my $FileName = $TestInfo->{ExeBase};
$FileName .= "64" if ($Bits eq "64");
$NewStep->FileName("$FileName.exe");
@@ -243,35 +239,26 @@ sub Submit($$$)
}
}
}
+ }
- # Save it all
- ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
- if (defined $ErrMessage)
- {
- $self->Disposition("Failed to submit job");
- return $ErrMessage;
- }
-
- # Switch Status to staging to indicate we are done setting up the job
- $NewJob->Status("staging");
- ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
- if (defined $ErrMessage)
- {
- $self->Disposition("Failed to submit job (staging)");
- return $ErrMessage;
- }
+ # Save it all
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
+ {
+ $self->Disposition("Failed to submit job");
+ return $ErrMessage;
+ }
- if ($First)
- {
- $First = !1;
- }
- else
- {
- $Disposition .= ", ";
- }
- $Disposition .= $NewJob->Id;
+ # Switch Status to staging to indicate we are done setting up the job
+ $NewJob->Status("staging");
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
+ {
+ $self->Disposition("Failed to submit job (staging)");
+ return $ErrMessage;
}
- $self->Disposition($Disposition);
+
+ $self->Disposition("Submitted job ". $NewJob->Id);
return undef;
}
--
2.17.1
June 13, 2018
[PATCH 1/2] testbot: Remove the unneeded Build.pl parameters.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineRunBuild.pl | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/testbot/bin/WineRunBuild.pl b/testbot/bin/WineRunBuild.pl
index 7a474e76d..12e34d5c7 100755
--- a/testbot/bin/WineRunBuild.pl
+++ b/testbot/bin/WineRunBuild.pl
@@ -363,8 +363,7 @@ if (!$TA->SendFile($FileName, "staging/patch.diff", 0))
}
my $Script = "#!/bin/sh\n" .
"rm -f Build.log\n" .
- "../bin/build/Build.pl patch.diff " . $Step->FileType .
- " $BaseName 32";
+ "../bin/build/Build.pl patch.diff 32";
$Script .= ",64"if ($Run64);
$Script .= " >>Build.log 2>&1\n";
Debug(Elapsed($Start), " Sending the script: [$Script]\n");
--
2.17.1
June 13, 2018
[PATCH v2] comctl32/taskdialog: Create buttons without templates.
by Zhiyi Zhang
Supersede 147257 and 147258.
Create buttons without templates and delete all unnecessary
templates related infrastructures.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 293 ++++++++++---------------------------
1 file changed, 74 insertions(+), 219 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index d71189d4de..7a09b8a6d2 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -34,16 +34,10 @@
#include "comctl32.h"
#include "wine/debug.h"
-#include "wine/list.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(taskdialog);
-#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
-#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
-#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
-#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
-
static const UINT DIALOG_MIN_WIDTH = 240;
static const UINT DIALOG_SPACING = 5;
static const UINT DIALOG_BUTTON_WIDTH = 50;
@@ -52,28 +46,6 @@ static const UINT DIALOG_TIMER_MS = 200;
static const UINT ID_TIMER = 1;
-struct taskdialog_control
-{
- struct list entry;
- DLGITEMTEMPLATE *template;
- unsigned int template_size;
-};
-
-struct taskdialog_button_desc
-{
- int id;
- const WCHAR *text;
- HINSTANCE hinst;
-};
-
-struct taskdialog_template_desc
-{
- const TASKDIALOGCONFIG *taskconfig;
- struct list controls;
- WORD control_count;
- struct taskdialog_button_desc *default_button;
-};
-
struct taskdialog_info
{
HWND hwnd;
@@ -84,6 +56,9 @@ struct taskdialog_info
/* Control handles */
HWND main_instruction;
HWND content;
+ HWND *buttons;
+ INT button_count;
+ HWND default_button;
/* Dialog metrics */
struct
{
@@ -96,8 +71,6 @@ struct taskdialog_info
struct button_layout_info
{
- INT id;
- HWND hwnd;
LONG width;
LONG line;
};
@@ -114,138 +87,6 @@ static void template_write_data(char **ptr, const void *src, unsigned int size)
*ptr += size;
}
-static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc, WORD id, const WCHAR *class,
- HINSTANCE hInstance, const WCHAR *text, DWORD style)
-{
- struct taskdialog_control *control = Alloc(sizeof(*control));
- unsigned int size, class_size, text_size;
- DLGITEMTEMPLATE *template;
- static const WCHAR nulW;
- const WCHAR *textW;
- char *ptr;
-
- class_size = (strlenW(class) + 1) * sizeof(WCHAR);
-
- if (IS_INTRESOURCE(text))
- text_size = LoadStringW(hInstance, (UINT_PTR)text, (WCHAR *)&textW, 0) * sizeof(WCHAR);
- else
- {
- textW = text;
- text_size = strlenW(textW) * sizeof(WCHAR);
- }
-
- size = sizeof(DLGITEMTEMPLATE);
- size += class_size;
- size += text_size + sizeof(WCHAR);
- size += sizeof(WORD); /* creation data */
-
- control->template = template = Alloc(size);
- control->template_size = size;
-
- template->style = WS_VISIBLE | style;
- template->dwExtendedStyle = 0;
- template->id = id;
- ptr = (char *)(template + 1);
- template_write_data(&ptr, class, class_size);
- template_write_data(&ptr, textW, text_size);
- template_write_data(&ptr, &nulW, sizeof(nulW));
-
- list_add_tail(&desc->controls, &control->entry);
- desc->control_count++;
- return ALIGNED_LENGTH(size, 3);
-}
-
-static void taskdialog_init_button(struct taskdialog_button_desc *button, struct taskdialog_template_desc *desc,
- int id, const WCHAR *text, BOOL custom_button)
-{
- button->id = id;
- button->text = text;
- button->hinst = custom_button ? desc->taskconfig->hInstance : COMCTL32_hModule;
-
- if (id == desc->taskconfig->nDefaultButton)
- desc->default_button = button;
-}
-
-static void taskdialog_init_common_buttons(struct taskdialog_template_desc *desc, struct taskdialog_button_desc *buttons,
- unsigned int *button_count)
-{
- DWORD flags = desc->taskconfig->dwCommonButtons;
-
-#define TASKDIALOG_INIT_COMMON_BUTTON(id) \
- do { \
- taskdialog_init_button(&buttons[(*button_count)++], desc, ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), FALSE); \
- } while(0)
-
- if (flags & TDCBF_OK_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(OK);
- if (flags & TDCBF_YES_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(YES);
- if (flags & TDCBF_NO_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(NO);
- if (flags & TDCBF_RETRY_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(RETRY);
- if (flags & TDCBF_CANCEL_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
- if (flags & TDCBF_CLOSE_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
-
-#undef TASKDIALOG_INIT_COMMON_BUTTON
-}
-
-static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc)
-{
- unsigned int count = 0, buttons_size, i, size = 0;
- const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
- struct taskdialog_button_desc *buttons;
-
- /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
- buttons_size = 6;
- if (taskconfig->cButtons && taskconfig->pButtons)
- buttons_size += taskconfig->cButtons;
-
- if (!(buttons = Alloc(buttons_size * sizeof(*buttons))))
- return 0;
-
- /* Custom buttons */
- if (taskconfig->cButtons && taskconfig->pButtons)
- for (i = 0; i < taskconfig->cButtons; i++)
- taskdialog_init_button(&buttons[count++], desc, taskconfig->pButtons[i].nButtonID,
- taskconfig->pButtons[i].pszButtonText, TRUE);
-
- /* Common buttons */
- taskdialog_init_common_buttons(desc, buttons, &count);
-
- /* There must be at least one button */
- if (count == 0)
- taskdialog_init_button(&buttons[count++], desc, IDOK, MAKEINTRESOURCEW(IDS_BUTTON_OK), FALSE);
-
- if (!desc->default_button)
- desc->default_button = &buttons[0];
-
- /* create all buttons */
- for (i = 0; i < count; i++)
- {
- DWORD style = &buttons[i] == desc->default_button ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON;
- size += taskdialog_add_control(desc, buttons[i].id, WC_BUTTONW, buttons[i].hinst, buttons[i].text, style);
- }
-
- Free(buttons);
-
- return size;
-}
-
-static void taskdialog_clear_controls(struct list *controls)
-{
- struct taskdialog_control *control, *control2;
-
- LIST_FOR_EACH_ENTRY_SAFE(control, control2, controls, struct taskdialog_control, entry)
- {
- list_remove(&control->entry);
- Free(control->template);
- Free(control);
- }
-}
-
static unsigned int taskdialog_get_reference_rect(const TASKDIALOGCONFIG *taskconfig, RECT *ret)
{
HMONITOR monitor = MonitorFromWindow(taskconfig->hwndParent ? taskconfig->hwndParent : GetActiveWindow(),
@@ -279,9 +120,7 @@ static WCHAR *taskdialog_get_exe_name(WCHAR *name, DWORD length)
static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfig)
{
- struct taskdialog_control *control, *control2;
unsigned int size, title_size;
- struct taskdialog_template_desc desc;
static const WORD fontsize = 0x7fff;
static const WCHAR emptyW[] = { 0 };
const WCHAR *titleW = NULL;
@@ -307,25 +146,13 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
size += title_size;
size += 2; /* font size */
- list_init(&desc.controls);
- desc.taskconfig = taskconfig;
- desc.control_count = 0;
- desc.default_button = NULL;
-
- size += taskdialog_add_buttons(&desc);
-
template = Alloc(size);
- if (!template)
- {
- taskdialog_clear_controls(&desc.controls);
- return NULL;
- }
+ if (!template) return NULL;
template->style = DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
if (taskconfig->dwFlags & TDF_CAN_BE_MINIMIZED) template->style |= WS_MINIMIZEBOX;
if (!(taskconfig->dwFlags & TDF_NO_SET_FOREGROUND)) template->style |= DS_SETFOREGROUND;
if (taskconfig->dwFlags & TDF_RTL_LAYOUT) template->dwExtendedStyle = WS_EX_LAYOUTRTL | WS_EX_RIGHT | WS_EX_RTLREADING;
- template->cdit = desc.control_count;
ptr = (char *)(template + 1);
ptr += 2; /* menu */
@@ -333,19 +160,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
template_write_data(&ptr, titleW, title_size);
template_write_data(&ptr, &fontsize, sizeof(fontsize));
- /* write control entries */
- LIST_FOR_EACH_ENTRY_SAFE(control, control2, &desc.controls, struct taskdialog_control, entry)
- {
- ALIGN_POINTER(ptr, 3);
-
- template_write_data(&ptr, control->template, control->template_size);
-
- /* list item won't be needed later */
- list_remove(&control->entry);
- Free(control->template);
- Free(control);
- }
-
return template;
}
@@ -450,6 +264,58 @@ static void taskdialog_add_content(struct taskdialog_info *dialog_info)
dialog_info->content = taskdialog_create_label(dialog_info, dialog_info->taskconfig->pszContent, dialog_info->font);
}
+static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT id, const WCHAR *text,
+ BOOL custom_button)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ WCHAR *textW;
+
+ textW = taskdialog_gettext(dialog_info, custom_button, text);
+ *button = CreateWindowW(WC_BUTTONW, textW, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 0, 0, dialog_info->hwnd,
+ (HMENU)id, 0, NULL);
+ Free(textW);
+ SendMessageW(*button, WM_SETFONT, (WPARAM)dialog_info->font, 0);
+
+ if (id == taskconfig->nDefaultButton && !dialog_info->default_button) dialog_info->default_button = *button;
+}
+
+static void taskdialog_add_buttons(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ DWORD flags = taskconfig->dwCommonButtons;
+ INT count, max_count;
+
+ /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
+ max_count = 6;
+ if (taskconfig->cButtons && taskconfig->pButtons) max_count += taskconfig->cButtons;
+
+ dialog_info->buttons = Alloc(max_count * sizeof(*dialog_info->buttons));
+ if (!dialog_info->buttons) return;
+
+ for (count = 0; count < taskconfig->cButtons; count++)
+ taskdialog_add_button(dialog_info, &dialog_info->buttons[count], taskconfig->pButtons[count].nButtonID,
+ taskconfig->pButtons[count].pszButtonText, TRUE);
+
+#define TASKDIALOG_INIT_COMMON_BUTTON(id) \
+ do \
+ { \
+ taskdialog_add_button(dialog_info, &dialog_info->buttons[count++], ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), \
+ FALSE); \
+ } while (0)
+
+ if (flags & TDCBF_OK_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(OK);
+ if (flags & TDCBF_YES_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(YES);
+ if (flags & TDCBF_NO_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(NO);
+ if (flags & TDCBF_RETRY_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(RETRY);
+ if (flags & TDCBF_CANCEL_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
+ if (flags & TDCBF_CLOSE_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
+
+ if (!count) TASKDIALOG_INIT_COMMON_BUTTON(OK);
+#undef TASKDIALOG_INIT_COMMON_BUTTON
+
+ dialog_info->button_count = count;
+}
+
static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hwnd, INT start_x, LONG dialog_width,
LONG *dialog_height)
{
@@ -469,12 +335,10 @@ static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hw
static void taskdialog_layout(struct taskdialog_info *dialog_info)
{
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
- DWORD flags = taskconfig->dwCommonButtons;
static BOOL first_time = TRUE;
RECT ref_rect;
LONG screen_width, dialog_width, dialog_height = 0;
LONG h_spacing, v_spacing;
- INT button_max_count, button_count = 0;
struct button_layout_info *button_layout_infos;
LONG button_min_width, button_height;
LONG *line_widths, line_count, align;
@@ -497,39 +361,21 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
taskdialog_label_layout(dialog_info, dialog_info->content, 0, dialog_width, &dialog_height);
/* Common and custom buttons */
- /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
- button_max_count = 6;
- /* Custom buttons */
- if (taskconfig->cButtons && taskconfig->pButtons) button_max_count += taskconfig->cButtons;
-
- button_layout_infos = Alloc(button_max_count * sizeof(*button_layout_infos));
- line_widths = Alloc(button_max_count * sizeof(*line_widths));
-
- if (taskconfig->cButtons && taskconfig->pButtons)
- for (button_count = 0; button_count < taskconfig->cButtons; button_count++)
- button_layout_infos[button_count].id = taskconfig->pButtons[button_count].nButtonID;
-
- /* Ok button may be added if no button is specified in taskconfig */
- if (GetDlgItem(dialog_info->hwnd, IDOK)) button_layout_infos[button_count++].id = IDOK;
- if (flags & TDCBF_YES_BUTTON) button_layout_infos[button_count++].id = IDYES;
- if (flags & TDCBF_NO_BUTTON) button_layout_infos[button_count++].id = IDNO;
- if (flags & TDCBF_RETRY_BUTTON) button_layout_infos[button_count++].id = IDRETRY;
- if (flags & TDCBF_CANCEL_BUTTON) button_layout_infos[button_count++].id = IDCANCEL;
- if (flags & TDCBF_CLOSE_BUTTON) button_layout_infos[button_count++].id = IDCLOSE;
+ button_layout_infos = Alloc(dialog_info->button_count * sizeof(*button_layout_infos));
+ line_widths = Alloc(dialog_info->button_count * sizeof(*line_widths));
button_min_width = DIALOG_BUTTON_WIDTH;
button_height = DIALOG_BUTTON_HEIGHT;
taskdialog_du_to_px(dialog_info, &button_min_width, &button_height);
- for (i = 0; i < button_count; i++)
+ for (i = 0; i < dialog_info->button_count; i++)
{
- button_layout_infos[i].hwnd = GetDlgItem(dialog_info->hwnd, button_layout_infos[i].id);
- taskdialog_get_label_size(dialog_info, button_layout_infos[i].hwnd, dialog_width - h_spacing * 2, &size);
+ taskdialog_get_label_size(dialog_info, dialog_info->buttons[i], dialog_width - h_spacing * 2, &size);
button_layout_infos[i].width = max(size.cx, button_min_width);
}
/* Separate buttons into lines */
x = h_spacing;
- for (i = 0, line_count = 0; i < button_count; i++)
+ for (i = 0, line_count = 0; i < dialog_info->button_count; i++)
{
if (x + button_layout_infos[i].width + h_spacing >= dialog_width)
{
@@ -551,7 +397,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
unsigned int j, last_button = 0;
int diff_changed;
- for (j = 0; j < button_count; j++)
+ for (j = 0; j < dialog_info->button_count; j++)
if (button_layout_infos[j].line == i - 1) last_button = j;
/* Difference in length of both lines if we wrapped the last button from the last line into this one */
@@ -576,7 +422,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
/* Now that we got them all positioned, move all buttons */
x = align;
size.cy = button_height;
- for (i = 0; i < button_count; i++)
+ for (i = 0; i < dialog_info->button_count; i++)
{
/* New line */
if (i > 0 && button_layout_infos[i].line != button_layout_infos[i - 1].line)
@@ -587,7 +433,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
y = dialog_height + v_spacing;
size.cx = button_layout_infos[i].width;
- SetWindowPos(button_layout_infos[i].hwnd, 0, x, y, size.cx, size.cy, SWP_NOZORDER);
+ SetWindowPos(dialog_info->buttons[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
x += button_layout_infos[i].width + h_spacing;
}
@@ -618,6 +464,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
NONCLIENTMETRICSW ncm;
HDC hdc;
+ INT id;
ncm.cbSize = sizeof(ncm);
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
@@ -644,6 +491,13 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
taskdialog_add_main_instruction(dialog_info);
taskdialog_add_content(dialog_info);
+ taskdialog_add_buttons(dialog_info);
+
+ /* Set default button */
+ if (!dialog_info->default_button) dialog_info->default_button = dialog_info->buttons[0];
+ SendMessageW(dialog_info->hwnd, WM_NEXTDLGCTL, (WPARAM)dialog_info->default_button, TRUE);
+ id = GetWindowLongW(dialog_info->default_button, GWLP_ID);
+ SendMessageW(dialog_info->hwnd, DM_SETDEFID, id, 0);
taskdialog_layout(dialog_info);
}
@@ -653,6 +507,7 @@ static void taskdialog_destroy(struct taskdialog_info *dialog_info)
if (dialog_info->taskconfig->dwFlags & TDF_CALLBACK_TIMER) KillTimer(dialog_info->hwnd, ID_TIMER);
if (dialog_info->font) DeleteObject(dialog_info->font);
if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
+ if (dialog_info->buttons) Free(dialog_info->buttons);
}
static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -678,7 +533,7 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
taskdialog_notify(dialog_info, TDN_CREATED, 0, 0);
- break;
+ return FALSE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
--
2.17.1
June 13, 2018
Re: [PATCH] msi/tests: Avoid ARRAY_SIZE-like macros
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
June 13, 2018
Re: [PATCH 3/3] msvcrt: Implement quick_exit and _crt_at_quick_exit
by Fabian Maurer
> atexit and at_quick_exit needs to manage similar table of functions.
> Because of that there's a set of helper functions that can be used to
> accomplish it (*_onexit_table functions). It's even documented that it's
> used internally: https://msdn.microsoft.com/en-us/library/mt670601.aspx
Yes, this makes sense.
Should I also send in a patch for MSVCRT__onexit to use _register_onexit_function,
and for __MSVCRT__call_atexit to use _execute_onexit_table?
Because those too duplicate the functionality, that's where I got that from.
I'd also add some tests while I'm on it.
Regards,
Fabian Maurer
June 13, 2018